Merge tag 'r8169-20060912-00' of git://electric-eye.fr.zoreil.com/home/romieu/linux-2.6 into tmp
diff --git a/.gitignore b/.gitignore
index 27fd376..b1f5b9d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,11 @@
 include/linux/autoconf.h
 include/linux/compile.h
 include/linux/version.h
+include/linux/utsrelease.h
 
 # stgit generated dirs
 patches-*
+
+# quilt's files
+patches
+series
diff --git a/CREDITS b/CREDITS
index 29be6d1..0fe904e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2209,7 +2209,7 @@
 S: USA
 
 N: Ian McDonald
-E: iam4@cs.waikato.ac.nz
+E: ian.mcdonald@jandi.co.nz
 E: imcdnzl@gmail.com
 W: http://wand.net.nz/~iam4
 W: http://imcdnzl.blogspot.com
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 1ae4dc0..f8fe882 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -59,6 +59,9 @@
 !Iinclude/linux/hrtimer.h
 !Ekernel/hrtimer.c
      </sect1>
+     <sect1><title>Workqueues and Kevents</title>
+!Ekernel/workqueue.c
+     </sect1>
      <sect1><title>Internal Functions</title>
 !Ikernel/exit.c
 !Ikernel/signal.c
@@ -300,7 +303,7 @@
      </sect1>
 
      <sect1><title>Resources Management</title>
-!Ekernel/resource.c
+!Ikernel/resource.c
      </sect1>
 
      <sect1><title>MTRR Handling</title>
@@ -312,9 +315,7 @@
 !Edrivers/pci/pci-driver.c
 !Edrivers/pci/remove.c
 !Edrivers/pci/pci-acpi.c
-<!-- kerneldoc does not understand __devinit
-X!Edrivers/pci/search.c
- -->
+!Edrivers/pci/search.c
 !Edrivers/pci/msi.c
 !Edrivers/pci/bus.c
 <!-- FIXME: Removed for now since no structured comments in source
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index c2c85bc..2cd7f02 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -10,7 +10,9 @@
 with "the system."  This text is a collection of suggestions which
 can greatly increase the chances of your change being accepted.
 
-If you are submitting a driver, also read Documentation/SubmittingDrivers.
+Read Documentation/SubmitChecklist for a list of items to check
+before submitting code.  If you are submitting a driver, also read
+Documentation/SubmittingDrivers.
 
 
 
@@ -74,9 +76,6 @@
 Quilt:
 http://savannah.nongnu.org/projects/quilt
 
-Randy Dunlap's patch scripts:
-http://www.xenotime.net/linux/scripts/patching-scripts-002.tar.gz
-
 Andrew Morton's patch scripts:
 http://www.zip.com.au/~akpm/linux/patches/
 Instead of these scripts, quilt is the recommended patch management
@@ -484,7 +483,7 @@
   <http://www.kroah.com/log/2005/10/19/>
   <http://www.kroah.com/log/2006/01/11/>
 
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!.
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
   <http://marc.theaimsgroup.com/?l=linux-kernel&m=112112749912944&w=2>
 
 Kernel Documentation/CodingStyle
@@ -493,4 +492,3 @@
 Linus Torvald's mail on the canonical patch format:
   <http://lkml.org/lkml/2005/4/7/183>
 --
-Last updated on 17 Nov 2005.
diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt
index be215e5..1443cd7 100644
--- a/Documentation/accounting/delay-accounting.txt
+++ b/Documentation/accounting/delay-accounting.txt
@@ -64,11 +64,13 @@
 	CONFIG_TASK_DELAY_ACCT=y
 	CONFIG_TASKSTATS=y
 
-Enable the accounting at boot time by adding
-the following to the kernel boot options
-	delayacct
+Delay accounting is enabled by default at boot up.
+To disable, add
+   nodelayacct
+to the kernel boot options. The rest of the instructions
+below assume this has not been done.
 
-and after the system has booted up, use a utility
+After the system has booted up, use a utility
 similar to  getdelays.c to access the delays
 seen by a given task or a task group (tgid).
 The utility also allows a given command to be
diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c
new file mode 100644
index 0000000..d738cde
--- /dev/null
+++ b/Documentation/connector/ucon.c
@@ -0,0 +1,206 @@
+/*
+ * 	ucon.c
+ *
+ * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ *
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <asm/types.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#include <linux/connector.h>
+
+#define DEBUG
+#define NETLINK_CONNECTOR 	11
+
+#ifdef DEBUG
+#define ulog(f, a...) fprintf(stdout, f, ##a)
+#else
+#define ulog(f, a...) do {} while (0)
+#endif
+
+static int need_exit;
+static __u32 seq;
+
+static int netlink_send(int s, struct cn_msg *msg)
+{
+	struct nlmsghdr *nlh;
+	unsigned int size;
+	int err;
+	char buf[128];
+	struct cn_msg *m;
+
+	size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
+
+	nlh = (struct nlmsghdr *)buf;
+	nlh->nlmsg_seq = seq++;
+	nlh->nlmsg_pid = getpid();
+	nlh->nlmsg_type = NLMSG_DONE;
+	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+	nlh->nlmsg_flags = 0;
+
+	m = NLMSG_DATA(nlh);
+#if 0
+	ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n",
+	       __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack);
+#endif
+	memcpy(m, msg, sizeof(*m) + msg->len);
+
+	err = send(s, nlh, size, 0);
+	if (err == -1)
+		ulog("Failed to send: %s [%d].\n",
+			strerror(errno), errno);
+
+	return err;
+}
+
+int main(int argc, char *argv[])
+{
+	int s;
+	char buf[1024];
+	int len;
+	struct nlmsghdr *reply;
+	struct sockaddr_nl l_local;
+	struct cn_msg *data;
+	FILE *out;
+	time_t tm;
+	struct pollfd pfd;
+
+	if (argc < 2)
+		out = stdout;
+	else {
+		out = fopen(argv[1], "a+");
+		if (!out) {
+			ulog("Unable to open %s for writing: %s\n",
+				argv[1], strerror(errno));
+			out = stdout;
+		}
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+	if (s == -1) {
+		perror("socket");
+		return -1;
+	}
+
+	l_local.nl_family = AF_NETLINK;
+	l_local.nl_groups = 0x123; /* bitmask of requested groups */
+	l_local.nl_pid = 0;
+
+	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
+		perror("bind");
+		close(s);
+		return -1;
+	}
+
+#if 0
+	{
+		int on = 0x57; /* Additional group number */
+		setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
+	}
+#endif
+	if (0) {
+		int i, j;
+
+		memset(buf, 0, sizeof(buf));
+
+		data = (struct cn_msg *)buf;
+
+		data->id.idx = 0x123;
+		data->id.val = 0x456;
+		data->seq = seq++;
+		data->ack = 0;
+		data->len = 0;
+
+		for (j=0; j<10; ++j) {
+			for (i=0; i<1000; ++i) {
+				len = netlink_send(s, data);
+			}
+
+			ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val);
+		}
+
+		return 0;
+	}
+
+
+	pfd.fd = s;
+
+	while (!need_exit) {
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		switch (poll(&pfd, 1, -1)) {
+			case 0:
+				need_exit = 1;
+				break;
+			case -1:
+				if (errno != EINTR) {
+					need_exit = 1;
+					break;
+				}
+				continue;
+		}
+		if (need_exit)
+			break;
+
+		memset(buf, 0, sizeof(buf));
+		len = recv(s, buf, sizeof(buf), 0);
+		if (len == -1) {
+			perror("recv buf");
+			close(s);
+			return -1;
+		}
+		reply = (struct nlmsghdr *)buf;
+
+		switch (reply->nlmsg_type) {
+		case NLMSG_ERROR:
+			fprintf(out, "Error message received.\n");
+			fflush(out);
+			break;
+		case NLMSG_DONE:
+			data = (struct cn_msg *)NLMSG_DATA(reply);
+
+			time(&tm);
+			fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n",
+				ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack);
+			fflush(out);
+			break;
+		default:
+			break;
+		}
+	}
+
+	close(s);
+	return 0;
+}
diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
index 7fedc00..555c8cf 100644
--- a/Documentation/cpu-freq/user-guide.txt
+++ b/Documentation/cpu-freq/user-guide.txt
@@ -153,10 +153,13 @@
 				that some governors won't load - they only
 				work on some specific architectures or
 				processors.
-scaling_min_freq and 
+scaling_min_freq and
 scaling_max_freq		show the current "policy limits" (in
 				kHz). By echoing new values into these
 				files, you can change these limits.
+				NOTE: when setting a policy you need to
+				first set scaling_max_freq, then
+				scaling_min_freq.
 
 
 If you have selected the "userspace" governor which allows you to
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index 1bcf699..bc107cb 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -251,16 +251,24 @@
 		return NOTIFY_OK;
 	}
 
-	static struct notifier_block foobar_cpu_notifer =
+	static struct notifier_block __cpuinitdata foobar_cpu_notifer =
 	{
 	   .notifier_call = foobar_cpu_callback,
 	};
 
+You need to call register_cpu_notifier() from your init function.
+Init functions could be of two types:
+1. early init (init function called when only the boot processor is online).
+2. late init (init function called _after_ all the CPUs are online).
 
-In your init function,
+For the first case, you should add the following to your init function
 
 	register_cpu_notifier(&foobar_cpu_notifier);
 
+For the second case, you should add the following to your init function
+
+	register_hotcpu_notifier(&foobar_cpu_notifier);
+
 You can fail PREPARE notifiers if something doesn't work to prepare resources.
 This will stop the activity and send a following CANCELED event back.
 
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 159e2a0..76b4429 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -217,6 +217,12 @@
 to represent the cpuset hierarchy provides for a familiar permission
 and name space for cpusets, with a minimum of additional kernel code.
 
+The cpus file in the root (top_cpuset) cpuset is read-only.
+It automatically tracks the value of cpu_online_map, using a CPU
+hotplug notifier.  If and when memory nodes can be hotplugged,
+we expect to make the mems file in the root cpuset read-only
+as well, and have it track the value of node_online_map.
+
 
 1.4 What are exclusive cpusets ?
 --------------------------------
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 4aaf68f..66c725f 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -2565,10 +2565,10 @@
 		243 = /dev/usb/dabusb3	Fourth dabusb device
 
 180 block	USB block devices
-		0 = /dev/uba		First USB block device
-		8 = /dev/ubb		Second USB block device
-		16 = /dev/ubc		Thrid USB block device
-		...
+		  0 = /dev/uba		First USB block device
+		  8 = /dev/ubb		Second USB block device
+		 16 = /dev/ubc		Third USB block device
+		    ...
 
 181 char	Conrad Electronic parallel port radio clocks
 		  0 = /dev/pcfclock0	First Conrad radio clock
diff --git a/Documentation/fb/imacfb.txt b/Documentation/fb/imacfb.txt
new file mode 100644
index 0000000..7590285
--- /dev/null
+++ b/Documentation/fb/imacfb.txt
@@ -0,0 +1,31 @@
+
+What is imacfb?
+===============
+
+This is a generic EFI platform driver for Intel based Apple computers.
+Imacfb is only for EFI booted Intel Macs.
+
+Supported Hardware
+==================
+
+iMac 17"/20"
+Macbook
+Macbook Pro 15"/17"
+MacMini
+
+How to use it?
+==============
+
+Imacfb does not have any kind of autodetection of your machine.
+You have to add the fillowing kernel parameters in your elilo.conf:
+	Macbook :
+		video=imacfb:macbook
+	MacMini :
+		video=imacfb:mini
+	Macbook Pro 15", iMac 17" :
+		video=imacfb:i17
+	Macbook Pro 17", iMac 20" :
+		video=imacfb:i20
+
+--
+Edgar Hucek <gimli@dark-green.com>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 87851ef..d1cd5f9 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -120,6 +120,13 @@
 
 ---------------------------
 
+What:  drivers depending on OSS_OBSOLETE_DRIVER
+When:  options in 2.6.20, code in 2.6.22
+Why:   OSS drivers with ALSA replacements
+Who:   Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
 What:	pci_module_init(driver)
 When:	January 2007
 Why:	Is replaced by pci_register_driver(pci_driver).
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 66fdc07..16dec61 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -62,8 +62,8 @@
 	- info on the 'in memory' filesystems ramfs, rootfs and initramfs.
 reiser4.txt
 	- info on the Reiser4 filesystem based on dancing tree algorithms.
-relayfs.txt
-	- info on relayfs, for efficient streaming from kernel to user space.
+relay.txt
+	- info on relay, for efficient streaming from kernel to user space.
 romfs.txt
 	- description of the ROMFS filesystem.
 smbfs.txt
diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt
new file mode 100644
index 0000000..d6788da
--- /dev/null
+++ b/Documentation/filesystems/relay.txt
@@ -0,0 +1,479 @@
+relay interface (formerly relayfs)
+==================================
+
+The relay interface provides a means for kernel applications to
+efficiently log and transfer large quantities of data from the kernel
+to userspace via user-defined 'relay channels'.
+
+A 'relay channel' is a kernel->user data relay mechanism implemented
+as a set of per-cpu kernel buffers ('channel buffers'), each
+represented as a regular file ('relay file') in user space.  Kernel
+clients write into the channel buffers using efficient write
+functions; these automatically log into the current cpu's channel
+buffer.  User space applications mmap() or read() from the relay files
+and retrieve the data as it becomes available.  The relay files
+themselves are files created in a host filesystem, e.g. debugfs, and
+are associated with the channel buffers using the API described below.
+
+The format of the data logged into the channel buffers is completely
+up to the kernel client; the relay interface does however provide
+hooks which allow kernel clients to impose some structure on the
+buffer data.  The relay interface doesn't implement any form of data
+filtering - this also is left to the kernel client.  The purpose is to
+keep things as simple as possible.
+
+This document provides an overview of the relay interface API.  The
+details of the function parameters are documented along with the
+functions in the relay interface code - please see that for details.
+
+Semantics
+=========
+
+Each relay channel has one buffer per CPU, each buffer has one or more
+sub-buffers.  Messages are written to the first sub-buffer until it is
+too full to contain a new message, in which case it it is written to
+the next (if available).  Messages are never split across sub-buffers.
+At this point, userspace can be notified so it empties the first
+sub-buffer, while the kernel continues writing to the next.
+
+When notified that a sub-buffer is full, the kernel knows how many
+bytes of it are padding i.e. unused space occurring because a complete
+message couldn't fit into a sub-buffer.  Userspace can use this
+knowledge to copy only valid data.
+
+After copying it, userspace can notify the kernel that a sub-buffer
+has been consumed.
+
+A relay channel can operate in a mode where it will overwrite data not
+yet collected by userspace, and not wait for it to be consumed.
+
+The relay channel itself does not provide for communication of such
+data between userspace and kernel, allowing the kernel side to remain
+simple and not impose a single interface on userspace.  It does
+provide a set of examples and a separate helper though, described
+below.
+
+The read() interface both removes padding and internally consumes the
+read sub-buffers; thus in cases where read(2) is being used to drain
+the channel buffers, special-purpose communication between kernel and
+user isn't necessary for basic operation.
+
+One of the major goals of the relay interface is to provide a low
+overhead mechanism for conveying kernel data to userspace.  While the
+read() interface is easy to use, it's not as efficient as the mmap()
+approach; the example code attempts to make the tradeoff between the
+two approaches as small as possible.
+
+klog and relay-apps example code
+================================
+
+The relay interface itself is ready to use, but to make things easier,
+a couple simple utility functions and a set of examples are provided.
+
+The relay-apps example tarball, available on the relay sourceforge
+site, contains a set of self-contained examples, each consisting of a
+pair of .c files containing boilerplate code for each of the user and
+kernel sides of a relay application.  When combined these two sets of
+boilerplate code provide glue to easily stream data to disk, without
+having to bother with mundane housekeeping chores.
+
+The 'klog debugging functions' patch (klog.patch in the relay-apps
+tarball) provides a couple of high-level logging functions to the
+kernel which allow writing formatted text or raw data to a channel,
+regardless of whether a channel to write into exists or not, or even
+whether the relay interface is compiled into the kernel or not.  These
+functions allow you to put unconditional 'trace' statements anywhere
+in the kernel or kernel modules; only when there is a 'klog handler'
+registered will data actually be logged (see the klog and kleak
+examples for details).
+
+It is of course possible to use the relay interface from scratch,
+i.e. without using any of the relay-apps example code or klog, but
+you'll have to implement communication between userspace and kernel,
+allowing both to convey the state of buffers (full, empty, amount of
+padding).  The read() interface both removes padding and internally
+consumes the read sub-buffers; thus in cases where read(2) is being
+used to drain the channel buffers, special-purpose communication
+between kernel and user isn't necessary for basic operation.  Things
+such as buffer-full conditions would still need to be communicated via
+some channel though.
+
+klog and the relay-apps examples can be found in the relay-apps
+tarball on http://relayfs.sourceforge.net
+
+The relay interface user space API
+==================================
+
+The relay interface implements basic file operations for user space
+access to relay channel buffer data.  Here are the file operations
+that are available and some comments regarding their behavior:
+
+open()	    enables user to open an _existing_ channel buffer.
+
+mmap()      results in channel buffer being mapped into the caller's
+	    memory space. Note that you can't do a partial mmap - you
+	    must map the entire file, which is NRBUF * SUBBUFSIZE.
+
+read()      read the contents of a channel buffer.  The bytes read are
+	    'consumed' by the reader, i.e. they won't be available
+	    again to subsequent reads.  If the channel is being used
+	    in no-overwrite mode (the default), it can be read at any
+	    time even if there's an active kernel writer.  If the
+	    channel is being used in overwrite mode and there are
+	    active channel writers, results may be unpredictable -
+	    users should make sure that all logging to the channel has
+	    ended before using read() with overwrite mode.  Sub-buffer
+	    padding is automatically removed and will not be seen by
+	    the reader.
+
+sendfile()  transfer data from a channel buffer to an output file
+	    descriptor. Sub-buffer padding is automatically removed
+	    and will not be seen by the reader.
+
+poll()      POLLIN/POLLRDNORM/POLLERR supported.  User applications are
+	    notified when sub-buffer boundaries are crossed.
+
+close()     decrements the channel buffer's refcount.  When the refcount
+	    reaches 0, i.e. when no process or kernel client has the
+	    buffer open, the channel buffer is freed.
+
+In order for a user application to make use of relay files, the
+host filesystem must be mounted.  For example,
+
+	mount -t debugfs debugfs /debug
+
+NOTE:   the host filesystem doesn't need to be mounted for kernel
+	clients to create or use channels - it only needs to be
+	mounted when user space applications need access to the buffer
+	data.
+
+
+The relay interface kernel API
+==============================
+
+Here's a summary of the API the relay interface provides to in-kernel clients:
+
+TBD(curr. line MT:/API/)
+  channel management functions:
+
+    relay_open(base_filename, parent, subbuf_size, n_subbufs,
+               callbacks)
+    relay_close(chan)
+    relay_flush(chan)
+    relay_reset(chan)
+
+  channel management typically called on instigation of userspace:
+
+    relay_subbufs_consumed(chan, cpu, subbufs_consumed)
+
+  write functions:
+
+    relay_write(chan, data, length)
+    __relay_write(chan, data, length)
+    relay_reserve(chan, length)
+
+  callbacks:
+
+    subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
+    buf_mapped(buf, filp)
+    buf_unmapped(buf, filp)
+    create_buf_file(filename, parent, mode, buf, is_global)
+    remove_buf_file(dentry)
+
+  helper functions:
+
+    relay_buf_full(buf)
+    subbuf_start_reserve(buf, length)
+
+
+Creating a channel
+------------------
+
+relay_open() is used to create a channel, along with its per-cpu
+channel buffers.  Each channel buffer will have an associated file
+created for it in the host filesystem, which can be and mmapped or
+read from in user space.  The files are named basename0...basenameN-1
+where N is the number of online cpus, and by default will be created
+in the root of the filesystem (if the parent param is NULL).  If you
+want a directory structure to contain your relay files, you should
+create it using the host filesystem's directory creation function,
+e.g. debugfs_create_dir(), and pass the parent directory to
+relay_open().  Users are responsible for cleaning up any directory
+structure they create, when the channel is closed - again the host
+filesystem's directory removal functions should be used for that,
+e.g. debugfs_remove().
+
+In order for a channel to be created and the host filesystem's files
+associated with its channel buffers, the user must provide definitions
+for two callback functions, create_buf_file() and remove_buf_file().
+create_buf_file() is called once for each per-cpu buffer from
+relay_open() and allows the user to create the file which will be used
+to represent the corresponding channel buffer.  The callback should
+return the dentry of the file created to represent the channel buffer.
+remove_buf_file() must also be defined; it's responsible for deleting
+the file(s) created in create_buf_file() and is called during
+relay_close().
+
+Here are some typical definitions for these callbacks, in this case
+using debugfs:
+
+/*
+ * create_buf_file() callback.  Creates relay file in debugfs.
+ */
+static struct dentry *create_buf_file_handler(const char *filename,
+                                              struct dentry *parent,
+                                              int mode,
+                                              struct rchan_buf *buf,
+                                              int *is_global)
+{
+        return debugfs_create_file(filename, mode, parent, buf,
+	                           &relay_file_operations);
+}
+
+/*
+ * remove_buf_file() callback.  Removes relay file from debugfs.
+ */
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+        debugfs_remove(dentry);
+
+        return 0;
+}
+
+/*
+ * relay interface callbacks
+ */
+static struct rchan_callbacks relay_callbacks =
+{
+        .create_buf_file = create_buf_file_handler,
+        .remove_buf_file = remove_buf_file_handler,
+};
+
+And an example relay_open() invocation using them:
+
+  chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks);
+
+If the create_buf_file() callback fails, or isn't defined, channel
+creation and thus relay_open() will fail.
+
+The total size of each per-cpu buffer is calculated by multiplying the
+number of sub-buffers by the sub-buffer size passed into relay_open().
+The idea behind sub-buffers is that they're basically an extension of
+double-buffering to N buffers, and they also allow applications to
+easily implement random-access-on-buffer-boundary schemes, which can
+be important for some high-volume applications.  The number and size
+of sub-buffers is completely dependent on the application and even for
+the same application, different conditions will warrant different
+values for these parameters at different times.  Typically, the right
+values to use are best decided after some experimentation; in general,
+though, it's safe to assume that having only 1 sub-buffer is a bad
+idea - you're guaranteed to either overwrite data or lose events
+depending on the channel mode being used.
+
+The create_buf_file() implementation can also be defined in such a way
+as to allow the creation of a single 'global' buffer instead of the
+default per-cpu set.  This can be useful for applications interested
+mainly in seeing the relative ordering of system-wide events without
+the need to bother with saving explicit timestamps for the purpose of
+merging/sorting per-cpu files in a postprocessing step.
+
+To have relay_open() create a global buffer, the create_buf_file()
+implementation should set the value of the is_global outparam to a
+non-zero value in addition to creating the file that will be used to
+represent the single buffer.  In the case of a global buffer,
+create_buf_file() and remove_buf_file() will be called only once.  The
+normal channel-writing functions, e.g. relay_write(), can still be
+used - writes from any cpu will transparently end up in the global
+buffer - but since it is a global buffer, callers should make sure
+they use the proper locking for such a buffer, either by wrapping
+writes in a spinlock, or by copying a write function from relay.h and
+creating a local version that internally does the proper locking.
+
+Channel 'modes'
+---------------
+
+relay channels can be used in either of two modes - 'overwrite' or
+'no-overwrite'.  The mode is entirely determined by the implementation
+of the subbuf_start() callback, as described below.  The default if no
+subbuf_start() callback is defined is 'no-overwrite' mode.  If the
+default mode suits your needs, and you plan to use the read()
+interface to retrieve channel data, you can ignore the details of this
+section, as it pertains mainly to mmap() implementations.
+
+In 'overwrite' mode, also known as 'flight recorder' mode, writes
+continuously cycle around the buffer and will never fail, but will
+unconditionally overwrite old data regardless of whether it's actually
+been consumed.  In no-overwrite mode, writes will fail, i.e. data will
+be lost, if the number of unconsumed sub-buffers equals the total
+number of sub-buffers in the channel.  It should be clear that if
+there is no consumer or if the consumer can't consume sub-buffers fast
+enough, data will be lost in either case; the only difference is
+whether data is lost from the beginning or the end of a buffer.
+
+As explained above, a relay channel is made of up one or more
+per-cpu channel buffers, each implemented as a circular buffer
+subdivided into one or more sub-buffers.  Messages are written into
+the current sub-buffer of the channel's current per-cpu buffer via the
+write functions described below.  Whenever a message can't fit into
+the current sub-buffer, because there's no room left for it, the
+client is notified via the subbuf_start() callback that a switch to a
+new sub-buffer is about to occur.  The client uses this callback to 1)
+initialize the next sub-buffer if appropriate 2) finalize the previous
+sub-buffer if appropriate and 3) return a boolean value indicating
+whether or not to actually move on to the next sub-buffer.
+
+To implement 'no-overwrite' mode, the userspace client would provide
+an implementation of the subbuf_start() callback something like the
+following:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+			void *prev_subbuf,
+			unsigned int prev_padding)
+{
+	if (prev_subbuf)
+		*((unsigned *)prev_subbuf) = prev_padding;
+
+	if (relay_buf_full(buf))
+		return 0;
+
+	subbuf_start_reserve(buf, sizeof(unsigned int));
+
+	return 1;
+}
+
+If the current buffer is full, i.e. all sub-buffers remain unconsumed,
+the callback returns 0 to indicate that the buffer switch should not
+occur yet, i.e. until the consumer has had a chance to read the
+current set of ready sub-buffers.  For the relay_buf_full() function
+to make sense, the consumer is reponsible for notifying the relay
+interface when sub-buffers have been consumed via
+relay_subbufs_consumed().  Any subsequent attempts to write into the
+buffer will again invoke the subbuf_start() callback with the same
+parameters; only when the consumer has consumed one or more of the
+ready sub-buffers will relay_buf_full() return 0, in which case the
+buffer switch can continue.
+
+The implementation of the subbuf_start() callback for 'overwrite' mode
+would be very similar:
+
+static int subbuf_start(struct rchan_buf *buf,
+                        void *subbuf,
+			void *prev_subbuf,
+			unsigned int prev_padding)
+{
+	if (prev_subbuf)
+		*((unsigned *)prev_subbuf) = prev_padding;
+
+	subbuf_start_reserve(buf, sizeof(unsigned int));
+
+	return 1;
+}
+
+In this case, the relay_buf_full() check is meaningless and the
+callback always returns 1, causing the buffer switch to occur
+unconditionally.  It's also meaningless for the client to use the
+relay_subbufs_consumed() function in this mode, as it's never
+consulted.
+
+The default subbuf_start() implementation, used if the client doesn't
+define any callbacks, or doesn't define the subbuf_start() callback,
+implements the simplest possible 'no-overwrite' mode, i.e. it does
+nothing but return 0.
+
+Header information can be reserved at the beginning of each sub-buffer
+by calling the subbuf_start_reserve() helper function from within the
+subbuf_start() callback.  This reserved area can be used to store
+whatever information the client wants.  In the example above, room is
+reserved in each sub-buffer to store the padding count for that
+sub-buffer.  This is filled in for the previous sub-buffer in the
+subbuf_start() implementation; the padding value for the previous
+sub-buffer is passed into the subbuf_start() callback along with a
+pointer to the previous sub-buffer, since the padding value isn't
+known until a sub-buffer is filled.  The subbuf_start() callback is
+also called for the first sub-buffer when the channel is opened, to
+give the client a chance to reserve space in it.  In this case the
+previous sub-buffer pointer passed into the callback will be NULL, so
+the client should check the value of the prev_subbuf pointer before
+writing into the previous sub-buffer.
+
+Writing to a channel
+--------------------
+
+Kernel clients write data into the current cpu's channel buffer using
+relay_write() or __relay_write().  relay_write() is the main logging
+function - it uses local_irqsave() to protect the buffer and should be
+used if you might be logging from interrupt context.  If you know
+you'll never be logging from interrupt context, you can use
+__relay_write(), which only disables preemption.  These functions
+don't return a value, so you can't determine whether or not they
+failed - the assumption is that you wouldn't want to check a return
+value in the fast logging path anyway, and that they'll always succeed
+unless the buffer is full and no-overwrite mode is being used, in
+which case you can detect a failed write in the subbuf_start()
+callback by calling the relay_buf_full() helper function.
+
+relay_reserve() is used to reserve a slot in a channel buffer which
+can be written to later.  This would typically be used in applications
+that need to write directly into a channel buffer without having to
+stage data in a temporary buffer beforehand.  Because the actual write
+may not happen immediately after the slot is reserved, applications
+using relay_reserve() can keep a count of the number of bytes actually
+written, either in space reserved in the sub-buffers themselves or as
+a separate array.  See the 'reserve' example in the relay-apps tarball
+at http://relayfs.sourceforge.net for an example of how this can be
+done.  Because the write is under control of the client and is
+separated from the reserve, relay_reserve() doesn't protect the buffer
+at all - it's up to the client to provide the appropriate
+synchronization when using relay_reserve().
+
+Closing a channel
+-----------------
+
+The client calls relay_close() when it's finished using the channel.
+The channel and its associated buffers are destroyed when there are no
+longer any references to any of the channel buffers.  relay_flush()
+forces a sub-buffer switch on all the channel buffers, and can be used
+to finalize and process the last sub-buffers before the channel is
+closed.
+
+Misc
+----
+
+Some applications may want to keep a channel around and re-use it
+rather than open and close a new channel for each use.  relay_reset()
+can be used for this purpose - it resets a channel to its initial
+state without reallocating channel buffer memory or destroying
+existing mappings.  It should however only be called when it's safe to
+do so, i.e. when the channel isn't currently being written to.
+
+Finally, there are a couple of utility callbacks that can be used for
+different purposes.  buf_mapped() is called whenever a channel buffer
+is mmapped from user space and buf_unmapped() is called when it's
+unmapped.  The client can use this notification to trigger actions
+within the kernel application, such as enabling/disabling logging to
+the channel.
+
+
+Resources
+=========
+
+For news, example code, mailing list, etc. see the relay interface homepage:
+
+    http://relayfs.sourceforge.net
+
+
+Credits
+=======
+
+The ideas and specs for the relay interface came about as a result of
+discussions on tracing involving the following:
+
+Michel Dagenais		<michel.dagenais@polymtl.ca>
+Richard Moore		<richardj_moore@uk.ibm.com>
+Bob Wisniewski		<bob@watson.ibm.com>
+Karim Yaghmour		<karim@opersys.com>
+Tom Zanussi		<zanussi@us.ibm.com>
+
+Also thanks to Hubertus Franke for a lot of useful suggestions and bug
+reports.
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt
deleted file mode 100644
index 5832377..0000000
--- a/Documentation/filesystems/relayfs.txt
+++ /dev/null
@@ -1,442 +0,0 @@
-
-relayfs - a high-speed data relay filesystem
-============================================
-
-relayfs is a filesystem designed to provide an efficient mechanism for
-tools and facilities to relay large and potentially sustained streams
-of data from kernel space to user space.
-
-The main abstraction of relayfs is the 'channel'.  A channel consists
-of a set of per-cpu kernel buffers each represented by a file in the
-relayfs filesystem.  Kernel clients write into a channel using
-efficient write functions which automatically log to the current cpu's
-channel buffer.  User space applications mmap() the per-cpu files and
-retrieve the data as it becomes available.
-
-The format of the data logged into the channel buffers is completely
-up to the relayfs client; relayfs does however provide hooks which
-allow clients to impose some structure on the buffer data.  Nor does
-relayfs implement any form of data filtering - this also is left to
-the client.  The purpose is to keep relayfs as simple as possible.
-
-This document provides an overview of the relayfs API.  The details of
-the function parameters are documented along with the functions in the
-filesystem code - please see that for details.
-
-Semantics
-=========
-
-Each relayfs channel has one buffer per CPU, each buffer has one or
-more sub-buffers. Messages are written to the first sub-buffer until
-it is too full to contain a new message, in which case it it is
-written to the next (if available).  Messages are never split across
-sub-buffers.  At this point, userspace can be notified so it empties
-the first sub-buffer, while the kernel continues writing to the next.
-
-When notified that a sub-buffer is full, the kernel knows how many
-bytes of it are padding i.e. unused.  Userspace can use this knowledge
-to copy only valid data.
-
-After copying it, userspace can notify the kernel that a sub-buffer
-has been consumed.
-
-relayfs can operate in a mode where it will overwrite data not yet
-collected by userspace, and not wait for it to consume it.
-
-relayfs itself does not provide for communication of such data between
-userspace and kernel, allowing the kernel side to remain simple and
-not impose a single interface on userspace. It does provide a set of
-examples and a separate helper though, described below.
-
-klog and relay-apps example code
-================================
-
-relayfs itself is ready to use, but to make things easier, a couple
-simple utility functions and a set of examples are provided.
-
-The relay-apps example tarball, available on the relayfs sourceforge
-site, contains a set of self-contained examples, each consisting of a
-pair of .c files containing boilerplate code for each of the user and
-kernel sides of a relayfs application; combined these two sets of
-boilerplate code provide glue to easily stream data to disk, without
-having to bother with mundane housekeeping chores.
-
-The 'klog debugging functions' patch (klog.patch in the relay-apps
-tarball) provides a couple of high-level logging functions to the
-kernel which allow writing formatted text or raw data to a channel,
-regardless of whether a channel to write into exists or not, or
-whether relayfs is compiled into the kernel or is configured as a
-module.  These functions allow you to put unconditional 'trace'
-statements anywhere in the kernel or kernel modules; only when there
-is a 'klog handler' registered will data actually be logged (see the
-klog and kleak examples for details).
-
-It is of course possible to use relayfs from scratch i.e. without
-using any of the relay-apps example code or klog, but you'll have to
-implement communication between userspace and kernel, allowing both to
-convey the state of buffers (full, empty, amount of padding).
-
-klog and the relay-apps examples can be found in the relay-apps
-tarball on http://relayfs.sourceforge.net
-
-
-The relayfs user space API
-==========================
-
-relayfs implements basic file operations for user space access to
-relayfs channel buffer data.  Here are the file operations that are
-available and some comments regarding their behavior:
-
-open()	 enables user to open an _existing_ buffer.
-
-mmap()	 results in channel buffer being mapped into the caller's
-	 memory space. Note that you can't do a partial mmap - you must
-	 map the entire file, which is NRBUF * SUBBUFSIZE.
-
-read()	 read the contents of a channel buffer.  The bytes read are
-	 'consumed' by the reader i.e. they won't be available again
-	 to subsequent reads.  If the channel is being used in
-	 no-overwrite mode (the default), it can be read at any time
-	 even if there's an active kernel writer.  If the channel is
-	 being used in overwrite mode and there are active channel
-	 writers, results may be unpredictable - users should make
-	 sure that all logging to the channel has ended before using
-	 read() with overwrite mode.
-
-poll()	 POLLIN/POLLRDNORM/POLLERR supported.  User applications are
-	 notified when sub-buffer boundaries are crossed.
-
-close() decrements the channel buffer's refcount.  When the refcount
-	reaches 0 i.e. when no process or kernel client has the buffer
-	open, the channel buffer is freed.
-
-
-In order for a user application to make use of relayfs files, the
-relayfs filesystem must be mounted.  For example,
-
-	mount -t relayfs relayfs /mnt/relay
-
-NOTE:	relayfs doesn't need to be mounted for kernel clients to create
-	or use channels - it only needs to be mounted when user space
-	applications need access to the buffer data.
-
-
-The relayfs kernel API
-======================
-
-Here's a summary of the API relayfs provides to in-kernel clients:
-
-
-  channel management functions:
-
-    relay_open(base_filename, parent, subbuf_size, n_subbufs,
-               callbacks)
-    relay_close(chan)
-    relay_flush(chan)
-    relay_reset(chan)
-    relayfs_create_dir(name, parent)
-    relayfs_remove_dir(dentry)
-    relayfs_create_file(name, parent, mode, fops, data)
-    relayfs_remove_file(dentry)
-
-  channel management typically called on instigation of userspace:
-
-    relay_subbufs_consumed(chan, cpu, subbufs_consumed)
-
-  write functions:
-
-    relay_write(chan, data, length)
-    __relay_write(chan, data, length)
-    relay_reserve(chan, length)
-
-  callbacks:
-
-    subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
-    buf_mapped(buf, filp)
-    buf_unmapped(buf, filp)
-    create_buf_file(filename, parent, mode, buf, is_global)
-    remove_buf_file(dentry)
-
-  helper functions:
-
-    relay_buf_full(buf)
-    subbuf_start_reserve(buf, length)
-
-
-Creating a channel
-------------------
-
-relay_open() is used to create a channel, along with its per-cpu
-channel buffers.  Each channel buffer will have an associated file
-created for it in the relayfs filesystem, which can be opened and
-mmapped from user space if desired.  The files are named
-basename0...basenameN-1 where N is the number of online cpus, and by
-default will be created in the root of the filesystem.  If you want a
-directory structure to contain your relayfs files, you can create it
-with relayfs_create_dir() and pass the parent directory to
-relay_open().  Clients are responsible for cleaning up any directory
-structure they create when the channel is closed - use
-relayfs_remove_dir() for that.
-
-The total size of each per-cpu buffer is calculated by multiplying the
-number of sub-buffers by the sub-buffer size passed into relay_open().
-The idea behind sub-buffers is that they're basically an extension of
-double-buffering to N buffers, and they also allow applications to
-easily implement random-access-on-buffer-boundary schemes, which can
-be important for some high-volume applications.  The number and size
-of sub-buffers is completely dependent on the application and even for
-the same application, different conditions will warrant different
-values for these parameters at different times.  Typically, the right
-values to use are best decided after some experimentation; in general,
-though, it's safe to assume that having only 1 sub-buffer is a bad
-idea - you're guaranteed to either overwrite data or lose events
-depending on the channel mode being used.
-
-Channel 'modes'
----------------
-
-relayfs channels can be used in either of two modes - 'overwrite' or
-'no-overwrite'.  The mode is entirely determined by the implementation
-of the subbuf_start() callback, as described below.  In 'overwrite'
-mode, also known as 'flight recorder' mode, writes continuously cycle
-around the buffer and will never fail, but will unconditionally
-overwrite old data regardless of whether it's actually been consumed.
-In no-overwrite mode, writes will fail i.e. data will be lost, if the
-number of unconsumed sub-buffers equals the total number of
-sub-buffers in the channel.  It should be clear that if there is no
-consumer or if the consumer can't consume sub-buffers fast enought,
-data will be lost in either case; the only difference is whether data
-is lost from the beginning or the end of a buffer.
-
-As explained above, a relayfs channel is made of up one or more
-per-cpu channel buffers, each implemented as a circular buffer
-subdivided into one or more sub-buffers.  Messages are written into
-the current sub-buffer of the channel's current per-cpu buffer via the
-write functions described below.  Whenever a message can't fit into
-the current sub-buffer, because there's no room left for it, the
-client is notified via the subbuf_start() callback that a switch to a
-new sub-buffer is about to occur.  The client uses this callback to 1)
-initialize the next sub-buffer if appropriate 2) finalize the previous
-sub-buffer if appropriate and 3) return a boolean value indicating
-whether or not to actually go ahead with the sub-buffer switch.
-
-To implement 'no-overwrite' mode, the userspace client would provide
-an implementation of the subbuf_start() callback something like the
-following:
-
-static int subbuf_start(struct rchan_buf *buf,
-                        void *subbuf,
-			void *prev_subbuf,
-			unsigned int prev_padding)
-{
-	if (prev_subbuf)
-		*((unsigned *)prev_subbuf) = prev_padding;
-
-	if (relay_buf_full(buf))
-		return 0;
-
-	subbuf_start_reserve(buf, sizeof(unsigned int));
-
-	return 1;
-}
-
-If the current buffer is full i.e. all sub-buffers remain unconsumed,
-the callback returns 0 to indicate that the buffer switch should not
-occur yet i.e. until the consumer has had a chance to read the current
-set of ready sub-buffers.  For the relay_buf_full() function to make
-sense, the consumer is reponsible for notifying relayfs when
-sub-buffers have been consumed via relay_subbufs_consumed().  Any
-subsequent attempts to write into the buffer will again invoke the
-subbuf_start() callback with the same parameters; only when the
-consumer has consumed one or more of the ready sub-buffers will
-relay_buf_full() return 0, in which case the buffer switch can
-continue.
-
-The implementation of the subbuf_start() callback for 'overwrite' mode
-would be very similar:
-
-static int subbuf_start(struct rchan_buf *buf,
-                        void *subbuf,
-			void *prev_subbuf,
-			unsigned int prev_padding)
-{
-	if (prev_subbuf)
-		*((unsigned *)prev_subbuf) = prev_padding;
-
-	subbuf_start_reserve(buf, sizeof(unsigned int));
-
-	return 1;
-}
-
-In this case, the relay_buf_full() check is meaningless and the
-callback always returns 1, causing the buffer switch to occur
-unconditionally.  It's also meaningless for the client to use the
-relay_subbufs_consumed() function in this mode, as it's never
-consulted.
-
-The default subbuf_start() implementation, used if the client doesn't
-define any callbacks, or doesn't define the subbuf_start() callback,
-implements the simplest possible 'no-overwrite' mode i.e. it does
-nothing but return 0.
-
-Header information can be reserved at the beginning of each sub-buffer
-by calling the subbuf_start_reserve() helper function from within the
-subbuf_start() callback.  This reserved area can be used to store
-whatever information the client wants.  In the example above, room is
-reserved in each sub-buffer to store the padding count for that
-sub-buffer.  This is filled in for the previous sub-buffer in the
-subbuf_start() implementation; the padding value for the previous
-sub-buffer is passed into the subbuf_start() callback along with a
-pointer to the previous sub-buffer, since the padding value isn't
-known until a sub-buffer is filled.  The subbuf_start() callback is
-also called for the first sub-buffer when the channel is opened, to
-give the client a chance to reserve space in it.  In this case the
-previous sub-buffer pointer passed into the callback will be NULL, so
-the client should check the value of the prev_subbuf pointer before
-writing into the previous sub-buffer.
-
-Writing to a channel
---------------------
-
-kernel clients write data into the current cpu's channel buffer using
-relay_write() or __relay_write().  relay_write() is the main logging
-function - it uses local_irqsave() to protect the buffer and should be
-used if you might be logging from interrupt context.  If you know
-you'll never be logging from interrupt context, you can use
-__relay_write(), which only disables preemption.  These functions
-don't return a value, so you can't determine whether or not they
-failed - the assumption is that you wouldn't want to check a return
-value in the fast logging path anyway, and that they'll always succeed
-unless the buffer is full and no-overwrite mode is being used, in
-which case you can detect a failed write in the subbuf_start()
-callback by calling the relay_buf_full() helper function.
-
-relay_reserve() is used to reserve a slot in a channel buffer which
-can be written to later.  This would typically be used in applications
-that need to write directly into a channel buffer without having to
-stage data in a temporary buffer beforehand.  Because the actual write
-may not happen immediately after the slot is reserved, applications
-using relay_reserve() can keep a count of the number of bytes actually
-written, either in space reserved in the sub-buffers themselves or as
-a separate array.  See the 'reserve' example in the relay-apps tarball
-at http://relayfs.sourceforge.net for an example of how this can be
-done.  Because the write is under control of the client and is
-separated from the reserve, relay_reserve() doesn't protect the buffer
-at all - it's up to the client to provide the appropriate
-synchronization when using relay_reserve().
-
-Closing a channel
------------------
-
-The client calls relay_close() when it's finished using the channel.
-The channel and its associated buffers are destroyed when there are no
-longer any references to any of the channel buffers.  relay_flush()
-forces a sub-buffer switch on all the channel buffers, and can be used
-to finalize and process the last sub-buffers before the channel is
-closed.
-
-Creating non-relay files
-------------------------
-
-relay_open() automatically creates files in the relayfs filesystem to
-represent the per-cpu kernel buffers; it's often useful for
-applications to be able to create their own files alongside the relay
-files in the relayfs filesystem as well e.g. 'control' files much like
-those created in /proc or debugfs for similar purposes, used to
-communicate control information between the kernel and user sides of a
-relayfs application.  For this purpose the relayfs_create_file() and
-relayfs_remove_file() API functions exist.  For relayfs_create_file(),
-the caller passes in a set of user-defined file operations to be used
-for the file and an optional void * to a user-specified data item,
-which will be accessible via inode->u.generic_ip (see the relay-apps
-tarball for examples).  The file_operations are a required parameter
-to relayfs_create_file() and thus the semantics of these files are
-completely defined by the caller.
-
-See the relay-apps tarball at http://relayfs.sourceforge.net for
-examples of how these non-relay files are meant to be used.
-
-Creating relay files in other filesystems
------------------------------------------
-
-By default of course, relay_open() creates relay files in the relayfs
-filesystem.  Because relay_file_operations is exported, however, it's
-also possible to create and use relay files in other pseudo-filesytems
-such as debugfs.
-
-For this purpose, two callback functions are provided,
-create_buf_file() and remove_buf_file().  create_buf_file() is called
-once for each per-cpu buffer from relay_open() to allow the client to
-create a file to be used to represent the corresponding buffer; if
-this callback is not defined, the default implementation will create
-and return a file in the relayfs filesystem to represent the buffer.
-The callback should return the dentry of the file created to represent
-the relay buffer.  Note that the parent directory passed to
-relay_open() (and passed along to the callback), if specified, must
-exist in the same filesystem the new relay file is created in.  If
-create_buf_file() is defined, remove_buf_file() must also be defined;
-it's responsible for deleting the file(s) created in create_buf_file()
-and is called during relay_close().
-
-The create_buf_file() implementation can also be defined in such a way
-as to allow the creation of a single 'global' buffer instead of the
-default per-cpu set.  This can be useful for applications interested
-mainly in seeing the relative ordering of system-wide events without
-the need to bother with saving explicit timestamps for the purpose of
-merging/sorting per-cpu files in a postprocessing step.
-
-To have relay_open() create a global buffer, the create_buf_file()
-implementation should set the value of the is_global outparam to a
-non-zero value in addition to creating the file that will be used to
-represent the single buffer.  In the case of a global buffer,
-create_buf_file() and remove_buf_file() will be called only once.  The
-normal channel-writing functions e.g. relay_write() can still be used
-- writes from any cpu will transparently end up in the global buffer -
-but since it is a global buffer, callers should make sure they use the
-proper locking for such a buffer, either by wrapping writes in a
-spinlock, or by copying a write function from relayfs_fs.h and
-creating a local version that internally does the proper locking.
-
-See the 'exported-relayfile' examples in the relay-apps tarball for
-examples of creating and using relay files in debugfs.
-
-Misc
-----
-
-Some applications may want to keep a channel around and re-use it
-rather than open and close a new channel for each use.  relay_reset()
-can be used for this purpose - it resets a channel to its initial
-state without reallocating channel buffer memory or destroying
-existing mappings.  It should however only be called when it's safe to
-do so i.e. when the channel isn't currently being written to.
-
-Finally, there are a couple of utility callbacks that can be used for
-different purposes.  buf_mapped() is called whenever a channel buffer
-is mmapped from user space and buf_unmapped() is called when it's
-unmapped.  The client can use this notification to trigger actions
-within the kernel application, such as enabling/disabling logging to
-the channel.
-
-
-Resources
-=========
-
-For news, example code, mailing list, etc. see the relayfs homepage:
-
-    http://relayfs.sourceforge.net
-
-
-Credits
-=======
-
-The ideas and specs for relayfs came about as a result of discussions
-on tracing involving the following:
-
-Michel Dagenais		<michel.dagenais@polymtl.ca>
-Richard Moore		<richardj_moore@uk.ibm.com>
-Bob Wisniewski		<bob@watson.ibm.com>
-Karim Yaghmour		<karim@opersys.com>
-Tom Zanussi		<zanussi@us.ibm.com>
-
-Also thanks to Hubertus Franke for a lot of useful suggestions and bug
-reports.
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 1870355..864ff32 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -51,8 +51,6 @@
 
 References
 
-  IETF IP over InfiniBand (ipoib) Working Group
-    http://ietf.org/html.charters/ipoib-charter.html
   Transmission of IP over InfiniBand (IPoIB) (RFC 4391)
     http://ietf.org/rfc/rfc4391.txt 
   IP over InfiniBand (IPoIB) Architecture (RFC 4392)
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
index b1b6440..15f1b35 100644
--- a/Documentation/initrd.txt
+++ b/Documentation/initrd.txt
@@ -72,6 +72,22 @@
     initrd is mounted as root, and the normal boot procedure is followed,
     with the RAM disk still mounted as root.
 
+Compressed cpio images
+----------------------
+
+Recent kernels have support for populating a ramdisk from a compressed cpio
+archive, on such systems, the creation of a ramdisk image doesn't need to
+involve special block devices or loopbacks, you merely create a directory on
+disk with the desired initrd content, cd to that directory, and run (as an
+example):
+
+find . | cpio --quiet -c -o | gzip -9 -n > /boot/imagefile.img
+
+Examining the contents of an existing image file is just as simple:
+
+mkdir /tmp/imagefile
+cd /tmp/imagefile
+gzip -cd /boot/imagefile.img | cpio -imd --quiet
 
 Installation
 ------------
diff --git a/Documentation/input/joystick.txt b/Documentation/input/joystick.txt
index d53b857..841c353 100644
--- a/Documentation/input/joystick.txt
+++ b/Documentation/input/joystick.txt
@@ -39,7 +39,6 @@
 
   The input project website is at:
 
-	http://www.suse.cz/development/input/
 	http://atrey.karlin.mff.cuni.cz/~vojtech/input/
 
   There is also a mailing list for the driver at:
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 14ef3868..0706699 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -407,6 +407,20 @@
 	The second argument is optional, and if supplied will be used
 	if first argument is not supported.
 
+    ld-option
+    	ld-option is used to check if $(CC) when used to link object files
+	supports the given option.  An optional second option may be
+	specified if first option are not supported.
+
+	Example:
+		#arch/i386/kernel/Makefile
+		vsyscall-flags += $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+	In the above example vsyscall-flags will be assigned the option
+	-Wl$(comma)--hash-style=sysv if it is supported by $(CC).
+	The second argument is optional, and if supplied will be used
+	if first argument is not supported.
+
     cc-option
 	cc-option is used to check if $(CC) support a given option, and not
 	supported to use an optional second option.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e11f772..7947ced 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -448,8 +448,6 @@
 			Format: <area>[,<node>]
 			See also Documentation/networking/decnet.txt.
 
-	delayacct	[KNL] Enable per-task delay accounting
-
 	dhash_entries=	[KNL]
 			Set number of hash buckets for dentry cache.
 
@@ -1031,6 +1029,8 @@
 
 	nocache		[ARM]
 
+	nodelayacct	[KNL] Disable per-task delay accounting
+
 	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
 
 	noexec		[IA-64]
@@ -1183,6 +1183,8 @@
 				Mechanism 2.
 		nommconf	[IA-32,X86_64] Disable use of MMCONFIG for PCI
 				Configuration
+		mmconf		[IA-32,X86_64] Force MMCONFIG. This is useful
+				to override the builtin blacklist.
 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
 				enabled, this kernel boot option can be used to
 				disable the use of MSI interrupts system-wide.
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index 8d9bffb..949f7b5 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -247,7 +247,7 @@
 - default_attrs: Default attributes to be exported via sysfs when the
   object is registered.Note that the last attribute has to be
   initialized to NULL ! You can find a complete implementation
-  in drivers/block/genhd.c
+  in block/genhd.c
 
 
 Instances of struct kobj_type are not registered; only referenced by
diff --git a/Documentation/networking/LICENSE.qla3xxx b/Documentation/networking/LICENSE.qla3xxx
new file mode 100644
index 0000000..2f2077e
--- /dev/null
+++ b/Documentation/networking/LICENSE.qla3xxx
@@ -0,0 +1,46 @@
+Copyright (c)  2003-2006 QLogic Corporation
+QLogic Linux Networking HBA Driver
+
+This program includes a device driver for Linux 2.6 that may be
+distributed with QLogic hardware specific firmware binary file.
+You may modify and redistribute the device driver code under the
+GNU General Public License as published by the Free Software
+Foundation (version 2 or a later version).
+
+You may redistribute the hardware specific firmware binary file
+under the following terms:
+
+	1. Redistribution of source code (only if applicable),
+	   must retain the above copyright notice, this list of
+	   conditions and the following disclaimer.
+
+	2. Redistribution in binary form must reproduce the above
+	   copyright notice, this list of conditions and the
+	   following disclaimer in the documentation and/or other
+	   materials provided with the distribution.
+
+	3. The name of QLogic Corporation may not be used to
+	   endorse or promote products derived from this software
+	   without specific prior written permission
+
+REGARDLESS OF WHAT LICENSING MECHANISM IS USED OR APPLICABLE,
+THIS PROGRAM IS PROVIDED BY QLOGIC CORPORATION "AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+USER ACKNOWLEDGES AND AGREES THAT USE OF THIS PROGRAM WILL NOT
+CREATE OR GIVE GROUNDS FOR A LICENSE BY IMPLICATION, ESTOPPEL, OR
+OTHERWISE IN ANY INTELLECTUAL PROPERTY RIGHTS (PATENT, COPYRIGHT,
+TRADE SECRET, MASK WORK, OR OTHER PROPRIETARY RIGHT) EMBODIED IN
+ANY OTHER QLOGIC HARDWARE OR SOFTWARE EITHER SOLELY OR IN
+COMBINATION WITH THIS PROGRAM.
+
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index d46338a..3e0c017 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -294,15 +294,15 @@
 	Default: 87380*2 bytes.
 
 tcp_mem - vector of 3 INTEGERs: min, pressure, max
-	low: below this number of pages TCP is not bothered about its
+	min: below this number of pages TCP is not bothered about its
 	memory appetite.
 
 	pressure: when amount of memory allocated by TCP exceeds this number
 	of pages, TCP moderates its memory consumption and enters memory
 	pressure mode, which is exited when memory consumption falls
-	under "low".
+	under "min".
 
-	high: number of pages allowed for queueing by all TCP sockets.
+	max: number of pages allowed for queueing by all TCP sockets.
 
 	Defaults are calculated at boot time from amount of available
 	memory.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index 3c62e66..5c0ba23 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1136,10 +1136,10 @@
    Devices connected to openPIC-compatible controllers should encode
    sense and polarity as follows:
 
-	0 = high to low edge sensitive type enabled
+	0 = low to high edge sensitive type enabled
 	1 = active low level sensitive type enabled
-	2 = low to high edge sensitive type enabled
-	3 = active high level sensitive type enabled
+	2 = active high level sensitive type enabled
+	3 = high to low edge sensitive type enabled
 
    ISA PIC interrupt controllers should adhere to the ISA PIC
    encodings listed below:
@@ -1196,7 +1196,7 @@
     - model : Model of the device.  Can be "TSEC", "eTSEC", or "FEC"
     - compatible : Should be "gianfar"
     - reg : Offset and length of the register set for the device
-    - address : List of bytes representing the ethernet address of
+    - mac-address : List of bytes representing the ethernet address of
       this controller
     - interrupts : <a b> where a is the interrupt number and b is a
       field that represents an encoding of the sense and level
@@ -1216,7 +1216,7 @@
 		model = "TSEC";
 		compatible = "gianfar";
 		reg = <24000 1000>;
-		address = [ 00 E0 0C 00 73 00 ];
+		mac-address = [ 00 E0 0C 00 73 00 ];
 		interrupts = <d 3 e 3 12 3>;
 		interrupt-parent = <40000>;
 		phy-handle = <2452000>
@@ -1498,7 +1498,7 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <24000 1000>;
-			address = [ 00 E0 0C 00 73 00 ];
+			mac-address = [ 00 E0 0C 00 73 00 ];
 			interrupts = <d 3 e 3 12 3>;
 			interrupt-parent = <40000>;
 			phy-handle = <2452000>;
@@ -1511,7 +1511,7 @@
 			model = "TSEC";
 			compatible = "gianfar";
 			reg = <25000 1000>;
-			address = [ 00 E0 0C 00 73 01 ];
+			mac-address = [ 00 E0 0C 00 73 01 ];
 			interrupts = <13 3 14 3 18 3>;
 			interrupt-parent = <40000>;
 			phy-handle = <2452001>;
@@ -1524,7 +1524,7 @@
 			model = "FEC";
 			compatible = "gianfar";
 			reg = <26000 1000>;
-			address = [ 00 E0 0C 00 73 02 ];
+			mac-address = [ 00 E0 0C 00 73 02 ];
 			interrupts = <19 3>;
 			interrupt-parent = <40000>;
 			phy-handle = <2452002>;
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index c173806..a056bbe 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,126 @@
+Release Date	: Fri May 19 09:31:45 EST 2006 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.9 (scsi module), 2.20.2.6 (cmm module)
+Older Version	: 2.20.4.8 (scsi module), 2.20.2.6 (cmm module)
+
+1.	Fixed a bug in megaraid_init_mbox().
+	Customer reported "garbage in file on x86_64 platform".
+	Root Cause: the driver registered controllers as 64-bit DMA capable
+	for those which are not support it.
+	Fix: Made change in the function inserting identification machanism
+	identifying 64-bit DMA capable controllers.
+
+	> -----Original Message-----
+	> From: Vasily Averin [mailto:vvs@sw.ru]
+	> Sent: Thursday, May 04, 2006 2:49 PM
+	> To: linux-scsi@vger.kernel.org; Kolli, Neela; Mukker, Atul;
+	> Ju, Seokmann; Bagalkote, Sreenivas;
+	> James.Bottomley@SteelEye.com; devel@openvz.org
+	> Subject: megaraid_mbox: garbage in file
+	>
+	> Hello all,
+	>
+	> I've investigated customers claim on the unstable work of
+	> their node and found a
+	> strange effect: reading from some files leads to the
+	>  "attempt to access beyond end of device" messages.
+	>
+	> I've checked filesystem, memory on the node, motherboard BIOS
+	> version, but it
+	> does not help and issue still has been reproduced by simple
+	> file reading.
+	>
+	> Reproducer is simple:
+	>
+	> echo 0xffffffff >/proc/sys/dev/scsi/logging_level ;
+	> cat /vz/private/101/root/etc/ld.so.cache >/tmp/ttt  ;
+	> echo 0 >/proc/sys/dev/scsi/logging
+	>
+	> It leads to the following messages in dmesg
+	>
+	> sd_init_command: disk=sda, block=871769260, count=26
+	> sda : block=871769260
+	> sda : reading 26/26 512 byte blocks.
+	> scsi_add_timer: scmd: f79ed980, time: 7500, (c02b1420)
+	> sd 0:1:0:0: send 0xf79ed980                  sd 0:1:0:0:
+	>         command: Read (10): 28 00 33 f6 24 ac 00 00 1a 00
+	> buffer = 0xf7cfb540, bufflen = 13312, done = 0xc0366b40,
+	> queuecommand 0xc0344010
+	> leaving scsi_dispatch_cmnd()
+	> scsi_delete_timer: scmd: f79ed980, rtn: 1
+	> sd 0:1:0:0: done 0xf79ed980 SUCCESS        0 sd 0:1:0:0:
+	>         command: Read (10): 28 00 33 f6 24 ac 00 00 1a 00
+	> scsi host busy 1 failed 0
+	> sd 0:1:0:0: Notifying upper driver of completion (result 0)
+	> sd_rw_intr: sda: res=0x0
+	> 26 sectors total, 13312 bytes done.
+	> use_sg is 4
+	> attempt to access beyond end of device
+	> sda6: rw=0, want=1044134458, limit=951401367
+	> Buffer I/O error on device sda6, logical block 522067228
+	> attempt to access beyond end of device
+
+2.	When INQUIRY with EVPD bit set issued to the MegaRAID controller,
+	system memory gets corrupted.
+	Root Cause: MegaRAID F/W handle the INQUIRY with EVPD bit set
+	incorrectly.
+	Fix: MegaRAID F/W has fixed the problem and being process of release,
+	soon. Meanwhile, driver will filter out the request.
+
+3.	One of member in the data structure of the driver leads unaligne
+	issue on 64-bit platform.
+	Customer reporeted "kernel unaligned access addrss" issue when
+	application communicates with MegaRAID HBA driver.
+	Root Cause: in uioc_t structure, one of member had misaligned and it
+	led system to display the error message.
+	Fix: A patch submitted to community from following folk.
+
+	> -----Original Message-----
+	> From: linux-scsi-owner@vger.kernel.org
+	> [mailto:linux-scsi-owner@vger.kernel.org] On Behalf Of Sakurai Hiroomi
+	> Sent: Wednesday, July 12, 2006 4:20 AM
+	> To: linux-scsi@vger.kernel.org; linux-kernel@vger.kernel.org
+	> Subject: Re: Help: strange messages from kernel on IA64 platform
+	>
+	> Hi,
+	>
+	> I saw same message.
+	>
+	> When GAM(Global Array Manager) is started, The following
+	> message output.
+	> kernel: kernel unaligned access to 0xe0000001fe1080d4,
+	> ip=0xa000000200053371
+	>
+	> The uioc structure used by ioctl is defined by packed,
+	> the allignment of each member are disturbed.
+	> In a 64 bit structure, the allignment of member doesn't fit 64 bit
+	> boundary. this causes this messages.
+	> In a 32 bit structure, we don't see the message because the allinment
+	> of member fit 32 bit boundary even if packed is specified.
+	>
+	> patch
+	> I Add 32 bit dummy member to fit 64 bit boundary. I tested.
+	> We confirmed this patch fix the problem by IA64 server.
+	>
+	> **************************************************************
+	> ****************
+	> --- linux-2.6.9/drivers/scsi/megaraid/megaraid_ioctl.h.orig
+	> 2006-04-03 17:13:03.000000000 +0900
+	> +++ linux-2.6.9/drivers/scsi/megaraid/megaraid_ioctl.h
+	> 2006-04-03 17:14:09.000000000 +0900
+	> @@ -132,6 +132,10 @@
+	>  /* Driver Data: */
+	>          void __user *           user_data;
+	>          uint32_t                user_data_len;
+	> +
+	> +        /* 64bit alignment */
+	> +        uint32_t                pad_0xBC;
+	> +
+	>          mraid_passthru_t        __user *user_pthru;
+	>
+	>          mraid_passthru_t        *pthru32;
+	> **************************************************************
+	> ****************
+
 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)
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 0b62c62..5c3a519 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -25,6 +25,7 @@
 - inode-state
 - overflowuid
 - overflowgid
+- suid_dumpable
 - super-max
 - super-nr
 
@@ -131,6 +132,25 @@
 
 ==============================================================
 
+suid_dumpable:
+
+This value can be used to query and set the core dump mode for setuid
+or otherwise protected/tainted binaries. The modes are
+
+0 - (default) - traditional behaviour. Any process which has changed
+	privilege levels or is execute only will not be dumped
+1 - (debug) - all processes dump core when possible. The core dump is
+	owned by the current user and no security is applied. This is
+	intended for system debugging situations only. Ptrace is unchecked.
+2 - (suidsafe) - any binary which normally would not be dumped is dumped
+	readable by root only. This allows the end user to remove
+	such a dump but not access it directly. For security reasons
+	core dumps in this mode will not overwrite one another or
+	other files. This mode is appropriate when adminstrators are
+	attempting to debug problems in a normal environment.
+
+==============================================================
+
 super-max & super-nr:
 
 These numbers control the maximum number of superblocks, and
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index b0c7ab9..89bf8c2 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -50,7 +50,6 @@
 - shmmax                      [ sysv ipc ]
 - shmmni
 - stop-a                      [ SPARC only ]
-- suid_dumpable
 - sysrq                       ==> Documentation/sysrq.txt
 - tainted
 - threads-max
@@ -211,9 +210,8 @@
 
 0: try to continue operation
 
-1: delay a few seconds (to give klogd time to record the oops output) and
-   then panic.  If the `panic' sysctl is also non-zero then the machine will
-   be rebooted.
+1: panic immediatly.  If the `panic' sysctl is also non-zero then the
+   machine will be rebooted.
 
 ==============================================================
 
@@ -311,25 +309,6 @@
 
 ==============================================================
 
-suid_dumpable:
-
-This value can be used to query and set the core dump mode for setuid
-or otherwise protected/tainted binaries. The modes are
-
-0 - (default) - traditional behaviour. Any process which has changed
-	privilege levels or is execute only will not be dumped
-1 - (debug) - all processes dump core when possible. The core dump is
-	owned by the current user and no security is applied. This is
-	intended for system debugging situations only. Ptrace is unchecked.
-2 - (suidsafe) - any binary which normally would not be dumped is dumped
-	readable by root only. This allows the end user to remove
-	such a dump but not access it directly. For security reasons
-	core dumps in this mode will not overwrite one another or
-	other files. This mode is appropriate when adminstrators are
-	attempting to debug problems in a normal environment.
-
-==============================================================
-
 tainted: 
 
 Non-zero if the kernel has been tainted.  Numeric values, which
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt
index f86550f..22c5331 100644
--- a/Documentation/usb/proc_usb_info.txt
+++ b/Documentation/usb/proc_usb_info.txt
@@ -59,7 +59,7 @@
 would issue more ioctls to the device to communicate to it using
 control, bulk, or other kinds of USB transfers.  The IOCTLs are
 listed in the <linux/usbdevice_fs.h> file, and at this writing the
-source code (linux/drivers/usb/devio.c) is the primary reference
+source code (linux/drivers/usb/core/devio.c) is the primary reference
 for how to access devices through those files.
 
 Note that since by default these BBB/DDD files are writable only by
diff --git a/Documentation/usb/usb-help.txt b/Documentation/usb/usb-help.txt
index b7c3249..a740859 100644
--- a/Documentation/usb/usb-help.txt
+++ b/Documentation/usb/usb-help.txt
@@ -5,8 +5,7 @@
 Documentation/usb/*, see the following:
 
 Linux-USB project:  http://www.linux-usb.org
-  mirrors at        http://www.suse.cz/development/linux-usb/
-         and        http://usb.in.tum.de/linux-usb/
+  mirrors at        http://usb.in.tum.de/linux-usb/
          and        http://it.linux-usb.org
 Linux USB Guide:    http://linux-usb.sourceforge.net
 Linux-USB device overview (working devices and drivers):
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 6887d44..6da24e7 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -238,6 +238,13 @@
   pagefaulttrace Dump all page faults. Only useful for extreme debugging
 		and will create a lot of output.
 
+  call_trace=[old|both|newfallback|new]
+		old: use old inexact backtracer
+		new: use new exact dwarf2 unwinder
+ 		both: print entries from both
+		newfallback: use new unwinder but fall back to old if it gets
+			stuck (default)
+
 Misc
 
   noreplacement  Don't replace instructions with more appropriate ones
diff --git a/MAINTAINERS b/MAINTAINERS
index b2afc7a..d13f985 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -214,6 +214,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
 S:	Maintained
 
+ACPI PCI HOTPLUG DRIVER
+P:	Kristen Carlson Accardi
+M:	kristen.c.accardi@intel.com
+L:	pcihpd-discuss@lists.sourceforge.net
+S:	Maintained
+
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
 M:	Thorsten Knabe <linux@thorsten-knabe.de>
@@ -292,6 +298,13 @@
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:	Supported
 
+AOA (Apple Onboard Audio) ALSA DRIVER
+P:	Johannes Berg
+M:	johannes@sipsolutions.net
+L:	linuxppc-dev@ozlabs.org
+L:	alsa-devel@alsa-project.org
+S:	Maintained
+
 APM DRIVER
 P:	Stephen Rothwell
 M:	sfr@canb.auug.org.au
@@ -436,9 +449,9 @@
 W:	http://www.baycom.org/~tom/ham/ham.html
 S:	Maintained
 
-BCM43XX WIRELESS DRIVER
-P:	Michael Buesch
-M:	mb@bu3sch.de
+BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION)
+P:	Larry Finger
+M:	Larry.Finger@lwfinger.net
 P:	Stefano Brivio
 M:	st3@riseup.net
 W:	http://bcm43xx.berlios.de/
@@ -876,6 +889,12 @@
 T:	git http://tali.admingilde.org/git/linux-docbook.git
 S:	Maintained
 
+DOCKING STATION DRIVER
+P:	Kristen Carlson Accardi
+M:	kristen.c.accardi@intel.com
+L:	linux-acpi@vger.kernel.org
+S:	Maintained
+
 DOUBLETALK DRIVER
 P:	James R. Van Zandt
 M:	jrv@vanzandt.mv.com
@@ -968,6 +987,10 @@
 M:	saw@saw.sw.com.sg
 S:	Maintained
 
+EFS FILESYSTEM
+W:	http://aeschi.ch.eu.org/efs/
+S:	Orphan
+
 EMU10K1 SOUND DRIVER
 P:	James Courtier-Dutton
 M:	James@superbug.demon.co.uk
@@ -1598,7 +1621,7 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
 S:	Supported
 
-JOURNALLING LAYER FOR BLOCK DEVICS (JBD)
+JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
 P:	Stephen Tweedie, Andrew Morton
 M:	sct@redhat.com, akpm@osdl.org
 L:	ext2-devel@lists.sourceforge.net
@@ -1642,9 +1665,8 @@
 
 KERNEL JANITORS
 P:	Several
-L:	kernel-janitors@osdl.org
+L:	kernel-janitors@lists.osdl.org
 W:	http://www.kerneljanitors.org/
-W:	http://sf.net/projects/kernel-janitor/
 S:	Maintained
 
 KERNEL NFSD
@@ -1882,6 +1904,12 @@
 W:     http://megaraid.lsilogic.com
 S:     Maintained
 
+MEMORY MANAGEMENT
+L:	linux-mm@kvack.org
+L:	linux-kernel@vger.kernel.org
+W:	http://www.linux-mm.org
+S:	Maintained
+
 MEMORY TECHNOLOGY DEVICES (MTD)
 P:	David Woodhouse
 M:	dwmw2@infradead.org
@@ -2338,6 +2366,12 @@
 L:	linux-scsi@vger.kernel.org
 S:	Supported
 
+QLOGIC QLA3XXX NETWORK DRIVER
+P:	Ron Mercer
+M:	linux-driver@qlogic.com
+L:	netdev@vger.kernel.org
+S:	Supported
+
 QNX4 FILESYSTEM
 P:	Anders Larsen
 M:	al@alarsen.net
@@ -2588,6 +2622,18 @@
 M:	nico@cam.org
 S:	Maintained
 
+SOFTMAC LAYER (IEEE 802.11)
+P:	Johannes Berg
+M:	johannes@sipsolutions.net
+P:	Joe Jezak
+M:	josejx@gentoo.org
+P:	Daniel Drake
+M:	dsd@gentoo.org
+W:	http://softmac.sipsolutions.net/
+L:	softmac-dev@sipsolutions.net
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
@@ -2626,6 +2672,22 @@
 L:	spi-devel-general@lists.sourceforge.net
 S:	Maintained
 
+STABLE BRANCH:
+P:	Greg Kroah-Hartman
+M:	greg@kroah.com
+P:	Chris Wright
+M:	chrisw@sous-sol.org
+L:	stable@kernel.org
+S:	Maintained
+
+STABLE BRANCH:
+P:	Greg Kroah-Hartman
+M:	greg@kroah.com
+P:	Chris Wright
+M:	chrisw@sous-sol.org
+L:	stable@kernel.org
+S:	Maintained
+
 TPM DEVICE DRIVER
 P:	Kylene Hall
 M:	kjhall@us.ibm.com
@@ -2845,8 +2907,8 @@
 S:	Maintained
 
 TULIP NETWORK DRIVER
-P:	Jeff Garzik
-M:	jgarzik@pobox.com
+P:	Valerie Henson
+M:	val_henson@linux.intel.com
 L:	tulip-users@lists.sourceforge.net
 W:	http://sourceforge.net/projects/tulip/
 S:	Maintained
@@ -3252,10 +3314,11 @@
 
 XFS FILESYSTEM
 P:	Silicon Graphics Inc
+P:	Tim Shimmin, David Chatterton
 M:	xfs-masters@oss.sgi.com
-M:	nathans@sgi.com
 L:	xfs@oss.sgi.com
 W:	http://oss.sgi.com/projects/xfs
+T:	git git://oss.sgi.com:8090/xfs/xfs-2.6
 S:	Supported
 
 X86 3-LEVEL PAGING (PAE) SUPPORT
@@ -3296,6 +3359,15 @@
 L:	linux-hams@vger.kernel.org
 S:	Maintained
 
+ZD1211RW WIRELESS DRIVER
+P:	Daniel Drake
+M:	dsd@gentoo.org
+P:	Ulrich Kunitz
+M:	kune@deine-taler.de
+W:	http://zd1211.ath.cx/wiki/DriverRewrite
+L:	zd1211-devs@lists.sourceforge.net (subscribers-only)
+S:	Maintained
+
 ZF MACHZ WATCHDOG
 P:	Fernando Fuganti
 M:	fuganti@netbank.com.br
diff --git a/Makefile b/Makefile
index 1dd58d3..c9ed7b4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 18
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc6
 NAME=Crazed Snow-Weasel
 
 # *DOCUMENTATION*
@@ -309,9 +309,6 @@
 
 CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                    -fno-strict-aliasing -fno-common
-# Force gcc to behave correct even for buggy distributions
-CFLAGS          += $(call cc-option, -fno-stack-protector-all \
-                                     -fno-stack-protector)
 AFLAGS          := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
@@ -368,6 +365,7 @@
 
 no-dot-config-targets := clean mrproper distclean \
 			 cscope TAGS tags help %docs check% \
+			 include/linux/version.h headers_% \
 			 kernelrelease kernelversion
 
 config-targets := 0
@@ -435,12 +433,13 @@
 endif # KBUILD_EXTMOD
 
 ifeq ($(dot-config),1)
-# In this section, we need .config
+# Read in config
+-include include/config/auto.conf
 
+ifeq ($(KBUILD_EXTMOD),)
 # Read in dependencies to all Kconfig* files, make sure to run
 # oldconfig if changes are detected.
 -include include/config/auto.conf.cmd
--include include/config/auto.conf
 
 # To avoid any implicit rule to kick in, define an empty command
 $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
@@ -450,16 +449,27 @@
 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
 include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
-ifeq ($(KBUILD_EXTMOD),)
 	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
-	$(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
-endif
+# external modules needs include/linux/autoconf.h and include/config/auto.conf
+# but do not care if they are up-to-date. Use auto.conf to trigger the test
+PHONY += include/config/auto.conf
+
+include/config/auto.conf:
+	$(Q)test -e include/linux/autoconf.h -a -e $@ || (		\
+	echo;								\
+	echo "  ERROR: Kernel configuration is invalid.";		\
+	echo "         include/linux/autoconf.h or $@ are missing.";	\
+	echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";	\
+	echo;								\
+	/bin/false)
+
+endif # KBUILD_EXTMOD
 
 else
 # Dummy target needed, because used as prerequisite
 include/config/auto.conf: ;
-endif
+endif # $(dot-config)
 
 # The all: target is the default when no target is given on the
 # command line.
@@ -473,6 +483,8 @@
 CFLAGS		+= -O2
 endif
 
+include $(srctree)/arch/$(ARCH)/Makefile
+
 ifdef CONFIG_FRAME_POINTER
 CFLAGS		+= -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
 else
@@ -487,7 +499,8 @@
 CFLAGS		+= -g
 endif
 
-include $(srctree)/arch/$(ARCH)/Makefile
+# Force gcc to behave correct even for buggy distributions
+CFLAGS          += $(call cc-option, -fno-stack-protector)
 
 # arch Makefile may override CC so keep this after arch Makefile is included
 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index bf52ba6..fed6b3d 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -274,16 +274,14 @@
 struct el_subpacket_handler ev7_pal_subpacket_handler =
 	SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
 
-void 
+void
 ev7_register_error_handlers(void)
 {
 	int i;
 
-	for(i = 0;
-	    i<sizeof(el_ev7_pal_annotations)/sizeof(el_ev7_pal_annotations[1]);
-	    i++) {
+	for (i = 0; i < ARRAY_SIZE(el_ev7_pal_annotations); i++)
 		cdl_register_subpacket_annotation(&el_ev7_pal_annotations[i]);
-	}	
+
 	cdl_register_subpacket_handler(&ev7_pal_subpacket_handler);
 }
 
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index e15dcf4..73c7622 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -623,12 +623,12 @@
 	long len, err = -EINVAL;
 
 	offset = command-1;
-	if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
+	if (offset >= ARRAY_SIZE(sysinfo_table)) {
 		/* Digital UNIX has a few unpublished interfaces here */
 		printk("sysinfo(%d)", command);
 		goto out;
 	}
-	
+
 	down_read(&uts_sem);
 	res = sysinfo_table[offset];
 	len = strlen(res)+1;
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 2cb9c43..fd4a8fa 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -114,8 +114,6 @@
 int alpha_using_srm;
 #endif
 
-#define N(a) (sizeof(a)/sizeof(a[0]))
-
 static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
 					       unsigned long);
 static struct alpha_machine_vector *get_sysvec_byname(const char *);
@@ -240,7 +238,7 @@
 	standard_io_resources[0].start = RTC_PORT(0);
 	standard_io_resources[0].end = RTC_PORT(0) + 0x10;
 
-	for (i = 0; i < N(standard_io_resources); ++i)
+	for (i = 0; i < ARRAY_SIZE(standard_io_resources); ++i)
 		request_resource(io, standard_io_resources+i);
 }
 
@@ -918,13 +916,13 @@
 
 	/* Search the system tables first... */
 	vec = NULL;
-	if (type < N(systype_vecs)) {
+	if (type < ARRAY_SIZE(systype_vecs)) {
 		vec = systype_vecs[type];
 	} else if ((type > ST_API_BIAS) &&
-		   (type - ST_API_BIAS) < N(api_vecs)) {
+		   (type - ST_API_BIAS) < ARRAY_SIZE(api_vecs)) {
 		vec = api_vecs[type - ST_API_BIAS];
 	} else if ((type > ST_UNOFFICIAL_BIAS) &&
-		   (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
+		   (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_vecs)) {
 		vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
 	}
 
@@ -938,11 +936,11 @@
 
 		switch (type) {
 		case ST_DEC_ALCOR:
-			if (member < N(alcor_indices))
+			if (member < ARRAY_SIZE(alcor_indices))
 				vec = alcor_vecs[alcor_indices[member]];
 			break;
 		case ST_DEC_EB164:
-			if (member < N(eb164_indices))
+			if (member < ARRAY_SIZE(eb164_indices))
 				vec = eb164_vecs[eb164_indices[member]];
 			/* PC164 may show as EB164 variation with EV56 CPU,
 			   but, since no true EB164 had anything but EV5... */
@@ -950,24 +948,24 @@
 				vec = &pc164_mv;
 			break;
 		case ST_DEC_EB64P:
-			if (member < N(eb64p_indices))
+			if (member < ARRAY_SIZE(eb64p_indices))
 				vec = eb64p_vecs[eb64p_indices[member]];
 			break;
 		case ST_DEC_EB66:
-			if (member < N(eb66_indices))
+			if (member < ARRAY_SIZE(eb66_indices))
 				vec = eb66_vecs[eb66_indices[member]];
 			break;
 		case ST_DEC_MARVEL:
-			if (member < N(marvel_indices))
+			if (member < ARRAY_SIZE(marvel_indices))
 				vec = marvel_vecs[marvel_indices[member]];
 			break;
 		case ST_DEC_TITAN:
 			vec = titan_vecs[0];	/* default */
-			if (member < N(titan_indices))
+			if (member < ARRAY_SIZE(titan_indices))
 				vec = titan_vecs[titan_indices[member]];
 			break;
 		case ST_DEC_TSUNAMI:
-			if (member < N(tsunami_indices))
+			if (member < ARRAY_SIZE(tsunami_indices))
 				vec = tsunami_vecs[tsunami_indices[member]];
 			break;
 		case ST_DEC_1000:
@@ -1039,7 +1037,7 @@
 
 	size_t i;
 
-	for (i = 0; i < N(all_vecs); ++i) {
+	for (i = 0; i < ARRAY_SIZE(all_vecs); ++i) {
 		struct alpha_machine_vector *mv = all_vecs[i];
 		if (strcasecmp(mv->vector_name, name) == 0)
 			return mv;
@@ -1055,13 +1053,13 @@
 
 	/* If not in the tables, make it UNKNOWN,
 	   else set type name to family */
-	if (type < N(systype_names)) {
+	if (type < ARRAY_SIZE(systype_names)) {
 		*type_name = systype_names[type];
 	} else if ((type > ST_API_BIAS) &&
-		   (type - ST_API_BIAS) < N(api_names)) {
+		   (type - ST_API_BIAS) < ARRAY_SIZE(api_names)) {
 		*type_name = api_names[type - ST_API_BIAS];
 	} else if ((type > ST_UNOFFICIAL_BIAS) &&
-		   (type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
+		   (type - ST_UNOFFICIAL_BIAS) < ARRAY_SIZE(unofficial_names)) {
 		*type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
 	} else {
 		*type_name = sys_unknown;
@@ -1083,7 +1081,7 @@
 	default: /* default to variation "0" for now */
 		break;
 	case ST_DEC_EB164:
-		if (member < N(eb164_indices))
+		if (member < ARRAY_SIZE(eb164_indices))
 			*variation_name = eb164_names[eb164_indices[member]];
 		/* PC164 may show as EB164 variation, but with EV56 CPU,
 		   so, since no true EB164 had anything but EV5... */
@@ -1091,32 +1089,32 @@
 			*variation_name = eb164_names[1]; /* make it PC164 */
 		break;
 	case ST_DEC_ALCOR:
-		if (member < N(alcor_indices))
+		if (member < ARRAY_SIZE(alcor_indices))
 			*variation_name = alcor_names[alcor_indices[member]];
 		break;
 	case ST_DEC_EB64P:
-		if (member < N(eb64p_indices))
+		if (member < ARRAY_SIZE(eb64p_indices))
 			*variation_name = eb64p_names[eb64p_indices[member]];
 		break;
 	case ST_DEC_EB66:
-		if (member < N(eb66_indices))
+		if (member < ARRAY_SIZE(eb66_indices))
 			*variation_name = eb66_names[eb66_indices[member]];
 		break;
 	case ST_DEC_MARVEL:
-		if (member < N(marvel_indices))
+		if (member < ARRAY_SIZE(marvel_indices))
 			*variation_name = marvel_names[marvel_indices[member]];
 		break;
 	case ST_DEC_RAWHIDE:
-		if (member < N(rawhide_indices))
+		if (member < ARRAY_SIZE(rawhide_indices))
 			*variation_name = rawhide_names[rawhide_indices[member]];
 		break;
 	case ST_DEC_TITAN:
 		*variation_name = titan_names[0];	/* default */
-		if (member < N(titan_indices))
+		if (member < ARRAY_SIZE(titan_indices))
 			*variation_name = titan_names[titan_indices[member]];
 		break;
 	case ST_DEC_TSUNAMI:
-		if (member < N(tsunami_indices))
+		if (member < ARRAY_SIZE(tsunami_indices))
 			*variation_name = tsunami_names[tsunami_indices[member]];
 		break;
 	}
@@ -1211,7 +1209,7 @@
 
 	cpu_index = (unsigned) (cpu->type - 1);
 	cpu_name = "Unknown";
-	if (cpu_index < N(cpu_names))
+	if (cpu_index < ARRAY_SIZE(cpu_names))
 		cpu_name = cpu_names[cpu_index];
 
 	get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index 78c30de..5b99cf3 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -182,16 +182,16 @@
 ruffian_get_bank_size(unsigned long offset)
 {
 	unsigned long bank_addr, bank, ret = 0;
-  
+
 	/* Valid offsets are: 0x800, 0x840 and 0x880
 	   since Ruffian only uses three banks.  */
 	bank_addr = (unsigned long)PYXIS_MCR + offset;
 	bank = *(vulp)bank_addr;
-    
+
 	/* Check BANK_ENABLE */
 	if (bank & 0x01) {
 		static unsigned long size[] __initdata = {
-			0x40000000UL, /* 0x00,   1G */ 
+			0x40000000UL, /* 0x00,   1G */
 			0x20000000UL, /* 0x02, 512M */
 			0x10000000UL, /* 0x04, 256M */
 			0x08000000UL, /* 0x06, 128M */
@@ -203,7 +203,7 @@
 		};
 
 		bank = (bank & 0x1e) >> 1;
-		if (bank < sizeof(size)/sizeof(*size))
+		if (bank < ARRAY_SIZE(size))
 			ret = size[bank];
 	}
 
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 50eccde..b191cc7 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -233,7 +233,7 @@
 	index = cpu->type & 0xffffffff;
 
 	/* If index out of bounds, no way to validate.  */
-	if (index >= sizeof(cpu_hz)/sizeof(cpu_hz[0]))
+	if (index >= ARRAY_SIZE(cpu_hz))
 		return cc;
 
 	/* If index contains no data, no way to validate.  */
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 3345c6d..92873cd 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -47,7 +47,8 @@
 # testing for a specific architecture or later rather impossible.
 arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
 arch-$(CONFIG_CPU_32v6K)	:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+arch-$(CONFIG_CPU_32v4T)	:=-D__LINUX_ARM_ARCH__=4 -march=armv4t
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5b7c263..028bdc9 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -179,17 +179,19 @@
 static inline struct safe_buffer *
 find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 {
-	struct safe_buffer *b = NULL;
+	struct safe_buffer *b, *rb = NULL;
 	unsigned long flags;
 
 	read_lock_irqsave(&device_info->lock, flags);
 
 	list_for_each_entry(b, &device_info->safe_buffers, node)
-		if (b->safe_dma_addr == safe_dma_addr)
+		if (b->safe_dma_addr == safe_dma_addr) {
+			rb = b;
 			break;
+		}
 
 	read_unlock_irqrestore(&device_info->lock, flags);
-	return b;
+	return rb;
 }
 
 static inline void
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index f3c1ebf..f3e020f 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -95,7 +95,8 @@
 }
 #endif
 
-static struct irqchip gic_chip = {
+static struct irq_chip gic_chip = {
+	.name		= "GIC",
 	.ack		= gic_ack_irq,
 	.mask		= gic_mask_irq,
 	.unmask		= gic_unmask_irq,
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 04de83f..4e0dcae 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -204,7 +204,8 @@
 	locomo_writel(r, mapbase + LOCOMO_ICR);
 }
 
-static struct irqchip locomo_chip = {
+static struct irq_chip locomo_chip = {
+	.name	= "LOCOMO",
 	.ack	= locomo_ack_irq,
 	.mask	= locomo_mask_irq,
 	.unmask	= locomo_unmask_irq,
@@ -249,7 +250,8 @@
 	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 }
 
-static struct irqchip locomo_key_chip = {
+static struct irq_chip locomo_key_chip = {
+	.name	= "LOCOMO-key",
 	.ack	= locomo_key_ack_irq,
 	.mask	= locomo_key_mask_irq,
 	.unmask	= locomo_key_unmask_irq,
@@ -312,7 +314,8 @@
 	locomo_writel(r, mapbase + LOCOMO_GIE);
 }
 
-static struct irqchip locomo_gpio_chip = {
+static struct irq_chip locomo_gpio_chip = {
+	.name	= "LOCOMO-gpio",
 	.ack	= locomo_gpio_ack_irq,
 	.mask	= locomo_gpio_mask_irq,
 	.unmask	= locomo_gpio_unmask_irq,
@@ -357,7 +360,8 @@
 	locomo_writel(r, mapbase + LOCOMO_LTINT);
 }
 
-static struct irqchip locomo_lt_chip = {
+static struct irq_chip locomo_lt_chip = {
+	.name	= "LOCOMO-lt",
 	.ack	= locomo_lt_ack_irq,
 	.mask	= locomo_lt_mask_irq,
 	.unmask	= locomo_lt_unmask_irq,
@@ -418,7 +422,8 @@
 	locomo_writel(r, mapbase + LOCOMO_SPIIE);
 }
 
-static struct irqchip locomo_spi_chip = {
+static struct irq_chip locomo_spi_chip = {
+	.name	= "LOCOMO-spi",
 	.ack	= locomo_spi_ack_irq,
 	.mask	= locomo_spi_mask_irq,
 	.unmask	= locomo_spi_unmask_irq,
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
index 35c9a64..4e5445c 100644
--- a/arch/arm/common/rtctime.c
+++ b/arch/arm/common/rtctime.c
@@ -68,6 +68,7 @@
 		rtc_time_to_tm(next_time, next);
 	}
 }
+EXPORT_SYMBOL(rtc_next_alarm_time);
 
 static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
 {
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 1cdb26a..29818bd 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -272,7 +272,8 @@
 	return 0;
 }
 
-static struct irqchip sa1111_low_chip = {
+static struct irq_chip sa1111_low_chip = {
+	.name		= "SA1111-l",
 	.ack		= sa1111_ack_irq,
 	.mask		= sa1111_mask_lowirq,
 	.unmask		= sa1111_unmask_lowirq,
@@ -368,7 +369,8 @@
 	return 0;
 }
 
-static struct irqchip sa1111_high_chip = {
+static struct irq_chip sa1111_high_chip = {
+	.name		= "SA1111-h",
 	.ack		= sa1111_ack_irq,
 	.mask		= sa1111_mask_highirq,
 	.unmask		= sa1111_unmask_highirq,
@@ -616,7 +618,7 @@
 {
 	struct sa1111 *sachip;
 	unsigned long id;
-	unsigned int has_devs, val;
+	unsigned int has_devs;
 	int i, ret = -ENODEV;
 
 	sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
@@ -667,6 +669,9 @@
 	sa1111_wake(sachip);
 
 #ifdef CONFIG_ARCH_SA1100
+	{
+	unsigned int val;
+
 	/*
 	 * The SDRAM configuration of the SA1110 and the SA1111 must
 	 * match.  This is very important to ensure that SA1111 accesses
@@ -690,6 +695,7 @@
 	 * Enable the SA1110 memory bus request and grant signals.
 	 */
 	sa1110_mb_enable();
+	}
 #endif
 
 	/*
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index a19bc4a..43d2781 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -39,7 +39,8 @@
 	writel(1 << irq, base + VIC_INT_ENABLE);
 }
 
-static struct irqchip vic_chip = {
+static struct irq_chip vic_chip = {
+	.name	= "VIC",
 	.ack	= vic_mask_irq,
 	.mask	= vic_mask_irq,
 	.unmask	= vic_unmask_irq,
diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig
index 3594155..cf3fa5c 100644
--- a/arch/arm/configs/csb337_defconfig
+++ b/arch/arm/configs/csb337_defconfig
@@ -621,9 +621,8 @@
 # USB-based Watchdog Cards
 #
 # CONFIG_USBPCWATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 # CONFIG_NVRAM is not set
-CONFIG_RTC=y
-# CONFIG_AT91_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 
@@ -956,10 +955,42 @@
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 CONFIG_MMC_BLOCK=y
-# CONFIG_MMC_WBSD is not set
 CONFIG_MMC_AT91RM9200=y
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+
+#
+# RTC interfaces
+#
+# CONFIG_RTC_INTF_SYSFS is not set
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index c0de6fc..2948b45 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Sun Jul  9 15:21:30 2006
+# Linux kernel version: 2.6.18-rc1-git9
+# Sat Jul 15 15:08:10 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -30,6 +30,7 @@
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
@@ -749,7 +750,7 @@
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
-# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
 # CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
@@ -766,6 +767,9 @@
 # USB Host Controller Drivers
 #
 # CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
 
 #
@@ -855,6 +859,7 @@
 CONFIG_USB_SERIAL_PL2303=y
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
 # CONFIG_USB_SERIAL_TI is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
@@ -871,7 +876,7 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -916,6 +921,7 @@
 # CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_DS1307 is not set
 # CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
 # CONFIG_RTC_DRV_DS1742 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
@@ -1023,7 +1029,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index f0c0cdb..1320a0e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -13,12 +13,11 @@
 obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_ISA_DMA_API)	+= dma.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o 
-obj-$(CONFIG_FOOTBRIDGE)	+= isa.o
 obj-$(CONFIG_FIQ)		+= fiq.o
 obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
-obj-$(CONFIG_PCI)		+= bios32.o
+obj-$(CONFIG_PCI)		+= bios32.o isa.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index b9a74a7..eca248d 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -470,7 +470,8 @@
 	}
 }
 
-static struct irqchip ecard_chip = {
+static struct irq_chip ecard_chip = {
+	.name	= "ECARD",
 	.ack	= ecard_irq_mask,
 	.mask	= ecard_irq_mask,
 	.unmask = ecard_irq_unmask,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7ea5f01..de4e331 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -634,6 +634,14 @@
  * purpose.
  */
 
+	.macro	usr_ret, reg
+#ifdef CONFIG_ARM_THUMB
+	bx	\reg
+#else
+	mov	pc, \reg
+#endif
+	.endm
+
 	.align	5
 	.globl	__kuser_helper_start
 __kuser_helper_start:
@@ -675,7 +683,7 @@
 #if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_SMP)
 	mcr	p15, 0, r0, c7, c10, 5	@ dmb
 #endif
-	mov	pc, lr
+	usr_ret	lr
 
 	.align	5
 
@@ -778,7 +786,7 @@
 	mov	r0, #-1
 	adds	r0, r0, #0
 #endif
-	mov	pc, lr
+	usr_ret	lr
 
 #else
 
@@ -792,7 +800,7 @@
 #ifdef CONFIG_SMP
 	mcr	p15, 0, r0, c7, c10, 5	@ dmb
 #endif
-	mov	pc, lr
+	usr_ret	lr
 
 #endif
 
@@ -834,16 +842,11 @@
 __kuser_get_tls:				@ 0xffff0fe0
 
 #if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
-
 	ldr	r0, [pc, #(16 - 8)]		@ TLS stored at 0xffff0ff0
-	mov	pc, lr
-
 #else
-
 	mrc	p15, 0, r0, c13, c0, 3		@ read TLS register
-	mov	pc, lr
-
 #endif
+	usr_ret	lr
 
 	.rep	5
 	.word	0			@ pad up to __kuser_helper_version
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 2242f5f..5365d4e 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -114,18 +114,18 @@
 	 * Use the page tables supplied from  __cpu_up.
 	 */
 	adr	r4, __secondary_data
-	ldmia	r4, {r5, r6, r13}		@ address to jump to after
+	ldmia	r4, {r5, r7, r13}		@ address to jump to after
 	sub	r4, r4, r5			@ mmu has been enabled
-	ldr	r4, [r6, r4]			@ get secondary_data.pgdir
+	ldr	r4, [r7, r4]			@ get secondary_data.pgdir
 	adr	lr, __enable_mmu		@ return address
-	add	pc, r10, #12			@ initialise processor
+	add	pc, r10, #PROCINFO_INITFUNC	@ initialise processor
 						@ (return control reg)
 
 	/*
 	 * r6  = &secondary_data
 	 */
 ENTRY(__secondary_switched)
-	ldr	sp, [r6, #4]			@ get secondary_data.stack
+	ldr	sp, [r7, #4]			@ get secondary_data.stack
 	mov	fp, #0
 	b	secondary_start_kernel
 
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 626feeec..2e1bf83 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -77,6 +77,7 @@
 		seq_printf(p, "%3d: ", i);
 		for_each_present_cpu(cpu)
 			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[i]);
+		seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, ", %s", action->name);
diff --git a/arch/arm/kernel/isa.c b/arch/arm/kernel/isa.c
index 685c3e5..54bbd9f 100644
--- a/arch/arm/kernel/isa.c
+++ b/arch/arm/kernel/isa.c
@@ -3,21 +3,14 @@
  *
  *  Copyright (C) 1999 Phil Blundell
  *
- *  ISA shared memory and I/O port support
- */
-
-/*
  * 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.
+ *
+ *  ISA shared memory and I/O port support, and is required to support
+ *  iopl, inb, outb and friends in userspace via glibc emulation.
  */
-
-/* 
- * Nothing about this is actually ARM specific.  One day we could move
- * it into kernel/resource.c or some place like that.  
- */
-
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/fs.h>
@@ -27,21 +20,49 @@
 static unsigned int isa_membase, isa_portbase, isa_portshift;
 
 static ctl_table ctl_isa_vars[4] = {
-	{BUS_ISA_MEM_BASE, "membase", &isa_membase, 
-	 sizeof(isa_membase), 0444, NULL, &proc_dointvec},
-	{BUS_ISA_PORT_BASE, "portbase", &isa_portbase, 
-	 sizeof(isa_portbase), 0444, NULL, &proc_dointvec},
-	{BUS_ISA_PORT_SHIFT, "portshift", &isa_portshift, 
-	 sizeof(isa_portshift), 0444, NULL, &proc_dointvec},
-	{0}
+	{
+		.ctl_name	= BUS_ISA_MEM_BASE,
+		.procname	= "membase",
+		.data		= &isa_membase, 
+		.maxlen		= sizeof(isa_membase),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {
+		.ctl_name	= BUS_ISA_PORT_BASE,
+		.procname	= "portbase",
+		.data		= &isa_portbase, 
+		.maxlen		= sizeof(isa_portbase),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {
+		.ctl_name	= BUS_ISA_PORT_SHIFT,
+		.procname	= "portshift",
+		.data		= &isa_portshift, 
+		.maxlen		= sizeof(isa_portshift),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {0}
 };
 
 static struct ctl_table_header *isa_sysctl_header;
 
-static ctl_table ctl_isa[2] = {{CTL_BUS_ISA, "isa", NULL, 0, 0555, ctl_isa_vars},
-			       {0}};
-static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
-			       {0}};
+static ctl_table ctl_isa[2] = {
+	{
+		.ctl_name	= CTL_BUS_ISA,
+		.procname	= "isa",
+		.mode		= 0555,
+		.child		= ctl_isa_vars,
+	}, {0}
+};
+
+static ctl_table ctl_bus[2] = {
+	{
+		.ctl_name	= CTL_BUS,
+		.procname	= "bus",
+		.mode		= 0555,
+		.child		= ctl_isa,
+	}, {0}
+};
 
 void __init
 register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 35a052f..aeeed80 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -232,11 +232,8 @@
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
 
-	if (panic_on_oops) {
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
-		ssleep(5);
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
 
 	do_exit(SIGSEGV);
 }
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 5783c28..cec199f 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -327,7 +327,8 @@
 	return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
 }
 
-static struct irqchip gpio_irqchip = {
+static struct irq_chip gpio_irqchip = {
+	.name		= "GPIO",
 	.mask		= gpio_irq_mask,
 	.unmask		= gpio_irq_unmask,
 	.set_type	= gpio_irq_type,
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
index 9b09113..c3a5e77 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -114,7 +114,8 @@
 #define at91_aic_set_wake	NULL
 #endif
 
-static struct irqchip at91_aic_chip = {
+static struct irq_chip at91_aic_chip = {
+	.name		= "AIC",
 	.ack		= at91_aic_mask_irq,
 	.mask		= at91_aic_mask_irq,
 	.unmask		= at91_aic_unmask_irq,
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 5b64d5c..ef6ccc8 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -8,7 +8,7 @@
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/tty.h>
+#include <linux/screen_info.h>
 
 #include <asm/hardware/dec21285.h>
 #include <asm/io.h>
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 607ed1f..823e25d 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -35,7 +35,6 @@
 
 extern int setup_arm_irq(int, struct irqaction *);
 extern void pcibios_report_status(u_int status_mask, int warn);
-extern void register_isa_ports(unsigned int, unsigned int, unsigned int);
 
 static unsigned long
 dc21285_base_address(struct pci_bus *bus, unsigned int devfn)
diff --git a/arch/arm/mach-imx/irq.c b/arch/arm/mach-imx/irq.c
index a5de5f1..2688bd8 100644
--- a/arch/arm/mach-imx/irq.c
+++ b/arch/arm/mach-imx/irq.c
@@ -204,13 +204,15 @@
 	imx_gpio_handler(mask, irq, desc, regs);
 }
 
-static struct irqchip imx_internal_chip = {
+static struct irq_chip imx_internal_chip = {
+	.name = "MPU",
 	.ack = imx_mask_irq,
 	.mask = imx_mask_irq,
 	.unmask = imx_unmask_irq,
 };
 
-static struct irqchip imx_gpio_chip = {
+static struct irq_chip imx_gpio_chip = {
+	.name = "GPIO",
 	.ack = imx_gpio_ack_irq,
 	.mask = imx_gpio_mask_irq,
 	.unmask = imx_gpio_unmask_irq,
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 6d65c96..191c57a 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -161,7 +161,8 @@
 	writel(1 << irq, VA_IC_BASE + IRQ_ENABLE_SET);
 }
 
-static struct irqchip sc_chip = {
+static struct irq_chip sc_chip = {
+	.name	= "SC",
 	.ack	= sc_mask_irq,
 	.mask	= sc_mask_irq,
 	.unmask = sc_unmask_irq,
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 9f55f5a..678b6ba 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -156,7 +156,8 @@
 	cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
 }
 
-static struct irqchip cic_chip = {
+static struct irq_chip cic_chip = {
+	.name	= "CIC",
 	.ack	= cic_mask_irq,
 	.mask	= cic_mask_irq,
 	.unmask	= cic_unmask_irq,
@@ -174,7 +175,8 @@
 	pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
 }
 
-static struct irqchip pic_chip = {
+static struct irq_chip pic_chip = {
+	.name	= "PIC",
 	.ack	= pic_mask_irq,
 	.mask	= pic_mask_irq,
 	.unmask = pic_unmask_irq,
@@ -192,7 +194,8 @@
 	sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
 }
 
-static struct irqchip sic_chip = {
+static struct irq_chip sic_chip = {
+	.name	= "SIC",
 	.ack	= sic_mask_irq,
 	.mask	= sic_mask_irq,
 	.unmask	= sic_unmask_irq,
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index f904359..4418f6d 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -600,4 +600,6 @@
 		printk(KERN_ERR "PCI: unable to grab local bus timeout "
 		       "interrupt: %d\n", ret);
 #endif
+
+	register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
 }
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
index d42aae6..88ac333 100644
--- a/arch/arm/mach-iop3xx/iop321-irq.c
+++ b/arch/arm/mach-iop3xx/iop321-irq.c
@@ -52,7 +52,8 @@
 	intctl_write(iop321_mask);
 }
 
-struct irqchip ext_chip = {
+struct irq_chip ext_chip = {
+	.name	= "IOP",
 	.ack    = iop321_irq_mask,
 	.mask   = iop321_irq_mask,
 	.unmask = iop321_irq_unmask,
diff --git a/arch/arm/mach-iop3xx/iop331-irq.c b/arch/arm/mach-iop3xx/iop331-irq.c
index f4d4321..cab1172 100644
--- a/arch/arm/mach-iop3xx/iop331-irq.c
+++ b/arch/arm/mach-iop3xx/iop331-irq.c
@@ -77,13 +77,15 @@
         intctl_write1(iop331_mask1);
 }
 
-struct irqchip iop331_irqchip1 = {
+struct irq_chip iop331_irqchip1 = {
+	.name	= "IOP-1",
 	.ack    = iop331_irq_mask1,
 	.mask   = iop331_irq_mask1,
 	.unmask = iop331_irq_unmask1,
 };
 
-struct irqchip iop331_irqchip2 = {
+struct irq_chip iop331_irqchip2 = {
+	.name	= "IOP-2",
 	.ack    = iop331_irq_mask2,
 	.mask   = iop331_irq_mask2,
 	.unmask = iop331_irq_unmask2,
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 2d40fe1..9562177 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -532,8 +532,6 @@
 	return -EIO;
 }
 
-EXPORT_SYMBOL(pci_set_dma_mask);
-EXPORT_SYMBOL(pci_set_consistent_dma_mask);
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
 
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 654e2ee..30f1300e 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -107,9 +107,9 @@
 	.width		= 2,
 };
 
-static struct gtw5715_flash_resource = {
+static struct resource gtwx5715_flash_resource = {
 	.flags		= IORESOURCE_MEM,
-}
+};
 
 static struct platform_device gtwx5715_flash = {
 	.name		= "IXP4XX-Flash",
@@ -130,9 +130,6 @@
 {
 	ixp4xx_sys_init();
 
-	if (!flash_resource)
-		printk(KERN_ERR "Could not allocate flash resource\n");
-
 	gtwx5715_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
 	gtwx5715_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1;
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c
index 0de639d..04661fe 100644
--- a/arch/arm/mach-ixp4xx/nslu2-pci.c
+++ b/arch/arm/mach-ixp4xx/nslu2-pci.c
@@ -17,6 +17,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
index e2a2230..a29b3b2 100644
--- a/arch/arm/mach-ixp4xx/nslu2-power.c
+++ b/arch/arm/mach-ixp4xx/nslu2-power.c
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/reboot.h>
+#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
 
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
index 2cccc27..4f2ab48 100644
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/arch-kev7a400.c
@@ -63,7 +63,8 @@
 	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
 }
 
-static struct irqchip kev7a400_cpld_chip = {
+static struct irq_chip kev7a400_cpld_chip = {
+	.name	= "CPLD",
 	.ack	= kev7a400_ack_cpld_irq,
 	.mask	= kev7a400_mask_cpld_irq,
 	.unmask	= kev7a400_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 35c3606..a691011 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -200,7 +200,8 @@
 	}
 }
 
-static struct irqchip lpd7a40x_cpld_chip = {
+static struct irq_chip lpd7a40x_cpld_chip = {
+	.name	= "CPLD",
 	.ack	= lh7a40x_ack_cpld_irq,
 	.mask	= lh7a40x_mask_cpld_irq,
 	.unmask	= lh7a40x_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c
index 8535764..f9b3fe9 100644
--- a/arch/arm/mach-lh7a40x/irq-kev7a400.c
+++ b/arch/arm/mach-lh7a40x/irq-kev7a400.c
@@ -43,7 +43,8 @@
 }
 
 static struct
-irqchip lh7a400_cpld_chip = {
+irq_chip lh7a400_cpld_chip = {
+	.name	= "CPLD",
 	.ack	= lh7a400_ack_cpld_irq,
 	.mask	= lh7a400_mask_cpld_irq,
 	.unmask	= lh7a400_unmask_cpld_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c
index f9fdefe..091b2dc 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a400.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a400.c
@@ -38,13 +38,15 @@
 	INTC_INTENC = (1 << irq);
 }
 
-static struct irqchip lh7a400_internal_chip = {
+static struct irq_chip lh7a400_internal_chip = {
+	.name	= "MPU",
 	.ack	= lh7a400_mask_irq, /* Level triggering -> mask is ack */
 	.mask	= lh7a400_mask_irq,
 	.unmask	= lh7a400_unmask_irq,
 };
 
-static struct irqchip lh7a400_gpio_chip = {
+static struct irq_chip lh7a400_gpio_chip = {
+	.name	= "GPIO",
 	.ack	= lh7a400_ack_gpio_irq,
 	.mask	= lh7a400_mask_irq,
 	.unmask	= lh7a400_unmask_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
index 2685a81..7059b98 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -76,25 +76,29 @@
 	VIC2_INTENCLR = (1 << irq);
 }
 
-static struct irqchip lh7a404_vic1_chip = {
+static struct irq_chip lh7a404_vic1_chip = {
+	.name	= "VIC1",
 	.ack	= lh7a404_vic1_mask_irq, /* Because level-triggered */
 	.mask	= lh7a404_vic1_mask_irq,
 	.unmask	= lh7a404_vic1_unmask_irq,
 };
 
-static struct irqchip lh7a404_vic2_chip = {
+static struct irq_chip lh7a404_vic2_chip = {
+	.name	= "VIC2",
 	.ack	= lh7a404_vic2_mask_irq, /* Because level-triggered */
 	.mask	= lh7a404_vic2_mask_irq,
 	.unmask	= lh7a404_vic2_unmask_irq,
 };
 
-static struct irqchip lh7a404_gpio_vic1_chip = {
+static struct irq_chip lh7a404_gpio_vic1_chip = {
+	.name	= "GPIO-VIC1",
 	.ack	= lh7a404_vic1_ack_gpio_irq,
 	.mask	= lh7a404_vic1_mask_irq,
 	.unmask	= lh7a404_vic1_unmask_irq,
 };
 
-static struct irqchip lh7a404_gpio_vic2_chip = {
+static struct irq_chip lh7a404_gpio_vic2_chip = {
+	.name	= "GPIO-VIC2",
 	.ack	= lh7a404_vic2_ack_gpio_irq,
 	.mask	= lh7a404_vic2_mask_irq,
 	.unmask	= lh7a404_vic2_unmask_irq,
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
index dcb4e17..d6055dd 100644
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
@@ -50,7 +50,8 @@
 	}
 }
 
-static struct irqchip lh7a40x_cpld_chip = {
+static struct irq_chip lh7a40x_cpld_chip = {
+	.name	= "CPLD",
 	.ack	= lh7a40x_ack_cpld_irq,
 	.mask	= lh7a40x_mask_cpld_irq,
 	.unmask	= lh7a40x_unmask_cpld_irq,
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c
index 34eb79e..efe9bfc 100644
--- a/arch/arm/mach-omap1/fpga.c
+++ b/arch/arm/mach-omap1/fpga.c
@@ -106,14 +106,16 @@
 	}
 }
 
-static struct irqchip omap_fpga_irq_ack = {
+static struct irq_chip omap_fpga_irq_ack = {
+	.name		= "FPGA-ack",
 	.ack		= fpga_mask_ack_irq,
 	.mask		= fpga_mask_irq,
 	.unmask		= fpga_unmask_irq,
 };
 
 
-static struct irqchip omap_fpga_irq = {
+static struct irq_chip omap_fpga_irq = {
+	.name		= "FPGA",
 	.ack		= fpga_ack_irq,
 	.mask		= fpga_mask_irq,
 	.unmask		= fpga_unmask_irq,
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c
index 9e03984..3ea140b 100644
--- a/arch/arm/mach-omap1/irq.c
+++ b/arch/arm/mach-omap1/irq.c
@@ -168,7 +168,8 @@
 };
 #endif
 
-static struct irqchip omap_irq_chip = {
+static struct irq_chip omap_irq_chip = {
+	.name		= "MPU",
 	.ack		= omap_mask_ack_irq,
 	.mask		= omap_mask_irq,
 	.unmask		= omap_unmask_irq,
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 3eed6a7..dfc3b35 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -94,7 +94,8 @@
 	omap_ack_irq(irq);
 }
 
-static struct irqchip omap_irq_chip = {
+static struct irq_chip omap_irq_chip = {
+	.name	= "INTC",
 	.ack	= omap_mask_ack_irq,
 	.mask	= omap_mask_irq,
 	.unmask	= omap_unmask_irq,
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index f942131..ff6b4ee 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -47,14 +47,15 @@
  */
 unsigned long corgi_ssp_ads7846_putget(ulong data)
 {
-	unsigned long ret,flag;
+	unsigned long flag;
+	u32 ret = 0;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
 	if (ssp_machinfo->cs_ads7846 >= 0)
 		GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 
 	ssp_write_word(&corgi_ssp_dev,data);
-	ret = ssp_read_word(&corgi_ssp_dev);
+ 	ssp_read_word(&corgi_ssp_dev, &ret);
 
 	if (ssp_machinfo->cs_ads7846 >= 0)
 		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
@@ -88,7 +89,9 @@
 
 unsigned long corgi_ssp_ads7846_get(void)
 {
-	return ssp_read_word(&corgi_ssp_dev);
+	u32 ret = 0;
+	ssp_read_word(&corgi_ssp_dev, &ret);
+	return ret;
 }
 
 EXPORT_SYMBOL(corgi_ssp_ads7846_putget);
@@ -104,6 +107,7 @@
 unsigned long corgi_ssp_dac_put(ulong data)
 {
 	unsigned long flag, sscr1 = SSCR1_SPH;
+	u32 tmp;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
 
@@ -118,7 +122,7 @@
 		GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 	ssp_write_word(&corgi_ssp_dev,data);
 	/* Read null data back from device to prevent SSP overflow */
-	ssp_read_word(&corgi_ssp_dev);
+	ssp_read_word(&corgi_ssp_dev, &tmp);
 	if (ssp_machinfo->cs_lcdcon >= 0)
 		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 
@@ -150,7 +154,7 @@
 int corgi_ssp_max1111_get(ulong data)
 {
 	unsigned long flag;
-	int voltage,voltage1,voltage2;
+	long voltage = 0, voltage1 = 0, voltage2 = 0;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
 	if (ssp_machinfo->cs_max1111 >= 0)
@@ -163,15 +167,15 @@
 
 	/* TB1/RB1 */
 	ssp_write_word(&corgi_ssp_dev,data);
-	ssp_read_word(&corgi_ssp_dev); /* null read */
+	ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */
 
 	/* TB12/RB2 */
 	ssp_write_word(&corgi_ssp_dev,0);
-	voltage1=ssp_read_word(&corgi_ssp_dev);
+	ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1);
 
 	/* TB13/RB3*/
 	ssp_write_word(&corgi_ssp_dev,0);
-	voltage2=ssp_read_word(&corgi_ssp_dev);
+	ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2);
 
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index d9635ff..12141e2 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -39,7 +39,8 @@
 	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
-static struct irqchip pxa_internal_chip_low = {
+static struct irq_chip pxa_internal_chip_low = {
+	.name		= "SC",
 	.ack		= pxa_mask_low_irq,
 	.mask		= pxa_mask_low_irq,
 	.unmask		= pxa_unmask_low_irq,
@@ -61,7 +62,8 @@
 	ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
 }
 
-static struct irqchip pxa_internal_chip_high = {
+static struct irq_chip pxa_internal_chip_high = {
+	.name		= "SC-hi",
 	.ack		= pxa_mask_high_irq,
 	.mask		= pxa_mask_high_irq,
 	.unmask		= pxa_unmask_high_irq,
@@ -129,7 +131,8 @@
 	GEDR0 = (1 << (irq - IRQ_GPIO0));
 }
 
-static struct irqchip pxa_low_gpio_chip = {
+static struct irq_chip pxa_low_gpio_chip = {
+	.name		= "GPIO-l",
 	.ack		= pxa_ack_low_gpio,
 	.mask		= pxa_mask_low_irq,
 	.unmask		= pxa_unmask_low_irq,
@@ -237,7 +240,8 @@
 	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
 }
 
-static struct irqchip pxa_muxed_gpio_chip = {
+static struct irq_chip pxa_muxed_gpio_chip = {
+	.name		= "GPIO",
 	.ack		= pxa_ack_muxed_gpio,
 	.mask		= pxa_mask_muxed_gpio,
 	.unmask		= pxa_unmask_muxed_gpio,
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 1a5f5c2..12479ae 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -68,7 +68,8 @@
 	__raw_writew(lpd270_irq_enabled, LPD270_INT_MASK);
 }
 
-static struct irqchip lpd270_irq_chip = {
+static struct irq_chip lpd270_irq_chip = {
+	.name		= "CPLD",
 	.ack		= lpd270_mask_irq,
 	.mask		= lpd270_mask_irq,
 	.unmask		= lpd270_unmask_irq,
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6a9a669..83ff5ce 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -78,7 +78,8 @@
 	LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
 }
 
-static struct irqchip lubbock_irq_chip = {
+static struct irq_chip lubbock_irq_chip = {
+	.name		= "FPGA",
 	.ack		= lubbock_mask_irq,
 	.mask		= lubbock_mask_irq,
 	.unmask		= lubbock_unmask_irq,
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 21ddf3d..a7e9b96 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -64,7 +64,8 @@
 	MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
 }
 
-static struct irqchip mainstone_irq_chip = {
+static struct irq_chip mainstone_irq_chip = {
+	.name		= "FPGA",
 	.ack		= mainstone_mask_irq,
 	.mask		= mainstone_mask_irq,
 	.unmask		= mainstone_unmask_irq,
diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c
index 93096be..1fddfea 100644
--- a/arch/arm/mach-pxa/ssp.c
+++ b/arch/arm/mach-pxa/ssp.c
@@ -40,6 +40,8 @@
 
 #define PXA_SSP_PORTS 	3
 
+#define TIMEOUT 100000
+
 struct ssp_info_ {
 	int irq;
 	u32 clock;
@@ -92,13 +94,18 @@
  * The caller is expected to perform the necessary locking.
  *
  * Returns:
- *   %-ETIMEDOUT	timeout occurred (for future)
+ *   %-ETIMEDOUT	timeout occurred
  *   0			success
  */
 int ssp_write_word(struct ssp_dev *dev, u32 data)
 {
-	while (!(SSSR_P(dev->port) & SSSR_TNF))
+	int timeout = TIMEOUT;
+
+	while (!(SSSR_P(dev->port) & SSSR_TNF)) {
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
 		cpu_relax();
+	}
 
 	SSDR_P(dev->port) = data;
 
@@ -117,15 +124,21 @@
  * The caller is expected to perform the necessary locking.
  *
  * Returns:
- *   %-ETIMEDOUT	timeout occurred (for future)
+ *   %-ETIMEDOUT	timeout occurred
  *   32-bit data	success
  */
-int ssp_read_word(struct ssp_dev *dev)
+int ssp_read_word(struct ssp_dev *dev, u32 *data)
 {
-	while (!(SSSR_P(dev->port) & SSSR_RNE))
-		cpu_relax();
+	int timeout = TIMEOUT;
 
-	return SSDR_P(dev->port);
+	while (!(SSSR_P(dev->port) & SSSR_RNE)) {
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	*data = SSDR_P(dev->port);
+	return 0;
 }
 
 /**
@@ -136,13 +149,21 @@
  *
  * The caller is expected to perform the necessary locking.
  */
-void ssp_flush(struct ssp_dev *dev)
+int ssp_flush(struct ssp_dev *dev)
 {
+	int timeout = TIMEOUT * 2;
+
 	do {
 		while (SSSR_P(dev->port) & SSSR_RNE) {
+		        if (!--timeout)
+		        	return -ETIMEDOUT;
 			(void) SSDR_P(dev->port);
 		}
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
 	} while (SSSR_P(dev->port) & SSSR_BSY);
+
+	return 0;
 }
 
 /**
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 0c79386..0eadec9 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -10,45 +10,48 @@
 obj-n			:=
 obj-			:=
 
+# DMA
+obj-$(CONFIG_S3C2410_DMA)	+= dma.o
+
 # S3C2400 support files
-obj-$(CONFIG_CPU_S3C2400)  += s3c2400-gpio.o
+obj-$(CONFIG_CPU_S3C2400)	+= s3c2400-gpio.o
 
 # S3C2410 support files
 
-obj-$(CONFIG_CPU_S3C2410)  += s3c2410.o
-obj-$(CONFIG_CPU_S3C2410)  += s3c2410-gpio.o
-obj-$(CONFIG_S3C2410_DMA)  += dma.o
+obj-$(CONFIG_CPU_S3C2410)	+= s3c2410.o
+obj-$(CONFIG_CPU_S3C2410)	+= s3c2410-gpio.o
 
 # Power Management support
 
-obj-$(CONFIG_PM)	   += pm.o sleep.o
-obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
+obj-$(CONFIG_PM)		+= pm.o sleep.o
+obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
 
 # S3C2412 support
-obj-$(CONFIG_CPU_S3C2412)  += s3c2412.o
-obj-$(CONFIG_CPU_S3C2412)  += s3c2412-clock.o
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-irq.o
+obj-$(CONFIG_CPU_S3C2412)	+= s3c2412-clock.o
 
 #
 # S3C244X support
 
-obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
-obj-$(CONFIG_CPU_S3C244X)  += s3c244x-irq.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)	+= s3c244x-irq.o
 
 # Clock control
 
-obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
+obj-$(CONFIG_S3C2410_CLOCK)	+= s3c2410-clock.o
 
 # S3C2440 support
 
-obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
-obj-$(CONFIG_CPU_S3C2440)  += s3c2440-irq.o
-obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
-obj-$(CONFIG_CPU_S3C2440)  += s3c2410-gpio.o
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440.o s3c2440-dsc.o
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-irq.o
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2440-clock.o
+obj-$(CONFIG_CPU_S3C2440)	+= s3c2410-gpio.o
 
 # S3C2442 support
 
-obj-$(CONFIG_CPU_S3C2442)  += s3c2442.o
-obj-$(CONFIG_CPU_S3C2442)  += s3c2442-clock.o
+obj-$(CONFIG_CPU_S3C2442)	+= s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)	+= s3c2442-clock.o
 
 # bast extras
 
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index b0ed9d2..be42e40 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -8,16 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     24-Aug-2004 BJD  Start of generic S3C24XX support
- *     18-Oct-2004 BJD  Moved board struct into this file
- *     04-Jan-2005 BJD  New uart initialisation
- *     10-Jan-2005 BJD  Moved generic init here, specific to cpu headers
- *     14-Jan-2005 BJD  Added s3c24xx_init_clocks() call
- *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT
- *     14-Mar-2005 BJD  Updated for __iomem
- *     15-Jan-2006 LCVR Updated S3C2410_PA_##x to new S3C24XX_PA_##x macro
 */
 
 /* todo - fix when rmk changes iodescs to use `void __iomem *` */
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index ad3845e..cae35ff 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -1,22 +1,14 @@
 /* linux/arch/arm/mach-s3c2410/devs.c
  *
  * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ *	Ben Dooks <ben@simtec.co.uk>
  *
- * Base S3C2410 platform device definitions
+ * Base S3C24XX platform device definitions
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *     15-Jan-2006 LCVR Using S3C24XX_PA_##x macro for common S3C24XX devices
- *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
- *     10-Feb-2005 BJD  Added camera from guillaume.gourat@nexvision.tv
- *     29-Aug-2004 BJD  Added timers 0 through 3
- *     29-Aug-2004 BJD  Changed index of devices we only have one of to -1
- *     21-Aug-2004 BJD  Added IRQ_TICK to RTC resources
- *     18-Aug-2004 BJD  Created initial version
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index 094cc52..cc92a7b 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -60,7 +60,7 @@
 static kmem_cache_t *dma_kmem;
 
 /* dma channel state information */
-s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
+struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
 
 /* debugging functions */
 
@@ -74,7 +74,7 @@
 #define dma_wrreg(chan, reg, val) writel((val), (chan)->regs + (reg))
 #else
 static inline void
-dma_wrreg(s3c2410_dma_chan_t *chan, int reg, unsigned long val)
+dma_wrreg(struct s3c2410_dma_chan *chan, int reg, unsigned long val)
 {
 	pr_debug("writing %08x to register %08x\n",(unsigned int)val,reg);
 	writel(val, dma_regaddr(chan, reg));
@@ -102,7 +102,7 @@
 */
 
 static void
-dmadbg_capture(s3c2410_dma_chan_t *chan, struct s3c2410_dma_regstate *regs)
+dmadbg_capture(struct s3c2410_dma_chan *chan, struct s3c2410_dma_regstate *regs)
 {
 	regs->dcsrc    = dma_rdreg(chan, S3C2410_DMA_DCSRC);
 	regs->disrc    = dma_rdreg(chan, S3C2410_DMA_DISRC);
@@ -112,7 +112,7 @@
 }
 
 static void
-dmadbg_showregs(const char *fname, int line, s3c2410_dma_chan_t *chan,
+dmadbg_dumpregs(const char *fname, int line, struct s3c2410_dma_chan *chan,
 		 struct s3c2410_dma_regstate *regs)
 {
 	printk(KERN_DEBUG "dma%d: %s:%d: DCSRC=%08lx, DISRC=%08lx, DSTAT=%08lx DMT=%02lx, DCON=%08lx\n",
@@ -122,7 +122,7 @@
 }
 
 static void
-dmadbg_showchan(const char *fname, int line, s3c2410_dma_chan_t *chan)
+dmadbg_showchan(const char *fname, int line, struct s3c2410_dma_chan *chan)
 {
 	struct s3c2410_dma_regstate state;
 
@@ -132,7 +132,16 @@
 	       chan->number, fname, line, chan->load_state,
 	       chan->curr, chan->next, chan->end);
 
-	dmadbg_showregs(fname, line, chan, &state);
+	dmadbg_dumpregs(fname, line, chan, &state);
+}
+
+static void
+dmadbg_showregs(const char *fname, int line, struct s3c2410_dma_chan *chan)
+{
+	struct s3c2410_dma_regstate state;
+
+	dmadbg_capture(chan, &state);
+	dmadbg_dumpregs(fname, line, chan, &state);
 }
 
 #define dbg_showregs(chan) dmadbg_showregs(__FUNCTION__, __LINE__, (chan))
@@ -155,7 +164,7 @@
 */
 
 static void
-s3c2410_dma_stats_timeout(s3c2410_dma_stats_t *stats, int val)
+s3c2410_dma_stats_timeout(struct s3c2410_dma_stats *stats, int val)
 {
 	if (stats == NULL)
 		return;
@@ -174,7 +183,7 @@
 */
 
 static int
-s3c2410_dma_waitforload(s3c2410_dma_chan_t *chan, int line)
+s3c2410_dma_waitforload(struct s3c2410_dma_chan *chan, int line)
 {
 	int timeout = chan->load_timeout;
 	int took;
@@ -221,8 +230,8 @@
 */
 
 static inline int
-s3c2410_dma_loadbuffer(s3c2410_dma_chan_t *chan,
-		       s3c2410_dma_buf_t *buf)
+s3c2410_dma_loadbuffer(struct s3c2410_dma_chan *chan,
+		       struct s3c2410_dma_buf *buf)
 {
 	unsigned long reload;
 
@@ -253,10 +262,14 @@
 			 buf->next);
 		reload = (buf->next == NULL) ? S3C2410_DCON_NORELOAD : 0;
 	} else {
-		pr_debug("load_state is %d => autoreload\n", chan->load_state);
+		//pr_debug("load_state is %d => autoreload\n", chan->load_state);
 		reload = S3C2410_DCON_AUTORELOAD;
 	}
 
+	if ((buf->data & 0xf0000000) != 0x30000000) {
+		dmawarn("dmaload: buffer is %p\n", (void *)buf->data);
+	}
+
 	writel(buf->data, chan->addr_reg);
 
 	dma_wrreg(chan, S3C2410_DMA_DCON,
@@ -291,7 +304,7 @@
 */
 
 static void
-s3c2410_dma_call_op(s3c2410_dma_chan_t *chan, s3c2410_chan_op_t op)
+s3c2410_dma_call_op(struct s3c2410_dma_chan *chan, enum s3c2410_chan_op op)
 {
 	if (chan->op_fn != NULL) {
 		(chan->op_fn)(chan, op);
@@ -305,8 +318,8 @@
 */
 
 static inline void
-s3c2410_dma_buffdone(s3c2410_dma_chan_t *chan, s3c2410_dma_buf_t *buf,
-		     s3c2410_dma_buffresult_t result)
+s3c2410_dma_buffdone(struct s3c2410_dma_chan *chan, struct s3c2410_dma_buf *buf,
+		     enum s3c2410_dma_buffresult result)
 {
 	pr_debug("callback_fn=%p, buf=%p, id=%p, size=%d, result=%d\n",
 		 chan->callback_fn, buf, buf->id, buf->size, result);
@@ -321,7 +334,7 @@
  * start a dma channel going
 */
 
-static int s3c2410_dma_start(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_start(struct s3c2410_dma_chan *chan)
 {
 	unsigned long tmp;
 	unsigned long flags;
@@ -370,7 +383,7 @@
 	tmp |= S3C2410_DMASKTRIG_ON;
 	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
 
-	pr_debug("wrote %08lx to DMASKTRIG\n", tmp);
+	pr_debug("dma%d: %08lx to DMASKTRIG\n", chan->number, tmp);
 
 #if 0
 	/* the dma buffer loads should take care of clearing the AUTO
@@ -384,7 +397,30 @@
 
 	dbg_showchan(chan);
 
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
 	local_irq_restore(flags);
+
 	return 0;
 }
 
@@ -394,7 +430,7 @@
 */
 
 static int
-s3c2410_dma_canload(s3c2410_dma_chan_t *chan)
+s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
 {
 	if (chan->load_state == S3C2410_DMALOAD_NONE ||
 	    chan->load_state == S3C2410_DMALOAD_1RUNNING)
@@ -424,8 +460,8 @@
 int s3c2410_dma_enqueue(unsigned int channel, void *id,
 			dma_addr_t data, int size)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
-	s3c2410_dma_buf_t *buf;
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_buf *buf;
 	unsigned long flags;
 
 	check_channel(channel);
@@ -436,12 +472,11 @@
 	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
 	if (buf == NULL) {
 		pr_debug("%s: out of memory (%ld alloc)\n",
-			 __FUNCTION__, sizeof(*buf));
+			 __FUNCTION__, (long)sizeof(*buf));
 		return -ENOMEM;
 	}
 
-	pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
-
+	//pr_debug("%s: new buffer %p\n", __FUNCTION__, buf);
 	//dbg_showchan(chan);
 
 	buf->next  = NULL;
@@ -505,7 +540,7 @@
 EXPORT_SYMBOL(s3c2410_dma_enqueue);
 
 static inline void
-s3c2410_dma_freebuf(s3c2410_dma_buf_t *buf)
+s3c2410_dma_freebuf(struct s3c2410_dma_buf *buf)
 {
 	int magicok = (buf->magic == BUF_MAGIC);
 
@@ -525,7 +560,7 @@
 */
 
 static inline void
-s3c2410_dma_lastxfer(s3c2410_dma_chan_t *chan)
+s3c2410_dma_lastxfer(struct s3c2410_dma_chan *chan)
 {
 	pr_debug("dma%d: s3c2410_dma_lastxfer: load_state %d\n",
 		 chan->number, chan->load_state);
@@ -537,14 +572,20 @@
 	case S3C2410_DMALOAD_1LOADED:
 		if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
 				/* flag error? */
-			printk(KERN_ERR "dma%d: timeout waiting for load\n",
-			       chan->number);
+			printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+			       chan->number, __FUNCTION__);
 			return;
 		}
 		break;
 
+	case S3C2410_DMALOAD_1LOADED_1RUNNING:
+		/* I belive in this case we do not have anything to do
+		 * until the next buffer comes along, and we turn off the
+		 * reload */
+		return;
+
 	default:
-		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next",
+		pr_debug("dma%d: lastxfer: unhandled load_state %d with no next\n",
 			 chan->number, chan->load_state);
 		return;
 
@@ -560,8 +601,8 @@
 static irqreturn_t
 s3c2410_dma_irq(int irq, void *devpw, struct pt_regs *regs)
 {
-	s3c2410_dma_chan_t *chan = (s3c2410_dma_chan_t *)devpw;
-	s3c2410_dma_buf_t  *buf;
+	struct s3c2410_dma_chan *chan = (struct s3c2410_dma_chan *)devpw;
+	struct s3c2410_dma_buf  *buf;
 
 	buf = chan->curr;
 
@@ -629,7 +670,14 @@
 	} else {
 	}
 
-	if (chan->next != NULL) {
+	/* only reload if the channel is still running... our buffer done
+	 * routine may have altered the state by requesting the dma channel
+	 * to stop or shutdown... */
+
+	/* todo: check that when the channel is shut-down from inside this
+	 * function, we cope with unsetting reload, etc */
+
+	if (chan->next != NULL && chan->state != S3C2410_DMA_IDLE) {
 		unsigned long flags;
 
 		switch (chan->load_state) {
@@ -644,8 +692,8 @@
 		case S3C2410_DMALOAD_1LOADED:
 			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
 				/* flag error? */
-				printk(KERN_ERR "dma%d: timeout waiting for load\n",
-				       chan->number);
+				printk(KERN_ERR "dma%d: timeout waiting for load (%s)\n",
+				       chan->number, __FUNCTION__);
 				return IRQ_HANDLED;
 			}
 
@@ -678,17 +726,15 @@
 	return IRQ_HANDLED;
 }
 
-
-
 /* s3c2410_request_dma
  *
  * get control of an dma channel
 */
 
-int s3c2410_dma_request(unsigned int channel, s3c2410_dma_client_t *client,
+int s3c2410_dma_request(unsigned int channel, struct s3c2410_dma_client *client,
 			void *dev)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 	unsigned long flags;
 	int err;
 
@@ -718,11 +764,17 @@
 		pr_debug("dma%d: %s : requesting irq %d\n",
 			 channel, __FUNCTION__, chan->irq);
 
+		chan->irq_claimed = 1;
+		local_irq_restore(flags);
+
 		err = request_irq(chan->irq, s3c2410_dma_irq, IRQF_DISABLED,
 				  client->name, (void *)chan);
 
+		local_irq_save(flags);
+
 		if (err) {
 			chan->in_use = 0;
+			chan->irq_claimed = 0;
 			local_irq_restore(flags);
 
 			printk(KERN_ERR "%s: cannot get IRQ %d for DMA %d\n",
@@ -730,7 +782,6 @@
 			return err;
 		}
 
-		chan->irq_claimed = 1;
 		chan->irq_enabled = 1;
 	}
 
@@ -756,9 +807,9 @@
  * allowed to go through.
 */
 
-int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
+int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *client)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 	unsigned long flags;
 
 	check_channel(channel);
@@ -795,7 +846,7 @@
 
 EXPORT_SYMBOL(s3c2410_dma_free);
 
-static int s3c2410_dma_dostop(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_dostop(struct s3c2410_dma_chan *chan)
 {
 	unsigned long tmp;
 	unsigned long flags;
@@ -810,6 +861,7 @@
 
 	tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
 	tmp |= S3C2410_DMASKTRIG_STOP;
+	//tmp &= ~S3C2410_DMASKTRIG_ON;
 	dma_wrreg(chan, S3C2410_DMA_DMASKTRIG, tmp);
 
 #if 0
@@ -819,6 +871,7 @@
 	dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
 #endif
 
+	/* should stop do this, or should we wait for flush? */
 	chan->state      = S3C2410_DMA_IDLE;
 	chan->load_state = S3C2410_DMALOAD_NONE;
 
@@ -827,17 +880,35 @@
 	return 0;
 }
 
+void s3c2410_dma_waitforstop(struct s3c2410_dma_chan *chan)
+{
+	unsigned long tmp;
+	unsigned int timeout = 0x10000;
+
+	while (timeout-- > 0) {
+		tmp = dma_rdreg(chan, S3C2410_DMA_DMASKTRIG);
+
+		if (!(tmp & S3C2410_DMASKTRIG_ON))
+			return;
+	}
+
+	pr_debug("dma%d: failed to stop?\n", chan->number);
+}
+
+
 /* s3c2410_dma_flush
  *
  * stop the channel, and remove all current and pending transfers
 */
 
-static int s3c2410_dma_flush(s3c2410_dma_chan_t *chan)
+static int s3c2410_dma_flush(struct s3c2410_dma_chan *chan)
 {
-	s3c2410_dma_buf_t *buf, *next;
+	struct s3c2410_dma_buf *buf, *next;
 	unsigned long flags;
 
-	pr_debug("%s:\n", __FUNCTION__);
+	pr_debug("%s: chan %p (%d)\n", __FUNCTION__, chan, chan->number);
+
+	dbg_showchan(chan);
 
 	local_irq_save(flags);
 
@@ -864,16 +935,69 @@
 		}
 	}
 
+	dbg_showregs(chan);
+
+	s3c2410_dma_waitforstop(chan);
+
+#if 0
+	/* should also clear interrupts, according to WinCE BSP */
+	{
+		unsigned long tmp;
+
+		tmp = dma_rdreg(chan, S3C2410_DMA_DCON);
+		tmp |= S3C2410_DCON_NORELOAD;
+		dma_wrreg(chan, S3C2410_DMA_DCON, tmp);
+	}
+#endif
+
+	dbg_showregs(chan);
+
 	local_irq_restore(flags);
 
 	return 0;
 }
 
+int
+s3c2410_dma_started(struct s3c2410_dma_chan *chan)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	dbg_showchan(chan);
+
+	/* if we've only loaded one buffer onto the channel, then chec
+	 * to see if we have another, and if so, try and load it so when
+	 * the first buffer is finished, the new one will be loaded onto
+	 * the channel */
+
+	if (chan->next != NULL) {
+		if (chan->load_state == S3C2410_DMALOAD_1LOADED) {
+
+			if (s3c2410_dma_waitforload(chan, __LINE__) == 0) {
+				pr_debug("%s: buff not yet loaded, no more todo\n",
+					 __FUNCTION__);
+			} else {
+				chan->load_state = S3C2410_DMALOAD_1RUNNING;
+				s3c2410_dma_loadbuffer(chan, chan->next);
+			}
+
+		} else if (chan->load_state == S3C2410_DMALOAD_1RUNNING) {
+			s3c2410_dma_loadbuffer(chan, chan->next);
+		}
+	}
+
+
+	local_irq_restore(flags);
+
+	return 0;
+
+}
 
 int
-s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op)
+s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	check_channel(channel);
 
@@ -885,14 +1009,15 @@
 		return s3c2410_dma_dostop(chan);
 
 	case S3C2410_DMAOP_PAUSE:
-		return -ENOENT;
-
 	case S3C2410_DMAOP_RESUME:
 		return -ENOENT;
 
 	case S3C2410_DMAOP_FLUSH:
 		return s3c2410_dma_flush(chan);
 
+	case S3C2410_DMAOP_STARTED:
+		return s3c2410_dma_started(chan);
+
 	case S3C2410_DMAOP_TIMEOUT:
 		return 0;
 
@@ -921,7 +1046,7 @@
 		       int xferunit,
 		       int dcon)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
 		 __FUNCTION__, channel, xferunit, dcon);
@@ -961,7 +1086,7 @@
 
 int s3c2410_dma_setflags(dmach_t channel, unsigned int flags)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	check_channel(channel);
 
@@ -981,7 +1106,7 @@
 
 int s3c2410_dma_set_opfn(dmach_t channel, s3c2410_dma_opfn_t rtn)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	check_channel(channel);
 
@@ -996,7 +1121,7 @@
 
 int s3c2410_dma_set_buffdone_fn(dmach_t channel, s3c2410_dma_cbfn_t rtn)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	check_channel(channel);
 
@@ -1024,11 +1149,11 @@
 */
 
 int s3c2410_dma_devconfig(int channel,
-			  s3c2410_dmasrc_t source,
+			  enum s3c2410_dmasrc source,
 			  int hwcfg,
 			  unsigned long devaddr)
 {
-	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
 	check_channel(channel);
 
@@ -1075,7 +1200,7 @@
 
 int s3c2410_dma_getposition(dmach_t channel, dma_addr_t *src, dma_addr_t *dst)
 {
- 	s3c2410_dma_chan_t *chan = &s3c2410_chans[channel];
+ 	struct s3c2410_dma_chan *chan = &s3c2410_chans[channel];
 
  	check_channel(channel);
 
@@ -1097,7 +1222,7 @@
 
 static int s3c2410_dma_suspend(struct sys_device *dev, pm_message_t state)
 {
-	s3c2410_dma_chan_t *cp = container_of(dev, s3c2410_dma_chan_t, dev);
+	struct s3c2410_dma_chan *cp = container_of(dev, struct s3c2410_dma_chan, dev);
 
 	printk(KERN_DEBUG "suspending dma channel %d\n", cp->number);
 
@@ -1137,7 +1262,7 @@
 
 static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
 {
-	memset(p, 0, sizeof(s3c2410_dma_buf_t));
+	memset(p, 0, sizeof(struct s3c2410_dma_buf));
 }
 
 
@@ -1145,7 +1270,7 @@
 
 static int __init s3c2410_init_dma(void)
 {
-	s3c2410_dma_chan_t *cp;
+	struct s3c2410_dma_chan *cp;
 	int channel;
 	int ret;
 
@@ -1163,7 +1288,7 @@
 		goto err;
 	}
 
-	dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0,
+	dma_kmem = kmem_cache_create("dma_desc", sizeof(struct s3c2410_dma_buf), 0,
 				     SLAB_HWCACHE_ALIGN,
 				     s3c2410_dma_cache_ctor, NULL);
 
@@ -1176,7 +1301,7 @@
 	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
 		cp = &s3c2410_chans[channel];
 
-		memset(cp, 0, sizeof(s3c2410_dma_chan_t));
+		memset(cp, 0, sizeof(struct s3c2410_dma_chan));
 
 		/* dma channel irqs are in order.. */
 		cp->number = channel;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 6822dc7..cd6139b 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -86,7 +86,7 @@
 unsigned long s3c_irqwake_eintallow	= 0x0000fff0L;
 unsigned long s3c_irqwake_eintmask	= 0xffffffffL;
 
-static int
+int
 s3c_irq_wake(unsigned int irqno, unsigned int state)
 {
 	unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
@@ -260,7 +260,7 @@
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
-static int
+int
 s3c_irqext_type(unsigned int irq, unsigned int type)
 {
 	void __iomem *extint_reg;
diff --git a/arch/arm/mach-s3c2410/irq.h b/arch/arm/mach-s3c2410/irq.h
index 4abf0ca..f7cc4c9 100644
--- a/arch/arm/mach-s3c2410/irq.h
+++ b/arch/arm/mach-s3c2410/irq.h
@@ -97,3 +97,8 @@
 		__raw_writel(parentmask, S3C2410_INTPND);
 	}
 }
+
+/* exported for use in arch/arm/mach-s3c2410 */
+
+extern int s3c_irq_wake(unsigned int irqno, unsigned int state);
+extern int s3c_irqext_type(unsigned int irq, unsigned int type);
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index 4a92d6f..60641d4 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -60,11 +60,12 @@
 	.virtual	= (u32)S3C24XX_VA_ISA_BYTE,
 	.pfn		= __phys_to_pfn(0x0),
 	.length		= SZ_4M,
-	.type		= MT_DEVICE
+	.type		= MT_DEVICE,
   }, {
 	.virtual	= (u32)S3C24XX_VA_ISA_WORD,
 	.pfn		= __phys_to_pfn(0x0),
-	.length 	= SZ_4M, MT_DEVICE
+	.length 	= SZ_4M,
+	.type		= MT_DEVICE,
   },
 
   /* we could possibly compress the next set down into a set of smaller tables
@@ -78,36 +79,12 @@
 	.virtual	= (u32)ANUBIS_VA_CTRL1,
 	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL1),
 	.length		= SZ_4K,
-	.type		= MT_DEVICE
+	.type		= MT_DEVICE,
   }, {
 	.virtual	= (u32)ANUBIS_VA_CTRL2,
 	.pfn		= __phys_to_pfn(ANUBIS_PA_CTRL2),
 	.length		= SZ_4K,
-	.type		=MT_DEVICE
-  },
-
-  /* IDE drives */
-
-  {
-	.virtual	= (u32)ANUBIS_IDEPRI,
-	.pfn		= __phys_to_pfn(S3C2410_CS3),
-	.length		= SZ_1M,
-	.type		= MT_DEVICE
-  }, {
-	.virtual	= (u32)ANUBIS_IDEPRIAUX,
-	.pfn		= __phys_to_pfn(S3C2410_CS3+(1<<26)),
-	.length		= SZ_1M,
-	.type		= MT_DEVICE
-  }, {
-	.virtual	= (u32)ANUBIS_IDESEC,
-	.pfn		= __phys_to_pfn(S3C2410_CS4),
-	.length		= SZ_1M,
-	.type		= MT_DEVICE
-  }, {
-	.virtual	= (u32)ANUBIS_IDESECAUX,
-	.pfn		= __phys_to_pfn(S3C2410_CS4+(1<<26)),
-	.length		= SZ_1M,
-	.type		= MT_DEVICE
+	.type		= MT_DEVICE,
   },
 };
 
@@ -126,7 +103,7 @@
 		.name		= "pclk",
 		.divisor	= 1,
 		.min_baud	= 0,
-		.max_baud	= 0.
+		.max_baud	= 0,
 	}
 };
 
@@ -139,7 +116,7 @@
 		.ulcon	     = ULCON,
 		.ufcon	     = UFCON,
 		.clocks	     = anubis_serial_clocks,
-		.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
 	},
 	[1] = {
 		.hwport	     = 2,
@@ -148,7 +125,7 @@
 		.ulcon	     = ULCON,
 		.ufcon	     = UFCON,
 		.clocks	     = anubis_serial_clocks,
-		.clocks_size = ARRAY_SIZE(anubis_serial_clocks)
+		.clocks_size = ARRAY_SIZE(anubis_serial_clocks),
 	},
 };
 
@@ -162,7 +139,7 @@
 	[0] = {
 		.name	= "Boot Agent",
 		.size	= SZ_16K,
-		.offset	= 0
+		.offset	= 0,
 	},
 	[1] = {
 		.name	= "/boot",
@@ -194,21 +171,21 @@
 		.nr_chips	= 1,
 		.nr_map		= external_map,
 		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part
+		.partitions	= anubis_default_nand_part,
 	},
 	[0] = {
 		.name		= "chip0",
 		.nr_chips	= 1,
 		.nr_map		= chip0_map,
 		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part
+		.partitions	= anubis_default_nand_part,
 	},
 	[2] = {
 		.name		= "chip1",
 		.nr_chips	= 1,
 		.nr_map		= chip1_map,
 		.nr_partitions	= ARRAY_SIZE(anubis_default_nand_part),
-		.partitions	= anubis_default_nand_part
+		.partitions	= anubis_default_nand_part,
 	},
 };
 
@@ -313,7 +290,7 @@
 	.devices       = anubis_devices,
 	.devices_count = ARRAY_SIZE(anubis_devices),
 	.clocks	       = anubis_clocks,
-	.clocks_count  = ARRAY_SIZE(anubis_clocks)
+	.clocks_count  = ARRAY_SIZE(anubis_clocks),
 };
 
 static void __init anubis_map_io(void)
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 947234d..2968fb2 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -8,31 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     14-Sep-2004 BJD  USB power control
- *     20-Aug-2004 BJD  Added s3c2410_board struct
- *     18-Aug-2004 BJD  Added platform devices from default set
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to v2.6 kernel
- *     06-Jan-2003 BJD  Updates for <arch/map.h>
- *     18-Jan-2003 BJD  Added serial port configuration
- *     05-Oct-2004 BJD  Power management code
- *     04-Nov-2004 BJD  Updated serial port clocks
- *     04-Jan-2005 BJD  New uart init call
- *     10-Jan-2005 BJD  Removed include of s3c2410.h
- *     14-Jan-2005 BJD  Add support for muitlple NAND devices
- *     03-Mar-2005 BJD  Ensured that bast-cpld.h is included
- *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- *     14-Mar-2005 BJD  Updated for __iomem changes
- *     22-Jun-2005 BJD  Added DM9000 platform information
- *     28-Jun-2005 BJD  Moved pm functionality out to common code
- *     17-Jul-2005 BJD  Changed to platform device for SuperIO 16550s
- *     25-Jul-2005 BJD  Removed ASIX static mappings
- *     27-Jul-2005 BJD  Ensure maximum frequency of i2c bus
- *     20-Sep-2005 BJD  Added static to non-exported items
- *     26-Oct-2005 BJD  Added FB platform data
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index aec431b..8c895c0 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -9,23 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to v2.6 kernel
- *     06-Jan-2003 BJD  Updates for <arch/map.h>
- *     18-Jan-2003 BJD  Added serial port configuration
- *     17-Feb-2003 BJD  Copied to mach-ipaq.c
- *     21-Aug-2004 BJD  Added struct s3c2410_board
- *     04-Sep-2004 BJD  Changed uart init, renamed ipaq_ -> h1940_
- *     18-Oct-2004 BJD  Updated new board structure name
- *     04-Nov-2004 BJD  Change for new serial clock
- *     04-Jan-2005 BJD  Updated uart init call
- *     10-Jan-2005 BJD  Removed include of s3c2410.h
- *     14-Jan-2005 BJD  Added clock init
- *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- *     20-Sep-2005 BJD  Added static to non-exported items
- *     26-Oct-2005 BJD  Changed name of fb init call
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
index 858fd03..e193ba6 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2410/mach-osiris.c
@@ -67,12 +67,12 @@
 	  .virtual	= (u32)OSIRIS_VA_CTRL1,
 	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL1),
 	  .length	= SZ_16K,
-	  .type		= MT_DEVICE
+	  .type		= MT_DEVICE,
   }, {
 	  .virtual	= (u32)OSIRIS_VA_CTRL2,
 	  .pfn		= __phys_to_pfn(OSIRIS_PA_CTRL2),
 	  .length	= SZ_16K,
-	  .type		= MT_DEVICE
+	  .type		= MT_DEVICE,
   },
 };
 
@@ -91,7 +91,7 @@
 		.name		= "pclk",
 		.divisor	= 1,
 		.min_baud	= 0,
-		.max_baud	= 0.
+		.max_baud	= 0,
 	}
 };
 
@@ -103,7 +103,7 @@
 		.ulcon	     = ULCON,
 		.ufcon	     = UFCON,
 		.clocks	     = osiris_serial_clocks,
-		.clocks_size = ARRAY_SIZE(osiris_serial_clocks)
+		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
 	},
 	[1] = {
 		.hwport	     = 1,
@@ -112,7 +112,7 @@
 		.ulcon	     = ULCON,
 		.ufcon	     = UFCON,
 		.clocks	     = osiris_serial_clocks,
-		.clocks_size = ARRAY_SIZE(osiris_serial_clocks)
+		.clocks_size = ARRAY_SIZE(osiris_serial_clocks),
 	},
 };
 
@@ -126,7 +126,7 @@
 	[0] = {
 		.name	= "Boot Agent",
 		.size	= SZ_16K,
-		.offset	= 0
+		.offset	= 0,
 	},
 	[1] = {
 		.name	= "/boot",
@@ -158,21 +158,21 @@
 		.nr_chips	= 1,
 		.nr_map		= external_map,
 		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part
+		.partitions	= osiris_default_nand_part,
 	},
 	[0] = {
 		.name		= "chip0",
 		.nr_chips	= 1,
 		.nr_map		= chip0_map,
 		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part
+		.partitions	= osiris_default_nand_part,
 	},
 	[2] = {
 		.name		= "chip1",
 		.nr_chips	= 1,
 		.nr_map		= chip1_map,
 		.nr_partitions	= ARRAY_SIZE(osiris_default_nand_part),
-		.partitions	= osiris_default_nand_part
+		.partitions	= osiris_default_nand_part,
 	},
 };
 
@@ -245,7 +245,7 @@
 	.devices       = osiris_devices,
 	.devices_count = ARRAY_SIZE(osiris_devices),
 	.clocks	       = osiris_clocks,
-	.clocks_count  = ARRAY_SIZE(osiris_clocks)
+	.clocks_count  = ARRAY_SIZE(osiris_clocks),
 };
 
 static void __init osiris_map_io(void)
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
index 306afc1..23d7c05 100644
--- a/arch/arm/mach-s3c2410/mach-rx3715.c
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c
@@ -9,15 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *	16-Sep-2004 BJD  Copied from mach-h1940.c
- *	25-Oct-2004 BJD  Updates for 2.6.10-rc1
- *	10-Jan-2005 BJD  Removed include of s3c2410.h s3c2440.h
- *	14-Jan-2005 BJD  Added new clock init
- *	10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- *	14-Mar-2005 BJD  Fixed __iomem warnings
- *	20-Sep-2005 BJD  Added static to non-exported items
- *	31-Oct-2005 BJD  Added LCD setup for framebuffer
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 25f7e9f..b3b0171 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -27,10 +27,6 @@
  * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
  * Ben Dooks <ben@simtec.co.uk>
  *
- * 10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
- * 20-Sep-2005 BJD   Added static to non-exported items
- * 01-Apr-2006 BJD   Moved init code to common smdk
- *
  ***********************************************************************/
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
index b7ef7d3..3a4ca7f 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2413.c
@@ -112,7 +112,20 @@
 	smdk_machine_init();
 }
 
-MACHINE_START(S3C2413, "SMDK2413")
+MACHINE_START(S3C2413, "S3C2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
+
+MACHINE_START(SMDK2413, "SMDK2413")
 	/* Maintainer: Ben Dooks <ben@fluff.org> */
 	.phys_io	= S3C2410_PA_UART,
 	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index d18efb2..a0d7692 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -10,25 +10,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *     14-Sep-2004 BJD  USB Power control
- *     04-Sep-2004 BJD  Added new uart init, and io init
- *     21-Aug-2004 BJD  Added struct s3c2410_board
- *     06-Aug-2004 BJD  Fixed call to time initialisation
- *     05-Apr-2004 BJD  Copied to make mach-vr1000.c
- *     18-Oct-2004 BJD  Updated board struct
- *     04-Nov-2004 BJD  Clock and serial configuration update
- *
- *     04-Jan-2005 BJD  Updated uart init call
- *     10-Jan-2005 BJD  Removed include of s3c2410.h
- *     14-Jan-2005 BJD  Added clock init
- *     15-Jan-2005 BJD  Add serial port device definition
- *     20-Jan-2005 BJD  Use UPF_IOREMAP for ports
- *     10-Feb-2005 BJD  Added power-off capability
- *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
- *     14-Mar-2006 BJD  void __iomem fixes
- *     22-Jun-2006 BJD  Added DM9000 platform information
- *     20-Sep-2005 BJD  Added static to non-exported items
 */
 
 #include <linux/kernel.h>
diff --git a/arch/arm/mach-s3c2410/s3c2400-gpio.c b/arch/arm/mach-s3c2410/s3c2400-gpio.c
index 5127f39..f2a7817 100644
--- a/arch/arm/mach-s3c2410/s3c2400-gpio.c
+++ b/arch/arm/mach-s3c2410/s3c2400-gpio.c
@@ -17,10 +17,7 @@
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog
- *	15-Jan-2006  LCVR  Splitted from gpio.c, adding support for the S3C2400
- */
+*/
 
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
index 73f1a24..fbed084 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/arch/arm/mach-s3c2410/s3c2410.h
@@ -9,14 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Modifications:
- *     18-Aug-2004 BJD  Created initial version
- *     20-Aug-2004 BJD  Added s3c2410_board struct
- *     04-Sep-2004 BJD  Added s3c2410_init_uarts() call
- *     17-Oct-2004 BJD  Moved board out to cpu
- *     04-Jan-2005 BJD  Changed uart init
- *     10-Jan-2005 BJD  Removed timer to cpu.h, moved 2410 specific bits here
- *     14-Jan-2005 BJD  Added s3c2410_init_clocks call
 */
 
 #ifdef CONFIG_CPU_S3C2410
diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c
new file mode 100644
index 0000000..c80ec93
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-irq.c
@@ -0,0 +1,130 @@
+/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "irq.h"
+
+/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
+ * having them turn up in both the INT* and the EINT* registers. Whilst
+ * both show the status, they both now need to be acked when the IRQs
+ * go off.
+*/
+
+static void
+s3c2412_irq_mask(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask | bitval, S3C2410_INTMSK);
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask | bitval, S3C2412_EINTMASK);
+}
+
+static inline void
+s3c2412_irq_ack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+
+	__raw_writel(bitval, S3C2412_EINTPEND);
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static inline void
+s3c2412_irq_maskack(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask|bitval, S3C2410_INTMSK);
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask | bitval, S3C2412_EINTMASK);
+
+	__raw_writel(bitval, S3C2412_EINTPEND);
+	__raw_writel(bitval, S3C2410_SRCPND);
+	__raw_writel(bitval, S3C2410_INTPND);
+}
+
+static void
+s3c2412_irq_unmask(unsigned int irqno)
+{
+	unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
+	unsigned long mask;
+
+	mask = __raw_readl(S3C2412_EINTMASK);
+	__raw_writel(mask & ~bitval, S3C2412_EINTMASK);
+
+	mask = __raw_readl(S3C2410_INTMSK);
+	__raw_writel(mask & ~bitval, S3C2410_INTMSK);
+}
+
+static struct irqchip s3c2412_irq_eint0t4 = {
+	.ack	   = s3c2412_irq_ack,
+	.mask	   = s3c2412_irq_mask,
+	.unmask	   = s3c2412_irq_unmask,
+	.set_wake  = s3c_irq_wake,
+	.set_type  = s3c_irqext_type,
+};
+
+static int s3c2412_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		set_irq_chip(irqno, &s3c2412_irq_eint0t4);
+		set_irq_handler(irqno, do_edge_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2412_irq_driver = {
+	.add		= s3c2412_irq_add,
+};
+
+static int s3c2412_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_irq_driver);
+}
+
+arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index acfe387..1667ba1 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Changelog:
- *	25-Jul-2005 BJD		Split from irq.c
- *
 */
 
 #include <linux/init.h>
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
index 2aadca1..44c5aff 100644
--- a/arch/arm/mach-s3c2410/s3c244x-irq.c
+++ b/arch/arm/mach-s3c2410/s3c244x-irq.c
@@ -17,9 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Changelog:
- *	25-Jul-2005 BJD		Split from irq.c
- *
 */
 
 #include <linux/init.h>
@@ -122,21 +119,24 @@
 	return 0;
 }
 
-static struct sysdev_driver s3c244x_irq_driver = {
+static struct sysdev_driver s3c2440_irq_driver = {
 	.add	= s3c244x_irq_add,
 };
 
 static int s3c2440_irq_init(void)
 {
-	return sysdev_driver_register(&s3c2440_sysclass, &s3c244x_irq_driver);
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
 }
 
 arch_initcall(s3c2440_irq_init);
 
+static struct sysdev_driver s3c2442_irq_driver = {
+	.add	= s3c244x_irq_add,
+};
 
 static int s3c2442_irq_init(void)
 {
-	return sysdev_driver_register(&s3c2442_sysclass, &s3c244x_irq_driver);
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver);
 }
 
 arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
index 2891b8c..b55b90a 100644
--- a/arch/arm/mach-sa1100/irq.c
+++ b/arch/arm/mach-sa1100/irq.c
@@ -95,7 +95,8 @@
 	return 0;
 }
 
-static struct irqchip sa1100_low_gpio_chip = {
+static struct irq_chip sa1100_low_gpio_chip = {
+	.name		= "GPIO-l",
 	.ack		= sa1100_low_gpio_ack,
 	.mask		= sa1100_low_gpio_mask,
 	.unmask		= sa1100_low_gpio_unmask,
@@ -178,7 +179,8 @@
 	return 0;
 }
 
-static struct irqchip sa1100_high_gpio_chip = {
+static struct irq_chip sa1100_high_gpio_chip = {
+	.name		= "GPIO-h",
 	.ack		= sa1100_high_gpio_ack,
 	.mask		= sa1100_high_gpio_mask,
 	.unmask		= sa1100_high_gpio_unmask,
@@ -215,7 +217,8 @@
 	return -EINVAL;
 }
 
-static struct irqchip sa1100_normal_chip = {
+static struct irq_chip sa1100_normal_chip = {
+	.name		= "SC",
 	.ack		= sa1100_mask_irq,
 	.mask		= sa1100_mask_irq,
 	.unmask		= sa1100_unmask_irq,
diff --git a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
index 1604dad..5eba5fb 100644
--- a/arch/arm/mach-sa1100/ssp.c
+++ b/arch/arm/mach-sa1100/ssp.c
@@ -23,6 +23,8 @@
 #include <asm/hardware.h>
 #include <asm/hardware/ssp.h>
 
+#define TIMEOUT 100000
+
 static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned int status = Ser4SSSR;
@@ -47,18 +49,27 @@
  * The caller is expected to perform the necessary locking.
  *
  * Returns:
- *   %-ETIMEDOUT	timeout occurred (for future)
+ *   %-ETIMEDOUT	timeout occurred
  *   0			success
  */
 int ssp_write_word(u16 data)
 {
-	while (!(Ser4SSSR & SSSR_TNF))
+	int timeout = TIMEOUT;
+
+	while (!(Ser4SSSR & SSSR_TNF)) {
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
 		cpu_relax();
+	}
 
 	Ser4SSDR = data;
 
-	while (!(Ser4SSSR & SSSR_BSY))
+	timeout = TIMEOUT;
+	while (!(Ser4SSSR & SSSR_BSY)) {
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
 		cpu_relax();
+	}
 
 	return 0;
 }
@@ -75,15 +86,22 @@
  * The caller is expected to perform the necessary locking.
  *
  * Returns:
- *   %-ETIMEDOUT	timeout occurred (for future)
+ *   %-ETIMEDOUT	timeout occurred
  *   16-bit data	success
  */
-int ssp_read_word(void)
+int ssp_read_word(u16 *data)
 {
-	while (!(Ser4SSSR & SSSR_RNE))
-		cpu_relax();
+	int timeout = TIMEOUT;
 
-	return Ser4SSDR;
+	while (!(Ser4SSSR & SSSR_RNE)) {
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	*data = (u16)Ser4SSDR;
+
+	return 0;
 }
 
 /**
@@ -93,14 +111,26 @@
  * is empty.
  *
  * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ *   %-ETIMEDOUT	timeout occurred
+ *   0			success
  */
-void ssp_flush(void)
+int ssp_flush(void)
 {
+	int timeout = TIMEOUT * 2;
+
 	do {
 		while (Ser4SSSR & SSSR_RNE) {
+		        if (!--timeout)
+		        	return -ETIMEDOUT;
 			(void) Ser4SSDR;
 		}
+	        if (!--timeout)
+	        	return -ETIMEDOUT;
 	} while (Ser4SSSR & SSSR_BSY);
+
+	return 0;
 }
 
 /**
diff --git a/arch/arm/mach-shark/irq.c b/arch/arm/mach-shark/irq.c
index 6cb67bd..b227052 100644
--- a/arch/arm/mach-shark/irq.c
+++ b/arch/arm/mach-shark/irq.c
@@ -69,7 +69,8 @@
 
 static struct irqaction cascade;
 
-static struct irqchip fb_chip = {
+static struct irq_chip fb_chip = {
+	.name	= "XT-PIC",
 	.ack	= shark_ack_8259A_irq,
 	.mask	= shark_disable_8259A_irq,
 	.unmask = shark_enable_8259A_irq,
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 8643771..f2bbef0 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -69,7 +69,8 @@
 	writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
 }
 
-static struct irqchip sic_chip = {
+static struct irq_chip sic_chip = {
+	.name	= "SIC",
 	.ack	= sic_mask_irq,
 	.mask	= sic_mask_irq,
 	.unmask	= sic_unmask_irq,
@@ -284,7 +285,7 @@
 
 static struct resource versatile_flash_resource = {
 	.start			= VERSATILE_FLASH_BASE,
-	.end			= VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE,
+	.end			= VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
 	.flags			= IORESOURCE_MEM,
 };
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 5f80f18..b4f220dd 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -46,7 +46,7 @@
 config CPU_ARM720T
 	bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
 	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
-	select CPU_32v4
+	select CPU_32v4T
 	select CPU_ABRT_LV4T
 	select CPU_CACHE_V4
 	select CPU_CACHE_VIVT
@@ -64,7 +64,7 @@
 	bool "Support ARM920T processor"
 	depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
 	default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
-	select CPU_32v4
+	select CPU_32v4T
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
@@ -85,7 +85,7 @@
 	bool "Support ARM922T processor" if ARCH_INTEGRATOR
 	depends on ARCH_LH7A40X || ARCH_INTEGRATOR
 	default y if ARCH_LH7A40X
-	select CPU_32v4
+	select CPU_32v4T
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
@@ -104,7 +104,7 @@
  	bool "Support ARM925T processor" if ARCH_OMAP1
  	depends on ARCH_OMAP15XX
  	default y if ARCH_OMAP15XX
-	select CPU_32v4
+	select CPU_32v4T
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
 	select CPU_CACHE_VIVT
@@ -285,6 +285,11 @@
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
 
+config CPU_32v4T
+	bool
+	select TLS_REG_EMUL if SMP || !MMU
+	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+
 config CPU_32v5
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index b103e56..d438ce4 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -87,6 +87,32 @@
 	if (cache_is_vipt_aliasing())
 		flush_pfn_alias(pfn, user_addr);
 }
+
+void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+			 unsigned long uaddr, void *kaddr,
+			 unsigned long len, int write)
+{
+	if (cache_is_vivt()) {
+		if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
+			unsigned long addr = (unsigned long)kaddr;
+			__cpuc_coherent_kern_range(addr, addr + len);
+		}
+		return;
+	}
+
+	if (cache_is_vipt_aliasing()) {
+		flush_pfn_alias(page_to_pfn(page), uaddr);
+		return;
+	}
+
+	/* VIPT non-aliasing cache */
+	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask) &&
+	    vma->vm_flags | VM_EXEC) {
+		unsigned long addr = (unsigned long)kaddr;
+		/* only flushing the kernel mapping on non-aliasing VIPT */
+		__cpuc_coherent_kern_range(addr, addr + len);
+	}
+}
 #else
 #define flush_pfn_alias(pfn,vaddr)	do { } while (0)
 #endif
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index dba7ddd..88a999d 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -363,7 +363,9 @@
 
 void __iounmap(void __iomem *addr)
 {
+#ifndef CONFIG_SMP
 	struct vm_struct **p, *tmp;
+#endif
 	unsigned int section_mapping = 0;
 
 	addr = (void __iomem *)(PAGE_MASK & (unsigned long)addr);
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 1e89d40..44a7a65 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -480,7 +480,7 @@
 	b	__arm926_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_arm926_name
 	.long	arm926_processor_functions
 	.long	v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 6c5f0fe..ab14355 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -13,6 +13,7 @@
 #include <asm/cacheflush.h>
 #include <asm/proc-fns.h>
 #include <asm/tlbflush.h>
+#include <asm/page.h>
 
 #ifndef MULTI_CPU
 EXPORT_SYMBOL(cpu_dcache_clean_area);
@@ -30,6 +31,13 @@
 EXPORT_SYMBOL(cpu_cache);
 #endif
 
+#ifndef MULTI_USER
+EXPORT_SYMBOL(__cpu_clear_user_page);
+EXPORT_SYMBOL(__cpu_copy_user_page);
+#else
+EXPORT_SYMBOL(cpu_user);
+#endif
+
 /*
  * No module should need to touch the TLB (and currently
  * no modules do.  We export this for "loadkernel" support
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5215386..561bff7 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -536,6 +536,11 @@
 	.asciz	"XScale-80200"
 	.size	cpu_80200_name, . - cpu_80200_name
 
+	.type	cpu_80219_name, #object
+cpu_80219_name:
+	.asciz	"XScale-80219"
+	.size	cpu_80219_name, . - cpu_80219_name
+
 	.type	cpu_8032x_name, #object
 cpu_8032x_name:
 	.asciz	"XScale-IOP8032x Family"
@@ -613,10 +618,33 @@
 	.long	xscale_cache_fns
 	.size	__80200_proc_info, . - __80200_proc_info
 
+	.type	__80219_proc_info,#object
+__80219_proc_info:
+	.long	0x69052e20
+	.long	0xffffffe0
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_BUFFERABLE | \
+		PMD_SECT_CACHEABLE | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	.long   PMD_TYPE_SECT | \
+		PMD_SECT_AP_WRITE | \
+		PMD_SECT_AP_READ
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_80219_name
+	.long	xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size	__80219_proc_info, . - __80219_proc_info
+
 	.type	__8032x_proc_info,#object
 __8032x_proc_info:
 	.long	0x69052420
-	.long	0xfffff5e0      @ mask should accomodate IOP80219 also
+	.long	0xffffffe0
 	.long   PMD_TYPE_SECT | \
 		PMD_SECT_BUFFERABLE | \
 		PMD_SECT_CACHEABLE | \
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index fec7970..cd7f973 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -944,7 +944,8 @@
 	_set_gpio_irqenable(bank, gpio, 1);
 }
 
-static struct irqchip gpio_irq_chip = {
+static struct irq_chip gpio_irq_chip = {
+	.name		= "GPIO",
 	.ack		= gpio_ack_irq,
 	.mask		= gpio_mask_irq,
 	.unmask		= gpio_unmask_irq,
@@ -952,10 +953,11 @@
 	.set_wake	= gpio_wake_enable,
 };
 
-static struct irqchip mpuio_irq_chip = {
+static struct irq_chip mpuio_irq_chip = {
+	.name	= "MPUIO",
 	.ack	= mpuio_ack_irq,
 	.mask	= mpuio_mask_irq,
-	.unmask = mpuio_unmask_irq
+	.unmask	= mpuio_unmask_irq
 };
 
 static int initialized;
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 4b97950..96fdf30 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -156,7 +156,7 @@
 };
 
 extern s32 vfp_get_float(unsigned int reg);
-extern void vfp_put_float(unsigned int reg, s32 val);
+extern void vfp_put_float(s32 val, unsigned int reg);
 
 /*
  * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
@@ -267,7 +267,7 @@
  */
 #define VFP_REG_ZERO	16
 extern u64 vfp_get_double(unsigned int reg);
-extern void vfp_put_double(unsigned int reg, u64 val);
+extern void vfp_put_double(u64 val, unsigned int reg);
 
 #define VFP_DOUBLE_MANTISSA_BITS	(52)
 #define VFP_DOUBLE_EXPONENT_BITS	(11)
@@ -341,15 +341,17 @@
 
 u32 vfp_double_normaliseround(int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func);
 
-/*
- * System registers
- */
-extern u32 vfp_get_sys(unsigned int reg);
-extern void vfp_put_sys(unsigned int reg, u32 val);
-
 u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
 
 /*
  * A special flag to tell the normalisation code not to normalise.
  */
 #define VFP_NAN_FLAG	0x100
+
+/*
+ * A bit pattern used to indicate the initial (unset) value of the
+ * exception mask, in case nothing handles an instruction.  This
+ * doesn't include the NAN flag, which get masked out before
+ * we check for an error.
+ */
+#define VFP_EXCEPTION_ERROR	((u32)-1 & ~VFP_NAN_FLAG)
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index 009038c..add48e3 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -195,7 +195,7 @@
 		s64 d = vfp_double_pack(vd);
 		pr_debug("VFP: %s: d(d%d)=%016llx exceptions=%08x\n", func,
 			 dd, d, exceptions);
-		vfp_put_double(dd, d);
+		vfp_put_double(d, dd);
 	}
 	return exceptions;
 }
@@ -250,19 +250,19 @@
  */
 static u32 vfp_double_fabs(int dd, int unused, int dm, u32 fpscr)
 {
-	vfp_put_double(dd, vfp_double_packed_abs(vfp_get_double(dm)));
+	vfp_put_double(vfp_double_packed_abs(vfp_get_double(dm)), dd);
 	return 0;
 }
 
 static u32 vfp_double_fcpy(int dd, int unused, int dm, u32 fpscr)
 {
-	vfp_put_double(dd, vfp_get_double(dm));
+	vfp_put_double(vfp_get_double(dm), dd);
 	return 0;
 }
 
 static u32 vfp_double_fneg(int dd, int unused, int dm, u32 fpscr)
 {
-	vfp_put_double(dd, vfp_double_packed_negate(vfp_get_double(dm)));
+	vfp_put_double(vfp_double_packed_negate(vfp_get_double(dm)), dd);
 	return 0;
 }
 
@@ -287,7 +287,7 @@
 			vdp = &vfp_double_default_qnan;
 			ret = FPSCR_IOC;
 		}
-		vfp_put_double(dd, vfp_double_pack(vdp));
+		vfp_put_double(vfp_double_pack(vdp), dd);
 		return ret;
 	}
 
@@ -465,7 +465,7 @@
 	 */
 	if (tm & (VFP_INFINITY|VFP_NAN)) {
 		vsd.exponent = 255;
-		if (tm & VFP_NAN)
+		if (tm == VFP_QNAN)
 			vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
 		goto pack_nan;
 	} else if (tm & VFP_ZERO)
@@ -476,7 +476,7 @@
 	return vfp_single_normaliseround(sd, &vsd, fpscr, exceptions, "fcvts");
 
  pack_nan:
-	vfp_put_float(sd, vfp_single_pack(&vsd));
+	vfp_put_float(vfp_single_pack(&vsd), sd);
 	return exceptions;
 }
 
@@ -573,7 +573,7 @@
 
 	pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
 
-	vfp_put_float(sd, d);
+	vfp_put_float(d, sd);
 
 	return exceptions;
 }
@@ -648,7 +648,7 @@
 
 	pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
 
-	vfp_put_float(sd, (s32)d);
+	vfp_put_float((s32)d, sd);
 
 	return exceptions;
 }
@@ -1084,7 +1084,7 @@
  vdn_nan:
 	exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr);
  pack:
-	vfp_put_double(dd, vfp_double_pack(&vdd));
+	vfp_put_double(vfp_double_pack(&vdd), dd);
 	return exceptions;
 
  vdm_nan:
@@ -1104,7 +1104,7 @@
 	goto pack;
 
  invalid:
-	vfp_put_double(dd, vfp_double_pack(&vfp_double_default_qnan));
+	vfp_put_double(vfp_double_pack(&vfp_double_default_qnan), dd);
 	return FPSCR_IOC;
 }
 
@@ -1127,7 +1127,7 @@
 {
 	u32 op = inst & FOP_MASK;
 	u32 exceptions = 0;
-	unsigned int dd = vfp_get_dd(inst);
+	unsigned int dest;
 	unsigned int dn = vfp_get_dn(inst);
 	unsigned int dm = vfp_get_dm(inst);
 	unsigned int vecitr, veclen, vecstride;
@@ -1137,10 +1137,20 @@
 	vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)) * 2;
 
 	/*
+	 * fcvtds takes an sN register number as destination, not dN.
+	 * It also always operates on scalars.
+	 */
+	if ((inst & FEXT_MASK) == FEXT_FCVT) {
+		veclen = 0;
+		dest = vfp_get_sd(inst);
+	} else
+		dest = vfp_get_dd(inst);
+
+	/*
 	 * If destination bank is zero, vector length is always '1'.
 	 * ARM DDI0100F C5.1.3, C5.3.2.
 	 */
-	if (FREG_BANK(dd) == 0)
+	if (FREG_BANK(dest) == 0)
 		veclen = 0;
 
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1153,16 +1163,20 @@
 	for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
 		u32 except;
 
-		if (op == FOP_EXT)
+		if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+			pr_debug("VFP: itr%d (s%u) = op[%u] (d%u)\n",
+				 vecitr >> FPSCR_LENGTH_BIT,
+				 dest, dn, dm);
+		else if (op == FOP_EXT)
 			pr_debug("VFP: itr%d (d%u) = op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dd, dn, dm);
+				 dest, dn, dm);
 		else
 			pr_debug("VFP: itr%d (d%u) = (d%u) op[%u] (d%u)\n",
 				 vecitr >> FPSCR_LENGTH_BIT,
-				 dd, dn, FOP_TO_IDX(op), dm);
+				 dest, dn, FOP_TO_IDX(op), dm);
 
-		except = fop(dd, dn, dm, fpscr);
+		except = fop(dest, dn, dm, fpscr);
 		pr_debug("VFP: itr%d: exceptions=%08x\n",
 			 vecitr >> FPSCR_LENGTH_BIT, except);
 
@@ -1180,7 +1194,7 @@
 		 * we encounter an exception.  We continue.
 		 */
 
-		dd = FREG_BANK(dd) + ((FREG_IDX(dd) + vecstride) & 6);
+		dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 6);
 		dn = FREG_BANK(dn) + ((FREG_IDX(dn) + vecstride) & 6);
 		if (FREG_BANK(dm) != 0)
 			dm = FREG_BANK(dm) + ((FREG_IDX(dm) + vecstride) & 6);
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index eb683cd..e51e667 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -178,12 +178,12 @@
 
 	.globl	vfp_put_float
 vfp_put_float:
-	add	pc, pc, r0, lsl #3
+	add	pc, pc, r1, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mcr	p10, 0, r1, c\dr, c0, 0	@ fmsr	r0, s0
+	mcr	p10, 0, r0, c\dr, c0, 0	@ fmsr	r0, s0
 	mov	pc, lr
-	mcr	p10, 0, r1, c\dr, c0, 4	@ fmsr	r0, s1
+	mcr	p10, 0, r0, c\dr, c0, 4	@ fmsr	r0, s1
 	mov	pc, lr
 	.endr
 
@@ -203,9 +203,9 @@
 
 	.globl	vfp_put_double
 vfp_put_double:
-	add	pc, pc, r0, lsl #3
+	add	pc, pc, r2, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	fmdrr	d\dr, r1, r2
+	fmdrr	d\dr, r0, r1
 	mov	pc, lr
 	.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 9d265d5..4178f6c 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -131,7 +131,7 @@
 
 	pr_debug("VFP: raising exceptions %08x\n", exceptions);
 
-	if (exceptions == (u32)-1) {
+	if (exceptions == VFP_EXCEPTION_ERROR) {
 		vfp_panic("unhandled bounce");
 		vfp_raise_sigfpe(0, regs);
 		return;
@@ -170,7 +170,7 @@
  */
 static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
 {
-	u32 exceptions = (u32)-1;
+	u32 exceptions = VFP_EXCEPTION_ERROR;
 
 	pr_debug("VFP: emulate: INST=0x%08x SCR=0x%08x\n", inst, fpscr);
 
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index dae2c2f..8f6c179 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -200,7 +200,7 @@
 		s32 d = vfp_single_pack(vs);
 		pr_debug("VFP: %s: d(s%d)=%08x exceptions=%08x\n", func,
 			 sd, d, exceptions);
-		vfp_put_float(sd, d);
+		vfp_put_float(d, sd);
 	}
 
 	return exceptions;
@@ -257,19 +257,19 @@
  */
 static u32 vfp_single_fabs(int sd, int unused, s32 m, u32 fpscr)
 {
-	vfp_put_float(sd, vfp_single_packed_abs(m));
+	vfp_put_float(vfp_single_packed_abs(m), sd);
 	return 0;
 }
 
 static u32 vfp_single_fcpy(int sd, int unused, s32 m, u32 fpscr)
 {
-	vfp_put_float(sd, m);
+	vfp_put_float(m, sd);
 	return 0;
 }
 
 static u32 vfp_single_fneg(int sd, int unused, s32 m, u32 fpscr)
 {
-	vfp_put_float(sd, vfp_single_packed_negate(m));
+	vfp_put_float(vfp_single_packed_negate(m), sd);
 	return 0;
 }
 
@@ -333,7 +333,7 @@
 			vsp = &vfp_single_default_qnan;
 			ret = FPSCR_IOC;
 		}
-		vfp_put_float(sd, vfp_single_pack(vsp));
+		vfp_put_float(vfp_single_pack(vsp), sd);
 		return ret;
 	}
 
@@ -506,7 +506,7 @@
 	 */
 	if (tm & (VFP_INFINITY|VFP_NAN)) {
 		vdd.exponent = 2047;
-		if (tm & VFP_NAN)
+		if (tm == VFP_QNAN)
 			vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
 		goto pack_nan;
 	} else if (tm & VFP_ZERO)
@@ -514,14 +514,10 @@
 	else
 		vdd.exponent = vsm.exponent + (1023 - 127);
 
-	/*
-	 * Technically, if bit 0 of dd is set, this is an invalid
-	 * instruction.  However, we ignore this for efficiency.
-	 */
 	return vfp_double_normaliseround(dd, &vdd, fpscr, exceptions, "fcvtd");
 
  pack_nan:
-	vfp_put_double(dd, vfp_double_pack(&vdd));
+	vfp_put_double(vfp_double_pack(&vdd), dd);
 	return exceptions;
 }
 
@@ -617,7 +613,7 @@
 
 	pr_debug("VFP: ftoui: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
 
-	vfp_put_float(sd, d);
+	vfp_put_float(d, sd);
 
 	return exceptions;
 }
@@ -696,7 +692,7 @@
 
 	pr_debug("VFP: ftosi: d(s%d)=%08x exceptions=%08x\n", sd, d, exceptions);
 
-	vfp_put_float(sd, (s32)d);
+	vfp_put_float((s32)d, sd);
 
 	return exceptions;
 }
@@ -1131,7 +1127,7 @@
  vsn_nan:
 	exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr);
  pack:
-	vfp_put_float(sd, vfp_single_pack(&vsd));
+	vfp_put_float(vfp_single_pack(&vsd), sd);
 	return exceptions;
 
  vsm_nan:
@@ -1151,7 +1147,7 @@
 	goto pack;
 
  invalid:
-	vfp_put_float(sd, vfp_single_pack(&vfp_single_default_qnan));
+	vfp_put_float(vfp_single_pack(&vfp_single_default_qnan), sd);
 	return FPSCR_IOC;
 }
 
@@ -1174,7 +1170,7 @@
 {
 	u32 op = inst & FOP_MASK;
 	u32 exceptions = 0;
-	unsigned int sd = vfp_get_sd(inst);
+	unsigned int dest;
 	unsigned int sn = vfp_get_sn(inst);
 	unsigned int sm = vfp_get_sm(inst);
 	unsigned int vecitr, veclen, vecstride;
@@ -1184,10 +1180,22 @@
 	vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
 
 	/*
+	 * fcvtsd takes a dN register number as destination, not sN.
+	 * Technically, if bit 0 of dd is set, this is an invalid
+	 * instruction.  However, we ignore this for efficiency.
+	 * It also only operates on scalars.
+	 */
+	if ((inst & FEXT_MASK) == FEXT_FCVT) {
+		veclen = 0;
+		dest = vfp_get_dd(inst);
+	} else
+		dest = vfp_get_sd(inst);
+
+	/*
 	 * If destination bank is zero, vector length is always '1'.
 	 * ARM DDI0100F C5.1.3, C5.3.2.
 	 */
-	if (FREG_BANK(sd) == 0)
+	if (FREG_BANK(dest) == 0)
 		veclen = 0;
 
 	pr_debug("VFP: vecstride=%u veclen=%u\n", vecstride,
@@ -1201,15 +1209,18 @@
 		s32 m = vfp_get_float(sm);
 		u32 except;
 
-		if (op == FOP_EXT)
+		if (op == FOP_EXT && (inst & FEXT_MASK) == FEXT_FCVT)
+			pr_debug("VFP: itr%d (d%u) = op[%u] (s%u=%08x)\n",
+				 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
+		else if (op == FOP_EXT)
 			pr_debug("VFP: itr%d (s%u) = op[%u] (s%u=%08x)\n",
-				 vecitr >> FPSCR_LENGTH_BIT, sd, sn, sm, m);
+				 vecitr >> FPSCR_LENGTH_BIT, dest, sn, sm, m);
 		else
 			pr_debug("VFP: itr%d (s%u) = (s%u) op[%u] (s%u=%08x)\n",
-				 vecitr >> FPSCR_LENGTH_BIT, sd, sn,
+				 vecitr >> FPSCR_LENGTH_BIT, dest, sn,
 				 FOP_TO_IDX(op), sm, m);
 
-		except = fop(sd, sn, m, fpscr);
+		except = fop(dest, sn, m, fpscr);
 		pr_debug("VFP: itr%d: exceptions=%08x\n",
 			 vecitr >> FPSCR_LENGTH_BIT, except);
 
@@ -1227,7 +1238,7 @@
 		 * we encounter an exception.  We continue.
 		 */
 
-		sd = FREG_BANK(sd) + ((FREG_IDX(sd) + vecstride) & 7);
+		dest = FREG_BANK(dest) + ((FREG_IDX(dest) + vecstride) & 7);
 		sn = FREG_BANK(sn) + ((FREG_IDX(sn) + vecstride) & 7);
 		if (FREG_BANK(sm) != 0)
 			sm = FREG_BANK(sm) + ((FREG_IDX(sm) + vecstride) & 7);
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 95a3892..a601a17 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -29,6 +29,10 @@
 	bool
 	default n
 
+config GENERIC_TIME
+	bool
+	default y
+
 config TIME_LOW_RES
 	bool
 	default y
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index d5b64e1..68a77fe 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -32,8 +32,6 @@
 
 #define TICK_SIZE (tick_nsec / 1000)
 
-extern unsigned long wall_jiffies;
-
 unsigned long __nongprelbss __clkin_clock_speed_HZ;
 unsigned long __nongprelbss __ext_bus_clock_speed_HZ;
 unsigned long __nongprelbss __res_bus_clock_speed_HZ;
@@ -145,85 +143,6 @@
 }
 
 /*
- * This version of gettimeofday has near microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-	unsigned long max_ntp_tick;
-
-	do {
-		unsigned long lost;
-
-		seq = read_seqbegin(&xtime_lock);
-
-		usec = 0;
-		lost = jiffies - wall_jiffies;
-
-		/*
-		 * If time_adjust is negative then NTP is slowing the clock
-		 * so make sure not to go into next possible interval.
-		 * Better to lose some accuracy than have time go backwards..
-		 */
-		if (unlikely(time_adjust < 0)) {
-			max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
-			usec = min(usec, max_ntp_tick);
-
-			if (lost)
-				usec += lost * max_ntp_tick;
-		}
-		else if (unlikely(lost))
-			usec += lost * (USEC_PER_SEC / HZ);
-
-		sec = xtime.tv_sec;
-		usec += (xtime.tv_nsec / 1000);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= 0 * NSEC_PER_USEC;
-	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/*
  * Scheduler clock - returns current time in nanosec units.
  */
 unsigned long long sched_clock(void)
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index daa75ce..b2751ea 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -142,6 +142,7 @@
 	  In particular, it is needed for the x440.
 
 	  If you don't have one of these computers, you should say N here.
+	  If you want to build a NUMA kernel, you must select ACPI.
 
 config X86_BIGSMP
 	bool "Support for other sub-arch SMP systems with more than 8 CPUs"
@@ -169,6 +170,7 @@
        help
           This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
 	  It is intended for a generic binary kernel.
+	  If you want a NUMA kernel, select ACPI.   We need SRAT for NUMA.
 
 config X86_ES7000
 	bool "Support for Unisys ES7000 IA32 series"
@@ -542,7 +544,7 @@
 # Common NUMA Features
 config NUMA
 	bool "Numa Memory Allocation and Scheduler Support"
-	depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
+	depends on SMP && HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT || X86_GENERICARCH) && ACPI)
 	default n if X86_PC
 	default y if (X86_NUMAQ || X86_SUMMIT)
 
@@ -672,7 +674,7 @@
 	  See <file:Documentation/mtrr.txt> for more information.
 
 config EFI
-	bool "Boot from EFI support (EXPERIMENTAL)"
+	bool "Boot from EFI support"
 	depends on ACPI
 	default n
 	---help---
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 1b452a1..ab98fc2 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -59,7 +59,8 @@
 
 export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
 
-vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
+		 $(call ld-option, -Wl$(comma)--hash-style=sysv)
 SYSCFLAGS_vsyscall-sysenter.so	= $(vsyscall-flags)
 SYSCFLAGS_vsyscall-int80.so	= $(vsyscall-flags)
 
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 0db6387..ee003bc 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -59,7 +59,7 @@
 
 #define BAD_MADT_ENTRY(entry, end) (					    \
 		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-		((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+		((acpi_table_entry_header *)entry)->length < sizeof(*entry))
 
 #define PREFIX			"ACPI: "
 
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index 9f408ee..b781b38 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -292,7 +292,10 @@
 	pushl	$3
 	call	acpi_enter_sleep_state
 	addl	$4, %esp
-	ret
+
+#	In case of S3 failure, we'll emerge here.  Jump
+# 	to ret_point to recover
+	jmp	ret_point
 	.p2align 4,,7
 ret_point:
 	call	restore_registers
diff --git a/arch/i386/kernel/audit.c b/arch/i386/kernel/audit.c
index 5a53c6f..3b97cff 100644
--- a/arch/i386/kernel/audit.c
+++ b/arch/i386/kernel/audit.c
@@ -8,13 +8,41 @@
 ~0U
 };
 
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
 static unsigned chattr_class[] = {
 #include <asm-generic/audit_change_attr.h>
 ~0U
 };
 
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
 static int __init audit_classes_init(void)
 {
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
 	return 0;
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index e44a4c6..ccc1edf 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -96,6 +96,7 @@
 
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
+	depends on PCI
 	help
 	 This add the CPUFreq driver for NatSemi Geode processors which
 	 support suspend modulation.
@@ -202,7 +203,7 @@
 config X86_LONGHAUL
 	tristate "VIA Cyrix III Longhaul"
 	select CPU_FREQ_TABLE
-	depends on BROKEN
+	depends on ACPI_PROCESSOR
 	help
 	  This adds the CPUFreq driver for VIA Samuel/CyrixIII,
 	  VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 567b39b..e6ea00e 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -384,8 +384,7 @@
 	}
 
 	/* Do initialization in ACPI core */
-	acpi_processor_preregister_performance(acpi_perf_data);
-	return 0;
+	return acpi_processor_preregister_performance(acpi_perf_data);
 }
 
 static int
@@ -568,16 +567,11 @@
 static int __init
 acpi_cpufreq_init (void)
 {
-	int                     result = 0;
-
 	dprintk("acpi_cpufreq_init\n");
 
-	result = acpi_cpufreq_early_init_acpi();
+	acpi_cpufreq_early_init_acpi();
 
-	if (!result)
- 		result = cpufreq_register_driver(&acpi_cpufreq_driver);
-	
-	return (result);
+ 	return cpufreq_register_driver(&acpi_cpufreq_driver);
 }
 
 
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 146f607..4f2c3ae 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,11 +29,13 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/pci.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
 #include <asm/io.h>
+#include <asm/acpi.h>
+#include <linux/acpi.h>
+#include <acpi/processor.h>
 
 #include "longhaul.h"
 
@@ -56,6 +58,8 @@
 static unsigned int minmult, maxmult;
 static int can_scale_voltage;
 static int vrmrev;
+static struct acpi_processor *pr = NULL;
+static struct acpi_processor_cx *cx = NULL;
 
 /* Module parameters */
 static int dont_scale_voltage;
@@ -118,84 +122,65 @@
 	return eblcr_table[invalue];
 }
 
+/* For processor with BCR2 MSR */
 
-static void do_powersaver(union msr_longhaul *longhaul,
-			unsigned int clock_ratio_index)
+static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
 {
-	struct pci_dev *dev;
-	unsigned long flags;
-	unsigned int tmp_mask;
-	int version;
-	int i;
-	u16 pci_cmd;
-	u16 cmd_state[64];
+	union msr_bcr2 bcr2;
+	u32 t;
 
-	switch (cpu_model) {
-	case CPU_EZRA_T:
-		version = 3;
-		break;
-	case CPU_NEHEMIAH:
-		version = 0xf;
-		break;
-	default:
-		return;
-	}
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	/* Enable software clock multiplier */
+	bcr2.bits.ESOFTBF = 1;
+	bcr2.bits.CLOCKMUL = clock_ratio_index;
 
-	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
-	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-	longhaul->bits.EnableSoftBusRatio = 1;
-	longhaul->bits.RevisionKey = 0;
-
-	preempt_disable();
-	local_irq_save(flags);
-
-	/*
-	 * get current pci bus master state for all devices
-	 * and clear bus master bit
-	 */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-			cmd_state[i++] = pci_cmd;
-			pci_cmd &= ~PCI_COMMAND_MASTER;
-			pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
-
-	tmp_mask=inb(0x21);	/* works on C3. save mask. */
-	outb(0xFE,0x21);	/* TMR0 only */
-	outb(0xFF,0x80);	/* delay */
-
+	/* Sync to timer tick */
 	safe_halt();
-	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	halt();
+	ACPI_FLUSH_CPU_CACHE();
+	/* Change frequency on next halt or sleep */
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);
+	/* Invoke C3 */
+	inb(cx_address);
+	/* Dummy op - must do something useless after P_LVL3 read */
+	t = inl(acpi_fadt.xpm_tmr_blk.address);
 
+	/* Disable software clock multiplier */
 	local_irq_disable();
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	bcr2.bits.ESOFTBF = 0;
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);
+}
 
-	outb(tmp_mask,0x21);	/* restore mask */
+/* For processor with Longhaul MSR */
 
-	/* restore pci bus master state for all devices */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_cmd = cmd_state[i++];
-			pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
-	local_irq_restore(flags);
-	preempt_enable();
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+{
+	union msr_longhaul longhaul;
+	u32 t;
 
-	/* disable bus ratio bit */
-	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
-	longhaul->bits.EnableSoftBusRatio = 0;
-	longhaul->bits.RevisionKey = version;
-	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+	longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
+	longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+	longhaul.bits.EnableSoftBusRatio = 1;
+
+	/* Sync to timer tick */
+	safe_halt();
+	ACPI_FLUSH_CPU_CACHE();
+	/* Change frequency on next halt or sleep */
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+	/* Invoke C3 */
+	inb(cx_address);
+	/* Dummy op - must do something useless after P_LVL3 read */
+	t = inl(acpi_fadt.xpm_tmr_blk.address);
+
+	/* Disable bus ratio bit */
+	local_irq_disable();
+	longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
+	longhaul.bits.EnableSoftBusRatio = 0;
+	longhaul.bits.EnableSoftBSEL = 0;
+	longhaul.bits.EnableSoftVID = 0;
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 }
 
 /**
@@ -209,9 +194,9 @@
 {
 	int speed, mult;
 	struct cpufreq_freqs freqs;
-	union msr_longhaul longhaul;
-	union msr_bcr2 bcr2;
 	static unsigned int old_ratio=-1;
+	unsigned long flags;
+	unsigned int pic1_mask, pic2_mask;
 
 	if (old_ratio == clock_ratio_index)
 		return;
@@ -234,6 +219,20 @@
 	dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
 			fsb, mult/10, mult%10, print_speed(speed/1000));
 
+	preempt_disable();
+	local_irq_save(flags);
+
+	pic2_mask = inb(0xA1);
+	pic1_mask = inb(0x21);	/* works on C3. save mask. */
+	outb(0xFF,0xA1);	/* Overkill */
+	outb(0xFE,0x21);	/* TMR0 only */
+
+	/* Disable bus master arbitration */
+	if (pr->flags.bm_check) {
+		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
+				  ACPI_MTX_DO_NOT_LOCK);
+	}
+
 	switch (longhaul_version) {
 
 	/*
@@ -245,20 +244,7 @@
 	 */
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		/* Enable software clock multiplier */
-		bcr2.bits.ESOFTBF = 1;
-		bcr2.bits.CLOCKMUL = clock_ratio_index;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		safe_halt();
-
-		/* Disable software clock multiplier */
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		bcr2.bits.ESOFTBF = 0;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		local_irq_enable();
+		do_longhaul1(cx->address, clock_ratio_index);
 		break;
 
 	/*
@@ -273,10 +259,22 @@
 	 * to work in practice.
 	 */
 	case TYPE_POWERSAVER:
-		do_powersaver(&longhaul, clock_ratio_index);
+		do_powersaver(cx->address, clock_ratio_index);
 		break;
 	}
 
+	/* Enable bus master arbitration */
+	if (pr->flags.bm_check) {
+		acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
+				  ACPI_MTX_DO_NOT_LOCK);
+	}
+
+	outb(pic2_mask,0xA1);	/* restore mask */
+	outb(pic1_mask,0x21);
+
+	local_irq_restore(flags);
+	preempt_enable();
+
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 }
 
@@ -324,9 +322,11 @@
 static int __init longhaul_get_ranges(void)
 {
 	unsigned long invalue;
-	unsigned int multipliers[32]= {
-		50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
-		-1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
+	unsigned int ezra_t_multipliers[32]= {
+			90,  30,  40, 100,  55,  35,  45,  95,
+			50,  70,  80,  60, 120,  75,  85,  65,
+			-1, 110, 120,  -1, 135, 115, 125, 105,
+			130, 150, 160, 140,  -1, 155,  -1, 145 };
 	unsigned int j, k = 0;
 	union msr_longhaul longhaul;
 	unsigned long lo, hi;
@@ -355,13 +355,13 @@
 			invalue = longhaul.bits.MaxMHzBR;
 			if (longhaul.bits.MaxMHzBR4)
 				invalue += 16;
-			maxmult=multipliers[invalue];
+			maxmult=ezra_t_multipliers[invalue];
 
 			invalue = longhaul.bits.MinMHzBR;
 			if (longhaul.bits.MinMHzBR4 == 1)
 				minmult = 30;
 			else
-				minmult = multipliers[invalue];
+				minmult = ezra_t_multipliers[invalue];
 			fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
 			break;
 		}
@@ -527,6 +527,18 @@
 	return calc_speed(longhaul_get_cpu_mult());
 }
 
+static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
+					  u32 nesting_level,
+					  void *context, void **return_value)
+{
+	struct acpi_device *d;
+
+	if ( acpi_bus_get_device(obj_handle, &d) ) {
+		return 0;
+	}
+	*return_value = (void *)acpi_driver_data(d);
+	return 1;
+}
 
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
@@ -534,6 +546,15 @@
 	char *cpuname=NULL;
 	int ret;
 
+	/* Check ACPI support for C3 state */
+	acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			 &longhaul_walk_callback, NULL, (void *)&pr);
+	if (pr == NULL) goto err_acpi;
+
+	cx = &pr->power.states[ACPI_STATE_C3];
+	if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
+
+	/* Now check what we have on this motherboard */
 	switch (c->x86_model) {
 	case 6:
 		cpu_model = CPU_SAMUEL;
@@ -634,6 +655,10 @@
 	cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
 
 	return 0;
+
+err_acpi:
+	printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n");
+	return -ENODEV;
 }
 
 static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
@@ -666,6 +691,18 @@
 	if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
 		return -ENODEV;
 
+#ifdef CONFIG_SMP
+	if (num_online_cpus() > 1) {
+		return -ENODEV;
+		printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
+	}
+#endif
+#ifdef CONFIG_X86_IO_APIC
+	if (cpu_has_apic) {
+		printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n");
+		return -ENODEV;
+	}
+#endif
 	switch (c->x86_model) {
 	case 6 ... 9:
 		return cpufreq_register_driver(&longhaul_driver);
@@ -699,6 +736,6 @@
 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
 MODULE_LICENSE ("GPL");
 
-module_init(longhaul_init);
+late_initcall(longhaul_init);
 module_exit(longhaul_exit);
 
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index e9f0b92..5c43be4 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -759,7 +759,7 @@
 	if (num_cache_leaves == 0)
 		return 0;
 
-	register_cpu_notifier(&cacheinfo_cpu_notifier);
+	register_hotcpu_notifier(&cacheinfo_cpu_notifier);
 
 	for_each_online_cpu(i) {
 		cacheinfo_cpu_callback(&cacheinfo_cpu_notifier, CPU_ONLINE,
diff --git a/arch/i386/kernel/cpu/mcheck/mce.h b/arch/i386/kernel/cpu/mcheck/mce.h
index dc2416d..84fd4cf 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.h
+++ b/arch/i386/kernel/cpu/mcheck/mce.h
@@ -9,6 +9,6 @@
 /* Call the installed machine check handler for this CPU setup. */
 extern fastcall void (*machine_check_vector)(struct pt_regs *, long error_code);
 
-extern int mce_disabled __initdata;
+extern int mce_disabled;
 extern int nr_mce_banks;
 
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index d9a260f..37a7d2e 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -204,7 +204,7 @@
 ENTRY(ret_from_fork)
 	CFI_STARTPROC
 	pushl %eax
-	CFI_ADJUST_CFA_OFFSET -4
+	CFI_ADJUST_CFA_OFFSET 4
 	call schedule_tail
 	GET_THREAD_INFO(%ebp)
 	popl %eax
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index eb79aa2..a6b8bd8 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -317,20 +317,14 @@
 	movl %eax,%gs
 	lldt %ax
 	cld			# gcc2 wants the direction flag cleared at all times
+	pushl %eax		# fake return address
 #ifdef CONFIG_SMP
 	movb ready, %cl
 	movb $1, ready
-	cmpb $0,%cl
-	je 1f			# the first CPU calls start_kernel
-				# all other CPUs call initialize_secondary
-	call initialize_secondary
-	jmp L6
-1:
+	cmpb $0,%cl		# the first CPU calls start_kernel
+	jne initialize_secondary # all other CPUs call initialize_secondary
 #endif /* CONFIG_SMP */
-	call start_kernel
-L6:
-	jmp L6			# main should never return here, but
-				# just in case, we know what happens.
+	jmp start_kernel
 
 /*
  * We depend on ET to be correct. This checks for 287/387.
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index c6737c3..17647a5 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -35,7 +35,7 @@
 	void __iomem* hpet_base;
 	u64 tmp;
 
-	if (!hpet_address)
+	if (!is_hpet_enabled())
 		return -ENODEV;
 
 	/* calculate the hpet address: */
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 6cb529f..5fe547c 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -82,10 +82,6 @@
 	}
 #endif
 
-	if (!irq_desc[irq].handle_irq) {
-		__do_IRQ(irq, regs);
-		goto out_exit;
-	}
 #ifdef CONFIG_4KSTACKS
 
 	curctx = (union irq_ctx *) current_thread_info();
@@ -125,7 +121,6 @@
 #endif
 		__do_IRQ(irq, regs);
 
-out_exit:
 	irq_exit();
 
 	return 1;
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index de2e16e..afe6505 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -256,11 +256,6 @@
 	int ret = 0;
 	kprobe_opcode_t *addr;
 	struct kprobe_ctlblk *kcb;
-#ifdef CONFIG_PREEMPT
-	unsigned pre_preempt_count = preempt_count();
-#else
-	unsigned pre_preempt_count = 1;
-#endif
 
 	addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
 
@@ -338,13 +333,15 @@
 		return 1;
 
 ss_probe:
-	if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
+#ifndef CONFIG_PREEMPT
+	if (p->ainsn.boostable == 1 && !p->post_handler){
 		/* Boost up -- we can execute copied instructions directly */
 		reset_current_kprobe();
 		regs->eip = (unsigned long)p->ainsn.insn;
 		preempt_enable_no_resched();
 		return 1;
 	}
+#endif
 	prepare_singlestep(p, regs);
 	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
index 511abe5..6b1ae6b 100644
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -189,14 +189,11 @@
 	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
 						relocate_new_kernel_size);
 
-	/* The segment registers are funny things, they are
-	 * automatically loaded from a table, in memory wherever you
-	 * set them to a specific selector, but this table is never
-	 * accessed again you set the segment to a different selector.
-	 *
-	 * The more common model is are caches where the behide
-	 * the scenes work is done, but is also dropped at arbitrary
-	 * times.
+	/* The segment registers are funny things, they have both a
+	 * visible and an invisible part.  Whenever the visible part is
+	 * set to a specific selector, the invisible part is loaded
+	 * with from a table in memory.  At no other time is the
+	 * descriptor table in memory accessed.
 	 *
 	 * I take advantage of this here by force loading the
 	 * segments, before I zap the gdt with an invalid value.
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2dd928a..acb3514 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -575,6 +575,7 @@
 	 */
 	touch_softlockup_watchdog();
 }
+EXPORT_SYMBOL(touch_nmi_watchdog);
 
 extern void die_nmi(struct pt_regs *, const char *msg);
 
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 923bb29..8657c73 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -690,8 +690,8 @@
 	/*
 	 * Now maybe handle debug registers and/or IO bitmaps
 	 */
-	if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
-	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+	if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
+	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
 		__switch_to_xtra(next_p, tss);
 
 	disable_tsc(prev_p, next_p);
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index f168220..345ffb7 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -956,38 +956,6 @@
 	return 0;
 }
 
- /*
-  * This function checks if the entire range <start,end> is mapped with type.
-  *
-  * Note: this function only works correct if the e820 table is sorted and
-  * not-overlapping, which is the case
-  */
-int __init
-e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
-{
-	u64 start = s;
-	u64 end = e;
-	int i;
-	for (i = 0; i < e820.nr_map; i++) {
-		struct e820entry *ei = &e820.map[i];
-		if (type && ei->type != type)
-			continue;
-		/* is the region (part) in overlap with the current region ?*/
-		if (ei->addr >= end || ei->addr + ei->size <= start)
-			continue;
-		/* if the region is at the beginning of <start,end> we move
-		 * start to the end of the region since it's ok until there
-		 */
-		if (ei->addr <= start)
-			start = ei->addr + ei->size;
-		/* if start is now at or beyond end, we're done, full
-		 * coverage */
-		if (start >= end)
-			return 1; /* we're done */
-	}
-	return 0;
-}
-
 /*
  * Find the highest page frame number we have available
  */
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 6f5fea0..f948419 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -212,14 +212,20 @@
  * then we print a warning if not, and always resync.
  */
 
-static atomic_t tsc_start_flag = ATOMIC_INIT(0);
-static atomic_t tsc_count_start = ATOMIC_INIT(0);
-static atomic_t tsc_count_stop = ATOMIC_INIT(0);
-static unsigned long long tsc_values[NR_CPUS];
+static struct {
+	atomic_t start_flag;
+	atomic_t count_start;
+	atomic_t count_stop;
+	unsigned long long values[NR_CPUS];
+} tsc __initdata = {
+	.start_flag = ATOMIC_INIT(0),
+	.count_start = ATOMIC_INIT(0),
+	.count_stop = ATOMIC_INIT(0),
+};
 
 #define NR_LOOPS 5
 
-static void __init synchronize_tsc_bp (void)
+static void __init synchronize_tsc_bp(void)
 {
 	int i;
 	unsigned long long t0;
@@ -233,7 +239,7 @@
 	/* convert from kcyc/sec to cyc/usec */
 	one_usec = cpu_khz / 1000;
 
-	atomic_set(&tsc_start_flag, 1);
+	atomic_set(&tsc.start_flag, 1);
 	wmb();
 
 	/*
@@ -250,16 +256,16 @@
 		/*
 		 * all APs synchronize but they loop on '== num_cpus'
 		 */
-		while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
+		while (atomic_read(&tsc.count_start) != num_booting_cpus()-1)
 			cpu_relax();
-		atomic_set(&tsc_count_stop, 0);
+		atomic_set(&tsc.count_stop, 0);
 		wmb();
 		/*
 		 * this lets the APs save their current TSC:
 		 */
-		atomic_inc(&tsc_count_start);
+		atomic_inc(&tsc.count_start);
 
-		rdtscll(tsc_values[smp_processor_id()]);
+		rdtscll(tsc.values[smp_processor_id()]);
 		/*
 		 * We clear the TSC in the last loop:
 		 */
@@ -269,56 +275,54 @@
 		/*
 		 * Wait for all APs to leave the synchronization point:
 		 */
-		while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
+		while (atomic_read(&tsc.count_stop) != num_booting_cpus()-1)
 			cpu_relax();
-		atomic_set(&tsc_count_start, 0);
+		atomic_set(&tsc.count_start, 0);
 		wmb();
-		atomic_inc(&tsc_count_stop);
+		atomic_inc(&tsc.count_stop);
 	}
 
 	sum = 0;
 	for (i = 0; i < NR_CPUS; i++) {
 		if (cpu_isset(i, cpu_callout_map)) {
-			t0 = tsc_values[i];
+			t0 = tsc.values[i];
 			sum += t0;
 		}
 	}
 	avg = sum;
 	do_div(avg, num_booting_cpus());
 
-	sum = 0;
 	for (i = 0; i < NR_CPUS; i++) {
 		if (!cpu_isset(i, cpu_callout_map))
 			continue;
-		delta = tsc_values[i] - avg;
+		delta = tsc.values[i] - avg;
 		if (delta < 0)
 			delta = -delta;
 		/*
 		 * We report bigger than 2 microseconds clock differences.
 		 */
 		if (delta > 2*one_usec) {
-			long realdelta;
+			long long realdelta;
+
 			if (!buggy) {
 				buggy = 1;
 				printk("\n");
 			}
 			realdelta = delta;
 			do_div(realdelta, one_usec);
-			if (tsc_values[i] < avg)
+			if (tsc.values[i] < avg)
 				realdelta = -realdelta;
 
-			if (realdelta > 0)
-				printk(KERN_INFO "CPU#%d had %ld usecs TSC "
+			if (realdelta)
+				printk(KERN_INFO "CPU#%d had %Ld usecs TSC "
 					"skew, fixed it up.\n", i, realdelta);
 		}
-
-		sum += delta;
 	}
 	if (!buggy)
 		printk("passed.\n");
 }
 
-static void __init synchronize_tsc_ap (void)
+static void __init synchronize_tsc_ap(void)
 {
 	int i;
 
@@ -327,20 +331,20 @@
 	 * this gets called, so we first wait for the BP to
 	 * finish SMP initialization:
 	 */
-	while (!atomic_read(&tsc_start_flag))
+	while (!atomic_read(&tsc.start_flag))
 		cpu_relax();
 
 	for (i = 0; i < NR_LOOPS; i++) {
-		atomic_inc(&tsc_count_start);
-		while (atomic_read(&tsc_count_start) != num_booting_cpus())
+		atomic_inc(&tsc.count_start);
+		while (atomic_read(&tsc.count_start) != num_booting_cpus())
 			cpu_relax();
 
-		rdtscll(tsc_values[smp_processor_id()]);
+		rdtscll(tsc.values[smp_processor_id()]);
 		if (i == NR_LOOPS-1)
 			write_tsc(0, 0);
 
-		atomic_inc(&tsc_count_stop);
-		while (atomic_read(&tsc_count_stop) != num_booting_cpus())
+		atomic_inc(&tsc.count_stop);
+		while (atomic_read(&tsc.count_stop) != num_booting_cpus())
 			cpu_relax();
 	}
 }
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 8705c0f..edd00f6 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -135,7 +135,7 @@
 {
 	unsigned long pc = instruction_pointer(regs);
 
-	if (in_lock_functions(pc))
+	if (!user_mode_vm(regs) && in_lock_functions(pc))
 		return *(unsigned long *)(regs->ebp + 4);
 
 	return pc;
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 313ac1f..7e9edaf 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -92,7 +92,11 @@
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
+#ifdef CONFIG_STACK_UNWIND
 static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
@@ -188,10 +192,20 @@
 				unw_ret = show_trace_unwind(&info, log_lvl);
 		}
 		if (unw_ret > 0) {
-			if (call_trace > 0)
+			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+				print_symbol("DWARF2 unwinder stuck at %s\n",
+					     UNW_PC(&info));
+				if (UNW_SP(&info) >= PAGE_OFFSET) {
+					printk("Leftover inexact backtrace:\n");
+					stack = (void *)UNW_SP(&info);
+				} else
+					printk("Full inexact backtrace again:\n");
+			} else if (call_trace >= 1)
 				return;
-			printk("%sLegacy call trace:\n", log_lvl);
-		}
+			else
+				printk("Full inexact backtrace again:\n");
+		} else
+			printk("Inexact backtrace:\n");
 	}
 
 	if (task == current) {
@@ -442,11 +456,9 @@
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
-	if (panic_on_oops) {
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
-		ssleep(5);
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
+
 	oops_exit();
 	do_exit(SIGSEGV);
 }
@@ -1232,14 +1244,18 @@
 }
 __setup("kstack=", kstack_setup);
 
+#ifdef CONFIG_STACK_UNWIND
 static int __init call_trace_setup(char *s)
 {
 	if (strcmp(s, "old") == 0)
 		call_trace = -1;
 	else if (strcmp(s, "both") == 0)
 		call_trace = 0;
-	else if (strcmp(s, "new") == 0)
+	else if (strcmp(s, "newfallback") == 0)
 		call_trace = 1;
+	else if (strcmp(s, "new") == 2)
+		call_trace = 2;
 	return 1;
 }
 __setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
index e26975f..f66cd11 100644
--- a/arch/i386/kernel/vsyscall.lds.S
+++ b/arch/i386/kernel/vsyscall.lds.S
@@ -10,6 +10,7 @@
   . = VDSO_PRELINK + SIZEOF_HEADERS;
 
   .hash           : { *(.hash) }		:text
+  .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
   .dynstr         : { *(.dynstr) }
   .gnu.version    : { *(.gnu.version) }
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 0a362e3..1220dd8 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -237,6 +237,11 @@
 		pci_probe &= ~PCI_PROBE_MMCONF;
 		return NULL;
 	}
+	/* override DMI blacklist */
+	else if (!strcmp(str, "mmconf")) {
+		pci_probe |= PCI_PROBE_MMCONF_FORCE;
+		return NULL;
+	}
 #endif
 	else if (!strcmp(str, "noacpi")) {
 		acpi_noirq_set();
diff --git a/arch/i386/pci/init.c b/arch/i386/pci/init.c
index c7650a7..51087a9 100644
--- a/arch/i386/pci/init.c
+++ b/arch/i386/pci/init.c
@@ -14,8 +14,12 @@
 #ifdef CONFIG_PCI_BIOS
 	pci_pcbios_init();
 #endif
-	if (raw_pci_ops)
-		return 0;
+	/*
+	 * don't check for raw_pci_ops here because we want pcbios as last
+	 * fallback, yet it's needed to run first to set pcibios_last_bus
+	 * in case legacy PCI probing is used. otherwise detecting peer busses
+	 * fails.
+	 */
 #ifdef CONFIG_PCI_DIRECT
 	pci_direct_init();
 #endif
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index e545b09..ef5a2fa 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -12,6 +12,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <asm/e820.h>
 #include "pci.h"
 
@@ -178,7 +179,7 @@
 				pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
 			if (addr == 0 ||
 			    readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
-				set_bit(i, fallback_slots);
+				set_bit(i + 32*k, fallback_slots);
 				printk(KERN_NOTICE
 			"PCI: No mmconfig possible on %x:%x\n", k, i);
 			}
@@ -187,9 +188,31 @@
 	}
 }
 
+static int disable_mcfg(struct dmi_system_id *d)
+{
+	printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+	pci_probe &= ~PCI_PROBE_MMCONF;
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+	/* Has broken MCFG table that makes the system hang when used */
+        {
+         .callback = disable_mcfg,
+         .ident = "Intel D3C5105 SDV",
+         .matches = {
+                     DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+                     DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+                     },
+         },
+         {}
+};
+
 void __init pci_mmcfg_init(void)
 {
-	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+	dmi_check_system(dmi_bad_mcfg);
+
+	if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
 		return;
 
 	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -198,15 +221,6 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
-	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
-			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
-				pci_mmcfg_config[0].base_address);
-		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-		return;
-	}
-
 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
 	raw_pci_ops = &pci_mmcfg;
 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index bf4e793..49a849b 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -16,7 +16,8 @@
 #define PCI_PROBE_CONF1		0x0002
 #define PCI_PROBE_CONF2		0x0004
 #define PCI_PROBE_MMCONF	0x0008
-#define PCI_PROBE_MASK		0x000f
+#define PCI_PROBE_MMCONF_FORCE	0x0010
+#define PCI_PROBE_MASK		0x00ff
 
 #define PCI_NO_SORT		0x0100
 #define PCI_BIOS_SORT		0x0200
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 47de9ee..674de89 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -258,7 +258,7 @@
 	int "Maximum number of CPUs (2-1024)"
 	range 2 1024
 	depends on SMP
-	default "64"
+	default "1024"
 	help
 	  You should set this to the number of CPUs in your system, but
 	  keep in mind that a kernel compiled for, e.g., 2 CPUs will boot but
@@ -354,7 +354,7 @@
 config NODES_SHIFT
 	int "Max num nodes shift(3-10)"
 	range 3 10
-	default "8"
+	default "10"
 	depends on NEED_MULTIPLE_NODES
 	help
 	  This option specifies the maximum number of nodes in your SSI system.
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 9ea3539..0f14a82 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -363,7 +363,7 @@
 #
 CONFIG_IDE_GENERIC=y
 CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 6cba55d..9001b3f 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -366,7 +366,7 @@
 # CONFIG_IDE_GENERIC is not set
 # CONFIG_BLK_DEV_IDEPNP is not set
 CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
index a3fe975..8f0a16a7 100644
--- a/arch/ia64/hp/sim/simscsi.c
+++ b/arch/ia64/hp/sim/simscsi.c
@@ -151,7 +151,7 @@
 simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset)
 {
 	int list_len = sc->use_sg;
-	struct scatterlist *sl = (struct scatterlist *)sc->buffer;
+	struct scatterlist *sl = (struct scatterlist *)sc->request_buffer;
 	struct disk_stat stat;
 	struct disk_req req;
 
@@ -244,7 +244,8 @@
 
 	if (scatterlen == 0)
 		memcpy(sc->request_buffer, buf, len);
-	else for (slp = (struct scatterlist *)sc->buffer; scatterlen-- > 0 && len > 0; slp++) {
+	else for (slp = (struct scatterlist *)sc->request_buffer;
+		  scatterlen-- > 0 && len > 0; slp++) {
 		unsigned thislen = min(len, slp->length);
 
 		memcpy(page_address(slp->page) + slp->offset, buf, thislen);
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
index ab94f2e..92d7d0c 100644
--- a/arch/ia64/ia32/audit.c
+++ b/arch/ia64/ia32/audit.c
@@ -9,3 +9,29 @@
 #include <asm-generic/audit_change_attr.h>
 ~0U
 };
+
+unsigned ia32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ia32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ia32_classify_syscall(unsigned syscall)
+{
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 1;
+	}
+}
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 0e4553f..ad8215a 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -45,7 +45,8 @@
 quiet_cmd_gate = GATE $@
       cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
 
-GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1
+GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
+		     $(call ld-option, -Wl$(comma)--hash-style=sysv)
 $(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
 	$(call if_changed,gate)
 
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 99761b8..0176556 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -55,7 +55,7 @@
 
 #define BAD_MADT_ENTRY(entry, end) (                                        \
 		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-		((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+		((acpi_table_entry_header *)entry)->length < sizeof(*entry))
 
 #define PREFIX			"ACPI: "
 
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
index f251293..0468255 100644
--- a/arch/ia64/kernel/audit.c
+++ b/arch/ia64/kernel/audit.c
@@ -8,19 +8,54 @@
 ~0U
 };
 
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
 static unsigned chattr_class[] = {
 #include <asm-generic/audit_change_attr.h>
 ~0U
 };
 
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_IA32_SUPPORT
+	extern int ia32_classify_syscall(unsigned);
+	if (abi == AUDIT_ARCH_I386)
+		return ia32_classify_syscall(syscall);
+#endif
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
 static int __init audit_classes_init(void)
 {
 #ifdef CONFIG_IA32_SUPPORT
 	extern __u32 ia32_dir_class[];
+	extern __u32 ia32_write_class[];
+	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
+	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
 #endif
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
 	return 0;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index e4bfa9d..bb8770a 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -632,7 +632,7 @@
 		if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT))
 			 return md;
 	}
-	return 0;
+	return NULL;
 }
 
 static efi_memory_desc_t *
@@ -652,7 +652,7 @@
 		if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
 			 return md;
 	}
-	return 0;
+	return NULL;
 }
 
 u32
@@ -923,7 +923,7 @@
 void
 efi_memmap_init(unsigned long *s, unsigned long *e)
 {
-	struct kern_memdesc *k, *prev = 0;
+	struct kern_memdesc *k, *prev = NULL;
 	u64	contig_low=0, contig_high=0;
 	u64	as, ae, lim;
 	void *efi_map_start, *efi_map_end, *p, *q;
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 12701cf..fef0657 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1605,8 +1605,8 @@
 	data8 sys_ni_syscall			// 1295 reserved for ppoll
 	data8 sys_unshare
 	data8 sys_splice
-	data8 sys_set_robust_list
-	data8 sys_get_robust_list
+	data8 sys_ni_syscall			// reserved for set_robust_list
+	data8 sys_ni_syscall			// reserved for get_robust_list
 	data8 sys_sync_file_range		// 1300
 	data8 sys_tee
 	data8 sys_vmsplice
diff --git a/arch/ia64/kernel/gate.lds.S b/arch/ia64/kernel/gate.lds.S
index cc35cdd..6d19833 100644
--- a/arch/ia64/kernel/gate.lds.S
+++ b/arch/ia64/kernel/gate.lds.S
@@ -12,6 +12,7 @@
   . = GATE_ADDR + SIZEOF_HEADERS;
 
   .hash				: { *(.hash) }				:readable
+  .gnu.hash			: { *(.gnu.hash) }
   .dynsym			: { *(.dynsym) }
   .dynstr			: { *(.dynstr) }
   .gnu.version			: { *(.gnu.version) }
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 561b8f1..44d540e 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -197,6 +197,11 @@
 	;;
 	srlz.i
 	;;
+ {
+	flushrs				// must be first insn in group
+	srlz.i
+ }
+	;;
 	/*
 	 * Save the region registers, predicate before they get clobbered
 	 */
@@ -853,7 +858,6 @@
  */
 GLOBAL_ENTRY(ia64_switch_mode_phys)
  {
-	alloc r2=ar.pfs,0,0,0,0
 	rsm psr.i | psr.ic		// disable interrupts and interrupt collection
 	mov r15=ip
  }
@@ -902,7 +906,6 @@
  */
 GLOBAL_ENTRY(ia64_switch_mode_virt)
  {
-	alloc r2=ar.pfs,0,0,0,0
 	rsm psr.i | psr.ic		// disable interrupts and interrupt collection
 	mov r15=ip
  }
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index b7cf651..3ead20f 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -62,7 +62,7 @@
 EXPORT_SYMBOL(__moddi3);
 EXPORT_SYMBOL(__umoddi3);
 
-#if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE)
+#if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
 extern void xor_ia64_2(void);
 extern void xor_ia64_3(void);
 extern void xor_ia64_4(void);
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 00d9c83..781960f 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -448,11 +448,20 @@
 	return 0;
 }
 
+void __kprobes flush_insn_slot(struct kprobe *p)
+{
+	unsigned long arm_addr;
+
+	arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
+	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
 	unsigned long addr = (unsigned long)p->addr;
 	unsigned long arm_addr = addr & ~0xFULL;
 
+	flush_insn_slot(p);
 	memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
 	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
 }
diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S
index 5018c7f..ebaf1e6 100644
--- a/arch/ia64/kernel/pal.S
+++ b/arch/ia64/kernel/pal.S
@@ -217,12 +217,7 @@
 	.body
 	;;
 	ld8 loc2 = [loc2]		// loc2 <- entry point
-	mov out0 = in0		// first argument
-	mov out1 = in1		// copy arg2
-	mov out2 = in2		// copy arg3
-	mov out3 = in3		// copy arg3
-	;;
-	mov loc3 = psr		// save psr
+	mov loc3 = psr			// save psr
 	;;
 	mov loc4=ar.rsc			// save RSE configuration
 	dep.z loc2=loc2,0,61		// convert pal entry point to physical
@@ -236,18 +231,23 @@
 	;;
 	andcm r16=loc3,r16		// removes bits to clear from psr
 	br.call.sptk.many rp=ia64_switch_mode_phys
-.ret6:
+
+	mov out0 = in0			// first argument
+	mov out1 = in1			// copy arg2
+	mov out2 = in2			// copy arg3
+	mov out3 = in3			// copy arg3
 	mov loc5 = r19
 	mov loc6 = r20
+
 	br.call.sptk.many rp=b7		// now make the call
-.ret7:
+
 	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3			// r16= original psr
 	mov r19=loc5
 	mov r20=loc6
 	br.call.sptk.many rp=ia64_switch_mode_virt	// return to virtual mode
 
-.ret8:	mov psr.l  = loc3		// restore init PSR
+	mov psr.l  = loc3		// restore init PSR
 	mov ar.pfs = loc1
 	mov rp = loc0
 	;;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 3f5bac5..0b546e2 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -566,29 +566,23 @@
 	pal_version_u_t min_ver, cur_ver;
 	char *p = page;
 
-	/* The PAL_VERSION call is advertised as being able to support
-	 * both physical and virtual mode calls. This seems to be a documentation
-	 * bug rather than firmware bug. In fact, it does only support physical mode.
-	 * So now the code reflects this fact and the pal_version() has been updated
-	 * accordingly.
-	 */
-	if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
+	if (ia64_pal_version(&min_ver, &cur_ver) != 0)
+		return 0;
 
 	p += sprintf(p,
 		     "PAL_vendor : 0x%02x (min=0x%02x)\n"
-		     "PAL_A      : %x.%x.%x (min=%x.%x.%x)\n"
-		     "PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
-		     cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor,
-
-		     cur_ver.pal_version_s.pv_pal_a_model>>4,
-		     cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev,
-		     min_ver.pal_version_s.pv_pal_a_model>>4,
-		     min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev,
-
-		     cur_ver.pal_version_s.pv_pal_b_model>>4,
-		     cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev,
-		     min_ver.pal_version_s.pv_pal_b_model>>4,
-		     min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev);
+		     "PAL_A      : %02x.%02x (min=%02x.%02x)\n"
+		     "PAL_B      : %02x.%02x (min=%02x.%02x)\n",
+		     cur_ver.pal_version_s.pv_pal_vendor,
+		     min_ver.pal_version_s.pv_pal_vendor,
+		     cur_ver.pal_version_s.pv_pal_a_model,
+		     cur_ver.pal_version_s.pv_pal_a_rev,
+		     min_ver.pal_version_s.pv_pal_a_model,
+		     min_ver.pal_version_s.pv_pal_a_rev,
+		     cur_ver.pal_version_s.pv_pal_b_model,
+		     cur_ver.pal_version_s.pv_pal_b_rev,
+		     min_ver.pal_version_s.pv_pal_b_model,
+		     min_ver.pal_version_s.pv_pal_b_rev);
 	return p - page;
 }
 
@@ -958,9 +952,9 @@
 	}
 }
 
-static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
-								unsigned long action,
-								void *hcpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static int palinfo_cpu_callback(struct notifier_block *nfb,
+					unsigned long action, void *hcpu)
 {
 	unsigned int hotcpu = (unsigned long)hcpu;
 
@@ -968,20 +962,19 @@
 	case CPU_ONLINE:
 		create_palinfo_proc_entries(hotcpu);
 		break;
-#ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 		remove_palinfo_proc_entries(hotcpu);
 		break;
-#endif
 	}
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata palinfo_cpu_notifier =
+static struct notifier_block palinfo_cpu_notifier =
 {
 	.notifier_call = palinfo_cpu_callback,
 	.priority = 0,
 };
+#endif
 
 static int __init
 palinfo_init(void)
@@ -1020,7 +1013,7 @@
 	/*
 	 * Unregister from cpu notifier callbacks
 	 */
-	unregister_cpu_notifier(&palinfo_cpu_notifier);
+	unregister_hotcpu_notifier(&palinfo_cpu_notifier);
 }
 
 module_init(palinfo_init);
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index c7ccd6e..84a7e52 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -4936,13 +4936,15 @@
 	if (likely(ctx)) {
 		DPRINT(("context unlocked\n"));
 		UNPROTECT_CTX(ctx, flags);
-		fput(file);
 	}
 
 	/* copy argument back to user, if needed */
 	if (call_made && PFM_CMD_RW_ARG(cmd) && copy_to_user(arg, args_k, base_sz*count)) ret = -EFAULT;
 
 error_args:
+	if (file)
+		fput(file);
+
 	kfree(args_k);
 
 	DPRINT(("cmd=%s ret=%ld\n", PFM_CMD_NAME(cmd), ret));
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 40722d8..9ef62a3 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -163,10 +163,25 @@
 	return retval;
 }
 
+int ia64_mmap_check(unsigned long addr, unsigned long len,
+		unsigned long flags)
+{
+	unsigned long roff;
+
+	/*
+	 * Don't permit mappings into unmapped space, the virtual page table
+	 * of a region, or across a region boundary.  Note: RGN_MAP_LIMIT is
+	 * equal to 2^n-PAGE_SIZE (for some integer n <= 61) and len > 0.
+	 */
+	roff = REGION_OFFSET(addr);
+	if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len)))
+		return -EINVAL;
+	return 0;
+}
+
 static inline unsigned long
 do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
 {
-	unsigned long roff;
 	struct file *file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -188,17 +203,6 @@
 		goto out;
 	}
 
-	/*
-	 * Don't permit mappings into unmapped space, the virtual page table of a region,
-	 * or across a region boundary.  Note: RGN_MAP_LIMIT is equal to 2^n-PAGE_SIZE
-	 * (for some integer n <= 61) and len > 0.
-	 */
-	roff = REGION_OFFSET(addr);
-	if ((len > RGN_MAP_LIMIT) || (roff > (RGN_MAP_LIMIT - len))) {
-		addr = -EINVAL;
-		goto out;
-	}
-
 	down_write(&current->mm->mmap_sem);
 	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index b146f1c..f648c61 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -67,10 +67,8 @@
 #endif
 
 	sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
-	if (!sysfs_cpus) {
-		err = -ENOMEM;
-		goto out;
-	}
+	if (!sysfs_cpus)
+		panic("kzalloc in topology_init failed - NR_CPUS too big?");
 
 	for_each_present_cpu(i) {
 		if((err = arch_register_cpu(i)))
@@ -435,7 +433,7 @@
 				(void *)(long)i);
 	}
 
-	register_cpu_notifier(&cache_cpu_notifier);
+	register_hotcpu_notifier(&cache_cpu_notifier);
 
 	return 0;
 }
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index e7bbb0f..fffa9e0 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -117,11 +117,8 @@
 	die.lock_owner = -1;
 	spin_unlock_irq(&die.lock);
 
-	if (panic_on_oops) {
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
-		ssleep(5);
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
 
   	do_exit(SIGSEGV);
 }
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 5f03b9e..4c73a67 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -32,32 +32,38 @@
 
 extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
 
-#define MAX_UNCACHED_GRANULES	5
-static int allocated_granules;
+struct uncached_pool {
+	struct gen_pool *pool;
+	struct mutex add_chunk_mutex;	/* serialize adding a converted chunk */
+	int nchunks_added;		/* #of converted chunks added to pool */
+	atomic_t status;		/* smp called function's return status*/
+};
 
-struct gen_pool *uncached_pool[MAX_NUMNODES];
+#define MAX_CONVERTED_CHUNKS_PER_NODE	2
+
+struct uncached_pool uncached_pools[MAX_NUMNODES];
 
 
 static void uncached_ipi_visibility(void *data)
 {
 	int status;
+	struct uncached_pool *uc_pool = (struct uncached_pool *)data;
 
 	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
 	if ((status != PAL_VISIBILITY_OK) &&
 	    (status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
-		printk(KERN_DEBUG "pal_prefetch_visibility() returns %i on "
-		       "CPU %i\n", status, raw_smp_processor_id());
+		atomic_inc(&uc_pool->status);
 }
 
 
 static void uncached_ipi_mc_drain(void *data)
 {
 	int status;
+	struct uncached_pool *uc_pool = (struct uncached_pool *)data;
 
 	status = ia64_pal_mc_drain();
-	if (status)
-		printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
-		       "CPU %i\n", status, raw_smp_processor_id());
+	if (status != PAL_STATUS_SUCCESS)
+		atomic_inc(&uc_pool->status);
 }
 
 
@@ -70,21 +76,34 @@
  * This is accomplished by first allocating a granule of cached memory pages
  * and then converting them to uncached memory pages.
  */
-static int uncached_add_chunk(struct gen_pool *pool, int nid)
+static int uncached_add_chunk(struct uncached_pool *uc_pool, int nid)
 {
 	struct page *page;
-	int status, i;
+	int status, i, nchunks_added = uc_pool->nchunks_added;
 	unsigned long c_addr, uc_addr;
 
-	if (allocated_granules >= MAX_UNCACHED_GRANULES)
+	if (mutex_lock_interruptible(&uc_pool->add_chunk_mutex) != 0)
+		return -1;	/* interrupted by a signal */
+
+	if (uc_pool->nchunks_added > nchunks_added) {
+		/* someone added a new chunk while we were waiting */
+		mutex_unlock(&uc_pool->add_chunk_mutex);
+		return 0;
+	}
+
+	if (uc_pool->nchunks_added >= MAX_CONVERTED_CHUNKS_PER_NODE) {
+		mutex_unlock(&uc_pool->add_chunk_mutex);
 		return -1;
+	}
 
 	/* attempt to allocate a granule's worth of cached memory pages */
 
 	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
 				IA64_GRANULE_SHIFT-PAGE_SHIFT);
-	if (!page)
+	if (!page) {
+		mutex_unlock(&uc_pool->add_chunk_mutex);
 		return -1;
+	}
 
 	/* convert the memory pages from cached to uncached */
 
@@ -102,11 +121,14 @@
 	flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE);
 
 	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
-	if (!status) {
-		status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
-		if (status)
+	if (status == PAL_VISIBILITY_OK_REMOTE_NEEDED) {
+		atomic_set(&uc_pool->status, 0);
+		status = smp_call_function(uncached_ipi_visibility, uc_pool,
+					   0, 1);
+		if (status || atomic_read(&uc_pool->status))
 			goto failed;
-	}
+	} else if (status != PAL_VISIBILITY_OK)
+		goto failed;
 
 	preempt_disable();
 
@@ -120,20 +142,24 @@
 
 	preempt_enable();
 
-	ia64_pal_mc_drain();
-	status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
-	if (status)
+	status = ia64_pal_mc_drain();
+	if (status != PAL_STATUS_SUCCESS)
+		goto failed;
+	atomic_set(&uc_pool->status, 0);
+	status = smp_call_function(uncached_ipi_mc_drain, uc_pool, 0, 1);
+	if (status || atomic_read(&uc_pool->status))
 		goto failed;
 
 	/*
 	 * The chunk of memory pages has been converted to uncached so now we
 	 * can add it to the pool.
 	 */
-	status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid);
+	status = gen_pool_add(uc_pool->pool, uc_addr, IA64_GRANULE_SIZE, nid);
 	if (status)
 		goto failed;
 
-	allocated_granules++;
+	uc_pool->nchunks_added++;
+	mutex_unlock(&uc_pool->add_chunk_mutex);
 	return 0;
 
 	/* failed to convert or add the chunk so give it back to the kernel */
@@ -142,6 +168,7 @@
 		ClearPageUncached(&page[i]);
 
 	free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
+	mutex_unlock(&uc_pool->add_chunk_mutex);
 	return -1;
 }
 
@@ -158,7 +185,7 @@
 unsigned long uncached_alloc_page(int starting_nid)
 {
 	unsigned long uc_addr;
-	struct gen_pool *pool;
+	struct uncached_pool *uc_pool;
 	int nid;
 
 	if (unlikely(starting_nid >= MAX_NUMNODES))
@@ -171,14 +198,14 @@
 	do {
 		if (!node_online(nid))
 			continue;
-		pool = uncached_pool[nid];
-		if (pool == NULL)
+		uc_pool = &uncached_pools[nid];
+		if (uc_pool->pool == NULL)
 			continue;
 		do {
-			uc_addr = gen_pool_alloc(pool, PAGE_SIZE);
+			uc_addr = gen_pool_alloc(uc_pool->pool, PAGE_SIZE);
 			if (uc_addr != 0)
 				return uc_addr;
-		} while (uncached_add_chunk(pool, nid) == 0);
+		} while (uncached_add_chunk(uc_pool, nid) == 0);
 
 	} while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
 
@@ -197,7 +224,7 @@
 void uncached_free_page(unsigned long uc_addr)
 {
 	int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
-	struct gen_pool *pool = uncached_pool[nid];
+	struct gen_pool *pool = uncached_pools[nid].pool;
 
 	if (unlikely(pool == NULL))
 		return;
@@ -224,7 +251,7 @@
 					unsigned long uc_end, void *arg)
 {
 	int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
-	struct gen_pool *pool = uncached_pool[nid];
+	struct gen_pool *pool = uncached_pools[nid].pool;
 	size_t size = uc_end - uc_start;
 
 	touch_softlockup_watchdog();
@@ -242,7 +269,8 @@
 	int nid;
 
 	for_each_online_node(nid) {
-		uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid);
+		uncached_pools[nid].pool = gen_pool_create(PAGE_SHIFT, nid);
+		mutex_init(&uncached_pools[nid].add_chunk_mutex);
 	}
 
 	efi_memmap_walk_uc(uncached_build_memmap, NULL);
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index d8536a2..38fa6e4 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -14,7 +14,7 @@
 lib-$(CONFIG_ITANIUM)	+= copy_page.o copy_user.o memcpy.o
 lib-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
 lib-$(CONFIG_PERFMON)	+= carta_random.o
-lib-$(CONFIG_MD_RAID5)	+= xor.o
+lib-$(CONFIG_MD_RAID456)	+= xor.o
 
 AFLAGS___divdi3.o	=
 AFLAGS___udivdi3.o	= -DUNSIGNED
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 2a88cdd..e004143 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -27,6 +27,7 @@
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 static unsigned long num_dma_physpages;
+static unsigned long max_gap;
 #endif
 
 /**
@@ -45,9 +46,15 @@
 
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	i = max_mapnr;
-	while (i-- > 0) {
-		if (!pfn_valid(i))
+	for (i = 0; i < max_mapnr; i++) {
+		if (!pfn_valid(i)) {
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+			if (max_gap < LARGE_GAP)
+				continue;
+			i = vmemmap_find_next_valid_pfn(0, i) - 1;
+#endif
 			continue;
+		}
 		total++;
 		if (PageReserved(mem_map+i))
 			reserved++;
@@ -234,7 +241,6 @@
 	unsigned long zones_size[MAX_NR_ZONES];
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 	unsigned long zholes_size[MAX_NR_ZONES];
-	unsigned long max_gap;
 #endif
 
 	/* initialize mem_map[] */
@@ -266,7 +272,6 @@
 		}
 	}
 
-	max_gap = 0;
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 	if (max_gap < LARGE_GAP) {
 		vmem_map = (struct page *) 0;
@@ -277,7 +282,8 @@
 
 		/* allocate virtual_mem_map */
 
-		map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+		map_size = PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+			sizeof(struct page));
 		vmalloc_end -= map_size;
 		vmem_map = (struct page *) vmalloc_end;
 		efi_memmap_walk(create_mem_map_page_table, NULL);
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 99bd9e3..d260bff 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -534,68 +534,6 @@
 }
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
-{
-	unsigned long end_address, hole_next_pfn;
-	unsigned long stop_address;
-
-	end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
-	end_address = PAGE_ALIGN(end_address);
-
-	stop_address = (unsigned long) &vmem_map[
-		pgdat->node_start_pfn + pgdat->node_spanned_pages];
-
-	do {
-		pgd_t *pgd;
-		pud_t *pud;
-		pmd_t *pmd;
-		pte_t *pte;
-
-		pgd = pgd_offset_k(end_address);
-		if (pgd_none(*pgd)) {
-			end_address += PGDIR_SIZE;
-			continue;
-		}
-
-		pud = pud_offset(pgd, end_address);
-		if (pud_none(*pud)) {
-			end_address += PUD_SIZE;
-			continue;
-		}
-
-		pmd = pmd_offset(pud, end_address);
-		if (pmd_none(*pmd)) {
-			end_address += PMD_SIZE;
-			continue;
-		}
-
-		pte = pte_offset_kernel(pmd, end_address);
-retry_pte:
-		if (pte_none(*pte)) {
-			end_address += PAGE_SIZE;
-			pte++;
-			if ((end_address < stop_address) &&
-			    (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
-				goto retry_pte;
-			continue;
-		}
-		/* Found next valid vmem_map page */
-		break;
-	} while (end_address < stop_address);
-
-	end_address = min(end_address, stop_address);
-	end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
-	hole_next_pfn = end_address / sizeof(struct page);
-	return hole_next_pfn - pgdat->node_start_pfn;
-}
-#else
-static inline int find_next_valid_pfn_for_pgdat(pg_data_t *pgdat, int i)
-{
-	return i + 1;
-}
-#endif
-
 /**
  * show_mem - give short summary of memory stats
  *
@@ -625,7 +563,8 @@
 			if (pfn_valid(pgdat->node_start_pfn + i))
 				page = pfn_to_page(pgdat->node_start_pfn + i);
 			else {
-				i = find_next_valid_pfn_for_pgdat(pgdat, i) - 1;
+				i = vmemmap_find_next_valid_pfn(pgdat->node_id,
+					 i) - 1;
 				continue;
 			}
 			if (PageReserved(page))
@@ -751,7 +690,8 @@
 	efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-	vmalloc_end -= PAGE_ALIGN(max_low_pfn * sizeof(struct page));
+	vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
+		sizeof(struct page));
 	vmem_map = (struct page *) vmalloc_end;
 	efi_memmap_walk(create_mem_map_page_table, NULL);
 	printk("Virtual mem_map starts at 0x%p\n", vmem_map);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 2f50c06..30617cc 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -415,6 +415,61 @@
 }
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
+int vmemmap_find_next_valid_pfn(int node, int i)
+{
+	unsigned long end_address, hole_next_pfn;
+	unsigned long stop_address;
+	pg_data_t *pgdat = NODE_DATA(node);
+
+	end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i];
+	end_address = PAGE_ALIGN(end_address);
+
+	stop_address = (unsigned long) &vmem_map[
+		pgdat->node_start_pfn + pgdat->node_spanned_pages];
+
+	do {
+		pgd_t *pgd;
+		pud_t *pud;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		pgd = pgd_offset_k(end_address);
+		if (pgd_none(*pgd)) {
+			end_address += PGDIR_SIZE;
+			continue;
+		}
+
+		pud = pud_offset(pgd, end_address);
+		if (pud_none(*pud)) {
+			end_address += PUD_SIZE;
+			continue;
+		}
+
+		pmd = pmd_offset(pud, end_address);
+		if (pmd_none(*pmd)) {
+			end_address += PMD_SIZE;
+			continue;
+		}
+
+		pte = pte_offset_kernel(pmd, end_address);
+retry_pte:
+		if (pte_none(*pte)) {
+			end_address += PAGE_SIZE;
+			pte++;
+			if ((end_address < stop_address) &&
+			    (end_address != ALIGN(end_address, 1UL << PMD_SHIFT)))
+				goto retry_pte;
+			continue;
+		}
+		/* Found next valid vmem_map page */
+		break;
+	} while (end_address < stop_address);
+
+	end_address = min(end_address, stop_address);
+	end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1;
+	hole_next_pfn = end_address / sizeof(struct page);
+	return hole_next_pfn - pgdat->node_start_pfn;
+}
 
 int __init
 create_mem_map_page_table (u64 start, u64 end, void *arg)
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 07bd02b..4280c07 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -32,7 +32,7 @@
 	 */
 	attr = kern_mem_attribute(offset, size);
 	if (attr & EFI_MEMORY_WB)
-		return phys_to_virt(offset);
+		return (void __iomem *) phys_to_virt(offset);
 	else if (attr & EFI_MEMORY_UC)
 		return __ioremap(offset, size);
 
@@ -43,7 +43,7 @@
 	gran_base = GRANULEROUNDDOWN(offset);
 	gran_size = GRANULEROUNDUP(offset + size) - gran_base;
 	if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
-		return phys_to_virt(offset);
+		return (void __iomem *) phys_to_virt(offset);
 
 	return __ioremap(offset, size);
 }
@@ -53,7 +53,7 @@
 ioremap_nocache (unsigned long offset, unsigned long size)
 {
 	if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
-		return 0;
+		return NULL;
 
 	return __ioremap(offset, size);
 }
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index c119e8b..5f2dcba 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -565,7 +565,7 @@
  * Also sets up a few fields in the nodepda.  Also known as
  * platform_cpu_init() by the ia64 machvec code.
  */
-void __init sn_cpu_init(void)
+void __cpuinit sn_cpu_init(void)
 {
 	int cpuid;
 	int cpuphyid;
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index c2f69f7..1f35408 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -279,8 +279,8 @@
 		return part->reason;
 	}
 
-	bte_ret = xp_bte_copy((u64) src, (u64) ia64_tpa((u64) dst),
-				(u64) cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL);
+	bte_ret = xp_bte_copy((u64) src, (u64) dst, (u64) cnt,
+					(BTE_NORMAL | BTE_WACQUIRE), NULL);
 	if (bte_ret == BTE_SUCCESS) {
 		return xpcSuccess;
 	}
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 99b123a..4d026f9 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -480,7 +480,7 @@
 	partid_t partid = (u64) __partid;
 	struct xpc_partition *part = &xpc_partitions[partid];
 	unsigned long irq_flags;
-	struct sched_param param = { sched_priority: MAX_RT_PRIO - 1 };
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
 	int ret;
 
 
@@ -1052,6 +1052,8 @@
 	if (xpc_sysctl) {
 		unregister_sysctl_table(xpc_sysctl);
 	}
+
+	kfree(xpc_remote_copy_buffer_base);
 }
 
 
@@ -1212,24 +1214,20 @@
 	partid_t partid;
 	struct xpc_partition *part;
 	pid_t pid;
+	size_t buf_size;
 
 
 	if (!ia64_platform_is("sn2")) {
 		return -ENODEV;
 	}
 
-	/*
-	 * xpc_remote_copy_buffer is used as a temporary buffer for bte_copy'ng
-	 * various portions of a partition's reserved page. Its size is based
-	 * on the size of the reserved page header and part_nasids mask. So we
-	 * need to ensure that the other items will fit as well.
-	 */
-	if (XPC_RP_VARS_SIZE > XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES) {
-		dev_err(xpc_part, "xpc_remote_copy_buffer is not big enough\n");
-		return -EPERM;
-	}
-	DBUG_ON((u64) xpc_remote_copy_buffer !=
-				L1_CACHE_ALIGN((u64) xpc_remote_copy_buffer));
+
+	buf_size = max(XPC_RP_VARS_SIZE,
+				XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES);
+	xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size,
+				     GFP_KERNEL, &xpc_remote_copy_buffer_base);
+	if (xpc_remote_copy_buffer == NULL)
+		return -ENOMEM;
 
 	snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part");
 	snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan");
@@ -1293,6 +1291,8 @@
 		if (xpc_sysctl) {
 			unregister_sysctl_table(xpc_sysctl);
 		}
+
+		kfree(xpc_remote_copy_buffer_base);
 		return -EBUSY;
 	}
 
@@ -1311,6 +1311,8 @@
 		if (xpc_sysctl) {
 			unregister_sysctl_table(xpc_sysctl);
 		}
+
+		kfree(xpc_remote_copy_buffer_base);
 		return -EBUSY;
 	}
 
@@ -1362,6 +1364,8 @@
 		if (xpc_sysctl) {
 			unregister_sysctl_table(xpc_sysctl);
 		}
+
+		kfree(xpc_remote_copy_buffer_base);
 		return -EBUSY;
 	}
 
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 2a89cfc..57c723f 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -71,19 +71,15 @@
  * Generic buffer used to store a local copy of portions of a remote
  * partition's reserved page (either its header and part_nasids mask,
  * or its vars).
- *
- * xpc_discovery runs only once and is a seperate thread that is
- * very likely going to be processing in parallel with receiving
- * interrupts.
  */
-char ____cacheline_aligned xpc_remote_copy_buffer[XPC_RP_HEADER_SIZE +
-							XP_NASID_MASK_BYTES];
+char *xpc_remote_copy_buffer;
+void *xpc_remote_copy_buffer_base;
 
 
 /*
  * Guarantee that the kmalloc'd memory is cacheline aligned.
  */
-static void *
+void *
 xpc_kmalloc_cacheline_aligned(size_t size, gfp_t flags, void **base)
 {
 	/* see if kmalloc will give us cachline aligned memory by default */
@@ -148,7 +144,7 @@
 			}
 		}
 
-		bte_res = xp_bte_copy(rp_pa, ia64_tpa(buf), buf_len,
+		bte_res = xp_bte_copy(rp_pa, buf, buf_len,
 					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 		if (bte_res != BTE_SUCCESS) {
 			dev_dbg(xpc_part, "xp_bte_copy failed %i\n", bte_res);
@@ -447,7 +443,7 @@
 
 		/* pull the remote_hb cache line */
 		bres = xp_bte_copy(part->remote_vars_pa,
-					ia64_tpa((u64) remote_vars),
+					(u64) remote_vars,
 					XPC_RP_VARS_SIZE,
 					(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 		if (bres != BTE_SUCCESS) {
@@ -498,8 +494,7 @@
 
 
 	/* pull over the reserved page header and part_nasids mask */
-
-	bres = xp_bte_copy(*remote_rp_pa, ia64_tpa((u64) remote_rp),
+	bres = xp_bte_copy(*remote_rp_pa, (u64) remote_rp,
 				XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes,
 				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 	if (bres != BTE_SUCCESS) {
@@ -554,11 +549,8 @@
 		return xpcVarsNotSet;
 	}
 
-
 	/* pull over the cross partition variables */
-
-	bres = xp_bte_copy(remote_vars_pa, ia64_tpa((u64) remote_vars),
-				XPC_RP_VARS_SIZE,
+	bres = xp_bte_copy(remote_vars_pa, (u64) remote_vars, XPC_RP_VARS_SIZE,
 				(BTE_NOTIFY | BTE_WACQUIRE), NULL);
 	if (bres != BTE_SUCCESS) {
 		return xpc_map_bte_errors(bres);
@@ -1239,7 +1231,7 @@
 
 	part_nasid_pa = (u64) XPC_RP_PART_NASIDS(part->remote_rp_pa);
 
-	bte_res = xp_bte_copy(part_nasid_pa, ia64_tpa((u64) nasid_mask),
+	bte_res = xp_bte_copy(part_nasid_pa, (u64) nasid_mask,
 			xp_nasid_mask_bytes, (BTE_NOTIFY | BTE_WACQUIRE), NULL);
 
 	return xpc_map_bte_errors(bte_res);
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 17cd342..af7171a 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -74,7 +74,7 @@
 		else
 			mmr_war_offset = 0x158;
 
-		readq_relaxed((void *)(mmr_base + mmr_war_offset));
+		readq_relaxed((void __iomem *)(mmr_base + mmr_war_offset));
 	}
 }
 
@@ -92,8 +92,8 @@
 
 	if (mmr_offset < 0x45000) {
 		if (mmr_offset == 0x100)
-			readq_relaxed((void *)(mmr_base + 0x38));
-		readq_relaxed((void *)(mmr_base + 0xb050));
+			readq_relaxed((void __iomem *)(mmr_base + 0x38));
+		readq_relaxed((void __iomem *)(mmr_base + 0xb050));
 	}
 }
 
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 9989495..b3677fc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -204,6 +204,7 @@
 	*(.dynstr)
 	*(.dynamic)
 	*(.hash)
+	*(.gnu.hash)
 #endif
 	}
 
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 2643dbc..4d4b6fb 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -354,6 +354,7 @@
 config PPC_PSERIES
 	depends on PPC_MULTIPLATFORM && PPC64
 	bool "IBM pSeries & new (POWER5-based) iSeries"
+	select MPIC
 	select PPC_I8259
 	select PPC_RTAS
 	select RTAS_ERROR_LOGGING
@@ -363,6 +364,7 @@
 config PPC_CHRP
 	bool "Common Hardware Reference Platform (CHRP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32
+	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
 	select PPC_RTAS
@@ -373,6 +375,7 @@
 config PPC_PMAC
 	bool "Apple PowerMac based machines"
 	depends on PPC_MULTIPLATFORM
+	select MPIC
 	select PPC_INDIRECT_PCI if PPC32
 	select PPC_MPC106 if PPC32
 	default y
@@ -380,6 +383,7 @@
 config PPC_PMAC64
 	bool
 	depends on PPC_PMAC && POWER4
+	select MPIC
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
@@ -389,6 +393,7 @@
 config PPC_PREP
 	bool "PowerPC Reference Platform (PReP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
+	select MPIC
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
 	select PPC_UDBG_16550
@@ -397,6 +402,7 @@
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM && PPC64
 	bool "Maple 970FX Evaluation Board"
+	select MPIC
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
@@ -439,12 +445,6 @@
 	depends on PPC_MULTIPLATFORM && PPC64
 	default n
 
-config MPIC
-	depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \
-			       || MPC7448HPC2
-	bool
-	default y
-
 config PPC_RTAS
 	bool
 	default n
@@ -504,7 +504,7 @@
 
 config CPU_FREQ_PMAC64
 	bool "Support for some Apple G5s"
-	depends on CPU_FREQ && PMAC_SMU && PPC64
+	depends on CPU_FREQ && PPC64
 	select CPU_FREQ_TABLE
 	help
 	  This adds support for frequency switching on Apple iMac G5,
@@ -812,6 +812,14 @@
 	depends on PPC64 || POWER4 || 6xx && !CPM2
 	default y
 
+config MPIC
+	bool
+	default n
+
+config MPIC_WEIRD
+	bool
+	default n
+
 config PPC_I8259
 	bool
 	default n
@@ -836,9 +844,10 @@
 	bool
 
 config PCI
-	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) \
-				  || MPC7448HPC2
-	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx
+	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
+		|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2
+	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
+		&& !PPC_85xx && !PPC_86xx
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	help
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
new file mode 100644
index 0000000..d7b985e
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -0,0 +1,190 @@
+/*
+ * MPC7448HPC2 (Taiga) board Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ * 2006 Roy Zang <Roy Zang at freescale.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 the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+/ {
+	model = "mpc7448hpc2";
+	compatible = "mpc74xx";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells =<0>;
+		linux,phandle = <200>;
+				
+		PowerPC,7448@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K bytes
+			i-cache-size = <8000>;		// L1, 32K bytes
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			clock-frequency = <0>;		// From U-Boot
+			bus-frequency = <0>;		// From U-Boot
+			32-bit;
+			linux,phandle = <201>;
+			linux,boot-cpu;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 20000000	// DDR2   512M at 0
+		       >;
+	};
+
+  	tsi108@c0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "tsi-bridge";
+		ranges = <00000000 c0000000 00010000>;
+		reg = <c0000000 00010000>;
+		bus-frequency = <0>;
+
+		i2c@7000 {
+			interrupt-parent = <7400>;
+			interrupts = <E 0>;
+			reg = <7000 400>;
+			device_type = "i2c";
+			compatible  = "tsi-i2c";
+		};
+
+		mdio@6000 {
+			device_type = "mdio";
+			compatible = "tsi-ethernet";
+
+			ethernet-phy@6000 {
+				linux,phandle = <6000>;
+				interrupt-parent = <7400>;
+				interrupts = <2 1>;
+				reg = <6000 50>;
+				phy-id = <8>;
+				device_type = "ethernet-phy";
+			};
+
+			ethernet-phy@6400 {
+				linux,phandle = <6400>;
+				interrupt-parent = <7400>;
+				interrupts = <2 1>;
+				reg = <6000 50>;
+				phy-id = <9>;
+				device_type = "ethernet-phy";
+			};
+
+		};
+
+		ethernet@6200 {
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSI-ETH";
+			compatible = "tsi-ethernet";
+			reg = <6000 200>;
+			address = [ 00 06 D2 00 00 01 ];
+			interrupts = <10 2>;
+			interrupt-parent = <7400>;
+			phy-handle = <6000>;
+		};
+
+		ethernet@6600 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSI-ETH";
+			compatible = "tsi-ethernet";
+			reg = <6400 200>;
+			address = [ 00 06 D2 00 00 02 ];
+			interrupts = <11 2>;
+			interrupt-parent = <7400>;
+			phy-handle = <6400>;
+		};
+
+		serial@7808 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <7808 200>;
+			clock-frequency = <3f6b5a00>;
+			interrupts = <c 0>;
+			interrupt-parent = <7400>;
+		};
+
+		serial@7c08 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <7c08 200>;
+			clock-frequency = <3f6b5a00>;
+			interrupts = <d 0>;
+			interrupt-parent = <7400>;
+		};
+
+	  	pic@7400 {
+			linux,phandle = <7400>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <7400 400>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                       	big-endian;
+		};
+		pci@1000 {
+			compatible = "tsi10x";
+			device_type = "pci";
+			linux,phandle = <1000>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <1000 1000>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 e0000000 e0000000 0 1A000000	
+				  01000000 0 00000000 fa000000 0 00010000>;
+			clock-frequency = <7f28154>;
+			interrupt-parent = <7400>;
+			interrupts = <17 2>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x11 */
+				0800 0 0 1 7400 24 0
+				0800 0 0 2 7400 25 0
+				0800 0 0 3 7400 26 0
+				0800 0 0 4 7400 27 0
+
+				/* IDSEL 0x12 */
+				1000 0 0 1 7400 25 0
+				1000 0 0 2 7400 26 0
+				1000 0 0 3 7400 27 0
+				1000 0 0 4 7400 24 0
+
+				/* IDSEL 0x13 */
+				1800 0 0 1 7400 26 0
+				1800 0 0 2 7400 27 0
+				1800 0 0 3 7400 24 0
+				1800 0 0 4 7400 25 0
+
+				/* IDSEL 0x14 */
+				2000 0 0 1 7400 27 0
+				2000 0 0 2 7400 24 0
+				2000 0 0 3 7400 25 0
+				2000 0 0 4 7400 26 0
+				>;
+		};
+	};
+
+};
diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts
new file mode 100644
index 0000000..12f5dbf
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8349emds.dts
@@ -0,0 +1,328 @@
+/*
+ * MPC8349E MDS Device Tree Source
+ *
+ * Copyright 2005, 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+/ {
+	model = "MPC8349EMDS";
+	compatible = "MPC834xMDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8349@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 10000000>;	// 256MB at 0
+	};
+
+	soc8349@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00000200>;
+		bus-frequency = <0>;
+
+		wdt@200 {
+			device_type = "watchdog";
+			compatible = "mpc83xx_wdt";
+			reg = <200 100>;
+		};
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <e 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <f 8>;
+			interrupt-parent = <700>;
+			dfsrr;
+		};
+
+		spi@7000 {
+			device_type = "spi";
+			compatible = "mpc83xx_spi";
+			reg = <7000 1000>;
+			interrupts = <10 8>;
+			interrupt-parent = <700>;
+			mode = <0>;
+		};
+
+		/* phy type (ULPI or SERIAL) are only types supportted for MPH */
+		/* port = 0 or 1 */
+		usb@22000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-mph";
+			reg = <22000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <27 2>;
+			phy_type = "ulpi";
+			port1;
+		};
+		/* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */
+		usb@23000 {
+			device_type = "usb";
+			compatible = "fsl-usb2-dr";
+			reg = <23000 1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupt-parent = <700>;
+			interrupts = <26 2>;
+			phy_type = "ulpi";
+		};
+
+		mdio@24520 {
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <700>;
+				interrupts = <11 2>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <700>;
+				interrupts = <12 2>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <20 8 21 8 22 8>;
+			interrupt-parent = <700>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 00 00 00 00 00 ];
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <23 8 24 8 25 8>;
+			interrupt-parent = <700>;
+			phy-handle = <2452001>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <9 8>;
+			interrupt-parent = <700>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <a 8>;
+			interrupt-parent = <700>;
+		};
+
+		pci@8500 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 700 14 8
+					 8800 0 0 2 700 15 8
+					 8800 0 0 3 700 16 8
+					 8800 0 0 4 700 17 8
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 700 16 8
+					 9000 0 0 2 700 17 8
+					 9000 0 0 3 700 14 8
+					 9000 0 0 4 700 15 8
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 700 17 8
+					 9800 0 0 2 700 14 8
+					 9800 0 0 3 700 15 8
+					 9800 0 0 4 700 16 8
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 700 14 8
+					 a800 0 0 2 700 15 8
+					 a800 0 0 3 700 16 8
+					 a800 0 0 4 700 17 8
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 700 17 8
+					 b000 0 0 2 700 14 8
+					 b000 0 0 3 700 15 8
+					 b000 0 0 4 700 16 8
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 700 16 8
+					 b800 0 0 2 700 17 8
+					 b800 0 0 3 700 14 8
+					 b800 0 0 4 700 15 8
+
+					/* IDSEL 0x18 */
+					 b000 0 0 1 700 15 8
+					 b000 0 0 2 700 16 8
+					 b000 0 0 3 700 17 8
+					 b000 0 0 4 700 14 8>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 10000000
+				  42000000 0 80000000 80000000 0 10000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8500 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		pci@8600 {
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+					/* IDSEL 0x11 */
+					 8800 0 0 1 700 14 8
+					 8800 0 0 2 700 15 8
+					 8800 0 0 3 700 16 8
+					 8800 0 0 4 700 17 8
+
+					/* IDSEL 0x12 */
+					 9000 0 0 1 700 16 8
+					 9000 0 0 2 700 17 8
+					 9000 0 0 3 700 14 8
+					 9000 0 0 4 700 15 8
+
+					/* IDSEL 0x13 */
+					 9800 0 0 1 700 17 8
+					 9800 0 0 2 700 14 8
+					 9800 0 0 3 700 15 8
+					 9800 0 0 4 700 16 8
+
+					/* IDSEL 0x15 */
+					 a800 0 0 1 700 14 8
+					 a800 0 0 2 700 15 8
+					 a800 0 0 3 700 16 8
+					 a800 0 0 4 700 17 8
+
+					/* IDSEL 0x16 */
+					 b000 0 0 1 700 17 8
+					 b000 0 0 2 700 14 8
+					 b000 0 0 3 700 15 8
+					 b000 0 0 4 700 16 8
+
+					/* IDSEL 0x17 */
+					 b800 0 0 1 700 16 8
+					 b800 0 0 2 700 17 8
+					 b800 0 0 3 700 14 8
+					 b800 0 0 4 700 15 8
+
+					/* IDSEL 0x18 */
+					 b000 0 0 1 700 15 8
+					 b000 0 0 2 700 16 8
+					 b000 0 0 3 700 17 8
+					 b000 0 0 4 700 14 8>;
+			interrupt-parent = <700>;
+			interrupts = <42 8>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 b0000000 b0000000 0 10000000
+				  42000000 0 90000000 90000000 0 10000000
+				  01000000 0 00000000 e2100000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8600 100>;
+			compatible = "83xx";
+			device_type = "pci";
+		};
+
+		/* May need to remove if on a part without crypto engine */
+		crypto@30000 {
+			device_type = "crypto";
+			model = "SEC2";
+			compatible = "talitos";
+			reg = <30000 10000>;
+			interrupts = <b 8>;
+			interrupt-parent = <700>;
+			num-channels = <4>;
+			channel-fifo-len = <18>;
+			exec-units-mask = <0000007e>;
+			/* desc mask is for rev2.0,
+			 * we need runtime fixup for >2.0 */
+			descriptor-types-mask = <01010ebf>;
+		};
+
+		/* IPIC
+		 * interrupts cell = <intr #, sense>
+		 * sense values match linux IORESOURCE_IRQ_* defines:
+		 * sense == 8: Level, low assertion
+		 * sense == 2: Edge, high-to-low change
+		 */
+		pic@700 {
+			linux,phandle = <700>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <700 100>;
+			built-in;
+			device_type = "ipic";
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
new file mode 100644
index 0000000..5f41c1f
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -0,0 +1,257 @@
+/*
+ * MPC8540 ADS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "MPC8540ADS";
+	compatible = "MPC85xxADS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		linux,phandle = <200>;
+
+		PowerPC,8540@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	//  33 MHz, from uboot
+			bus-frequency = <0>;	// 166 MHz
+			clock-frequency = <0>;	// 825 MHz, from uboot
+			32-bit;
+			linux,phandle = <201>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 08000000>;	// 128M at 0x0
+	};
+
+	soc8540@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00100000>;	// CCSRBAR 1M
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <40000>;
+				interrupts = <35 1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <40000>;
+				interrupts = <35 1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@3 {
+				linux,phandle = <2452003>;
+				interrupt-parent = <40000>;
+				interrupts = <37 1>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			address = [ 00 E0 0C 00 73 00 ];
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <d 2 e 2 12 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			address = [ 00 E0 0C 00 73 01 ];
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+		ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "FEC";
+			compatible = "gianfar";
+			reg = <26000 1000>;
+			address = [ 00 E0 0C 00 73 02 ];
+			local-mac-address = [ 00 E0 0C 00 73 02 ];
+			interrupts = <19 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452003>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>; 	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+		pci@8000 {
+			linux,phandle = <8000>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x02 */
+				1000 0 0 1 40000 31 1
+				1000 0 0 2 40000 32 1
+				1000 0 0 3 40000 33 1
+				1000 0 0 4 40000 34 1
+
+				/* IDSEL 0x03 */
+				1800 0 0 1 40000 34 1
+				1800 0 0 2 40000 31 1
+				1800 0 0 3 40000 32 1
+				1800 0 0 4 40000 33 1
+
+				/* IDSEL 0x04 */
+				2000 0 0 1 40000 33 1
+				2000 0 0 2 40000 34 1
+				2000 0 0 3 40000 31 1
+				2000 0 0 4 40000 32 1
+
+				/* IDSEL 0x05 */
+				2800 0 0 1 40000 32 1
+				2800 0 0 2 40000 33 1
+				2800 0 0 3 40000 34 1
+				2800 0 0 4 40000 31 1
+
+				/* IDSEL 0x0c */
+				6000 0 0 1 40000 31 1
+				6000 0 0 2 40000 32 1
+				6000 0 0 3 40000 33 1
+				6000 0 0 4 40000 34 1
+
+				/* IDSEL 0x0d */
+				6800 0 0 1 40000 34 1
+				6800 0 0 2 40000 31 1
+				6800 0 0 3 40000 32 1
+				6800 0 0 4 40000 33 1
+
+				/* IDSEL 0x0e */
+				7000 0 0 1 40000 33 1
+				7000 0 0 2 40000 34 1
+				7000 0 0 3 40000 31 1
+				7000 0 0 4 40000 32 1
+
+				/* IDSEL 0x0f */
+				7800 0 0 1 40000 32 1
+				7800 0 0 2 40000 33 1
+				7800 0 0 3 40000 34 1
+				7800 0 0 4 40000 31 1
+
+				/* IDSEL 0x12 */
+				9000 0 0 1 40000 31 1
+				9000 0 0 2 40000 32 1
+				9000 0 0 3 40000 33 1
+				9000 0 0 4 40000 34 1
+
+				/* IDSEL 0x13 */
+				9800 0 0 1 40000 34 1
+				9800 0 0 2 40000 31 1
+				9800 0 0 3 40000 32 1
+				9800 0 0 4 40000 33 1
+
+				/* IDSEL 0x14 */
+				a000 0 0 1 40000 33 1
+				a000 0 0 2 40000 34 1
+				a000 0 0 3 40000 31 1
+				a000 0 0 4 40000 32 1
+
+				/* IDSEL 0x15 */
+				a800 0 0 1 40000 32 1
+				a800 0 0 2 40000 33 1
+				a800 0 0 3 40000 34 1
+				a800 0 0 4 40000 31 1>;
+			interrupt-parent = <40000>;
+			interrupts = <08 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 80000000 80000000 0 20000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+		};
+
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+			big-endian;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
new file mode 100644
index 0000000..7be0bc6
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -0,0 +1,244 @@
+/*
+ * MPC8541 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "MPC8541CDS";
+	compatible = "MPC85xxCDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		linux,phandle = <200>;
+
+		PowerPC,8541@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	//  33 MHz, from uboot
+			bus-frequency = <0>;	// 166 MHz
+			clock-frequency = <0>;	// 825 MHz, from uboot
+			32-bit;
+			linux,phandle = <201>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 08000000>;	// 128M at 0x0
+	};
+
+	soc8541@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00100000>;	// CCSRBAR 1M
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <d 2 e 2 12 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>; 	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		pci@8000 {
+			linux,phandle = <8000>;
+			interrupt-map-mask = <1f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x10 */
+				08000 0 0 1 40000 30 1
+				08000 0 0 2 40000 31 1
+				08000 0 0 3 40000 32 1
+				08000 0 0 4 40000 33 1
+
+				/* IDSEL 0x11 */
+				08800 0 0 1 40000 30 1
+				08800 0 0 2 40000 31 1
+				08800 0 0 3 40000 32 1
+				08800 0 0 4 40000 33 1
+
+				/* IDSEL 0x12 (Slot 1) */
+				09000 0 0 1 40000 30 1
+				09000 0 0 2 40000 31 1
+				09000 0 0 3 40000 32 1
+				09000 0 0 4 40000 33 1
+
+				/* IDSEL 0x13 (Slot 2) */
+				09800 0 0 1 40000 31 1
+				09800 0 0 2 40000 32 1
+				09800 0 0 3 40000 33 1
+				09800 0 0 4 40000 30 1
+
+				/* IDSEL 0x14 (Slot 3) */
+				0a000 0 0 1 40000 32 1
+				0a000 0 0 2 40000 33 1
+				0a000 0 0 3 40000 30 1
+				0a000 0 0 4 40000 31 1
+
+				/* IDSEL 0x15 (Slot 4) */
+				0a800 0 0 1 40000 33 1
+				0a800 0 0 2 40000 30 1
+				0a800 0 0 3 40000 31 1
+				0a800 0 0 4 40000 32 1
+
+				/* Bus 1 (Tundra Bridge) */
+				/* IDSEL 0x12 (ISA bridge) */
+				19000 0 0 1 40000 30 1
+				19000 0 0 2 40000 31 1
+				19000 0 0 3 40000 32 1
+				19000 0 0 4 40000 33 1>;
+			interrupt-parent = <40000>;
+			interrupts = <08 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 80000000 80000000 0 20000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+
+			i8259@19000 {
+				clock-frequency = <0>;
+				interrupt-controller;
+				device_type = "interrupt-controller";
+				reg = <19000 0 0 0 1>;
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				built-in;
+				compatible = "chrp,iic";
+				big-endian;
+				interrupts = <1>;
+				interrupt-parent = <8000>;
+			};
+		};
+
+		pci@9000 {
+			linux,phandle = <9000>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x15 */
+				a800 0 0 1 40000 3b 1
+				a800 0 0 2 40000 3b 1
+				a800 0 0 3 40000 3b 1
+				a800 0 0 4 40000 3b 1>;
+			interrupt-parent = <40000>;
+			interrupts = <09 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 20000000
+				  01000000 0 00000000 e3000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <9000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+		};
+
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts
new file mode 100644
index 0000000..893d795
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8548cds.dts
@@ -0,0 +1,287 @@
+/*
+ * MPC8555 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "MPC8548CDS";
+	compatible = "MPC85xxCDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		linux,phandle = <200>;
+
+		PowerPC,8548@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	//  33 MHz, from uboot
+			bus-frequency = <0>;	// 166 MHz
+			clock-frequency = <0>;	// 825 MHz, from uboot
+			32-bit;
+			linux,phandle = <201>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 08000000>;	// 128M at 0x0
+	};
+
+	soc8548@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00100000>;	// CCSRBAR 1M
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+
+			ethernet-phy@2 {
+				linux,phandle = <2452002>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <2>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@3 {
+				linux,phandle = <2452003>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <d 2 e 2 12 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+		ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <26000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 02 ];
+			interrupts = <f 2 10 2 11 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+/* eTSEC 4 is currently broken
+		ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "eTSEC";
+			compatible = "gianfar";
+			reg = <27000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 03 ];
+			interrupts = <15 2 16 2 17 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+ */
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>; 	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		pci@8000 {
+			linux,phandle = <8000>;
+			interrupt-map-mask = <1f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x10 */
+				08000 0 0 1 40000 30 1
+				08000 0 0 2 40000 31 1
+				08000 0 0 3 40000 32 1
+				08000 0 0 4 40000 33 1
+
+				/* IDSEL 0x11 */
+				08800 0 0 1 40000 30 1
+				08800 0 0 2 40000 31 1
+				08800 0 0 3 40000 32 1
+				08800 0 0 4 40000 33 1
+
+				/* IDSEL 0x12 (Slot 1) */
+				09000 0 0 1 40000 30 1
+				09000 0 0 2 40000 31 1
+				09000 0 0 3 40000 32 1
+				09000 0 0 4 40000 33 1
+
+				/* IDSEL 0x13 (Slot 2) */
+				09800 0 0 1 40000 31 1
+				09800 0 0 2 40000 32 1
+				09800 0 0 3 40000 33 1
+				09800 0 0 4 40000 30 1
+
+				/* IDSEL 0x14 (Slot 3) */
+				0a000 0 0 1 40000 32 1
+				0a000 0 0 2 40000 33 1
+				0a000 0 0 3 40000 30 1
+				0a000 0 0 4 40000 31 1
+
+				/* IDSEL 0x15 (Slot 4) */
+				0a800 0 0 1 40000 33 1
+				0a800 0 0 2 40000 30 1
+				0a800 0 0 3 40000 31 1
+				0a800 0 0 4 40000 32 1
+
+				/* Bus 1 (Tundra Bridge) */
+				/* IDSEL 0x12 (ISA bridge) */
+				19000 0 0 1 40000 30 1
+				19000 0 0 2 40000 31 1
+				19000 0 0 3 40000 32 1
+				19000 0 0 4 40000 33 1>;
+			interrupt-parent = <40000>;
+			interrupts = <08 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 80000000 80000000 0 20000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+
+			i8259@19000 {
+				clock-frequency = <0>;
+				interrupt-controller;
+				device_type = "interrupt-controller";
+				reg = <19000 0 0 0 1>;
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				built-in;
+				compatible = "chrp,iic";
+				big-endian;
+				interrupts = <1>;
+				interrupt-parent = <8000>;
+			};
+		};
+
+		pci@9000 {
+			linux,phandle = <9000>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x15 */
+				a800 0 0 1 40000 3b 1
+				a800 0 0 2 40000 3b 1
+				a800 0 0 3 40000 3b 1
+				a800 0 0 4 40000 3b 1>;
+			interrupt-parent = <40000>;
+			interrupts = <09 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 20000000
+				  01000000 0 00000000 e3000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <9000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+		};
+
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
new file mode 100644
index 0000000..118f5a8
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -0,0 +1,244 @@
+/*
+ * MPC8555 CDS Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "MPC8555CDS";
+	compatible = "MPC85xxCDS";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		linux,phandle = <200>;
+
+		PowerPC,8555@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	//  33 MHz, from uboot
+			bus-frequency = <0>;	// 166 MHz
+			clock-frequency = <0>;	// 825 MHz, from uboot
+			32-bit;
+			linux,phandle = <201>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 08000000>;	// 128M at 0x0
+	};
+
+	soc8555@e0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 e0000000 00100000>;
+		reg = <e0000000 00100000>;	// CCSRBAR 1M
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <1b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <40000>;
+				interrupts = <35 0>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <0d 2 0e 2 12 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			local-mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <13 2 14 2 18 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>; 	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;	// reg base, size
+			clock-frequency = <0>; 	// should we fill in in uboot?
+			interrupts = <1a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		pci@8000 {
+			linux,phandle = <8000>;
+			interrupt-map-mask = <1f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x10 */
+				08000 0 0 1 40000 30 1
+				08000 0 0 2 40000 31 1
+				08000 0 0 3 40000 32 1
+				08000 0 0 4 40000 33 1
+
+				/* IDSEL 0x11 */
+				08800 0 0 1 40000 30 1
+				08800 0 0 2 40000 31 1
+				08800 0 0 3 40000 32 1
+				08800 0 0 4 40000 33 1
+
+				/* IDSEL 0x12 (Slot 1) */
+				09000 0 0 1 40000 30 1
+				09000 0 0 2 40000 31 1
+				09000 0 0 3 40000 32 1
+				09000 0 0 4 40000 33 1
+
+				/* IDSEL 0x13 (Slot 2) */
+				09800 0 0 1 40000 31 1
+				09800 0 0 2 40000 32 1
+				09800 0 0 3 40000 33 1
+				09800 0 0 4 40000 30 1
+
+				/* IDSEL 0x14 (Slot 3) */
+				0a000 0 0 1 40000 32 1
+				0a000 0 0 2 40000 33 1
+				0a000 0 0 3 40000 30 1
+				0a000 0 0 4 40000 31 1
+
+				/* IDSEL 0x15 (Slot 4) */
+				0a800 0 0 1 40000 33 1
+				0a800 0 0 2 40000 30 1
+				0a800 0 0 3 40000 31 1
+				0a800 0 0 4 40000 32 1
+
+				/* Bus 1 (Tundra Bridge) */
+				/* IDSEL 0x12 (ISA bridge) */
+				19000 0 0 1 40000 30 1
+				19000 0 0 2 40000 31 1
+				19000 0 0 3 40000 32 1
+				19000 0 0 4 40000 33 1>;
+			interrupt-parent = <40000>;
+			interrupts = <08 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 80000000 80000000 0 20000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+
+			i8259@19000 {
+				clock-frequency = <0>;
+				interrupt-controller;
+				device_type = "interrupt-controller";
+				reg = <19000 0 0 0 1>;
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				built-in;
+				compatible = "chrp,iic";
+				big-endian;
+				interrupts = <1>;
+				interrupt-parent = <8000>;
+			};
+		};
+
+		pci@9000 {
+			linux,phandle = <9000>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+
+				/* IDSEL 0x15 */
+				a800 0 0 1 40000 3b 1
+				a800 0 0 2 40000 3b 1
+				a800 0 0 3 40000 3b 1
+				a800 0 0 4 40000 3b 1>;
+			interrupt-parent = <40000>;
+			interrupts = <09 2>;
+			bus-range = <0 0>;
+			ranges = <02000000 0 a0000000 a0000000 0 20000000
+				  01000000 0 00000000 e3000000 0 00100000>;
+			clock-frequency = <3f940aa>;
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <9000 1000>;
+			compatible = "85xx";
+			device_type = "pci";
+		};
+
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
new file mode 100644
index 0000000..f0c7731
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts
@@ -0,0 +1,339 @@
+/*
+ * MPC8641 HPCN Device Tree Source
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * 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.
+ */
+
+
+/ {
+	model = "MPC8641HPCN";
+	compatible = "mpc86xx";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#cpus = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,8641@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+			32-bit;
+			linux,boot-cpu;
+		};
+		PowerPC,8641@1 {
+			device_type = "cpu";
+			reg = <1>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <8000>;		// L1, 32K
+			i-cache-size = <8000>;		// L1, 32K
+			timebase-frequency = <0>;	// 33 MHz, from uboot
+			bus-frequency = <0>;		// From uboot
+			clock-frequency = <0>;		// From uboot
+			32-bit;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <00000000 40000000>;	// 1G at 0x0
+	};
+
+	soc8641@f8000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 f8000000 00100000>;
+		reg = <f8000000 00100000>;	// CCSRBAR 1M
+		bus-frequency = <0>;
+
+		i2c@3000 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3000 100>;
+			interrupts = <2b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		i2c@3100 {
+			device_type = "i2c";
+			compatible = "fsl-i2c";
+			reg = <3100 100>;
+			interrupts = <2b 2>;
+			interrupt-parent = <40000>;
+			dfsrr;
+		};
+
+		mdio@24520 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "mdio";
+			compatible = "gianfar";
+			reg = <24520 20>;
+			linux,phandle = <24520>;
+			ethernet-phy@0 {
+				linux,phandle = <2452000>;
+				interrupt-parent = <40000>;
+				interrupts = <4a 1>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <2452001>;
+				interrupt-parent = <40000>;
+				interrupts = <4a 1>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@2 {
+				linux,phandle = <2452002>;
+				interrupt-parent = <40000>;
+				interrupts = <4a 1>;
+				reg = <2>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@3 {
+				linux,phandle = <2452003>;
+				interrupt-parent = <40000>;
+				interrupts = <4a 1>;
+				reg = <3>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		ethernet@24000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <24000 1000>;
+			mac-address = [ 00 E0 0C 00 73 00 ];
+			interrupts = <1d 2 1e 2 22 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452000>;
+		};
+
+		ethernet@25000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <25000 1000>;
+			mac-address = [ 00 E0 0C 00 73 01 ];
+			interrupts = <23 2 24 2 28 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452001>;
+		};
+		
+		ethernet@26000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <26000 1000>;
+			mac-address = [ 00 E0 0C 00 02 FD ];
+			interrupts = <1F 2 20 2 21 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452002>;
+		};
+
+		ethernet@27000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			device_type = "network";
+			model = "TSEC";
+			compatible = "gianfar";
+			reg = <27000 1000>;
+			mac-address = [ 00 E0 0C 00 03 FD ];
+			interrupts = <25 2 26 2 27 2>;
+			interrupt-parent = <40000>;
+			phy-handle = <2452003>;
+		};
+		serial@4500 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4500 100>;
+			clock-frequency = <0>;
+			interrupts = <2a 2>;
+			interrupt-parent = <40000>;
+		};
+
+		serial@4600 {
+			device_type = "serial";
+			compatible = "ns16550";
+			reg = <4600 100>;
+			clock-frequency = <0>;
+			interrupts = <1c 2>;
+			interrupt-parent = <40000>;
+		};
+
+		pci@8000 {
+			compatible = "86xx";
+			device_type = "pci";
+			#interrupt-cells = <1>;
+			#size-cells = <2>;
+			#address-cells = <3>;
+			reg = <8000 1000>;
+			bus-range = <0 fe>;
+			ranges = <02000000 0 80000000 80000000 0 20000000
+				  01000000 0 00000000 e2000000 0 00100000>;
+			clock-frequency = <1fca055>;
+			interrupt-parent = <40000>;
+			interrupts = <18 2>;
+			interrupt-map-mask = <f800 0 0 7>;
+			interrupt-map = <
+				/* IDSEL 0x11 */
+				8800 0 0 1 4d0 3 2
+				8800 0 0 2 4d0 4 2
+				8800 0 0 3 4d0 5 2
+				8800 0 0 4 4d0 6 2
+
+				/* IDSEL 0x12 */
+				9000 0 0 1 4d0 4 2
+				9000 0 0 2 4d0 5 2
+				9000 0 0 3 4d0 6 2
+				9000 0 0 4 4d0 3 2
+
+				/* IDSEL 0x13 */
+				9800 0 0 1 4d0 0 0
+				9800 0 0 2 4d0 0 0
+				9800 0 0 3 4d0 0 0
+				9800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x14 */
+				a000 0 0 1 4d0 0 0
+				a000 0 0 2 4d0 0 0
+				a000 0 0 3 4d0 0 0
+				a000 0 0 4 4d0 0 0
+
+				/* IDSEL 0x15 */
+				a800 0 0 1 4d0 0 0
+				a800 0 0 2 4d0 0 0
+				a800 0 0 3 4d0 0 0
+				a800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x16 */
+				b000 0 0 1 4d0 0 0
+				b000 0 0 2 4d0 0 0
+				b000 0 0 3 4d0 0 0
+				b000 0 0 4 4d0 0 0
+
+				/* IDSEL 0x17 */
+				b800 0 0 1 4d0 0 0
+				b800 0 0 2 4d0 0 0
+				b800 0 0 3 4d0 0 0
+				b800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x18 */
+				c000 0 0 1 4d0 0 0
+				c000 0 0 2 4d0 0 0
+				c000 0 0 3 4d0 0 0
+				c000 0 0 4 4d0 0 0
+
+				/* IDSEL 0x19 */
+				c800 0 0 1 4d0 0 0
+				c800 0 0 2 4d0 0 0
+				c800 0 0 3 4d0 0 0
+				c800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x1a */
+				d000 0 0 1 4d0 6 2
+				d000 0 0 2 4d0 3 2
+				d000 0 0 3 4d0 4 2
+				d000 0 0 4 4d0 5 2
+
+
+				/* IDSEL 0x1b */
+				d800 0 0 1 4d0 5 2
+				d800 0 0 2 4d0 0 0
+				d800 0 0 3 4d0 0 0
+				d800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x1c */
+				e000 0 0 1 4d0 9 2
+				e000 0 0 2 4d0 a 2
+				e000 0 0 3 4d0 c 2
+				e000 0 0 4 4d0 7 2
+
+				/* IDSEL 0x1d */
+				e800 0 0 1 4d0 9 2
+				e800 0 0 2 4d0 a 2
+				e800 0 0 3 4d0 b 2
+				e800 0 0 4 4d0 0 0
+
+				/* IDSEL 0x1e */
+				f000 0 0 1 4d0 c 2
+				f000 0 0 2 4d0 0 0
+				f000 0 0 3 4d0 0 0
+				f000 0 0 4 4d0 0 0
+
+				/* IDSEL 0x1f */
+				f800 0 0 1 4d0 6 2
+				f800 0 0 2 4d0 0 0
+				f800 0 0 3 4d0 0 0
+				f800 0 0 4 4d0 0 0
+				>;
+			i8259@4d0 {
+				linux,phandle = <4d0>;
+				clock-frequency = <0>;
+				interrupt-controller;
+				device_type = "interrupt-controller";
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				built-in;
+				compatible = "chrp,iic";
+                	        big-endian;
+				interrupts = <49 2>;
+				interrupt-parent = <40000>;
+			};
+
+		};
+		pic@40000 {
+			linux,phandle = <40000>;
+			clock-frequency = <0>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <40000 40000>;
+			built-in;
+			compatible = "chrp,open-pic";
+			device_type = "open-pic";
+                        big-endian;
+			interrupts = <
+				10 2 11 2 12 2 13 2
+				14 2 15 2 16 2 17 2
+				18 2 19 2 1a 2 1b 2
+				1c 2 1d 2 1e 2 1f 2
+				20 2 21 2 22 2 23 2
+				24 2 25 2 26 2 27 2
+				28 2 29 2 2a 2 2b 2
+				2c 2 2d 2 2e 2 2f 2
+				30 2 31 2 32 2 33 2
+				34 2 35 2 36 2 37 2
+				38 2 39 2 2a 2 3b 2
+				3c 2 3d 2 3e 2 3f 2
+				48 1 49 2 4a 1
+				>;
+			interrupt-parent = <40000>;
+		};
+	};
+};
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index a456275..8c6bd17 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 13:24:37 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:12:29 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -33,6 +35,7 @@
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -50,6 +53,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
@@ -67,10 +71,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -116,12 +122,16 @@
 CONFIG_PPC_PMAC64=y
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_U3_DART=y
 CONFIG_MPIC=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_MPIC_BROKEN_U3=y
 # CONFIG_PPC_MPC106 is not set
+CONFIG_PPC_970_NAP=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -153,6 +163,7 @@
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 # CONFIG_HOTPLUG_CPU is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
@@ -168,6 +179,7 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
@@ -184,6 +196,7 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -227,6 +240,8 @@
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -239,6 +254,7 @@
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -263,6 +279,7 @@
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -318,6 +335,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -355,6 +373,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
@@ -417,7 +436,6 @@
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-# CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -478,6 +496,7 @@
 # CONFIG_SCSI_SATA_MV is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_SX4 is not set
@@ -497,7 +516,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -514,9 +532,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -559,7 +575,6 @@
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=y
@@ -573,6 +588,7 @@
 # Macintosh device drivers
 #
 CONFIG_ADB_PMU=y
+# CONFIG_ADB_PMU_LED is not set
 CONFIG_PMAC_SMU=y
 CONFIG_THERM_PM72=y
 CONFIG_WINDFARM=y
@@ -643,6 +659,7 @@
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -739,6 +756,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -754,6 +772,7 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 
 #
 # IPMI
@@ -764,6 +783,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -774,6 +794,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_SIS is not set
 # CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
@@ -813,6 +834,7 @@
 # CONFIG_I2C_PIIX4 is not set
 CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -849,7 +871,6 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -865,6 +886,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -875,22 +897,19 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
-# CONFIG_FB_CONTROL is not set
-# CONFIG_FB_PLATINUM is not set
-# CONFIG_FB_VALKYRIE is not set
-# CONFIG_FB_CT65550 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
@@ -990,6 +1009,18 @@
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1027,6 +1058,17 @@
 CONFIG_SND_POWERMAC_AUTO_DRC=y
 
 #
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
 # USB devices
 #
 CONFIG_SND_USB_AUDIO=m
@@ -1060,6 +1102,7 @@
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1110,9 +1153,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1155,6 +1196,7 @@
 CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
 CONFIG_USB_SERIAL_BELKIN=m
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
@@ -1162,6 +1204,7 @@
 CONFIG_USB_SERIAL_CYPRESS_M8=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 CONFIG_USB_SERIAL_VISOR=m
 CONFIG_USB_SERIAL_IPAQ=m
 CONFIG_USB_SERIAL_IR=m
@@ -1191,9 +1234,11 @@
 # CONFIG_USB_SERIAL_HP4X is not set
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
 CONFIG_USB_SERIAL_TI=m
 CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_XIRCOM=m
+# CONFIG_USB_SERIAL_OPTION is not set
 CONFIG_USB_SERIAL_OMNINET=m
 CONFIG_USB_EZUSB=y
 
@@ -1207,10 +1252,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1235,6 +1282,14 @@
 # CONFIG_NEW_LEDS is not set
 
 #
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -1249,6 +1304,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1273,7 +1341,6 @@
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
@@ -1282,6 +1349,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
@@ -1363,7 +1431,9 @@
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 # CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1444,6 +1514,9 @@
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1457,14 +1530,19 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
@@ -1476,11 +1554,7 @@
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
 CONFIG_BOOTX_TEXT=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index a95e455..72ed95b 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 11:46:44 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:15:46 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -34,6 +36,7 @@
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -51,6 +54,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
@@ -69,10 +73,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -113,10 +119,14 @@
 CONFIG_PPC_ISERIES=y
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_APUS is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
 # CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -135,6 +145,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_LPARCFG=y
 # CONFIG_NUMA is not set
@@ -149,6 +160,7 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
 # CONFIG_PPC_64K_PAGES is not set
 # CONFIG_SCHED_SMT is not set
 CONFIG_PROC_DEVICETREE=y
@@ -164,6 +176,7 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -207,6 +220,8 @@
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -219,6 +234,7 @@
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -246,9 +262,11 @@
 # CONFIG_NETFILTER_XT_MATCH_POLICY is not set
 # CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
@@ -267,6 +285,7 @@
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -360,6 +379,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -396,6 +416,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -453,6 +474,7 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -464,7 +486,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -481,9 +502,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -596,6 +615,7 @@
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -696,6 +716,7 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 
 #
 # IPMI
@@ -706,6 +727,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -741,7 +763,6 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -757,6 +778,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -766,7 +788,9 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 # CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -801,6 +825,14 @@
 # CONFIG_NEW_LEDS is not set
 
 #
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -815,6 +847,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -843,7 +888,6 @@
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
@@ -852,6 +896,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
@@ -933,8 +978,10 @@
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1013,10 +1060,12 @@
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
 #
+# CONFIG_PROFILING is not set
 # CONFIG_KPROBES is not set
 
 #
@@ -1024,14 +1073,19 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
@@ -1042,11 +1096,7 @@
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUGGER is not set
 CONFIG_IRQSTACKS=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
similarity index 100%
rename from arch/powerpc/configs/mpc834x_sys_defconfig
rename to arch/powerpc/configs/mpc834x_mds_defconfig
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index addc793..3545af9 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,16 +1,18 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc5
-# Mon May 29 14:47:49 2006
+# Linux kernel version: 2.6.17
+# Mon Jul  3 14:20:49 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_NVRAM=y
@@ -29,6 +31,7 @@
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
 # CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_8xx is not set
@@ -39,6 +42,7 @@
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -72,10 +76,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -119,6 +125,9 @@
 # CONFIG_APUS is not set
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_PMAC=y
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_MPIC=y
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -154,6 +163,7 @@
 # CONFIG_PREEMPT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 # CONFIG_KEXEC is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -164,6 +174,7 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_PM=y
@@ -182,6 +193,7 @@
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -256,6 +268,8 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -268,6 +282,7 @@
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -292,9 +307,11 @@
 CONFIG_NETFILTER_XT_MATCH_POLICY=m
 CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
 CONFIG_NETFILTER_XT_MATCH_STRING=m
 CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
 
@@ -313,6 +330,7 @@
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
 CONFIG_IP_NF_H323=m
+# CONFIG_IP_NF_SIP is not set
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -457,6 +475,7 @@
 # CONFIG_ALI_FIR is not set
 # CONFIG_VLSI_FIR is not set
 # CONFIG_VIA_FIR is not set
+# CONFIG_MCS_FIR is not set
 CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 CONFIG_BT_SCO=m
@@ -500,6 +519,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -600,7 +620,6 @@
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -661,6 +680,7 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -705,9 +725,7 @@
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=m
-CONFIG_MD_RAID5_RESHAPE=y
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
@@ -750,7 +768,6 @@
 #
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
-# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
 # CONFIG_IEEE1394_ETH1394 is not set
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
@@ -766,9 +783,12 @@
 CONFIG_ADB=y
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_PMU=y
+CONFIG_ADB_PMU_LED=y
+CONFIG_ADB_PMU_LED_IDE=y
 CONFIG_PMAC_APM_EMU=m
 CONFIG_PMAC_MEDIABAY=y
 CONFIG_PMAC_BACKLIGHT=y
+CONFIG_PMAC_BACKLIGHT_LEGACY=y
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_EMUMOUSEBTN=y
 CONFIG_THERM_WINDTUNNEL=m
@@ -858,6 +878,7 @@
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -908,6 +929,7 @@
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 CONFIG_PRISM54=m
+# CONFIG_USB_ZD1201 is not set
 # CONFIG_HOSTAP is not set
 CONFIG_NET_WIRELESS=y
 
@@ -998,6 +1020,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -1029,6 +1052,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_NVRAM=y
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
@@ -1040,6 +1064,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_SIS is not set
 # CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 CONFIG_DRM=m
@@ -1092,6 +1117,7 @@
 CONFIG_I2C_POWERMAC=y
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -1156,12 +1182,13 @@
 #
 # Graphics support
 #
+# CONFIG_FIRMWARE_EDID is not set
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+CONFIG_FB_BACKLIGHT=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -1178,6 +1205,7 @@
 # CONFIG_FB_S1D13XXX is not set
 CONFIG_FB_NVIDIA=y
 CONFIG_FB_NVIDIA_I2C=y
+CONFIG_FB_NVIDIA_BACKLIGHT=y
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
@@ -1187,12 +1215,15 @@
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
 # CONFIG_FB_RADEON_DEBUG is not set
 CONFIG_FB_ATY128=y
+CONFIG_FB_ATY128_BACKLIGHT=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
 # CONFIG_FB_ATY_GENERIC_LCD is not set
 CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
 # CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
@@ -1221,7 +1252,11 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
-# 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=m
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -1278,6 +1313,18 @@
 # CONFIG_SND_CMIPCI is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
 # CONFIG_SND_EMU10K1 is not set
 # CONFIG_SND_EMU10K1X is not set
 # CONFIG_SND_ENS1370 is not set
@@ -1315,6 +1362,17 @@
 CONFIG_SND_POWERMAC_AUTO_DRC=y
 
 #
+# Apple Onboard Audio driver
+#
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
+CONFIG_SND_AOA_SOUNDBUS=m
+CONFIG_SND_AOA_SOUNDBUS_I2S=m
+
+#
 # USB devices
 #
 CONFIG_SND_USB_AUDIO=m
@@ -1355,6 +1413,7 @@
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_SPLIT_ISO=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1431,7 +1490,6 @@
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 CONFIG_USB_NET_ZAURUS=m
-# CONFIG_USB_ZD1201 is not set
 CONFIG_USB_MON=y
 
 #
@@ -1499,10 +1557,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_APPLEDISPLAY=m
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1524,7 +1584,8 @@
 #
 # LED devices
 #
-# CONFIG_NEW_LEDS is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
 
 #
 # LED drivers
@@ -1533,6 +1594,10 @@
 #
 # LED Triggers
 #
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
 
 #
 # InfiniBand support
@@ -1549,6 +1614,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1569,6 +1647,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -1649,6 +1728,7 @@
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1732,6 +1812,7 @@
 CONFIG_TEXTSEARCH_KMP=m
 CONFIG_TEXTSEARCH_BM=m
 CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1744,12 +1825,15 @@
 #
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
 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_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1763,11 +1847,7 @@
 CONFIG_XMON_DEFAULT=y
 # CONFIG_BDI_SWITCH is not set
 CONFIG_BOOTX_TEXT=y
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 31708ad..c18e860 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc4
-# Sun May 28 07:26:56 2006
+# Linux kernel version: 2.6.18-rc3
+# Tue Aug  8 09:14:48 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
 CONFIG_PPC_MERGE=y
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -35,6 +36,7 @@
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -52,6 +54,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
@@ -70,10 +73,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -118,6 +123,9 @@
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PPC_IBM_CELL_BLADE is not set
+# CONFIG_UDBG_RTAS_CONSOLE is not set
 CONFIG_XICS=y
 # CONFIG_U3_DART is not set
 CONFIG_MPIC=y
@@ -149,6 +157,7 @@
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
@@ -173,6 +182,7 @@
 # CONFIG_MEMORY_HOTPLUG is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
+CONFIG_RESOURCES_64BIT=y
 CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
@@ -190,6 +200,7 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -238,6 +249,8 @@
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -250,6 +263,7 @@
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -277,6 +291,7 @@
 CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_PPTP is not set
 # CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_SIP is not set
 CONFIG_IP_NF_QUEUE=m
 
 #
@@ -316,6 +331,7 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -332,6 +348,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -352,6 +369,7 @@
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
 # CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -376,6 +394,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -487,6 +506,7 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -508,12 +528,6 @@
 CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA_FC=m
-CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
-CONFIG_SCSI_QLA21XX=m
-CONFIG_SCSI_QLA22XX=m
-CONFIG_SCSI_QLA2300=m
-CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -528,9 +542,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
-CONFIG_MD_RAID5=y
-CONFIG_MD_RAID5_RESHAPE=y
-CONFIG_MD_RAID6=m
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
@@ -651,6 +663,7 @@
 # CONFIG_IXGB_NAPI is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -754,6 +767,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -776,6 +790,7 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_BRIQ_PANEL is not set
 # CONFIG_PRINTER is not set
 # CONFIG_PPDEV is not set
 # CONFIG_TIPAR is not set
@@ -793,6 +808,7 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 # CONFIG_GEN_RTC_X is not set
 # CONFIG_DTLK is not set
@@ -839,6 +855,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -876,7 +893,6 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
@@ -892,6 +908,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -902,19 +919,19 @@
 #
 # Graphics support
 #
+CONFIG_FIRMWARE_EDID=y
 CONFIG_FB=y
 CONFIG_FB_CFB_FILLRECT=y
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
-CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
-# CONFIG_FB_CT65550 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
@@ -993,6 +1010,7 @@
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1083,10 +1101,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1124,12 +1144,14 @@
 CONFIG_INFINIBAND=m
 CONFIG_INFINIBAND_USER_MAD=m
 CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_ADDR_TRANS=y
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_DEBUG=y
 # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
 CONFIG_INFINIBAND_SRP=m
+# CONFIG_INFINIBAND_ISER is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1141,6 +1163,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1169,15 +1204,16 @@
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_QUOTA is not set
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
 CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_DEBUG_MASKLOG=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -1259,8 +1295,10 @@
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -1326,6 +1364,9 @@
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_PLIST=y
 
 #
 # Instrumentation Support
@@ -1339,14 +1380,19 @@
 #
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RWSEMS is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 814f242..7d32ad0 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -67,9 +67,11 @@
 				   pci_direct_iommu.o iomap.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
 obj-$(CONFIG_PCI)		+= $(pci64-y) $(pci32-y)
-kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o crash.o
+kexec-$(CONFIG_PPC64)		:= machine_kexec_64.o
 kexec-$(CONFIG_PPC32)		:= machine_kexec_32.o
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o $(kexec-y)
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o crash.o $(kexec-y)
+obj-$(CONFIG_AUDIT)		+= audit.o
+obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
 ifeq ($(CONFIG_PPC_ISERIES),y)
 $(obj)/head_64.o: $(obj)/lparmap.s
diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c
new file mode 100644
index 0000000..7fe5e63
--- /dev/null
+++ b/arch/powerpc/kernel/audit.c
@@ -0,0 +1,66 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_PPC64
+	extern int ppc32_classify_syscall(unsigned);
+	if (abi == AUDIT_ARCH_PPC)
+		return ppc32_classify_syscall(syscall);
+#endif
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_PPC64
+	extern __u32 ppc32_dir_class[];
+	extern __u32 ppc32_write_class[];
+	extern __u32 ppc32_read_class[];
+	extern __u32 ppc32_chattr_class[];
+	audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
+	audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
+#endif
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c
new file mode 100644
index 0000000..640d4bb
--- /dev/null
+++ b/arch/powerpc/kernel/compat_audit.c
@@ -0,0 +1,38 @@
+#undef __powerpc64__
+#include <asm/unistd.h>
+
+unsigned ppc32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ppc32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned ppc32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ppc32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ppc32_classify_syscall(unsigned syscall)
+{
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 1;
+	}
+}
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index f69af2c..76e97aa 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -76,6 +76,8 @@
 	mfspr	r0,SPRN_HID0
 	li	r11,5			/* clear DOZE and SLEEP */
 	rldimi	r0,r11,52,8		/* set NAP and DPM */
+	li	r11,0
+	rldimi	r0,r11,32,31		/* clear EN_ATTN */
 	mtspr	SPRN_HID0,r0
 	mfspr	r0,SPRN_HID0
 	mfspr	r0,SPRN_HID0
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 358cecd..f04c18e 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -44,6 +44,7 @@
 /* This keeps a track of which one is crashing cpu. */
 int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+cpumask_t cpus_in_sr = CPU_MASK_NONE;
 
 static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
 							       size_t data_len)
@@ -139,7 +140,13 @@
 
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 1);
+
+#ifdef CONFIG_PPC64
 	kexec_smp_wait();
+#else
+	for (;;);	/* FIXME */
+#endif
+
 	/* NOTREACHED */
 }
 
@@ -255,7 +262,11 @@
 	 *
 	 * do this if kexec in setup.c ?
 	 */
+#ifdef CONFIG_PPC64
 	smp_release_cpus();
+#else
+	/* FIXME */
+#endif
 }
 
 void crash_kexec_secondary(struct pt_regs *regs)
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 7e2c9fe..821e152 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -2,6 +2,11 @@
  *  FPU support code, moved here from head.S so that it can be used
  *  by chips which use other head-whatever.S files.
  *
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *    Copyright (C) 1996 Paul Mackerras.
+ *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
  *  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
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index e16eb2a..6ff3cf5 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -191,6 +191,37 @@
 	ori	reg,reg,(label)@l;	/* virt addr of handler ... */
 #endif
 
+/*
+ * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
+ * The firmware calls the registered system_reset_fwnmi and
+ * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
+ * a 32bit application at the time of the event.
+ * This firmware bug is present on POWER4 and JS20.
+ */
+#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label)		\
+	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\
+	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
+	std	r10,area+EX_R10(r13);					\
+	std	r11,area+EX_R11(r13);					\
+	std	r12,area+EX_R12(r13);					\
+	mfspr	r9,SPRN_SPRG1;						\
+	std	r9,area+EX_R13(r13);					\
+	mfcr	r9;							\
+	clrrdi	r12,r13,32;		/* get high part of &label */	\
+	mfmsr	r10;							\
+	/* force 64bit mode */						\
+	li	r11,5;			/* MSR_SF_LG|MSR_ISF_LG */	\
+	rldimi	r10,r11,61,0;		/* insert into top 3 bits */	\
+	/* done 64bit mode */						\
+	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\
+	LOAD_HANDLER(r12,label)						\
+	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
+	mtspr	SPRN_SRR0,r12;						\
+	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\
+	mtspr	SPRN_SRR1,r10;						\
+	rfid;								\
+	b	.	/* prevent speculative execution */
+
 #define EXCEPTION_PROLOG_PSERIES(area, label)				\
 	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\
 	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\
@@ -604,14 +635,14 @@
 system_reset_fwnmi:
 	HMT_MEDIUM
 	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
 
 	.globl machine_check_fwnmi
       .align 7
 machine_check_fwnmi:
 	HMT_MEDIUM
 	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
 
 #ifdef CONFIG_PPC_ISERIES
 /***  ISeries-LPAR interrupt handlers ***/
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 01bdae3..12c5971 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -322,7 +322,8 @@
 
 static LIST_HEAD(irq_hosts);
 static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED;
-
+static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
+static unsigned int irq_radix_writer;
 struct irq_map_entry irq_map[NR_IRQS];
 static unsigned int irq_virq_count = NR_IRQS;
 static struct irq_host *irq_default_host;
@@ -455,6 +456,58 @@
 		irq_virq_count = count;
 }
 
+/* radix tree not lockless safe ! we use a brlock-type mecanism
+ * for now, until we can use a lockless radix tree
+ */
+static void irq_radix_wrlock(unsigned long *flags)
+{
+	unsigned int cpu, ok;
+
+	spin_lock_irqsave(&irq_big_lock, *flags);
+	irq_radix_writer = 1;
+	smp_mb();
+	do {
+		barrier();
+		ok = 1;
+		for_each_possible_cpu(cpu) {
+			if (per_cpu(irq_radix_reader, cpu)) {
+				ok = 0;
+				break;
+			}
+		}
+		if (!ok)
+			cpu_relax();
+	} while(!ok);
+}
+
+static void irq_radix_wrunlock(unsigned long flags)
+{
+	smp_wmb();
+	irq_radix_writer = 0;
+	spin_unlock_irqrestore(&irq_big_lock, flags);
+}
+
+static void irq_radix_rdlock(unsigned long *flags)
+{
+	local_irq_save(*flags);
+	__get_cpu_var(irq_radix_reader) = 1;
+	smp_mb();
+	if (likely(irq_radix_writer == 0))
+		return;
+	__get_cpu_var(irq_radix_reader) = 0;
+	smp_wmb();
+	spin_lock(&irq_big_lock);
+	__get_cpu_var(irq_radix_reader) = 1;
+	spin_unlock(&irq_big_lock);
+}
+
+static void irq_radix_rdunlock(unsigned long flags)
+{
+	__get_cpu_var(irq_radix_reader) = 0;
+	local_irq_restore(flags);
+}
+
+
 unsigned int irq_create_mapping(struct irq_host *host,
 				irq_hw_number_t hwirq)
 {
@@ -604,13 +657,9 @@
 		/* Check if radix tree allocated yet */
 		if (host->revmap_data.tree.gfp_mask == 0)
 			break;
-		/* XXX radix tree not safe ! remove lock whem it becomes safe
-		 * and use some RCU sync to make sure everything is ok before we
-		 * can re-use that map entry
-		 */
-		spin_lock_irqsave(&irq_big_lock, flags);
+		irq_radix_wrlock(&flags);
 		radix_tree_delete(&host->revmap_data.tree, hwirq);
-		spin_unlock_irqrestore(&irq_big_lock, flags);
+		irq_radix_wrunlock(flags);
 		break;
 	}
 
@@ -677,25 +726,24 @@
 	if (tree->gfp_mask == 0)
 		return irq_find_mapping(host, hwirq);
 
-	/* XXX Current radix trees are NOT SMP safe !!! Remove that lock
-	 * when that is fixed (when Nick's patch gets in
-	 */
-	spin_lock_irqsave(&irq_big_lock, flags);
-
 	/* Now try to resolve */
+	irq_radix_rdlock(&flags);
 	ptr = radix_tree_lookup(tree, hwirq);
+	irq_radix_rdunlock(flags);
+
 	/* Found it, return */
 	if (ptr) {
 		virq = ptr - irq_map;
-		goto bail;
+		return virq;
 	}
 
 	/* If not there, try to insert it */
 	virq = irq_find_mapping(host, hwirq);
-	if (virq != NO_IRQ)
-		radix_tree_insert(tree, virq, &irq_map[virq]);
- bail:
-	spin_unlock_irqrestore(&irq_big_lock, flags);
+	if (virq != NO_IRQ) {
+		irq_radix_wrlock(&flags);
+		radix_tree_insert(tree, hwirq, &irq_map[virq]);
+		irq_radix_wrunlock(flags);
+	}
 	return virq;
 }
 
@@ -806,12 +854,12 @@
 	struct irq_host *h;
 	unsigned long flags;
 
-	spin_lock_irqsave(&irq_big_lock, flags);
+	irq_radix_wrlock(&flags);
 	list_for_each_entry(h, &irq_hosts, link) {
 		if (h->revmap_type == IRQ_HOST_MAP_TREE)
 			INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
 	}
-	spin_unlock_irqrestore(&irq_big_lock, flags);
+	irq_radix_wrunlock(flags);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 9f0898c..cd65c36 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -61,6 +61,8 @@
 	if (!ret) {
 		memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 		p->opcode = *p->addr;
+		flush_icache_range((unsigned long)p->ainsn.insn,
+			(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
 	}
 
 	return ret;
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c
index 7e98e77..40a3929 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -112,9 +112,10 @@
 static int __init add_legacy_soc_port(struct device_node *np,
 				      struct device_node *soc_dev)
 {
-	phys_addr_t addr;
+	u64 addr;
 	u32 *addrp;
 	upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
+	struct device_node *tsi = of_get_parent(np);
 
 	/* We only support ports that have a clock frequency properly
 	 * encoded in the device-tree.
@@ -134,7 +135,10 @@
 	/* Add port, irq will be dealt with later. We passed a translated
 	 * IO port value. It will be fixed up later along with the irq
 	 */
-	return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags, 0);
+	if (tsi && !strcmp(tsi->type, "tsi-bridge"))
+		return add_legacy_port(np, -1, UPIO_TSI, addr, addr, NO_IRQ, flags, 0);
+	else
+		return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags, 0);
 }
 
 static int __init add_legacy_isa_port(struct device_node *np,
@@ -143,7 +147,7 @@
 	u32 *reg;
 	char *typep;
 	int index = -1;
-	phys_addr_t taddr;
+	u64 taddr;
 
 	DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
 
@@ -165,10 +169,13 @@
 	if (typep && *typep == 'S')
 		index = simple_strtol(typep+1, NULL, 0) - 1;
 
-	/* Translate ISA address */
+	/* Translate ISA address. If it fails, we still register the port
+	 * with no translated address so that it can be picked up as an IO
+	 * port later by the serial driver
+	 */
 	taddr = of_translate_address(np, reg);
 	if (taddr == OF_BAD_ADDR)
-		return -1;
+		taddr = 0;
 
 	/* Add port, irq will be dealt with later */
 	return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
@@ -180,7 +187,7 @@
 static int __init add_legacy_pci_port(struct device_node *np,
 				      struct device_node *pci_dev)
 {
-	phys_addr_t addr, base;
+	u64 addr, base;
 	u32 *addrp;
 	unsigned int flags;
 	int iotype, index = -1, lindex = 0;
@@ -461,7 +468,7 @@
 			fixup_port_irq(i, np, port);
 		if (port->iotype == UPIO_PORT)
 			fixup_port_pio(i, np, port);
-		if (port->iotype == UPIO_MEM)
+		if ((port->iotype == UPIO_MEM) || (port->iotype == UPIO_TSI))
 			fixup_port_mmio(i, np, port);
 	}
 
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index a81ca1b..e60a0c5 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -13,6 +13,7 @@
 #include <linux/reboot.h>
 #include <linux/threads.h>
 #include <asm/machdep.h>
+#include <asm/lmb.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -59,3 +60,58 @@
 	}
 	for(;;);
 }
+
+static int __init early_parse_crashk(char *p)
+{
+	unsigned long size;
+
+	if (!p)
+		return 1;
+
+	size = memparse(p, &p);
+
+	if (*p == '@')
+		crashk_res.start = memparse(p + 1, &p);
+	else
+		crashk_res.start = KDUMP_KERNELBASE;
+
+	crashk_res.end = crashk_res.start + size - 1;
+
+	return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+	unsigned long size;
+
+	if (crashk_res.start == 0)
+		return;
+
+	/* We might have got these values via the command line or the
+	 * device tree, either way sanitise them now. */
+
+	size = crashk_res.end - crashk_res.start + 1;
+
+	if (crashk_res.start != KDUMP_KERNELBASE)
+		printk("Crash kernel location must be 0x%x\n",
+				KDUMP_KERNELBASE);
+
+	crashk_res.start = KDUMP_KERNELBASE;
+	size = PAGE_ALIGN(size);
+	crashk_res.end = crashk_res.start + size - 1;
+
+	/* Crash kernel trumps memory limit */
+	if (memory_limit && memory_limit <= crashk_res.end) {
+		memory_limit = crashk_res.end + 1;
+		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+				memory_limit);
+	}
+
+	lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+	return (start + size) > crashk_res.start && start <= crashk_res.end;
+}
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index b438d45..be58985 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -10,7 +10,6 @@
  */
 
 
-#include <linux/cpumask.h>
 #include <linux/kexec.h>
 #include <linux/smp.h>
 #include <linux/thread_info.h>
@@ -21,7 +20,6 @@
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
 #include <asm/paca.h>
-#include <asm/lmb.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>	/* _end */
 #include <asm/prom.h>
@@ -385,58 +383,3 @@
 	return 0;
 }
 __initcall(kexec_setup);
-
-static int __init early_parse_crashk(char *p)
-{
-	unsigned long size;
-
-	if (!p)
-		return 1;
-
-	size = memparse(p, &p);
-
-	if (*p == '@')
-		crashk_res.start = memparse(p + 1, &p);
-	else
-		crashk_res.start = KDUMP_KERNELBASE;
-
-	crashk_res.end = crashk_res.start + size - 1;
-
-	return 0;
-}
-early_param("crashkernel", early_parse_crashk);
-
-void __init reserve_crashkernel(void)
-{
-	unsigned long size;
-
-	if (crashk_res.start == 0)
-		return;
-
-	/* We might have got these values via the command line or the
-	 * device tree, either way sanitise them now. */
-
-	size = crashk_res.end - crashk_res.start + 1;
-
-	if (crashk_res.start != KDUMP_KERNELBASE)
-		printk("Crash kernel location must be 0x%x\n",
-				KDUMP_KERNELBASE);
-
-	crashk_res.start = KDUMP_KERNELBASE;
-	size = PAGE_ALIGN(size);
-	crashk_res.end = crashk_res.start + size - 1;
-
-	/* Crash kernel trumps memory limit */
-	if (memory_limit && memory_limit <= crashk_res.end) {
-		memory_limit = crashk_res.end + 1;
-		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
-				memory_limit);
-	}
-
-	lmb_reserve(crashk_res.start, size);
-}
-
-int overlaps_crashkernel(unsigned long start, unsigned long size)
-{
-	return (start + size) > crashk_res.start && start <= crashk_res.end;
-}
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index bfb407f..e3ed21c 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -687,7 +687,7 @@
 	/* clear out hardware hash page table and tlb */
 	ld	r5,0(r27)		/* deref function descriptor */
 	mtctr	r5
-	bctrl				/* ppc_md.hash_clear_all(void); */
+	bctrl				/* ppc_md.hpte_clear_all(void); */
 
 /*
  *   kexec image calling is:
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 2fce773..138134c 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1289,6 +1289,9 @@
 
 	DBG("Try to map irq for %s...\n", pci_name(pci_dev));
 
+#ifdef DEBUG
+	memset(&oirq, 0xff, sizeof(oirq));
+#endif
 	/* Try to get a mapping from the device-tree */
 	if (of_irq_map_pci(pci_dev, &oirq)) {
 		u8 line, pin;
@@ -1314,8 +1317,9 @@
 		if (virq != NO_IRQ)
 			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
 	} else {
-		DBG(" -> got one, spec %d cells (0x%08x...) on %s\n",
-		    oirq.size, oirq.specifier[0], oirq.controller->full_name);
+		DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+		    oirq.size, oirq.specifier[0], oirq.specifier[1],
+		    oirq.controller->full_name);
 
 		virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
 					     oirq.size);
@@ -1324,6 +1328,9 @@
 		DBG(" -> failed to map !\n");
 		return -1;
 	}
+
+	DBG(" -> mapped to linux irq %d\n", virq);
+
 	pci_dev->irq = virq;
 	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq);
 
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index f6a05f0..39d3bfc 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -126,10 +126,6 @@
 EXPORT_SYMBOL(pci_bus_to_hose);
 #endif /* CONFIG_PCI */
 
-#ifdef CONFIG_NOT_COHERENT_CACHE
-EXPORT_SYMBOL(flush_dcache_all);
-#endif
-
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index ebd501a..4394e54 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -557,7 +557,9 @@
 static void __init early_cmdline_parse(void)
 {
 	struct prom_t *_prom = &RELOC(prom);
+#ifdef CONFIG_PPC64
 	const char *opt;
+#endif
 	char *p;
 	int l = 0;
 
@@ -644,13 +646,13 @@
 	5 - 1,				/* 5 option vectors */
 
 	/* option vector 1: processor architectures supported */
-	3 - 1,				/* length */
+	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
 	OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
 	OV1_PPC_2_04 | OV1_PPC_2_05,
 
 	/* option vector 2: Open Firmware options supported */
-	34 - 1,				/* length */
+	34 - 2,				/* length */
 	OV2_REAL_MODE,
 	0, 0,
 	W(0xffffffff),			/* real_base */
@@ -664,16 +666,16 @@
 	48,				/* max log_2(hash table size) */
 
 	/* option vector 3: processor options supported */
-	3 - 1,				/* length */
+	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
 	OV3_FP | OV3_VMX,
 
 	/* option vector 4: IBM PAPR implementation */
-	2 - 1,				/* length */
+	2 - 2,				/* length */
 	0,				/* don't halt */
 
 	/* option vector 5: PAPR/OF options */
-	3 - 1,				/* length */
+	3 - 2,				/* length */
 	0,				/* don't ignore, don't halt */
 	OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES,
 };
@@ -2030,6 +2032,39 @@
 #define fixup_device_tree_maple()
 #endif
 
+#ifdef CONFIG_PPC_CHRP
+/* Pegasos lacks the "ranges" property in the isa node */
+static void __init fixup_device_tree_chrp(void)
+{
+	phandle isa;
+	u32 isa_ranges[6];
+	char *name;
+	int rc;
+
+	name = "/pci@80000000/isa@c";
+	isa = call_prom("finddevice", 1, 1, ADDR(name));
+	if (!PHANDLE_VALID(isa))
+		return;
+
+	rc = prom_getproplen(isa, "ranges");
+	if (rc != 0 && rc != PROM_ERROR)
+		return;
+
+	prom_printf("Fixing up missing ISA range on Pegasos...\n");
+
+	isa_ranges[0] = 0x1;
+	isa_ranges[1] = 0x0;
+	isa_ranges[2] = 0x01006000;
+	isa_ranges[3] = 0x0;
+	isa_ranges[4] = 0x0;
+	isa_ranges[5] = 0x00010000;
+	prom_setprop(isa, name, "ranges",
+			isa_ranges, sizeof(isa_ranges));
+}
+#else
+#define fixup_device_tree_chrp()
+#endif
+
 #if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
 static void __init fixup_device_tree_pmac(void)
 {
@@ -2077,6 +2112,7 @@
 static void __init fixup_device_tree(void)
 {
 	fixup_device_tree_maple();
+	fixup_device_tree_chrp();
 	fixup_device_tree_pmac();
 }
 
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 6a7e997c..a10825a 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -598,11 +598,6 @@
 	return p;
 }
 
-static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
-{
-	return (((pin - 1) + slot) % 4) + 1;
-}
-
 /* This doesn't need to be called if you don't have any special workaround
  * flags to pass
  */
@@ -644,14 +639,17 @@
 
 }
 
-int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
-		   struct of_irq *out_irq)
+int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
+		   u32 *addr, struct of_irq *out_irq)
 {
 	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
 	u32 *tmp, *imap, *imask;
 	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
 	int imaplen, match, i;
 
+	DBG("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+	    parent->full_name, intspec[0], intspec[1], ointsize);
+
 	ipar = of_node_get(parent);
 
 	/* First get the #interrupt-cells property of the current cursor
@@ -675,6 +673,9 @@
 
 	DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
 
+	if (ointsize != intsize)
+		return -EINVAL;
+
 	/* Look for this #address-cells. We have to implement the old linux
 	 * trick of looking for the parent here as some device-trees rely on it
 	 */
@@ -880,17 +881,26 @@
 	}
 	intsize = *tmp;
 
+	DBG(" intsize=%d intlen=%d\n", intsize, intlen);
+
 	/* Check index */
 	if ((index + 1) * intsize > intlen)
 		return -EINVAL;
 
 	/* Get new specifier and map it */
-	res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq);
+	res = of_irq_map_raw(p, intspec + index * intsize, intsize,
+			     addr, out_irq);
 	of_node_put(p);
 	return res;
 }
 EXPORT_SYMBOL_GPL(of_irq_map_one);
 
+#ifdef CONFIG_PCI
+static u8 of_irq_pci_swizzle(u8 slot, u8 pin)
+{
+	return (((pin - 1) + slot) % 4) + 1;
+}
+
 int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
 {
 	struct device_node *dn, *ppnode;
@@ -964,7 +974,7 @@
 	laddr[0] = (pdev->bus->number << 16)
 		| (pdev->devfn << 8);
 	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, laddr, out_irq);
+	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
 }
 EXPORT_SYMBOL_GPL(of_irq_map_pci);
-
+#endif /* CONFIG_PCI */
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4a4cb55..77f1e06 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -569,6 +569,27 @@
 }
 EXPORT_SYMBOL(rtas_set_indicator);
 
+/*
+ * Ignoring RTAS extended delay
+ */
+int rtas_set_indicator_fast(int indicator, int index, int new_value)
+{
+	int rc;
+	int token = rtas_token("set-indicator");
+
+	if (token == RTAS_UNKNOWN_SERVICE)
+		return -ENOENT;
+
+	rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
+
+	WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905));
+
+	if (rc < 0)
+		return rtas_error_rc(rc);
+
+	return rc;
+}
+
 void rtas_restart(char *cmd)
 {
 	if (rtas_flash_term_hook)
diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c
index f19e2e0..de59c6c 100644
--- a/arch/powerpc/kernel/smp-tbsync.c
+++ b/arch/powerpc/kernel/smp-tbsync.c
@@ -45,8 +45,9 @@
 {
 	int cmd;
 	u64 tb;
+	unsigned long flags;
 
-	local_irq_disable();
+	local_irq_save(flags);
 	while (!running)
 		barrier();
 	rmb();
@@ -70,7 +71,7 @@
 			set_tb(tb >> 32, tb & 0xfffffffful);
 		enter_contest(tbsync->mark, -1);
 	}
-	local_irq_enable();
+	local_irq_restore(flags);
 }
 
 static int __devinit start_contest(int cmd, long offset, int num)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 46c56cf..6a9bc9c 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -144,13 +144,15 @@
 
 void smp_send_reschedule(int cpu)
 {
-	smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
+	if (likely(smp_ops))
+		smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
 }
 
 #ifdef CONFIG_DEBUGGER
 void smp_send_debugger_break(int cpu)
 {
-	smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
+	if (likely(smp_ops))
+		smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK);
 }
 #endif
 
@@ -158,7 +160,7 @@
 void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
 {
 	crash_ipi_function_ptr = crash_ipi_callback;
-	if (crash_ipi_callback) {
+	if (crash_ipi_callback && smp_ops) {
 		mb();
 		smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_DEBUGGER_BREAK);
 	}
@@ -220,6 +222,9 @@
 	/* Can deadlock when called with interrupts disabled */
 	WARN_ON(irqs_disabled());
 
+	if (unlikely(smp_ops == NULL))
+		return -1;
+
 	data.func = func;
 	data.info = info;
 	atomic_set(&data.started, 0);
@@ -357,7 +362,10 @@
 	smp_store_cpu_info(boot_cpuid);
 	cpu_callin_map[boot_cpuid] = 1;
 
-	max_cpus = smp_ops->probe();
+	if (smp_ops)
+		max_cpus = smp_ops->probe();
+	else
+		max_cpus = 1;
  
 	smp_space_timers(max_cpus);
 
@@ -453,7 +461,7 @@
 
 static int __devinit cpu_enable(unsigned int cpu)
 {
-	if (smp_ops->cpu_enable)
+	if (smp_ops && smp_ops->cpu_enable)
 		return smp_ops->cpu_enable(cpu);
 
 	return -ENOSYS;
@@ -467,7 +475,8 @@
 	if (!cpu_enable(cpu))
 		return 0;
 
-	if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
+	if (smp_ops == NULL ||
+	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
 		return -EINVAL;
 
 	/* Make sure callin-map entry is 0 (can be leftover a CPU
@@ -568,7 +577,8 @@
 	old_mask = current->cpus_allowed;
 	set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid));
 	
-	smp_ops->setup_cpu(boot_cpuid);
+	if (smp_ops)
+		smp_ops->setup_cpu(boot_cpuid);
 
 	set_cpus_allowed(current, old_mask);
 
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0104350..fec228c 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -278,7 +278,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit sysfs_cpu_notify(struct notifier_block *self,
+static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
 				      unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned int)(long)hcpu;
@@ -296,7 +296,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata sysfs_cpu_nb = {
+static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
 	.notifier_call	= sysfs_cpu_notify,
 };
 
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 774c0a3..a124499 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -125,15 +125,8 @@
 unsigned long ppc_proc_freq;
 unsigned long ppc_tb_freq;
 
-u64 tb_last_jiffy __cacheline_aligned_in_smp;
-unsigned long tb_last_stamp;
-
-/*
- * Note that on ppc32 this only stores the bottom 32 bits of
- * the timebase value, but that's enough to tell when a jiffy
- * has passed.
- */
-DEFINE_PER_CPU(unsigned long, last_jiffy);
+static u64 tb_last_jiffy __cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(u64, last_jiffy);
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -417,7 +410,7 @@
 /*
  * This version of gettimeofday has microsecond resolution.
  */
-static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val)
+static inline void __do_gettimeofday(struct timeval *tv)
 {
 	unsigned long sec, usec;
 	u64 tb_ticks, xsec;
@@ -431,7 +424,12 @@
 	 * without a divide (and in fact, without a multiply)
 	 */
 	temp_varp = do_gtod.varp;
-	tb_ticks = tb_val - temp_varp->tb_orig_stamp;
+
+	/* Sampling the time base must be done after loading
+	 * do_gtod.varp in order to avoid racing with update_gtod.
+	 */
+	data_barrier(temp_varp);
+	tb_ticks = get_tb() - temp_varp->tb_orig_stamp;
 	temp_tb_to_xs = temp_varp->tb_to_xs;
 	temp_stamp_xsec = temp_varp->stamp_xsec;
 	xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
@@ -453,7 +451,7 @@
 		do {
 			seq = read_seqbegin_irqsave(&xtime_lock, flags);
 			sec = xtime.tv_sec;
-			nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp);
+			nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
 		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 		usec = nsec / 1000;
 		while (usec >= 1000000) {
@@ -464,7 +462,7 @@
 		tv->tv_usec = usec;
 		return;
 	}
-	__do_gettimeofday(tv, get_tb());
+	__do_gettimeofday(tv);
 }
 
 EXPORT_SYMBOL(do_gettimeofday);
@@ -650,6 +648,7 @@
 	int next_dec;
 	int cpu = smp_processor_id();
 	unsigned long ticks;
+	u64 tb_next_jiffy;
 
 #ifdef CONFIG_PPC32
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
@@ -691,11 +690,13 @@
 			continue;
 
 		write_seqlock(&xtime_lock);
-		tb_last_jiffy += tb_ticks_per_jiffy;
-		tb_last_stamp = per_cpu(last_jiffy, cpu);
-		do_timer(regs);
-		timer_recalc_offset(tb_last_jiffy);
-		timer_check_rtc();
+		tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
+		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
+			tb_last_jiffy = tb_next_jiffy;
+			do_timer(regs);
+			timer_recalc_offset(tb_last_jiffy);
+			timer_check_rtc();
+		}
 		write_sequnlock(&xtime_lock);
 	}
 	
@@ -740,7 +741,7 @@
 	int i;
 	unsigned long half = tb_ticks_per_jiffy / 2;
 	unsigned long offset = tb_ticks_per_jiffy / max_cpus;
-	unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid);
+	u64 previous_tb = per_cpu(last_jiffy, boot_cpuid);
 
 	/* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
 	previous_tb -= tb_ticks_per_jiffy;
@@ -821,7 +822,7 @@
 	 * and therefore the (jiffies - wall_jiffies) computation
 	 * has been removed.
 	 */
-	tb_delta = tb_ticks_since(tb_last_stamp);
+	tb_delta = tb_ticks_since(tb_last_jiffy);
 	tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
 	new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
 
@@ -941,8 +942,7 @@
 	if (__USE_RTC()) {
 		/* 601 processor: dec counts down by 128 every 128ns */
 		ppc_tb_freq = 1000000000;
-		tb_last_stamp = get_rtcl();
-		tb_last_jiffy = tb_last_stamp;
+		tb_last_jiffy = get_rtcl();
 	} else {
 		/* Normal PowerPC with timebase register */
 		ppc_md.calibrate_decr();
@@ -950,7 +950,7 @@
 		       ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
 		printk(KERN_DEBUG "time_init: processor frequency   = %lu.%.6lu MHz\n",
 		       ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
-		tb_last_stamp = tb_last_jiffy = get_tb();
+		tb_last_jiffy = get_tb();
 	}
 
 	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
@@ -1027,7 +1027,7 @@
 	do_gtod.varp = &do_gtod.vars[0];
 	do_gtod.var_idx = 0;
 	do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
-	__get_cpu_var(last_jiffy) = tb_last_stamp;
+	__get_cpu_var(last_jiffy) = tb_last_jiffy;
 	do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
 	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 	do_gtod.varp->tb_to_xs = tb_to_xs;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 3c66807..9b352bd 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -55,9 +55,6 @@
 
 #ifdef CONFIG_PPC64	/* XXX */
 #define _IO_BASE	pci_io_base
-#ifdef CONFIG_KEXEC
-cpumask_t cpus_in_sr = CPU_MASK_NONE;
-#endif
 #endif
 
 #ifdef CONFIG_DEBUGGER
@@ -150,13 +147,9 @@
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
-	if (panic_on_oops) {
-#ifdef CONFIG_PPC64
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
-		ssleep(5);
-#endif
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
+
 	do_exit(err);
 
 	return 0;
@@ -215,6 +208,19 @@
 
 	die("System Reset", regs, SIGABRT);
 
+	/*
+	 * Some CPUs when released from the debugger will execute this path.
+	 * These CPUs entered the debugger via a soft-reset. If the CPU was
+	 * hung before entering the debugger it will return to the hung
+	 * state when exiting this function.  This causes a problem in
+	 * kdump since the hung CPU(s) will not respond to the IPI sent
+	 * from kdump. To prevent the problem we call crash_kexec_secondary()
+	 * here. If a kdump had not been initiated or we exit the debugger
+	 * with the "exit and recover" command (x) crash_kexec_secondary()
+	 * will return after 5ms and the CPU returns to its previous state.
+	 */
+	crash_kexec_secondary(regs);
+
 	/* Must die if the interrupt is not recoverable */
 	if (!(regs->msr & MSR_RI))
 		panic("Unrecoverable System Reset");
@@ -579,14 +585,14 @@
 #define INST_MFSPR_PVR_MASK	0xfc1fffff
 
 #define INST_DCBA		0x7c0005ec
-#define INST_DCBA_MASK		0x7c0007fe
+#define INST_DCBA_MASK		0xfc0007fe
 
 #define INST_MCRXR		0x7c000400
-#define INST_MCRXR_MASK		0x7c0007fe
+#define INST_MCRXR_MASK		0xfc0007fe
 
 #define INST_STRING		0x7c00042a
-#define INST_STRING_MASK	0x7c0007fe
-#define INST_STRING_GEN_MASK	0x7c00067e
+#define INST_STRING_MASK	0xfc0007fe
+#define INST_STRING_GEN_MASK	0xfc00067e
 #define INST_LSWI		0x7c0004aa
 #define INST_LSWX		0x7c00042a
 #define INST_STSWI		0x7c0005aa
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
index 0835b48..2d17f2b 100644
--- a/arch/powerpc/kernel/udbg_16550.c
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -81,10 +81,14 @@
 void udbg_init_uart(void __iomem *comport, unsigned int speed,
 		    unsigned int clock)
 {
-	unsigned int dll, base_bauds = clock / 16;
+	unsigned int dll, base_bauds;
 
+	if (clock == 0)
+		clock = 1843200;
 	if (speed == 0)
 		speed = 9600;
+
+	base_bauds = clock / 16;
 	dll = base_bauds / speed;
 
 	if (comport) {
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index 8a3bed5..3726358 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -14,7 +14,8 @@
 
 
 EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
-EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \
+		$(call ld-option, -Wl$(comma)--hash-style=sysv)
 EXTRA_AFLAGS := -D__VDSO32__ -s
 
 obj-y += vdso32_wrapper.o
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
index f4bad72..6187af2 100644
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
@@ -14,6 +14,7 @@
 {
   . = VDSO32_LBASE + SIZEOF_HEADERS;
   .hash           : { *(.hash) }			:text
+  .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
   .dynstr         : { *(.dynstr) }
   .gnu.version    : { *(.gnu.version) }
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index ab39988..43af9b2 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -8,7 +8,8 @@
 obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
 
 EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
-EXTRA_CFLAGS +=  -nostdlib -Wl,-soname=linux-vdso64.so.1
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
+		$(call ld-option, -Wl$(comma)--hash-style=sysv)
 EXTRA_AFLAGS := -D__VDSO64__ -s
 
 obj-y += vdso64_wrapper.o
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S
index 4bdf224..4a2b6dc 100644
--- a/arch/powerpc/kernel/vdso64/vdso64.lds.S
+++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S
@@ -12,6 +12,7 @@
 {
   . = VDSO64_LBASE + SIZEOF_HEADERS;
   .hash           : { *(.hash) }		:text
+  .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
   .dynstr         : { *(.dynstr) }
   .gnu.version    : { *(.gnu.version) }
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S
index fd66acf..7173ba9 100644
--- a/arch/powerpc/lib/memcpy_64.S
+++ b/arch/powerpc/lib/memcpy_64.S
@@ -11,6 +11,7 @@
 
 	.align	7
 _GLOBAL(memcpy)
+	std	r3,48(r1)	/* save destination pointer for return value */
 	mtcrf	0x01,r5
 	cmpldi	cr1,r5,16
 	neg	r6,r3		# LS 3 bits = # bytes to 8-byte dest bdry
@@ -38,7 +39,7 @@
 	stdu	r9,16(r3)
 	bdnz	1b
 3:	std	r8,8(r3)
-	beqlr
+	beq	3f
 	addi	r3,r3,16
 	ld	r9,8(r4)
 .Ldo_tail:
@@ -53,7 +54,8 @@
 2:	bf	cr7*4+3,3f
 	rotldi	r9,r9,8
 	stb	r9,0(r3)
-3:	blr
+3:	ld	r3,48(r1)	/* return dest pointer */
+	blr
 
 .Lsrc_unaligned:
 	srdi	r6,r5,3
@@ -115,7 +117,7 @@
 5:	srd	r12,r9,r11
 	or	r12,r8,r12
 	std	r12,24(r3)
-	beqlr
+	beq	4f
 	cmpwi	cr1,r5,8
 	addi	r3,r3,32
 	sld	r9,r9,r10
@@ -167,4 +169,5 @@
 3:	bf	cr7*4+3,4f
 	lbz	r0,0(r4)
 	stb	r0,0(r3)
-4:	blr
+4:	ld	r3,48(r1)	/* return dest pointer */
+	blr
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 376829e..0a0a0487b 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -103,7 +103,7 @@
 
 	/* Determine number of entries necessary to cover lowmem */
 	pinned_tlbs = (unsigned int)
-		(_ALIGN(total_lowmem, PPC44x_PIN_SIZE) >> PPC44x_PIN_SHIFT);
+		(_ALIGN(total_lowmem, PPC_PIN_SIZE) >> PPC44x_PIN_SHIFT);
 
 	/* Write upper watermark to save location */
 	tlb_44x_hwater = PPC44x_LOW_SLOT - pinned_tlbs;
@@ -111,7 +111,7 @@
 	/* If necessary, set additional pinned TLBs */
 	if (pinned_tlbs > 1)
 		for (i = (PPC44x_LOW_SLOT-(pinned_tlbs-1)); i < PPC44x_LOW_SLOT; i++) {
-			unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
+			unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC_PIN_SIZE;
 			ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
 		}
 
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 266b8b2..5615acc 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -153,7 +153,7 @@
 	hpdp->pd = 0;
 	tlb->need_flush = 1;
 	pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
-						 HUGEPTE_TABLE_SIZE-1));
+						 PGF_CACHENUM_MASK));
 }
 
 #ifdef CONFIG_PPC_64K_PAGES
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 4b17a73..716a290 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -320,7 +320,8 @@
 		break;
 	}
 
-	lmb.rmo_size = lmb.memory.region[0].size;
+	if (lmb.memory.region[0].size < lmb.rmo_size)
+		lmb.rmo_size = lmb.memory.region[0].size;
 
 	/* And truncate any reserves above the limit also. */
 	for (i = 0; i < lmb.reserved.cnt; i++) {
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index b463056..cf3967a 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -46,26 +46,6 @@
 unsigned long isa_mem_base = 0;
 #endif
 
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	    /*
-	     *      PCI IDSEL/INTPIN->INTLINE
-	     *       A      B      C      D
-	     */
-	{
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* idsel 0x0e */
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x0f */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x10 */
-	};
-
-	const long min_idsel = 0x0e, max_idsel = 0x10, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif				/* CONFIG_PCI */
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -92,8 +72,6 @@
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc83xx_map_irq;
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
@@ -106,25 +84,13 @@
 
 void __init mpc834x_itx_init_IRQ(void)
 {
-	u8 senses[8] = {
-		0,			/* EXT 0 */
-		IRQ_SENSE_LEVEL,	/* EXT 1 */
-		IRQ_SENSE_LEVEL,	/* EXT 2 */
-		0,			/* EXT 3 */
-#ifdef CONFIG_PCI
-		IRQ_SENSE_LEVEL,	/* EXT 4 */
-		IRQ_SENSE_LEVEL,	/* EXT 5 */
-		IRQ_SENSE_LEVEL,	/* EXT 6 */
-		IRQ_SENSE_LEVEL,	/* EXT 7 */
-#else
-		0,			/* EXT 4 */
-		0,			/* EXT 5 */
-		0,			/* EXT 6 */
-		0,			/* EXT 7 */
-#endif
-	};
+	struct device_node *np;
 
-	ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
@@ -153,4 +119,7 @@
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup		= mpc83xx_pcibios_fixup,
+#endif
 };
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c
index 3e1c16e..32df239 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_sys.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c
@@ -43,33 +43,6 @@
 unsigned long isa_mem_base = 0;
 #endif
 
-#ifdef CONFIG_PCI
-static int
-mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	    /*
-	     *      PCI IDSEL/INTPIN->INTLINE
-	     *       A      B      C      D
-	     */
-	{
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x11 */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x12 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x13 */
-		{0, 0, 0, 0},
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* idsel 0x15 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* idsel 0x16 */
-		{PIRQC, PIRQD, PIRQA, PIRQB},	/* idsel 0x17 */
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* idsel 0x18 */
-		{0, 0, 0, 0},			/* idsel 0x19 */
-		{0, 0, 0, 0},			/* idsel 0x20 */
-	};
-
-	const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-#endif				/* CONFIG_PCI */
-
 /* ************************************************************************
  *
  * Setup the architecture
@@ -96,8 +69,6 @@
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc83xx_map_irq;
 	ppc_md.pci_exclude_device = mpc83xx_exclude_device;
 #endif
 
@@ -110,25 +81,13 @@
 
 void __init mpc834x_sys_init_IRQ(void)
 {
-	u8 senses[8] = {
-		0,			/* EXT 0 */
-		IRQ_SENSE_LEVEL,	/* EXT 1 */
-		IRQ_SENSE_LEVEL,	/* EXT 2 */
-		0,			/* EXT 3 */
-#ifdef CONFIG_PCI
-		IRQ_SENSE_LEVEL,	/* EXT 4 */
-		IRQ_SENSE_LEVEL,	/* EXT 5 */
-		IRQ_SENSE_LEVEL,	/* EXT 6 */
-		IRQ_SENSE_LEVEL,	/* EXT 7 */
-#else
-		0,			/* EXT 4 */
-		0,			/* EXT 5 */
-		0,			/* EXT 6 */
-		0,			/* EXT 7 */
-#endif
-	};
+	struct device_node *np;
 
-	ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8);
+	np = of_find_node_by_type(NULL, "ipic");
+	if (!np)
+		return;
+
+	ipic_init(np, 0);
 
 	/* Initialize the default interrupt mapping priorities,
 	 * in case the boot rom changed something on us.
@@ -178,4 +137,7 @@
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
+#ifdef CONFIG_PCI
+	.pcibios_fixup		= mpc83xx_pcibios_fixup,
+#endif
 };
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h
index 01cae10..2c82bca 100644
--- a/arch/powerpc/platforms/83xx/mpc83xx.h
+++ b/arch/powerpc/platforms/83xx/mpc83xx.h
@@ -11,6 +11,7 @@
 
 extern int add_bridge(struct device_node *dev);
 extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
+extern void mpc83xx_pcibios_fixup(void);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c
index 3b5e563..5d84a9c 100644
--- a/arch/powerpc/platforms/83xx/pci.c
+++ b/arch/powerpc/platforms/83xx/pci.c
@@ -45,6 +45,15 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
+void __init mpc83xx_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	/* map all the PCI irqs */
+	for_each_pci_dev(dev)
+		pci_read_irq_line(dev);
+}
+
 int __init add_bridge(struct device_node *dev)
 {
 	int len;
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 454fc53..c3268d9 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -14,7 +14,6 @@
 config MPC85xx_CDS
 	bool "Freescale MPC85xx CDS"
 	select DEFAULT_UIMAGE
-	select PPC_I8259 if PCI
 	help
 	  This option enables support for the MPC85xx CDS board
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 06a4976..9d2acfb 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -37,79 +37,7 @@
 unsigned long isa_mem_base = 0;
 #endif
 
-/*
- * Internal interrupts are all Level Sensitive, and Positive Polarity
- *
- * Note:  Likely, this table and the following function should be
- *        obtained and derived from the OF Device Tree.
- */
-static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
-	MPC85XX_INTERNAL_IRQ_SENSES,
-	0x0,			/* External  0: */
-#if defined(CONFIG_PCI)
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 1: PCI slot 0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 2: PCI slot 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 3: PCI slot 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 4: PCI slot 3 */
-#else
-	0x0,			/* External  1: */
-	0x0,			/* External  2: */
-	0x0,			/* External  3: */
-	0x0,			/* External  4: */
-#endif
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
-	0x0,			/* External  6: */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 7: PHY */
-	0x0,			/* External  8: */
-	0x0,			/* External  9: */
-	0x0,			/* External 10: */
-	0x0,			/* External 11: */
-};
-
 #ifdef CONFIG_PCI
-/*
- * interrupt routing
- */
-
-int
-mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] =
-	    /*
-	     * This is little evil, but works around the fact
-	     * that revA boards have IDSEL starting at 18
-	     * and others boards (older) start at 12
-	     *
-	     *      PCI IDSEL/INTPIN->INTLINE
-	     *       A      B      C      D
-	     */
-	{
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 2 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},
-		{PIRQC, PIRQD, PIRQA, PIRQB},
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 5 */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 12 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},
-		{PIRQC, PIRQD, PIRQA, PIRQB},
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 15 */
-		{0, 0, 0, 0},	/* -- */
-		{0, 0, 0, 0},	/* -- */
-		{PIRQA, PIRQB, PIRQC, PIRQD},	/* IDSEL 18 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},
-		{PIRQC, PIRQD, PIRQA, PIRQB},
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 21 */
-	};
-
-	const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP;
-}
-
 int
 mpc85xx_exclude_device(u_char bus, u_char devfn)
 {
@@ -119,44 +47,63 @@
 		return PCIBIOS_SUCCESSFUL;
 }
 
+void __init
+mpc85xx_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	for_each_pci_dev(dev)
+		pci_read_irq_line(dev);
+}
 #endif /* CONFIG_PCI */
 
 
 void __init mpc85xx_ads_pic_init(void)
 {
-	struct mpic *mpic1;
-	phys_addr_t OpenPIC_PAddr;
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np = NULL;
 
-	/* Determine the Physical Address of the OpenPIC regs */
-	OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
+	np = of_find_node_by_type(np, "open-pic");
 
-	mpic1 = mpic_alloc(OpenPIC_PAddr,
-			   MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			   4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
-			   mpc85xx_ads_openpic_initsenses,
-			   sizeof(mpc85xx_ads_openpic_initsenses),
-			   " OpenPIC  ");
-	BUG_ON(mpic1 == NULL);
-	mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
-	mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
-	mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
-	mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
-	mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
-	mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
-	mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
-	mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
 
-	/* dummy mappings to get to 48 */
-	mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
-	mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
-	mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
-	mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
+	if(of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Could not map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
 
-	/* External ints */
-	mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
-	mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
-	mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
-	mpic_init(mpic1);
+	mpic = mpic_alloc(np, r.start,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			4, 0, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	of_node_put(np);
+
+	mpic_assign_isu(mpic, 0, r.start + 0x10200);
+	mpic_assign_isu(mpic, 1, r.start + 0x10280);
+	mpic_assign_isu(mpic, 2, r.start + 0x10300);
+	mpic_assign_isu(mpic, 3, r.start + 0x10380);
+	mpic_assign_isu(mpic, 4, r.start + 0x10400);
+	mpic_assign_isu(mpic, 5, r.start + 0x10480);
+	mpic_assign_isu(mpic, 6, r.start + 0x10500);
+	mpic_assign_isu(mpic, 7, r.start + 0x10580);
+
+	/* Unused on this platform (leave room for 8548) */
+	mpic_assign_isu(mpic, 8, r.start + 0x10600);
+	mpic_assign_isu(mpic, 9, r.start + 0x10680);
+	mpic_assign_isu(mpic, 10, r.start + 0x10700);
+	mpic_assign_isu(mpic, 11, r.start + 0x10780);
+
+	/* External Interrupts */
+	mpic_assign_isu(mpic, 12, r.start + 0x10000);
+	mpic_assign_isu(mpic, 13, r.start + 0x10080);
+	mpic_assign_isu(mpic, 14, r.start + 0x10100);
+
+	mpic_init(mpic);
 }
 
 /*
@@ -165,7 +112,9 @@
 static void __init mpc85xx_ads_setup_arch(void)
 {
 	struct device_node *cpu;
+#ifdef CONFIG_PCI
 	struct device_node *np;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
@@ -186,8 +135,7 @@
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc85xx_map_irq;
+	ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 18e6e11..1d357d3 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -57,94 +57,8 @@
 static int cds_pci_slot = 2;
 static volatile u8 *cadmus;
 
-/*
- * Internal interrupts are all Level Sensitive, and Positive Polarity
- *
- * Note:  Likely, this table and the following function should be
- *        obtained and derived from the OF Device Tree.
- */
-static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
-	MPC85XX_INTERNAL_IRQ_SENSES,
-#if defined(CONFIG_PCI)
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Ext 0: PCI slot 0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 1: PCI slot 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 2: PCI slot 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 3: PCI slot 3 */
-#else
-	0x0,				/* External  0: */
-	0x0,				/* External  1: */
-	0x0,				/* External  2: */
-	0x0,				/* External  3: */
-#endif
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
-	0x0,				/* External  6: */
-	0x0,				/* External  7: */
-	0x0,				/* External  8: */
-	0x0,				/* External  9: */
-	0x0,				/* External 10: */
-#ifdef CONFIG_PCI
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),    /* Ext 11: PCI2 slot 0 */
-#else
-	0x0,				/* External 11: */
-#endif
-};
-
 
 #ifdef CONFIG_PCI
-/*
- * interrupt routing
- */
-int
-mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
-
-	if (!hose->index)
-	{
-		/* Handle PCI1 interrupts */
-		char pci_irq_table[][4] =
-			/*
-			 *      PCI IDSEL/INTPIN->INTLINE
-			 *        A      B      C      D
-			 */
-
-			/* Note IRQ assignment for slots is based on which slot the elysium is
-			 * in -- in this setup elysium is in slot #2 (this PIRQA as first
-			 * interrupt on slot */
-		{
-			{ 0, 1, 2, 3 }, /* 16 - PMC */
-			{ 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
-			{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
-			{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
-			{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
-			{ 3, 0, 1, 2 }, /* 21 - Slot 4 */
-		};
-
-		const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
-		int i, j;
-
-		for (i = 0; i < 6; i++)
-			for (j = 0; j < 4; j++)
-				pci_irq_table[i][j] =
-					((pci_irq_table[i][j] + 5 -
-					  cds_pci_slot) & 0x3) + PIRQ0A;
-
-		return PCI_IRQ_TABLE_LOOKUP;
-	} else {
-		/* Handle PCI2 interrupts (if we have one) */
-		char pci_irq_table[][4] =
-		{
-			/*
-			 * We only have one slot and one interrupt
-			 * going to PIRQA - PIRQD */
-			{ PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
-		};
-
-		const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
-
-		return PCI_IRQ_TABLE_LOOKUP;
-	}
-}
 
 #define ARCADIA_HOST_BRIDGE_IDSEL	17
 #define ARCADIA_2ND_BRIDGE_IDSEL	3
@@ -210,50 +124,104 @@
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
 		pci_dev_put(dev);
 	}
+
+	/* Now map all the PCI irqs */
+	dev = NULL;
+	for_each_pci_dev(dev)
+		pci_read_irq_line(dev);
 }
+
+#ifdef CONFIG_PPC_I8259
+#warning The i8259 PIC support is currently broken
+static void mpc85xx_8259_cascade(unsigned int irq, struct
+		irq_desc *desc, struct pt_regs *regs)
+{
+	unsigned int cascade_irq = i8259_irq(regs);
+
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq, regs);
+
+	desc->chip->eoi(irq);
+}
+#endif /* PPC_I8259 */
 #endif /* CONFIG_PCI */
 
 void __init mpc85xx_cds_pic_init(void)
 {
-	struct mpic *mpic1;
-	phys_addr_t OpenPIC_PAddr;
+	struct mpic *mpic;
+	struct resource r;
+	struct device_node *np = NULL;
+	struct device_node *cascade_node = NULL;
+	int cascade_irq;
 
-	/* Determine the Physical Address of the OpenPIC regs */
-	OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
+	np = of_find_node_by_type(np, "open-pic");
 
-	mpic1 = mpic_alloc(OpenPIC_PAddr,
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Failed to map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+
+	mpic = mpic_alloc(np, r.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
-			mpc85xx_cds_openpic_initsenses,
-			sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC  ");
-	BUG_ON(mpic1 == NULL);
-	mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
-	mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
-	mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
-	mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
-	mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
-	mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
-	mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
-	mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
+			4, 0, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
 
-	/* dummy mappings to get to 48 */
-	mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
-	mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
-	mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
-	mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
+	/* Return the mpic node */
+	of_node_put(np);
 
-	/* External ints */
-	mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
-	mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
-	mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
+	mpic_assign_isu(mpic, 0, r.start + 0x10200);
+	mpic_assign_isu(mpic, 1, r.start + 0x10280);
+	mpic_assign_isu(mpic, 2, r.start + 0x10300);
+	mpic_assign_isu(mpic, 3, r.start + 0x10380);
+	mpic_assign_isu(mpic, 4, r.start + 0x10400);
+	mpic_assign_isu(mpic, 5, r.start + 0x10480);
+	mpic_assign_isu(mpic, 6, r.start + 0x10500);
+	mpic_assign_isu(mpic, 7, r.start + 0x10580);
 
-	mpic_init(mpic1);
+	/* Used only for 8548 so far, but no harm in
+	 * allocating them for everyone */
+	mpic_assign_isu(mpic, 8, r.start + 0x10600);
+	mpic_assign_isu(mpic, 9, r.start + 0x10680);
+	mpic_assign_isu(mpic, 10, r.start + 0x10700);
+	mpic_assign_isu(mpic, 11, r.start + 0x10780);
 
-#ifdef CONFIG_PCI
-	mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL);
+	/* External Interrupts */
+	mpic_assign_isu(mpic, 12, r.start + 0x10000);
+	mpic_assign_isu(mpic, 13, r.start + 0x10080);
+	mpic_assign_isu(mpic, 14, r.start + 0x10100);
 
-	i8259_init(0,0);
-#endif
+	mpic_init(mpic);
+
+#ifdef CONFIG_PPC_I8259
+	/* Initialize the i8259 controller */
+	for_each_node_by_type(np, "interrupt-controller")
+		if (device_is_compatible(np, "chrp,iic")) {
+			cascade_node = np;
+			break;
+		}
+
+	if (cascade_node == NULL) {
+		printk(KERN_DEBUG "Could not find i8259 PIC\n");
+		return;
+	}
+
+	cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+	if (cascade_irq == NO_IRQ) {
+		printk(KERN_ERR "Failed to map cascade interrupt\n");
+		return;
+	}
+
+	i8259_init(cascade_node, 0);
+	of_node_put(cascade_node);
+
+	set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade);
+#endif /* CONFIG_PPC_I8259 */
 }
 
 
@@ -298,8 +266,6 @@
 		add_bridge(np);
 
 	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc85xx_map_irq;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
index 5d2bcf7..41e554c 100644
--- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -16,38 +16,6 @@
 
 #include <linux/init.h>
 
-/* PCI interrupt controller */
-#define PIRQA		3
-#define PIRQB		4
-#define PIRQC		5
-#define PIRQD		6
-#define PIRQ7		7
-#define PIRQE		9
-#define PIRQF		10
-#define PIRQG		11
-#define PIRQH		12
-
-/* PCI-Express memory map */
-#define MPC86XX_PCIE_LOWER_IO        0x00000000
-#define MPC86XX_PCIE_UPPER_IO        0x00ffffff
-
-#define MPC86XX_PCIE_LOWER_MEM       0x80000000
-#define MPC86XX_PCIE_UPPER_MEM       0x9fffffff
-
-#define MPC86XX_PCIE_IO_BASE         0xe2000000
-#define MPC86XX_PCIE_MEM_OFFSET      0x00000000
-
-#define MPC86XX_PCIE_IO_SIZE         0x01000000
-
-#define PCIE1_CFG_ADDR_OFFSET    (0x8000)
-#define PCIE1_CFG_DATA_OFFSET    (0x8004)
-
-#define PCIE2_CFG_ADDR_OFFSET    (0x9000)
-#define PCIE2_CFG_DATA_OFFSET    (0x9004)
-
-#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET
-#define MPC86xx_PCIE_SIZE	(0x1000)
-
 #define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
 
 #endif	/* __MPC8641_HPCN_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index ebae73e..0b1b521 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -37,6 +37,14 @@
 #include "mpc86xx.h"
 #include "mpc8641_hpcn.h"
 
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) do { printk(KERN_ERR fmt); } while(0)
+#else
+#define DBG(fmt...) do { } while(0)
+#endif
+
 #ifndef CONFIG_PCI
 unsigned long isa_io_base = 0;
 unsigned long isa_mem_base = 0;
@@ -44,205 +52,219 @@
 #endif
 
 
-/*
- * Internal interrupts are all Level Sensitive, and Positive Polarity
- */
-
-static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3 transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3 receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3 error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4 transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4 receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4 error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO error/write-port unit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO outbound doorbell */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO inbound doorbell */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO outbound message unit 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO inbound message unit 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO outbound message unit 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO inbound message unit 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
-	0x0,						/* External  0: */
-	0x0,						/* External  1: */
-	0x0,						/* External  2: */
-	0x0,						/* External  3: */
-	0x0,						/* External  4: */
-	0x0,						/* External  5: */
-	0x0,						/* External  6: */
-	0x0,						/* External  7: */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis FPGA */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI 8259 INTR Cascade */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad ETH PHY */
-	0x0,						/* External 11: */
-	0x0,
-	0x0,
-	0x0,
-	0x0,
-};
-
+#ifdef CONFIG_PCI
+static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc,
+				 struct pt_regs *regs)
+{
+	unsigned int cascade_irq = i8259_irq(regs);
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq, regs);
+	desc->chip->eoi(irq);
+}
+#endif	/* CONFIG_PCI */
 
 void __init
 mpc86xx_hpcn_init_irq(void)
 {
 	struct mpic *mpic1;
-	phys_addr_t openpic_paddr;
+	struct device_node *np;
+	struct resource res;
+#ifdef CONFIG_PCI
+	struct device_node *cascade_node = NULL;
+	int cascade_irq;
+#endif
 
-	/* Determine the Physical Address of the OpenPIC regs */
-	openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
+	/* Determine PIC address. */
+	np = of_find_node_by_type(NULL, "open-pic");
+	if (np == NULL)
+		return;
+	of_address_to_resource(np, 0, &res);
 
 	/* Alloc mpic structure and per isu has 16 INT entries. */
-	mpic1 = mpic_alloc(openpic_paddr,
+	mpic1 = mpic_alloc(np, res.start,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250,
-			mpc86xx_hpcn_openpic_initsenses,
-			sizeof(mpc86xx_hpcn_openpic_initsenses),
+			16, NR_IRQS - 4,
 			" MPIC     ");
 	BUG_ON(mpic1 == NULL);
 
-	/* 48 Internal Interrupts */
-	mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200);
-	mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400);
-	mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600);
+	mpic_assign_isu(mpic1, 0, res.start + 0x10000);
 
-	/* 16 External interrupts */
-	mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000);
+	/* 48 Internal Interrupts */
+	mpic_assign_isu(mpic1, 1, res.start + 0x10200);
+	mpic_assign_isu(mpic1, 2, res.start + 0x10400);
+	mpic_assign_isu(mpic1, 3, res.start + 0x10600);
+
+	/* 16 External interrupts
+	 * Moving them from [0 - 15] to [64 - 79]
+	 */
+	mpic_assign_isu(mpic1, 4, res.start + 0x10000);
 
 	mpic_init(mpic1);
 
 #ifdef CONFIG_PCI
-	mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL);
-	i8259_init(0, I8259_OFFSET);
+	/* Initialize i8259 controller */
+	for_each_node_by_type(np, "interrupt-controller")
+		if (device_is_compatible(np, "chrp,iic")) {
+			cascade_node = np;
+			break;
+		}
+	if (cascade_node == NULL) {
+		printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n");
+		return;
+	}
+
+	cascade_irq = irq_of_parse_and_map(cascade_node, 0);
+	if (cascade_irq == NO_IRQ) {
+		printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt");
+		return;
+	}
+	DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq);
+
+	i8259_init(cascade_node, 0);
+	set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
 #endif
 }
 
-
-
 #ifdef CONFIG_PCI
-/*
- * interrupt routing
- */
 
-int
-mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH};
+const unsigned char uli1575_irq_route_table[16] = {
+	0, 	/* 0: Reserved */
+	0x8, 	/* 1: 0b1000 */
+	0, 	/* 2: Reserved */
+	0x2,	/* 3: 0b0010 */
+	0x4,	/* 4: 0b0100 */
+	0x5, 	/* 5: 0b0101 */
+	0x7,	/* 6: 0b0111 */
+	0x6,	/* 7: 0b0110 */
+	0, 	/* 8: Reserved */
+	0x1,	/* 9: 0b0001 */
+	0x3,	/* 10: 0b0011 */
+	0x9,	/* 11: 0b1001 */
+	0xb,	/* 12: 0b1011 */
+	0, 	/* 13: Reserved */
+	0xd,	/* 14, 0b1101 */
+	0xf,	/* 15, 0b1111 */
+};
+
+static int __devinit
+get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin)
 {
-	static char pci_irq_table[][4] = {
-		/*
-		 *      PCI IDSEL/INTPIN->INTLINE
-		 *       A      B      C      D
-		 */
-		{PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 17 -- PCI Slot 1 */
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 18 -- PCI Slot 2 */
-		{0, 0, 0, 0},			/* IDSEL 19 */
-		{0, 0, 0, 0},			/* IDSEL 20 */
-		{0, 0, 0, 0},			/* IDSEL 21 */
-		{0, 0, 0, 0},			/* IDSEL 22 */
-		{0, 0, 0, 0},			/* IDSEL 23 */
-		{0, 0, 0, 0},			/* IDSEL 24 */
-		{0, 0, 0, 0},			/* IDSEL 25 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* IDSEL 26 -- PCI Bridge*/
-		{PIRQC, 0, 0, 0},		/* IDSEL 27 -- LAN */
-		{PIRQE, PIRQF, PIRQH, PIRQ7},	/* IDSEL 28 -- USB 1.1 */
-		{PIRQE, PIRQF, PIRQG, 0},	/* IDSEL 29 -- Audio & Modem */
-		{PIRQH, 0, 0, 0},		/* IDSEL 30 -- LPC & PMU*/
-		{PIRQD, 0, 0, 0},		/* IDSEL 31 -- ATA */
-	};
+	struct of_irq oirq;
+	u32 laddr[3];
+	struct device_node *hosenode = hose ? hose->arch_data : NULL;
 
-	const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
+	if (!hosenode) return -EINVAL;
+
+	laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8);
+	laddr[1] = laddr[2] = 0;
+	of_irq_map_raw(hosenode, &pin, laddr, &oirq);
+	DBG("mpc86xx_hpcn: pci irq addr %x, slot %d, pin %d, irq %d\n",
+			laddr[0], slot, pin, oirq.specifier[0]);
+	return oirq.specifier[0];
 }
 
-static void __devinit quirk_ali1575(struct pci_dev *dev)
+static void __devinit quirk_uli1575(struct pci_dev *dev)
 {
 	unsigned short temp;
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	unsigned char irq2pin[16];
+	unsigned long pirq_map_word = 0;
+	u32 irq;
+	int i;
 
 	/*
-	 * ALI1575 interrupts route table setup:
-	 *
-	 * IRQ pin   IRQ#
-	 * PIRQA ---- 3
-	 * PIRQB ---- 4
-	 * PIRQC ---- 5
-	 * PIRQD ---- 6
-	 * PIRQE ---- 9
-	 * PIRQF ---- 10
-	 * PIRQG ---- 11
-	 * PIRQH ---- 12
+	 * ULI1575 interrupts route setup
+	 */
+	memset(irq2pin, 0, 16); /* Initialize default value 0 */
+
+	/*
+	 * PIRQA -> PIRQD mapping read from OF-tree
 	 *
 	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
 	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
 	 */
-	pci_write_config_dword(dev, 0x48, 0xb9317542);
+	for (i = 0; i < 4; i++){
+		irq = get_pci_irq_from_of(hose, 17, i + 1);
+		if (irq > 0 && irq < 16)
+			irq2pin[irq] = PIRQA + i;
+		else
+			printk(KERN_WARNING "ULI1575 device"
+			    "(slot %d, pin %d) irq %d is invalid.\n",
+			    17, i, irq);
+	}
 
-	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
-	pci_write_config_byte(dev, 0x86, 0x0c);
+	/*
+	 * PIRQE -> PIRQF mapping set manually
+	 *
+	 * IRQ pin   IRQ#
+	 * PIRQE ---- 9
+	 * PIRQF ---- 10
+	 * PIRQG ---- 11
+	 * PIRQH ---- 12
+	 */
+	for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i;
 
-	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
-	pci_write_config_byte(dev, 0x87, 0x0d);
+	/* Set IRQ-PIRQ Mapping to ULI1575 */
+	for (i = 0; i < 16; i++)
+		if (irq2pin[i])
+			pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
+				<< ((irq2pin[i] - PIRQA) * 4);
 
-	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x88, 0x0f);
+	/* ULI1575 IRQ mapping conf register default value is 0xb9317542 */
+	DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n",
+			pirq_map_word);
+	pci_write_config_dword(dev, 0x48, pirq_map_word);
 
-	/* USB 2.0 controller, interrupt: PIRQ7 */
-	pci_write_config_byte(dev, 0x74, 0x06);
+#define ULI1575_SET_DEV_IRQ(slot, pin, reg) 				\
+	do { 								\
+		int irq; 						\
+		irq = get_pci_irq_from_of(hose, slot, pin); 		\
+		if (irq > 0 && irq < 16) 				\
+			pci_write_config_byte(dev, reg, irq2pin[irq]); 	\
+		else							\
+			printk(KERN_WARNING "ULI1575 device"		\
+			    "(slot %d, pin %d) irq %d is invalid.\n",	\
+			    slot, pin, irq);				\
+	} while(0)
 
-	/* Audio controller, interrupt: PIRQE */
-	pci_write_config_byte(dev, 0x8a, 0x0c);
+	/* USB 1.1 OHCI controller 1, slot 28, pin 1 */
+	ULI1575_SET_DEV_IRQ(28, 1, 0x86);
 
-	/* Modem controller, interrupt: PIRQF */
-	pci_write_config_byte(dev, 0x8b, 0x0d);
+	/* USB 1.1 OHCI controller 2, slot 28, pin 2 */
+	ULI1575_SET_DEV_IRQ(28, 2, 0x87);
 
-	/* HD audio controller, interrupt: PIRQG */
-	pci_write_config_byte(dev, 0x8c, 0x0e);
+	/* USB 1.1 OHCI controller 3, slot 28, pin 3 */
+	ULI1575_SET_DEV_IRQ(28, 3, 0x88);
 
-	/* Serial ATA interrupt: PIRQD */
-	pci_write_config_byte(dev, 0x8d, 0x0b);
+	/* USB 2.0 controller, slot 28, pin 4 */
+	irq = get_pci_irq_from_of(hose, 28, 4);
+	if (irq >= 0 && irq <=15)
+		pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
 
-	/* SMB interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x8e, 0x0f);
+	/* Audio controller, slot 29, pin 1 */
+	ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
 
-	/* PMU ACPI SCI interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x8f, 0x0f);
+	/* Modem controller, slot 29, pin 2 */
+	ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
+
+	/* HD audio controller, slot 29, pin 3 */
+	ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
+
+	/* SMB interrupt: slot 30, pin 1 */
+	ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
+
+	/* PMU ACPI SCI interrupt: slot 30, pin 2 */
+	ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
+
+	/* Serial ATA interrupt: slot 31, pin 1 */
+	ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
 
 	/* Primary PATA IDE IRQ: 14
 	 * Secondary PATA IDE IRQ: 15
 	 */
-	pci_write_config_byte(dev, 0x44, 0x3d);
-	pci_write_config_byte(dev, 0x75, 0x0f);
+	pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]);
+	pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
 
 	/* Set IRQ14 and IRQ15 to legacy IRQs */
 	pci_read_config_word(dev, 0x46, &temp);
@@ -264,6 +286,8 @@
 	 */
 	outb(0xfa, 0x4d0);
 	outb(0x1e, 0x4d1);
+
+#undef ULI1575_SET_DEV_IRQ
 }
 
 static void __devinit quirk_uli5288(struct pci_dev *dev)
@@ -306,7 +330,7 @@
 	dev->class |= 0x1;
 }
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
@@ -337,8 +361,6 @@
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc86xx_map_irq;
 	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
 #endif
 
@@ -377,6 +399,15 @@
 }
 
 
+void __init mpc86xx_hpcn_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	for_each_pci_dev(dev)
+		pci_read_irq_line(dev);
+}
+
+
 /*
  * Called very early, device-tree isn't unflattened
  */
@@ -431,6 +462,7 @@
 	.setup_arch		= mpc86xx_hpcn_setup_arch,
 	.init_IRQ		= mpc86xx_hpcn_init_irq,
 	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
+	.pcibios_fixup		= mpc86xx_hpcn_pcibios_fixup,
 	.get_irq		= mpic_get_irq,
 	.restart		= mpc86xx_restart,
 	.time_init		= mpc86xx_time_init,
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index bc51390..a8c8f0a 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -188,7 +188,8 @@
 
 	printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
 	       "Firmware bus number: %d->%d\n",
-		rsrc.start, hose->first_busno, hose->last_busno);
+	       (unsigned long) rsrc.start,
+	       hose->first_busno, hose->last_busno);
 
 	DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
 		hose, hose->cfg_addr, hose->cfg_data);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 538e337..9c08ff3 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -291,10 +291,6 @@
 
 	pci_create_OF_bus_map();
 
-#ifdef CONFIG_SMP
-	smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
-
 	/*
 	 * Print the banner, then scroll down so boot progress
 	 * can be printed.  -- Cort
@@ -479,6 +475,14 @@
 	chrp_find_openpic();
 	chrp_find_8259();
 
+#ifdef CONFIG_SMP
+	/* Pegasos has no MPIC, those ops would make it crash. It might be an
+	 * option to move setting them to after we probe the PIC though
+	 */
+	if (chrp_mpic != NULL)
+		smp_ops = &chrp_smp_ops;
+#endif /* CONFIG_SMP */
+
 	if (_chrp_type == _CHRP_Pegasos)
 		ppc_md.get_irq        = i8259_irq;
 
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index ba07a9a..234a861 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -80,6 +80,7 @@
 	select DEFAULT_UIMAGE
 	select PPC_UDBG_16550
 	select MPIC
+	select MPIC_WEIRD
 	help
 	  Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
 	  platform
diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
index d7a4fc7..5d393eb 100644
--- a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
+++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
@@ -1,7 +1,7 @@
 /*
  * mpc7448_hpc2.c
  *
- * Board setup routines for the Freescale Taiga platform
+ * Board setup routines for the Freescale mpc7448hpc2(taiga) platform
  *
  * Author: Jacob Pan
  *	 jacob.pan@freescale.com
@@ -12,10 +12,10 @@
  *
  * Copyright 2004-2006 Freescale Semiconductor, Inc.
  *
- * 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.
+ * 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/config.h>
@@ -62,43 +62,8 @@
 extern int tsi108_setup_pci(struct device_node *dev);
 extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 extern void tsi108_pci_int_init(void);
-extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused);
-
-/*
- * Define all of the IRQ senses and polarities.  Taken from the
- * mpc7448hpc  manual.
- * Note:  Likely, this table and the following function should be
- *        obtained and derived from the OF Device Tree.
- */
-
-static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
-	/* External on-board sources */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[0] XINT0 from FPGA */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[1] XINT1 from FPGA */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[2] PHY_INT from both GIGE */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[3] RESERVED */
-	/* Internal Tsi108/109 interrupt sources */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA0 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA1 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA2 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* DMA3 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART0 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* UART1 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* I2C */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* GPIO */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* GIGE1 */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* HLP */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* SDC */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Processor IF */
-	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),	/* Reserved IRQ */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* PCI/X block */
-};
+extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
+			    struct pt_regs *regs);
 
 int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
 {
@@ -229,6 +194,8 @@
 {
 	struct mpic *mpic;
 	phys_addr_t mpic_paddr = 0;
+	unsigned int cascade_pci_irq;
+	struct device_node *tsi_pci;
 	struct device_node *tsi_pic;
 
 	tsi_pic = of_find_node_by_type(NULL, "open-pic");
@@ -246,24 +213,31 @@
 	DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__,
 	    (u32) mpic_paddr);
 
-	mpic = mpic_alloc(mpic_paddr,
+	mpic = mpic_alloc(tsi_pic, mpic_paddr,
 			MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET |
-			MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108),
+			MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108,
 			0, /* num_sources used */
-			TSI108_IRQ_BASE,
 			0, /* num_sources used */
-			NR_IRQS - 4 /* XXXX */,
-			mpc7448_hpc2_pic_initsenses,
-			sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC");
+			"Tsi108_PIC");
 
 	BUG_ON(mpic == NULL); /* XXXX */
-
 	mpic_init(mpic);
-	mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic);
+
+	tsi_pci = of_find_node_by_type(NULL, "pci");
+	if (tsi_pci == 0) {
+		printk("%s: No tsi108 pci node found !\n", __FUNCTION__);
+		return;
+	}
+
+	cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
+	set_irq_data(cascade_pci_irq, mpic);
+	set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+
 	tsi108_pci_int_init();
 
 	/* Configure MPIC outputs to CPU0 */
 	tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
+	of_node_put(tsi_pic);
 }
 
 void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
@@ -320,6 +294,7 @@
 	return 0;
 
 }
+
 define_machine(mpc7448_hpc2){
 	.name 			= "MPC7448 HPC2",
 	.probe 			= mpc7448_hpc2_probe,
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index cb528c9..57567df 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -221,10 +221,17 @@
 	 * in Maple device-tree where the type of the controller is
 	 * open-pic and not interrupt-controller
 	 */
-	for_each_node_by_type(np, "open-pic") {
-		mpic_node = np;
-		break;
-	}
+
+	for_each_node_by_type(np, "interrupt-controller")
+		if (device_is_compatible(np, "open-pic")) {
+			mpic_node = np;
+			break;
+		}
+	if (mpic_node == NULL)
+		for_each_node_by_type(np, "open-pic") {
+			mpic_node = np;
+			break;
+		}
 	if (mpic_node == NULL) {
 		printk(KERN_ERR
 		       "Failed to locate the MPIC interrupt controller\n");
@@ -252,6 +259,8 @@
 
 	/* XXX Maple specific bits */
 	flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET;
+	/* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */
+	flags |= MPIC_BIG_ENDIAN;
 
 	/* Setup the openpic driver. More device-tree junks, we hard code no
 	 * ISUs for now. I'll have to revisit some stuffs with the folks doing
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 74eed6b..d664154 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -10,19 +10,32 @@
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/backlight.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/atomic.h>
 #include <asm/prom.h>
 #include <asm/backlight.h>
 
 #define OLD_BACKLIGHT_MAX 15
 
 static void pmac_backlight_key_worker(void *data);
-static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
+static void pmac_backlight_set_legacy_worker(void *data);
 
-/* Although this variable is used in interrupt context, it makes no sense to
- * protect it. No user is able to produce enough key events per second and
+static DECLARE_WORK(pmac_backlight_key_work, pmac_backlight_key_worker, NULL);
+static DECLARE_WORK(pmac_backlight_set_legacy_work, pmac_backlight_set_legacy_worker, NULL);
+
+/* Although these variables are used in interrupt context, it makes no sense to
+ * protect them. No user is able to produce enough key events per second and
  * notice the errors that might happen.
  */
 static int pmac_backlight_key_queued;
+static int pmac_backlight_set_legacy_queued;
+
+/* The via-pmu code allows the backlight to be grabbed, in which case the
+ * in-kernel control of the brightness needs to be disabled. This should
+ * only be used by really old PowerBooks.
+ */
+static atomic_t kernel_backlight_disabled = ATOMIC_INIT(0);
 
 /* Protect the pmac_backlight variable */
 DEFINE_MUTEX(pmac_backlight_mutex);
@@ -82,6 +95,9 @@
 
 static void pmac_backlight_key_worker(void *data)
 {
+	if (atomic_read(&kernel_backlight_disabled))
+		return;
+
 	mutex_lock(&pmac_backlight_mutex);
 	if (pmac_backlight) {
 		struct backlight_properties *props;
@@ -107,8 +123,12 @@
 	mutex_unlock(&pmac_backlight_mutex);
 }
 
+/* This function is called in interrupt context */
 void pmac_backlight_key(int direction)
 {
+	if (atomic_read(&kernel_backlight_disabled))
+		return;
+
 	/* we can receive multiple interrupts here, but the scheduled work
 	 * will run only once, with the last value
 	 */
@@ -116,7 +136,7 @@
 	schedule_work(&pmac_backlight_key_work);
 }
 
-int pmac_backlight_set_legacy_brightness(int brightness)
+static int __pmac_backlight_set_legacy_brightness(int brightness)
 {
 	int error = -ENXIO;
 
@@ -145,6 +165,28 @@
 	return error;
 }
 
+static void pmac_backlight_set_legacy_worker(void *data)
+{
+	if (atomic_read(&kernel_backlight_disabled))
+		return;
+
+	__pmac_backlight_set_legacy_brightness(pmac_backlight_set_legacy_queued);
+}
+
+/* This function is called in interrupt context */
+void pmac_backlight_set_legacy_brightness_pmu(int brightness) {
+	if (atomic_read(&kernel_backlight_disabled))
+		return;
+
+	pmac_backlight_set_legacy_queued = brightness;
+	schedule_work(&pmac_backlight_set_legacy_work);
+}
+
+int pmac_backlight_set_legacy_brightness(int brightness)
+{
+	return __pmac_backlight_set_legacy_brightness(brightness);
+}
+
 int pmac_backlight_get_legacy_brightness()
 {
 	int result = -ENXIO;
@@ -167,6 +209,16 @@
 	return result;
 }
 
+void pmac_backlight_disable()
+{
+	atomic_inc(&kernel_backlight_disabled);
+}
+
+void pmac_backlight_enable()
+{
+	atomic_dec(&kernel_backlight_disabled);
+}
+
 EXPORT_SYMBOL_GPL(pmac_backlight);
 EXPORT_SYMBOL_GPL(pmac_backlight_mutex);
 EXPORT_SYMBOL_GPL(pmac_has_backlight_type);
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
index 871b002..9d73d02 100644
--- a/arch/powerpc/platforms/powermac/bootx_init.c
+++ b/arch/powerpc/platforms/powermac/bootx_init.c
@@ -181,13 +181,18 @@
 }
 
 static void __init bootx_add_display_props(unsigned long base,
-					   unsigned long *mem_end)
+					   unsigned long *mem_end,
+					   int has_real_node)
 {
 	boot_infos_t *bi = bootx_info;
 	u32 tmp;
 
-	bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
-	bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+	if (has_real_node) {
+		bootx_dt_add_prop("linux,boot-display", NULL, 0, mem_end);
+		bootx_dt_add_prop("linux,opened", NULL, 0, mem_end);
+	} else
+		bootx_dt_add_prop("linux,bootx-noscreen", NULL, 0, mem_end);
+
 	tmp = bi->dispDeviceDepth;
 	bootx_dt_add_prop("linux,bootx-depth", &tmp, 4, mem_end);
 	tmp = bi->dispDeviceRect[2] - bi->dispDeviceRect[0];
@@ -241,11 +246,6 @@
 		DBG(" detected display ! adding properties names !\n");
 		bootx_dt_add_string("linux,boot-display", mem_end);
 		bootx_dt_add_string("linux,opened", mem_end);
-		bootx_dt_add_string("linux,bootx-depth", mem_end);
-		bootx_dt_add_string("linux,bootx-width", mem_end);
-		bootx_dt_add_string("linux,bootx-height", mem_end);
-		bootx_dt_add_string("linux,bootx-linebytes", mem_end);
-		bootx_dt_add_string("linux,bootx-addr", mem_end);
 		strncpy(bootx_disp_path, namep, 255);
 	}
 
@@ -329,10 +329,13 @@
 		ppp = &pp->next;
 	}
 
-	if (node == bootx_node_chosen)
+	if (node == bootx_node_chosen) {
 		bootx_add_chosen_props(base, mem_end);
-	if (node == bootx_info->dispDeviceRegEntryOffset)
-		bootx_add_display_props(base, mem_end);
+		if (bootx_info->dispDeviceRegEntryOffset == 0)
+			bootx_add_display_props(base, mem_end, 0);
+	}
+	else if (node == bootx_info->dispDeviceRegEntryOffset)
+		bootx_add_display_props(base, mem_end, 1);
 
 	/* do all our children */
 	cpp = &np->child;
@@ -374,6 +377,14 @@
 	mem_end += 4;
 	bootx_dt_strend = mem_end;
 	bootx_scan_dt_build_strings(base, 4, &mem_end);
+	/* Add some strings */
+	bootx_dt_add_string("linux,bootx-noscreen", &mem_end);
+	bootx_dt_add_string("linux,bootx-depth", &mem_end);
+	bootx_dt_add_string("linux,bootx-width", &mem_end);
+	bootx_dt_add_string("linux,bootx-height", &mem_end);
+	bootx_dt_add_string("linux,bootx-linebytes", &mem_end);
+	bootx_dt_add_string("linux,bootx-addr", &mem_end);
+	/* Wrap up strings */
 	hdr->off_dt_strings = bootx_dt_strbase - mem_start;
 	hdr->dt_strings_size = bootx_dt_strend - bootx_dt_strbase;
 
@@ -400,8 +411,15 @@
 	DBG("End of boot params: %x\n", mem_end);
 	rsvmap[0] = mem_start;
 	rsvmap[1] = mem_end;
-	rsvmap[2] = 0;
-	rsvmap[3] = 0;
+	if (bootx_info->ramDisk) {
+		rsvmap[2] = ((unsigned long)bootx_info) + bootx_info->ramDisk;
+		rsvmap[3] = rsvmap[2] + bootx_info->ramDiskSize;
+		rsvmap[4] = 0;
+		rsvmap[5] = 0;
+	} else {
+		rsvmap[2] = 0;
+		rsvmap[3] = 0;
+	}
 
 	return (unsigned long)hdr;
 }
@@ -471,6 +489,7 @@
 	if (bi->dispDeviceDepth == 16)
 		bi->dispDeviceDepth = 15;
 
+
 #ifdef CONFIG_BOOTX_TEXT
 	ptr = (unsigned long)bi->logicalDisplayBase;
 	ptr += bi->dispDeviceRect[1] * bi->dispDeviceRowBytes;
@@ -508,6 +527,7 @@
 #ifdef CONFIG_BOOTX_TEXT
 	btext_welcome(bi);
 #endif
+
 	/* New BootX enters kernel with MMU off, i/os are not allowed
 	 * here. This hack will have been done by the boostrap anyway.
 	 */
@@ -530,12 +550,12 @@
 	 */
 	if (bi->version < 5) {
 		space = bi->deviceTreeOffset + bi->deviceTreeSize;
-		if (bi->ramDisk)
+		if (bi->ramDisk >= space)
 			space = bi->ramDisk + bi->ramDiskSize;
 	} else
 		space = bi->totalParamsSize;
 
-	bootx_printf("Total space used by parameters & ramdisk: %x \n", space);
+	bootx_printf("Total space used by parameters & ramdisk: 0x%x \n", space);
 
 	/* New BootX will have flushed all TLBs and enters kernel with
 	 * MMU switched OFF, so this should not be useful anymore.
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index f08a145..7b1156e 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -10,6 +10,8 @@
  * that is iMac G5 and latest single CPU desktop.
  */
 
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -30,13 +32,7 @@
 #include <asm/smu.h>
 #include <asm/pmac_pfunc.h>
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#define DBG(fmt...) pr_debug(fmt)
 
 /* see 970FX user manual */
 
@@ -82,8 +78,6 @@
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
-static u32 *g5_pmode_data;
-static int g5_pmode_max;
 static int g5_pmode_cur;
 
 static void (*g5_switch_volt)(int speed_mode);
@@ -93,6 +87,11 @@
 static DEFINE_MUTEX(g5_switch_mutex);
 
 
+#ifdef CONFIG_PMAC_SMU
+
+static u32 *g5_pmode_data;
+static int g5_pmode_max;
+
 static struct smu_sdbp_fvt *g5_fvt_table;	/* table of op. points */
 static int g5_fvt_count;			/* number of op. points */
 static int g5_fvt_cur;				/* current op. point */
@@ -210,6 +209,16 @@
 }
 
 /*
+ * Fake voltage switching for platforms with missing support
+ */
+
+static void g5_dummy_switch_volt(int speed_mode)
+{
+}
+
+#endif /* CONFIG_PMAC_SMU */
+
+/*
  * Platform function based voltage switching for PowerMac7,2 & 7,3
  */
 
@@ -248,6 +257,9 @@
 	struct pmf_args args;
 	u32 done = 0;
 	unsigned long timeout;
+	int rc;
+
+	DBG("g5_pfunc_switch_freq(%d)\n", speed_mode);
 
 	/* If frequency is going up, first ramp up the voltage */
 	if (speed_mode < g5_pmode_cur)
@@ -255,9 +267,12 @@
 
 	/* Do it */
 	if (speed_mode == CPUFREQ_HIGH)
-		pmf_call_one(pfunc_cpu_setfreq_high, NULL);
+		rc = pmf_call_one(pfunc_cpu_setfreq_high, NULL);
 	else
-		pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+		rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
+
+	if (rc)
+		printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
 
 	/* It's an irq GPIO so we should be able to just block here,
 	 * I'll do that later after I've properly tested the IRQ code for
@@ -296,13 +311,6 @@
 	return val ? CPUFREQ_HIGH : CPUFREQ_LOW;
 }
 
-/*
- * Fake voltage switching for platforms with missing support
- */
-
-static void g5_dummy_switch_volt(int speed_mode)
-{
-}
 
 /*
  * Common interface to the cpufreq core
@@ -375,6 +383,8 @@
 };
 
 
+#ifdef CONFIG_PMAC_SMU
+
 static int __init g5_neo2_cpufreq_init(struct device_node *cpus)
 {
 	struct device_node *cpunode;
@@ -525,6 +535,9 @@
 	return rc;
 }
 
+#endif /* CONFIG_PMAC_SMU */
+
+
 static int __init g5_pm72_cpufreq_init(struct device_node *cpus)
 {
 	struct device_node *cpuid = NULL, *hwclock = NULL, *cpunode = NULL;
@@ -533,6 +546,9 @@
 	u64 max_freq, min_freq, ih, il;
 	int has_volt = 1, rc = 0;
 
+	DBG("cpufreq: Initializing for PowerMac7,2, PowerMac7,3 and"
+	    " RackMac3,1...\n");
+
 	/* Get first CPU node */
 	for (cpunode = NULL;
 	     (cpunode = of_get_next_child(cpus, cpunode)) != NULL;) {
@@ -636,6 +652,15 @@
 	 */
 	ih = *((u32 *)(eeprom + 0x10));
 	il = *((u32 *)(eeprom + 0x20));
+
+	/* Check for machines with no useful settings */
+	if (il == ih) {
+		printk(KERN_WARNING "cpufreq: No low frequency mode available"
+		       " on this model !\n");
+		rc = -ENODEV;
+		goto bail;
+	}
+
 	min_freq = 0;
 	if (ih != 0 && il != 0)
 		min_freq = (max_freq * il) / ih;
@@ -643,7 +668,7 @@
 	/* Sanity check */
 	if (min_freq >= max_freq || min_freq < 1000) {
 		printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
-		rc = -ENODEV;
+		rc = -ENXIO;
 		goto bail;
 	}
 	g5_cpu_freqs[0].frequency = max_freq;
@@ -690,16 +715,10 @@
 	return rc;
 }
 
-static int __init g5_rm31_cpufreq_init(struct device_node *cpus)
-{
-	/* NYI */
-	return 0;
-}
-
 static int __init g5_cpufreq_init(void)
 {
 	struct device_node *cpus;
-	int rc;
+	int rc = 0;
 
 	cpus = of_find_node_by_path("/cpus");
 	if (cpus == NULL) {
@@ -708,12 +727,13 @@
 	}
 
 	if (machine_is_compatible("PowerMac7,2") ||
-	    machine_is_compatible("PowerMac7,3"))
+	    machine_is_compatible("PowerMac7,3") ||
+	    machine_is_compatible("RackMac3,1"))
 		rc = g5_pm72_cpufreq_init(cpus);
-	else if (machine_is_compatible("RackMac3,1"))
-		rc = g5_rm31_cpufreq_init(cpus);
+#ifdef CONFIG_PMAC_SMU
 	else
 		rc = g5_neo2_cpufreq_init(cpus);
+#endif /* CONFIG_PMAC_SMU */
 
 	of_node_put(cpus);
 	return rc;
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c
index 6d66359..aacfa59 100644
--- a/arch/powerpc/platforms/powermac/pfunc_base.c
+++ b/arch/powerpc/platforms/powermac/pfunc_base.c
@@ -256,7 +256,7 @@
 	.write_reg32		= macio_do_write_reg32,
 	.read_reg32		= macio_do_read_reg32,
 	.write_reg8		= macio_do_write_reg8,
-	.read_reg32		= macio_do_read_reg8,
+	.read_reg8		= macio_do_read_reg8,
 	.read_reg32_msrx	= macio_do_read_reg32_msrx,
 	.read_reg8_msrx		= macio_do_read_reg8_msrx,
 	.write_reg32_slm	= macio_do_write_reg32_slm,
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 060789e..39f7ddb 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -87,8 +87,8 @@
 static void pmac_mask_and_ack_irq(unsigned int virq)
 {
 	unsigned int src = irq_map[virq].hwirq;
-        unsigned long bit = 1UL << (virq & 0x1f);
-        int i = virq >> 5;
+        unsigned long bit = 1UL << (src & 0x1f);
+        int i = src >> 5;
         unsigned long flags;
 
 	spin_lock_irqsave(&pmac_pic_lock, flags);
@@ -175,7 +175,7 @@
 
   	spin_lock_irqsave(&pmac_pic_lock, flags);
         __clear_bit(src, ppc_cached_irq_mask);
-        __pmac_set_irq_mask(src, 0);
+        __pmac_set_irq_mask(src, 1);
   	spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 54a5243..31867a7 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -213,8 +213,6 @@
 {
 	unsigned long set, reset;
 
-	power4_enable_pmcs();
-
 	set = 1UL << 63;
 	reset = 0;
 	plpar_hcall_norets(H_PERFMON, set, reset);
@@ -501,7 +499,8 @@
 	}
 
 	/*
-	 * Cede if the other thread is not idle, so that it can
+	 * If not SMT, cede processor.  If CPU is running SMT
+	 * cede if the other thread is not idle, so that it can
 	 * go single-threaded.  If the other thread is idle,
 	 * we ask the hypervisor if it has pending work it
 	 * wants to do and cede if it does.  Otherwise we keep
@@ -514,7 +513,8 @@
 	 * very low priority.  The cede enables interrupts, which
 	 * doesn't matter here.
 	 */
-	if (!lppaca[cpu ^ 1].idle || poll_pending() == H_PENDING)
+	if (!cpu_has_feature(CPU_FTR_SMT) || !lppaca[cpu ^ 1].idle
+	    || poll_pending() == H_PENDING)
 		cede_processor();
 
 out:
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d0da6f..e988630 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -467,7 +467,7 @@
 	 *
 	 * XXX: undo of teardown on kexec needs this too, as may hotplug
 	 */
-	rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+	rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
 		(1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
 }
 
@@ -796,7 +796,7 @@
 	 * so leave the master cpu in the group.
 	 */
 	if (secondary)
-		rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+		rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
 				   (1UL << interrupt_server_size) - 1 -
 				   default_distrib_server, 0);
 }
@@ -813,7 +813,7 @@
 	xics_set_cpu_priority(cpu, 0);
 
 	/* remove ourselves from the global interrupt queue */
-	status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+	status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
 		(1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
 	WARN_ON(status < 0);
 
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index cebfae2..e5e999e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -9,11 +9,11 @@
 obj-$(CONFIG_40x)		+= dcr.o
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
-obj-$(CONFIG_PPC_83xx)		+= ipic.o
 obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
 obj-$(CONFIG_PPC_TODC)		+= todc.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
- endif
+obj-$(CONFIG_PPC_83xx)		+= ipic.o
+endif
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index e983972..ef10bcf 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -85,11 +85,8 @@
 			mdio_data.irq[k] = -1;
 
 		while ((child = of_get_next_child(np, child)) != NULL) {
-			if (child->n_intrs) {
-				u32 *id =
-				    (u32 *) get_property(child, "reg", NULL);
-				mdio_data.irq[*id] = child->intrs[0].line;
-			}
+			u32 *id = get_property(child, "reg", NULL);
+			mdio_data.irq[*id] = irq_of_parse_and_map(child, 0);
 		}
 
 		ret =
@@ -131,6 +128,7 @@
 		char *model;
 		void *mac_addr;
 		phandle *ph;
+		int n_res = 1;
 
 		memset(r, 0, sizeof(r));
 		memset(&gfar_data, 0, sizeof(gfar_data));
@@ -139,8 +137,7 @@
 		if (ret)
 			goto err;
 
-		r[1].start = np->intrs[0].line;
-		r[1].end = np->intrs[0].line;
+		r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
 
 		model = get_property(np, "model", NULL);
@@ -150,27 +147,35 @@
 			r[1].name = gfar_tx_intr;
 
 			r[2].name = gfar_rx_intr;
-			r[2].start = np->intrs[1].line;
-			r[2].end = np->intrs[1].line;
+			r[2].start = r[2].end = irq_of_parse_and_map(np, 1);
 			r[2].flags = IORESOURCE_IRQ;
 
 			r[3].name = gfar_err_intr;
-			r[3].start = np->intrs[2].line;
-			r[3].end = np->intrs[2].line;
+			r[3].start = r[3].end = irq_of_parse_and_map(np, 2);
 			r[3].flags = IORESOURCE_IRQ;
+
+			n_res += 2;
 		}
 
 		gfar_dev =
 		    platform_device_register_simple("fsl-gianfar", i, &r[0],
-						    np->n_intrs + 1);
+						    n_res + 1);
 
 		if (IS_ERR(gfar_dev)) {
 			ret = PTR_ERR(gfar_dev);
 			goto err;
 		}
 
-		mac_addr = get_property(np, "address", NULL);
-		memcpy(gfar_data.mac_addr, mac_addr, 6);
+		mac_addr = get_property(np, "local-mac-address", NULL);
+		if (mac_addr == NULL)
+			mac_addr = get_property(np, "mac-address", NULL);
+		if (mac_addr == NULL) {
+			/* Obsolete */
+			mac_addr = get_property(np, "address", NULL);
+		}
+
+		if (mac_addr)
+			memcpy(gfar_data.mac_addr, mac_addr, 6);
 
 		if (model && !strcasecmp(model, "TSEC"))
 			gfar_data.device_flags =
@@ -251,8 +256,7 @@
 		if (ret)
 			goto err;
 
-		r[1].start = np->intrs[0].line;
-		r[1].end = np->intrs[0].line;
+		r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
 
 		i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
@@ -388,8 +392,7 @@
 		if (ret)
 			goto err;
 
-		r[1].start = np->intrs[0].line;
-		r[1].end = np->intrs[0].line;
+		r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
 
 		usb_dev_mph =
@@ -437,8 +440,7 @@
 		if (ret)
 			goto unreg_mph;
 
-		r[1].start = np->intrs[0].line;
-		r[1].end = np->intrs[0].line;
+		r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
 
 		usb_dev_dr =
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 46801f5..70e7077 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -19,15 +19,18 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/sysdev.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/prom.h>
 #include <asm/ipic.h>
-#include <asm/mpc83xx.h>
 
 #include "ipic.h"
 
-static struct ipic p_ipic;
 static struct ipic * primary_ipic;
+static DEFINE_SPINLOCK(ipic_lock);
 
 static struct ipic_info ipic_info[] = {
 	[9] = {
@@ -373,74 +376,220 @@
 	out_be32(base + (reg >> 2), value);
 }
 
-static inline struct ipic * ipic_from_irq(unsigned int irq)
+static inline struct ipic * ipic_from_irq(unsigned int virq)
 {
 	return primary_ipic;
 }
 
-static void ipic_enable_irq(unsigned int irq)
+#define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
+
+static void ipic_unmask_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned long flags;
 	u32 temp;
 
+	spin_lock_irqsave(&ipic_lock, flags);
+
 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
 	temp |= (1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_disable_irq(unsigned int irq)
+static void ipic_mask_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned long flags;
 	u32 temp;
 
+	spin_lock_irqsave(&ipic_lock, flags);
+
 	temp = ipic_read(ipic->regs, ipic_info[src].mask);
 	temp &= ~(1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_disable_irq_and_ack(unsigned int irq)
+static void ipic_ack_irq(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned long flags;
 	u32 temp;
 
-	ipic_disable_irq(irq);
+	spin_lock_irqsave(&ipic_lock, flags);
 
 	temp = ipic_read(ipic->regs, ipic_info[src].pend);
 	temp |= (1 << (31 - ipic_info[src].bit));
 	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_end_irq(unsigned int irq)
+static void ipic_mask_irq_and_ack(unsigned int virq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		ipic_enable_irq(irq);
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	unsigned long flags;
+	u32 temp;
+
+	spin_lock_irqsave(&ipic_lock, flags);
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp &= ~(1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+
+	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+
+	spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-struct hw_interrupt_type ipic = {
-	.typename = " IPIC  ",
-	.enable = ipic_enable_irq,
-	.disable = ipic_disable_irq,
-	.ack = ipic_disable_irq_and_ack,
-	.end = ipic_end_irq,
+static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
+	struct irq_desc *desc = get_irq_desc(virq);
+	unsigned int vold, vnew, edibit;
+
+	if (flow_type == IRQ_TYPE_NONE)
+		flow_type = IRQ_TYPE_LEVEL_LOW;
+
+	/* ipic supports only low assertion and high-to-low change senses
+	 */
+	if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
+		printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
+			flow_type);
+		return -EINVAL;
+	}
+
+	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
+		desc->status |= IRQ_LEVEL;
+		set_irq_handler(virq, handle_level_irq);
+	} else {
+		set_irq_handler(virq, handle_edge_irq);
+	}
+
+	/* only EXT IRQ senses are programmable on ipic
+	 * internal IRQ senses are LEVEL_LOW
+	 */
+	if (src == IPIC_IRQ_EXT0)
+		edibit = 15;
+	else
+		if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
+			edibit = (14 - (src - IPIC_IRQ_EXT1));
+		else
+			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
+
+	vold = ipic_read(ipic->regs, IPIC_SECNR);
+	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
+		vnew = vold | (1 << edibit);
+	} else {
+		vnew = vold & ~(1 << edibit);
+	}
+	if (vold != vnew)
+		ipic_write(ipic->regs, IPIC_SECNR, vnew);
+	return 0;
+}
+
+static struct irq_chip ipic_irq_chip = {
+	.typename	= " IPIC  ",
+	.unmask		= ipic_unmask_irq,
+	.mask		= ipic_mask_irq,
+	.mask_ack	= ipic_mask_irq_and_ack,
+	.ack		= ipic_ack_irq,
+	.set_type	= ipic_set_irq_type,
 };
 
-void __init ipic_init(phys_addr_t phys_addr,
-		unsigned int flags,
-		unsigned int irq_offset,
-		unsigned char *senses,
-		unsigned int senses_count)
+static int ipic_host_match(struct irq_host *h, struct device_node *node)
 {
-	u32 i, temp = 0;
+	struct ipic *ipic = h->host_data;
 
-	primary_ipic = &p_ipic;
-	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+	/* Exact match, unless ipic node is NULL */
+	return ipic->of_node == NULL || ipic->of_node == node;
+}
 
-	primary_ipic->irq_offset = irq_offset;
+static int ipic_host_map(struct irq_host *h, unsigned int virq,
+			 irq_hw_number_t hw)
+{
+	struct ipic *ipic = h->host_data;
+	struct irq_chip *chip;
 
-	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+	/* Default chip */
+	chip = &ipic->hc_irq;
+
+	set_irq_chip_data(virq, ipic);
+	set_irq_chip_and_handler(virq, chip, handle_level_irq);
+
+	/* Set default irq type */
+	set_irq_type(virq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
+			   u32 *intspec, unsigned int intsize,
+			   irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+
+{
+	/* interrupt sense values coming from the device tree equal either
+	 * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
+	 */
+	*out_hwirq = intspec[0];
+	if (intsize > 1)
+		*out_flags = intspec[1];
+	else
+		*out_flags = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_host_ops ipic_host_ops = {
+	.match	= ipic_host_match,
+	.map	= ipic_host_map,
+	.xlate	= ipic_host_xlate,
+};
+
+void __init ipic_init(struct device_node *node,
+		unsigned int flags)
+{
+	struct ipic	*ipic;
+	struct resource res;
+	u32 temp = 0, ret;
+
+	ipic = alloc_bootmem(sizeof(struct ipic));
+	if (ipic == NULL)
+		return;
+
+	memset(ipic, 0, sizeof(struct ipic));
+	ipic->of_node = node ? of_node_get(node) : NULL;
+
+	ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
+				       NR_IPIC_INTS,
+				       &ipic_host_ops, 0);
+	if (ipic->irqhost == NULL) {
+		of_node_put(node);
+		return;
+	}
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret)
+		return;
+
+	ipic->regs = ioremap(res.start, res.end - res.start + 1);
+
+	ipic->irqhost->host_data = ipic;
+	ipic->hc_irq = ipic_irq_chip;
+
+	/* init hw */
+	ipic_write(ipic->regs, IPIC_SICNR, 0x0);
 
 	/* default priority scheme is grouped. If spread mode is required
 	 * configure SICFR accordingly */
@@ -453,49 +602,35 @@
 	if (flags & IPIC_SPREADMODE_MIX_B)
 		temp |= SICFR_MPSB;
 
-	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+	ipic_write(ipic->regs, IPIC_SICNR, temp);
 
 	/* handle MCP route */
 	temp = 0;
 	if (flags & IPIC_DISABLE_MCP_OUT)
 		temp = SERCR_MCPR;
-	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+	ipic_write(ipic->regs, IPIC_SERCR, temp);
 
 	/* handle routing of IRQ0 to MCP */
-	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+	temp = ipic_read(ipic->regs, IPIC_SEMSR);
 
 	if (flags & IPIC_IRQ0_MCP)
 		temp |= SEMSR_SIRQ0;
 	else
 		temp &= ~SEMSR_SIRQ0;
 
-	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+	ipic_write(ipic->regs, IPIC_SEMSR, temp);
 
-	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
-		irq_desc[i+irq_offset].chip = &ipic;
-		irq_desc[i+irq_offset].status = IRQ_LEVEL;
-	}
+	primary_ipic = ipic;
+	irq_set_default_host(primary_ipic->irqhost);
 
-	temp = 0;
-	for (i = 0 ; i < senses_count ; i++) {
-		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
-			temp |= 1 << (15 - i);
-			if (i != 0)
-				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
-			else
-				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
-		}
-	}
-	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
-
-	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
-			senses_count, primary_ipic->regs);
+	printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
+			primary_ipic->regs);
 }
 
-int ipic_set_priority(unsigned int irq, unsigned int priority)
+int ipic_set_priority(unsigned int virq, unsigned int priority)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
 	u32 temp;
 
 	if (priority > 7)
@@ -520,10 +655,10 @@
 	return 0;
 }
 
-void ipic_set_highest_priority(unsigned int irq)
+void ipic_set_highest_priority(unsigned int virq)
 {
-	struct ipic *ipic = ipic_from_irq(irq);
-	unsigned int src = irq - ipic->irq_offset;
+	struct ipic *ipic = ipic_from_irq(virq);
+	unsigned int src = ipic_irq_to_hw(virq);
 	u32 temp;
 
 	temp = ipic_read(ipic->regs, IPIC_SICFR);
@@ -537,37 +672,10 @@
 
 void ipic_set_default_priority(void)
 {
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
-	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
-	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
-	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
-	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
-
-	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
-	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
-	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
-	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
-	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
-	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
-	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
-	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
-	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
-	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
-	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
-	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
-	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
-	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
-	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
-	ipic_set_priority(MPC83xx_IRQ_MU, 1);
-	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
-	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
-	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
-	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
-	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
-	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
+	ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
 }
 
 void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
@@ -600,17 +708,20 @@
 	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
 }
 
-/* Return an interrupt vector or -1 if no interrupt is pending. */
-int ipic_get_irq(struct pt_regs *regs)
+/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
+unsigned int ipic_get_irq(struct pt_regs *regs)
 {
 	int irq;
 
-	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+	BUG_ON(primary_ipic == NULL);
+
+#define IPIC_SIVCR_VECTOR_MASK	0x7f
+	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
 
 	if (irq == 0)    /* 0 --> no irq is pending */
-		irq = -1;
+		return NO_IRQ;
 
-	return irq;
+	return irq_linear_revmap(primary_ipic->irqhost, irq);
 }
 
 static struct sysdev_class ipic_sysclass = {
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h
index a60c9d1..c28e589 100644
--- a/arch/powerpc/sysdev/ipic.h
+++ b/arch/powerpc/sysdev/ipic.h
@@ -15,7 +15,18 @@
 
 #include <asm/ipic.h>
 
-#define MPC83xx_IPIC_SIZE	(0x00100)
+#define NR_IPIC_INTS 128
+
+/* External IRQS */
+#define IPIC_IRQ_EXT0 48
+#define IPIC_IRQ_EXT1 17
+#define IPIC_IRQ_EXT7 23
+
+/* Default Priority Registers */
+#define IPIC_SIPRR_A_DEFAULT 0x05309770
+#define IPIC_SIPRR_D_DEFAULT 0x05309770
+#define IPIC_SMPRR_A_DEFAULT 0x05309770
+#define IPIC_SMPRR_B_DEFAULT 0x05309770
 
 /* System Global Interrupt Configuration Register */
 #define	SICFR_IPSA	0x00010000
@@ -31,7 +42,15 @@
 
 struct ipic {
 	volatile u32 __iomem	*regs;
-	unsigned int		irq_offset;
+
+	/* The remapper for this IPIC */
+	struct irq_host		*irqhost;
+
+	/* The "linux" controller struct */
+	struct irq_chip		hc_irq;
+
+	/* The device node of the interrupt controller */
+	struct device_node	*of_node;
 };
 
 struct ipic_info {
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6e0281a..b604926 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -54,6 +54,94 @@
 #endif
 #endif
 
+#ifdef CONFIG_MPIC_WEIRD
+static u32 mpic_infos[][MPIC_IDX_END] = {
+	[0] = {	/* Original OpenPIC compatible MPIC */
+		MPIC_GREG_BASE,
+		MPIC_GREG_FEATURE_0,
+		MPIC_GREG_GLOBAL_CONF_0,
+		MPIC_GREG_VENDOR_ID,
+		MPIC_GREG_IPI_VECTOR_PRI_0,
+		MPIC_GREG_IPI_STRIDE,
+		MPIC_GREG_SPURIOUS,
+		MPIC_GREG_TIMER_FREQ,
+
+		MPIC_TIMER_BASE,
+		MPIC_TIMER_STRIDE,
+		MPIC_TIMER_CURRENT_CNT,
+		MPIC_TIMER_BASE_CNT,
+		MPIC_TIMER_VECTOR_PRI,
+		MPIC_TIMER_DESTINATION,
+
+		MPIC_CPU_BASE,
+		MPIC_CPU_STRIDE,
+		MPIC_CPU_IPI_DISPATCH_0,
+		MPIC_CPU_IPI_DISPATCH_STRIDE,
+		MPIC_CPU_CURRENT_TASK_PRI,
+		MPIC_CPU_WHOAMI,
+		MPIC_CPU_INTACK,
+		MPIC_CPU_EOI,
+
+		MPIC_IRQ_BASE,
+		MPIC_IRQ_STRIDE,
+		MPIC_IRQ_VECTOR_PRI,
+		MPIC_VECPRI_VECTOR_MASK,
+		MPIC_VECPRI_POLARITY_POSITIVE,
+		MPIC_VECPRI_POLARITY_NEGATIVE,
+		MPIC_VECPRI_SENSE_LEVEL,
+		MPIC_VECPRI_SENSE_EDGE,
+		MPIC_VECPRI_POLARITY_MASK,
+		MPIC_VECPRI_SENSE_MASK,
+		MPIC_IRQ_DESTINATION
+	},
+	[1] = {	/* Tsi108/109 PIC */
+		TSI108_GREG_BASE,
+		TSI108_GREG_FEATURE_0,
+		TSI108_GREG_GLOBAL_CONF_0,
+		TSI108_GREG_VENDOR_ID,
+		TSI108_GREG_IPI_VECTOR_PRI_0,
+		TSI108_GREG_IPI_STRIDE,
+		TSI108_GREG_SPURIOUS,
+		TSI108_GREG_TIMER_FREQ,
+
+		TSI108_TIMER_BASE,
+		TSI108_TIMER_STRIDE,
+		TSI108_TIMER_CURRENT_CNT,
+		TSI108_TIMER_BASE_CNT,
+		TSI108_TIMER_VECTOR_PRI,
+		TSI108_TIMER_DESTINATION,
+
+		TSI108_CPU_BASE,
+		TSI108_CPU_STRIDE,
+		TSI108_CPU_IPI_DISPATCH_0,
+		TSI108_CPU_IPI_DISPATCH_STRIDE,
+		TSI108_CPU_CURRENT_TASK_PRI,
+		TSI108_CPU_WHOAMI,
+		TSI108_CPU_INTACK,
+		TSI108_CPU_EOI,
+
+		TSI108_IRQ_BASE,
+		TSI108_IRQ_STRIDE,
+		TSI108_IRQ_VECTOR_PRI,
+		TSI108_VECPRI_VECTOR_MASK,
+		TSI108_VECPRI_POLARITY_POSITIVE,
+		TSI108_VECPRI_POLARITY_NEGATIVE,
+		TSI108_VECPRI_SENSE_LEVEL,
+		TSI108_VECPRI_SENSE_EDGE,
+		TSI108_VECPRI_POLARITY_MASK,
+		TSI108_VECPRI_SENSE_MASK,
+		TSI108_IRQ_DESTINATION
+	},
+};
+
+#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name]
+
+#else /* CONFIG_MPIC_WEIRD */
+
+#define MPIC_INFO(name) MPIC_##name
+
+#endif /* CONFIG_MPIC_WEIRD */
+
 /*
  * Register accessor functions
  */
@@ -80,7 +168,8 @@
 static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
 {
 	unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
-	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+	unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+			      (ipi * MPIC_INFO(GREG_IPI_STRIDE));
 
 	if (mpic->flags & MPIC_BROKEN_IPI)
 		be = !be;
@@ -89,7 +178,8 @@
 
 static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value)
 {
-	unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+	unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) +
+			      (ipi * MPIC_INFO(GREG_IPI_STRIDE));
 
 	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
 }
@@ -120,7 +210,7 @@
 	unsigned int	idx = src_no & mpic->isu_mask;
 
 	return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
-			  reg + (idx * MPIC_IRQ_STRIDE));
+			  reg + (idx * MPIC_INFO(IRQ_STRIDE)));
 }
 
 static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
@@ -130,7 +220,7 @@
 	unsigned int	idx = src_no & mpic->isu_mask;
 
 	_mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
-		    reg + (idx * MPIC_IRQ_STRIDE), value);
+		    reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
 }
 
 #define mpic_read(b,r)		_mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r))
@@ -156,8 +246,8 @@
 {
 	u32 r;
 
-	mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
-	r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+	mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK);
+	r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0));
 
 	if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
 		printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
@@ -394,8 +484,8 @@
 /* Send an EOI */
 static inline void mpic_eoi(struct mpic *mpic)
 {
-	mpic_cpu_write(MPIC_CPU_EOI, 0);
-	(void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+	mpic_cpu_write(MPIC_INFO(CPU_EOI), 0);
+	(void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
 }
 
 #ifdef CONFIG_SMP
@@ -419,8 +509,8 @@
 
 	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
 
-	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
-		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
 		       ~MPIC_VECPRI_MASK);
 	/* make sure mask gets to controller before we return to user */
 	do {
@@ -428,7 +518,7 @@
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);
+	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
 }
 
 static void mpic_mask_irq(unsigned int irq)
@@ -439,8 +529,8 @@
 
 	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
 
-	mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
-		       mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
+		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
 		       MPIC_VECPRI_MASK);
 
 	/* make sure mask gets to controller before we return to user */
@@ -449,7 +539,7 @@
 			printk(KERN_ERR "mpic_enable_irq timeout\n");
 			break;
 		}
-	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
 }
 
 static void mpic_end_irq(unsigned int irq)
@@ -560,24 +650,28 @@
 
 	cpus_and(tmp, cpumask, cpu_online_map);
 
-	mpic_irq_write(src, MPIC_IRQ_DESTINATION,
+	mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
 		       mpic_physmask(cpus_addr(tmp)[0]));	
 }
 
-static unsigned int mpic_type_to_vecpri(unsigned int type)
+static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
 {
 	/* Now convert sense value */
 	switch(type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_RISING:
-		return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE;
+		return MPIC_INFO(VECPRI_SENSE_EDGE) |
+		       MPIC_INFO(VECPRI_POLARITY_POSITIVE);
 	case IRQ_TYPE_EDGE_FALLING:
 	case IRQ_TYPE_EDGE_BOTH:
-		return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE;
+		return MPIC_INFO(VECPRI_SENSE_EDGE) |
+		       MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
 	case IRQ_TYPE_LEVEL_HIGH:
-		return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE;
+		return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+		       MPIC_INFO(VECPRI_POLARITY_POSITIVE);
 	case IRQ_TYPE_LEVEL_LOW:
 	default:
-		return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE;
+		return MPIC_INFO(VECPRI_SENSE_LEVEL) |
+		       MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
 	}
 }
 
@@ -609,13 +703,14 @@
 		vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
 			MPIC_VECPRI_SENSE_EDGE;
 	else
-		vecpri = mpic_type_to_vecpri(flow_type);
+		vecpri = mpic_type_to_vecpri(mpic, flow_type);
 
-	vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
-	vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK);
+	vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+	vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
+			MPIC_INFO(VECPRI_SENSE_MASK));
 	vnew |= vecpri;
 	if (vold != vnew)
-		mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew);
+		mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
 
 	return 0;
 }
@@ -798,17 +893,22 @@
 	mpic->irq_count = irq_count;
 	mpic->num_sources = 0; /* so far */
 
+#ifdef CONFIG_MPIC_WEIRD
+	mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
+#endif
+
 	/* Map the global registers */
-	mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
-	mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+	mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000);
+	mpic->tmregs = mpic->gregs +
+		       ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2);
 	BUG_ON(mpic->gregs == NULL);
 
 	/* Reset */
 	if (flags & MPIC_WANTS_RESET) {
-		mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
-			   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_RESET);
-		while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+		while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 		       & MPIC_GREG_GCONF_RESET)
 			mb();
 	}
@@ -817,7 +917,7 @@
 	 * MPICs, num sources as well. On ISU MPICs, sources are counted
 	 * as ISUs are added
 	 */
-	reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+	reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
 	mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
 			  >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 	if (isu_size == 0)
@@ -826,16 +926,16 @@
 
 	/* Map the per-CPU registers */
 	for (i = 0; i < mpic->num_cpus; i++) {
-		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
-					   i * MPIC_CPU_STRIDE, 0x1000);
+		mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) +
+					   i * MPIC_INFO(CPU_STRIDE), 0x1000);
 		BUG_ON(mpic->cpuregs[i] == NULL);
 	}
 
 	/* Initialize main ISU if none provided */
 	if (mpic->isu_size == 0) {
 		mpic->isu_size = mpic->num_sources;
-		mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
-					MPIC_IRQ_STRIDE * mpic->isu_size);
+		mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE),
+					MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
 		BUG_ON(mpic->isus[0] == NULL);
 	}
 	mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -879,7 +979,8 @@
 
 	BUG_ON(isu_num >= MPIC_MAX_ISU);
 
-	mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size);
+	mpic->isus[isu_num] = ioremap(phys_addr,
+				      MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
 	if ((isu_first + mpic->isu_size) > mpic->num_sources)
 		mpic->num_sources = isu_first + mpic->isu_size;
 }
@@ -904,14 +1005,16 @@
 	printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);
 
 	/* Set current processor priority to max */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
 
 	/* Initialize timers: just disable them all */
 	for (i = 0; i < 4; i++) {
 		mpic_write(mpic->tmregs,
-			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+			   i * MPIC_INFO(TIMER_STRIDE) +
+			   MPIC_INFO(TIMER_DESTINATION), 0);
 		mpic_write(mpic->tmregs,
-			   i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+			   i * MPIC_INFO(TIMER_STRIDE) +
+			   MPIC_INFO(TIMER_VECTOR_PRI),
 			   MPIC_VECPRI_MASK |
 			   (MPIC_VEC_TIMER_0 + i));
 	}
@@ -940,21 +1043,22 @@
 			(8 << MPIC_VECPRI_PRIORITY_SHIFT);
 		
 		/* init hw */
-		mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
-		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
 			       1 << hard_smp_processor_id());
 	}
 	
 	/* Init spurrious vector */
-	mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+	mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS);
 
-	/* Disable 8259 passthrough */
-	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
-		   mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
-		   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+	/* Disable 8259 passthrough, if supported */
+	if (!(mpic->flags & MPIC_NO_PTHROU_DIS))
+		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+			   | MPIC_GREG_GCONF_8259_PTHROU_DIS);
 
 	/* Set current processor priority to 0 */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
 }
 
 void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
@@ -997,9 +1101,9 @@
 		mpic_ipi_write(src - MPIC_VEC_IPI_0,
 			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
 	} else {
-		reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI)
+		reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI))
 			& ~MPIC_VECPRI_PRIORITY_MASK;
-		mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+		mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
 			       reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
 	}
 	spin_unlock_irqrestore(&mpic_lock, flags);
@@ -1017,7 +1121,7 @@
 	if (is_ipi)
 		reg = mpic_ipi_read(src = MPIC_VEC_IPI_0);
 	else
-		reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI);
+		reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
 	spin_unlock_irqrestore(&mpic_lock, flags);
 	return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
 }
@@ -1043,12 +1147,12 @@
  	 */
 	if (distribute_irqs) {
 	 	for (i = 0; i < mpic->num_sources ; i++)
-			mpic_irq_write(i, MPIC_IRQ_DESTINATION,
-				mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+				mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk);
 	}
 
 	/* Set current processor priority to 0 */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
 
 	spin_unlock_irqrestore(&mpic_lock, flags);
 #endif /* CONFIG_SMP */
@@ -1058,7 +1162,7 @@
 {
 	struct mpic *mpic = mpic_primary;
 
-	return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+	return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI));
 }
 
 void mpic_cpu_set_priority(int prio)
@@ -1066,7 +1170,7 @@
 	struct mpic *mpic = mpic_primary;
 
 	prio &= MPIC_CPU_TASKPRI_MASK;
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio);
 }
 
 /*
@@ -1088,11 +1192,11 @@
 
 	/* let the mpic know we don't want intrs.  */
 	for (i = 0; i < mpic->num_sources ; i++)
-		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
-			mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
+			mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk);
 
 	/* Set current processor priority to max */
-	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
 
 	spin_unlock_irqrestore(&mpic_lock, flags);
 }
@@ -1108,7 +1212,8 @@
 	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
 #endif
 
-	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+	mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) +
+		       ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE),
 		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
 }
 
@@ -1116,7 +1221,7 @@
 {
 	u32 src;
 
-	src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+	src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
 #ifdef DEBUG_LOW
 	DBG("%s: get_one_irq(): %d\n", mpic->name, src);
 #endif
diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c
index 26a0cc8..f303846 100644
--- a/arch/powerpc/sysdev/tsi108_dev.c
+++ b/arch/powerpc/sysdev/tsi108_dev.c
@@ -93,13 +93,15 @@
 			goto err;
 
 		r[1].name = "tx";
-		r[1].start = np->intrs[0].line;
-		r[1].end = np->intrs[0].line;
+		r[1].start = irq_of_parse_and_map(np, 0);
+		r[1].end = irq_of_parse_and_map(np, 0);
 		r[1].flags = IORESOURCE_IRQ;
+		DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n",
+			__FUNCTION__,r[1].name, r[1].start, r[1].end);
 
 		tsi_eth_dev =
 		    platform_device_register_simple("tsi-ethernet", i, &r[0],
-						    np->n_intrs + 1);
+						    1);
 
 		if (IS_ERR(tsi_eth_dev)) {
 			ret = PTR_ERR(tsi_eth_dev);
@@ -127,7 +129,7 @@
 		tsi_eth_data.regs = r[0].start;
 		tsi_eth_data.phyregs = res.start;
 		tsi_eth_data.phy = *phy_id;
-		tsi_eth_data.irq_num = np->intrs[0].line;
+		tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0);
 		of_node_put(phy);
 		ret =
 		    platform_device_add_data(tsi_eth_dev, &tsi_eth_data,
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 3265d54..2ab06ed 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -26,7 +26,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 
-
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -228,7 +227,7 @@
 
 	(hose)->ops = &tsi108_direct_pci_ops;
 
-	printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. "
+	printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. "
 	       "Firmware bus number: %d->%d\n",
 	       rsrc.start, hose->first_busno, hose->last_busno);
 
@@ -278,7 +277,7 @@
 	mb();
 }
 
-static inline int get_pci_source(void)
+static inline unsigned int get_pci_source(void)
 {
 	u_int temp = 0;
 	int irq = -1;
@@ -371,12 +370,12 @@
  * Interrupt controller descriptor for cascaded PCI interrupt controller.
  */
 
-struct hw_interrupt_type tsi108_pci_irq = {
+static struct irq_chip tsi108_pci_irq = {
 	.typename = "tsi108_PCI_int",
-	.enable = tsi108_pci_irq_enable,
-	.disable = tsi108_pci_irq_disable,
+	.mask = tsi108_pci_irq_disable,
 	.ack = tsi108_pci_irq_ack,
 	.end = tsi108_pci_irq_end,
+	.unmask = tsi108_pci_irq_enable,
 };
 
 /*
@@ -399,14 +398,18 @@
 	DBG("Tsi108_pci_int_init: initializing PCI interrupts\n");
 
 	for (i = 0; i < NUM_PCI_IRQS; i++) {
-		irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq;
+		irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq;
 		irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL;
 	}
 
 	init_pci_source();
 }
 
-int tsi108_irq_cascade(struct pt_regs *regs, void *unused)
+void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc,
+			    struct pt_regs *regs)
 {
-	return get_pci_source();
+	unsigned int cascade_irq = get_pci_source();
+	if (cascade_irq != NO_IRQ)
+		generic_handle_irq(cascade_irq, regs);
+	desc->chip->eoi(irq);
 }
diff --git a/arch/ppc/kernel/smp-tbsync.c b/arch/ppc/kernel/smp-tbsync.c
index 1576758..d0cf3f8 100644
--- a/arch/ppc/kernel/smp-tbsync.c
+++ b/arch/ppc/kernel/smp-tbsync.c
@@ -47,8 +47,9 @@
 smp_generic_take_timebase( void )
 {
 	int cmd, tbl, tbu;
+	unsigned long flags;
 
-	local_irq_disable();
+	local_irq_save(flags);
 	while( !running )
 		;
 	rmb();
@@ -64,7 +65,7 @@
 		tbu = tbsync->tbu;
 		tbsync->ack = 0;
 		if( cmd == kExit )
-			return;
+			break;
 
 		if( cmd == kSetAndTest ) {
 			while( tbsync->handshake )
@@ -77,7 +78,7 @@
 		}
 		enter_contest( tbsync->mark, -1 );
 	}
-	local_irq_enable();
+	local_irq_restore(flags);
 }
 
 static int __devinit
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 09c6525..095fd33 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -8,6 +8,7 @@
   . = + SIZEOF_HEADERS;
   .interp : { *(.interp) }
   .hash          : { *(.hash)		}
+  .gnu.hash      : { *(.gnu.hash)	}
   .dynsym        : { *(.dynsym)		}
   .dynstr        : { *(.dynstr)		}
   .rel.text      : { *(.rel.text)		}
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index d90cd24..94badaf 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -29,6 +29,7 @@
 #include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
+#include <linux/fs_enet_pd.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -58,6 +59,71 @@
  * Setup the architecture
  *
  */
+static void init_fcc_ioports(void)
+{
+	struct immap *immap;
+	struct io_port *io;
+	u32 tempval;
+
+	immap = cpm2_immr;
+
+	io = &immap->im_ioport;
+	/* FCC2/3 are on the ports B/C. */
+	tempval = in_be32(&io->iop_pdirb);
+	tempval &= ~PB2_DIRB0;
+	tempval |= PB2_DIRB1;
+	out_be32(&io->iop_pdirb, tempval);
+
+	tempval = in_be32(&io->iop_psorb);
+	tempval &= ~PB2_PSORB0;
+	tempval |= PB2_PSORB1;
+	out_be32(&io->iop_psorb, tempval);
+
+	tempval = in_be32(&io->iop_pparb);
+	tempval |= (PB2_DIRB0 | PB2_DIRB1);
+	out_be32(&io->iop_pparb, tempval);
+
+	tempval = in_be32(&io->iop_pdirb);
+	tempval &= ~PB3_DIRB0;
+	tempval |= PB3_DIRB1;
+	out_be32(&io->iop_pdirb, tempval);
+
+	tempval = in_be32(&io->iop_psorb);
+	tempval &= ~PB3_PSORB0;
+	tempval |= PB3_PSORB1;
+	out_be32(&io->iop_psorb, tempval);
+
+	tempval = in_be32(&io->iop_pparb);
+	tempval |= (PB3_DIRB0 | PB3_DIRB1);
+	out_be32(&io->iop_pparb, tempval);
+
+        tempval = in_be32(&io->iop_pdirc);
+        tempval |= PC3_DIRC1;
+        out_be32(&io->iop_pdirc, tempval);
+
+        tempval = in_be32(&io->iop_pparc);
+        tempval |= PC3_DIRC1;
+        out_be32(&io->iop_pparc, tempval);
+
+	/* Port C has clocks......  */
+	tempval = in_be32(&io->iop_psorc);
+	tempval &= ~(CLK_TRX);
+	out_be32(&io->iop_psorc, tempval);
+
+	tempval = in_be32(&io->iop_pdirc);
+	tempval &= ~(CLK_TRX);
+	out_be32(&io->iop_pdirc, tempval);
+	tempval = in_be32(&io->iop_pparc);
+	tempval |= (CLK_TRX);
+	out_be32(&io->iop_pparc, tempval);
+
+	/* Configure Serial Interface clock routing.
+	 * First,  clear all FCC bits to zero,
+	 * then set the ones we want.
+	 */
+	immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
+	immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
+}
 
 static void __init
 mpc8560ads_setup_arch(void)
@@ -66,6 +132,7 @@
 	unsigned int freq;
 	struct gianfar_platform_data *pdata;
 	struct gianfar_mdio_data *mdata;
+	struct fs_platform_info *fpi;
 
 	cpm2_reset();
 
@@ -110,6 +177,28 @@
 		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
 	}
 
+	init_fcc_ioports();
+	ppc_sys_device_remove(MPC85xx_CPM_FCC1);
+
+	fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
+	if (fpi) {
+		memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+		fpi->bus_id = "0:02";
+		fpi->phy_addr = 2;
+		fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+		fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
+	}
+
+	fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
+	if (fpi) {
+		memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
+		fpi->macaddr[5] += 1;
+		fpi->bus_id = "0:03";
+		fpi->phy_addr = 3;
+		fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
+		fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
+	}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
 		ROOT_DEV = Root_RAM0;
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
index abf3228..c8c322f 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h
@@ -45,4 +45,23 @@
 
 #define MPC85XX_PCI1_IO_SIZE	0x01000000
 
+/* FCC1 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK9-12 */
+#define F1_RXCLK       12
+#define F1_TXCLK       11
+
+/* FCC2 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK13-16 */
+#define F2_RXCLK       13
+#define F2_TXCLK       14
+
+/* FCC3 Clock Source Configuration.  These can be
+ * redefined in the board specific file.
+ *    Can only choose from CLK13-16 */
+#define F3_RXCLK       15
+#define F3_TXCLK       16
+
+
 #endif				/* __MACH_MPC85XX_ADS_H__ */
diff --git a/arch/ppc/platforms/mpc8272ads_setup.c b/arch/ppc/platforms/mpc8272ads_setup.c
index abb7154..2a35fe2 100644
--- a/arch/ppc/platforms/mpc8272ads_setup.c
+++ b/arch/ppc/platforms/mpc8272ads_setup.c
@@ -56,64 +56,51 @@
 	},
 };
 
-static struct fs_mii_bus_info mii_bus_info = {
-	.method                 = fsmii_bitbang,
-	.id                     = 0,
-	.i.bitbang = {
-		.mdio_port	= fsiop_portc,
-		.mdio_bit	= 18,
-		.mdc_port	= fsiop_portc,
-		.mdc_bit	= 19,
-		.delay		= 1,
+static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = {
+	.mdio_dat.bit	= 18,
+	.mdio_dir.bit	= 18,
+	.mdc_dat.bit	= 19,
+	.delay		= 1,
+};
+
+static struct fs_platform_info mpc82xx_enet_pdata[] = {
+	[fsid_fcc1] = {
+		.fs_no		= fsid_fcc1,
+		.cp_page	= CPM_CR_FCC1_PAGE,
+		.cp_block 	= CPM_CR_FCC1_SBLOCK,
+
+		.clk_trx 	= (PC_F1RXCLK | PC_F1TXCLK),
+		.clk_route	= CMX1_CLK_ROUTE,
+		.clk_mask	= CMX1_CLK_MASK,
+		.init_ioports 	= init_fcc1_ioports,
+
+		.mem_offset	= FCC1_MEM_OFFSET,
+
+		.rx_ring	= 32,
+		.tx_ring	= 32,
+		.rx_copybreak	= 240,
+		.use_napi	= 0,
+		.napi_weight	= 17,
+		.bus_id		= "0:00",
 	},
-};
+	[fsid_fcc2] = {
+		.fs_no		= fsid_fcc2,
+		.cp_page	= CPM_CR_FCC2_PAGE,
+		.cp_block 	= CPM_CR_FCC2_SBLOCK,
+		.clk_trx 	= (PC_F2RXCLK | PC_F2TXCLK),
+		.clk_route	= CMX2_CLK_ROUTE,
+		.clk_mask	= CMX2_CLK_MASK,
+		.init_ioports	= init_fcc2_ioports,
 
-static struct fs_platform_info mpc82xx_fcc1_pdata = {
-	.fs_no		= fsid_fcc1,
-	.cp_page	= CPM_CR_FCC1_PAGE,
-	.cp_block 	= CPM_CR_FCC1_SBLOCK,
-	.clk_trx 	= (PC_F1RXCLK | PC_F1TXCLK),
-	.clk_route	= CMX1_CLK_ROUTE,
-	.clk_mask	= CMX1_CLK_MASK,
-	.init_ioports 	= init_fcc1_ioports,
+		.mem_offset	= FCC2_MEM_OFFSET,
 
-	.phy_addr	= 0,
-#ifdef PHY_INTERRUPT
-	.phy_irq	= PHY_INTERRUPT,
-#else
-	.phy_irq	= -1;
-#endif
-	.mem_offset	= FCC1_MEM_OFFSET,
-	.bus_info	= &mii_bus_info,
-	.rx_ring	= 32,
-	.tx_ring	= 32,
-	.rx_copybreak	= 240,
-	.use_napi	= 0,
-	.napi_weight	= 17,
-};
-
-static struct fs_platform_info mpc82xx_fcc2_pdata = {
-	.fs_no		= fsid_fcc2,
-	.cp_page	= CPM_CR_FCC2_PAGE,
-	.cp_block 	= CPM_CR_FCC2_SBLOCK,
-	.clk_trx 	= (PC_F2RXCLK | PC_F2TXCLK),
-	.clk_route	= CMX2_CLK_ROUTE,
-	.clk_mask	= CMX2_CLK_MASK,
-	.init_ioports	= init_fcc2_ioports,
-
-	.phy_addr	= 3,
-#ifdef PHY_INTERRUPT
-	.phy_irq	= PHY_INTERRUPT,
-#else
-	.phy_irq	= -1;
-#endif
-	.mem_offset	= FCC2_MEM_OFFSET,
-	.bus_info	= &mii_bus_info,
-	.rx_ring	= 32,
-	.tx_ring	= 32,
-	.rx_copybreak	= 240,
-	.use_napi	= 0,
-	.napi_weight	= 17,
+		.rx_ring	= 32,
+		.tx_ring	= 32,
+		.rx_copybreak	= 240,
+		.use_napi	= 0,
+		.napi_weight	= 17,
+		.bus_id		= "0:03",
+	},
 };
 
 static void init_fcc1_ioports(void)
@@ -209,20 +196,21 @@
 	bd_t* bi = (void*)__res;
 	int fs_no = fsid_fcc1+pdev->id-1;
 
-	mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase;
-	mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c;
-
-	switch(fs_no) {
-		case fsid_fcc1:
-			memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6);
-			pdev->dev.platform_data = &mpc82xx_fcc1_pdata;
-		break;
-		case fsid_fcc2:
-			memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6);
-			mpc82xx_fcc2_pdata.macaddr[5] ^= 1;
-			pdev->dev.platform_data = &mpc82xx_fcc2_pdata;
-		break;
+	if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) {
+		return;
 	}
+
+	mpc82xx_enet_pdata[fs_no].dpram_offset=
+			(u32)cpm2_immr->im_dprambase;
+	mpc82xx_enet_pdata[fs_no].fcc_regs_c =
+			(u32)cpm2_immr->im_fcc_c;
+	memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6);
+
+	/* prevent dup mac */
+	if(fs_no == fsid_fcc2)
+		mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1;
+
+	pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no];
 }
 
 static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev,
@@ -274,6 +262,29 @@
 	iounmap(immap);
 }
 
+static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev,
+					      int idx)
+{
+	m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT;
+	m82xx_mii_bb_pdata.irq[1] = -1;
+	m82xx_mii_bb_pdata.irq[2] = -1;
+	m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT;
+	m82xx_mii_bb_pdata.irq[31] = -1;
+
+
+	m82xx_mii_bb_pdata.mdio_dat.offset =
+				(u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+	m82xx_mii_bb_pdata.mdio_dir.offset =
+				(u32)&cpm2_immr->im_ioport.iop_pdirc;
+
+	m82xx_mii_bb_pdata.mdc_dat.offset =
+				(u32)&cpm2_immr->im_ioport.iop_pdatc;
+
+
+	pdev->dev.platform_data = &m82xx_mii_bb_pdata;
+}
+
 static int mpc8272ads_platform_notify(struct device *dev)
 {
 	static const struct platform_notify_dev_map dev_map[] = {
@@ -286,6 +297,10 @@
 			.rtn = mpc8272ads_fixup_uart_pdata,
 		},
 		{
+			.bus_id = "fsl-bb-mdio",
+			.rtn = mpc8272ads_fixup_mdio_pdata,
+		},
+		{
 			.bus_id = NULL
 		}
 	};
@@ -319,6 +334,7 @@
 	ppc_sys_device_enable(MPC82xx_CPM_SCC4);
 #endif
 
+	ppc_sys_device_enable(MPC82xx_MDIO_BB);
 
 	return 0;
 }
diff --git a/arch/ppc/platforms/mpc866ads_setup.c b/arch/ppc/platforms/mpc866ads_setup.c
index f19b616..e12cece 100644
--- a/arch/ppc/platforms/mpc866ads_setup.c
+++ b/arch/ppc/platforms/mpc866ads_setup.c
@@ -1,10 +1,10 @@
-/*arch/ppc/platforms/mpc885ads-setup.c
+/*arch/ppc/platforms/mpc866ads-setup.c
  *
- * Platform setup for the Freescale mpc885ads board
+ * Platform setup for the Freescale mpc866ads board
  *
  * Vitaly Bordug <vbordug@ru.mvista.com>
  *
- * Copyright 2005 MontaVista Software Inc.
+ * Copyright 2005-2006 MontaVista Software Inc.
  *
  * 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
@@ -42,49 +42,36 @@
 static void setup_smc1_ioports(void);
 static void setup_smc2_ioports(void);
 
-static struct fs_mii_bus_info fec_mii_bus_info = {
-	.method = fsmii_fec,
-	.id = 0,
-};
+static struct fs_mii_fec_platform_info	mpc8xx_mdio_fec_pdata;
 
-static struct fs_mii_bus_info scc_mii_bus_info = {
-	.method = fsmii_fixed,
-	.id = 0,
-	.i.fixed.speed = 10,
-	.i.fixed.duplex = 0,
-};
+static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
 
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
-	{
-	 .rx_ring = 128,
-	 .tx_ring = 16,
-	 .rx_copybreak = 240,
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+	[fsid_fec1] = {
+		.rx_ring = 128,
+		.tx_ring = 16,
+		.rx_copybreak = 240,
 
-	 .use_napi = 1,
-	 .napi_weight = 17,
+		.use_napi = 1,
+		.napi_weight = 17,
 
-	 .phy_addr = 15,
-	 .phy_irq = -1,
+		.init_ioports = setup_fec1_ioports,
 
-	 .use_rmii = 0,
+		.bus_id = "0:0f",
+		.has_phy = 1,
+	},
+	[fsid_scc1] = {
+		.rx_ring = 64,
+		.tx_ring = 8,
+		.rx_copybreak = 240,
+		.use_napi = 1,
+		.napi_weight = 17,
 
-	 .bus_info = &fec_mii_bus_info,
-	 }
-};
 
-static struct fs_platform_info mpc8xx_scc_pdata = {
-	.rx_ring = 64,
-	.tx_ring = 8,
-	.rx_copybreak = 240,
+		.init_ioports = setup_scc1_ioports,
 
-	.use_napi = 1,
-	.napi_weight = 17,
-
-	.phy_addr = -1,
-	.phy_irq = -1,
-
-	.bus_info = &scc_mii_bus_info,
-
+		.bus_id = "fixed@100:1",
+	},
 };
 
 static struct fs_uart_platform_info mpc866_uart_pdata[] = {
@@ -207,63 +194,6 @@
 
 }
 
-static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
-{
-	struct fs_platform_info *fpi = pdev->dev.platform_data;
-
-	volatile cpm8xx_t *cp;
-	bd_t *bd = (bd_t *) __res;
-	char *e;
-	int i;
-
-	/* Get pointer to Communication Processor */
-	cp = cpmp;
-	switch (fs_no) {
-	case fsid_fec1:
-		fpi = &mpc8xx_fec_pdata[0];
-		fpi->init_ioports = &setup_fec1_ioports;
-
-		break;
-	case fsid_scc1:
-		fpi = &mpc8xx_scc_pdata;
-		fpi->init_ioports = &setup_scc1_ioports;
-
-		break;
-	default:
-		printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
-		return;
-	}
-
-	pdev->dev.platform_data = fpi;
-	fpi->fs_no = fs_no;
-
-	e = (unsigned char *)&bd->bi_enetaddr;
-	for (i = 0; i < 6; i++)
-		fpi->macaddr[i] = *e++;
-
-	fpi->macaddr[5 - pdev->id]++;
-
-}
-
-static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
-					   int idx)
-{
-	/* This is for FEC devices only */
-	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
-		return;
-	mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
-}
-
-static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
-					   int idx)
-{
-	/* This is for SCC devices only */
-	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
-		return;
-
-	mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
-}
-
 static void setup_smc1_ioports(void)
 {
 	immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -315,6 +245,56 @@
 
 }
 
+static int ma_count = 0;
+
+static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
+{
+	struct fs_platform_info *fpi;
+
+	volatile cpm8xx_t *cp;
+	bd_t *bd = (bd_t *) __res;
+	char *e;
+	int i;
+
+	/* Get pointer to Communication Processor */
+	cp = cpmp;
+
+	if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+		printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+		return;
+	}
+
+
+	fpi = &mpc8xx_enet_pdata[fs_no];
+	fpi->fs_no = fs_no;
+	pdev->dev.platform_data = fpi;
+
+	e = (unsigned char *)&bd->bi_enetaddr;
+	for (i = 0; i < 6; i++)
+		fpi->macaddr[i] = *e++;
+
+	fpi->macaddr[5] += ma_count++;
+}
+
+static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
+					   int idx)
+{
+	/* This is for FEC devices only */
+	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
+		return;
+	mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
+}
+
+static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
+					   int idx)
+{
+	/* This is for SCC devices only */
+	if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
+		return;
+
+	mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
+}
+
 static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
                                               int idx)
 {
@@ -359,6 +339,9 @@
 
 int __init mpc866ads_init(void)
 {
+	bd_t *bd = (bd_t *) __res;
+	struct fs_mii_fec_platform_info* fmpi;
+
 	printk(KERN_NOTICE "mpc866ads: Init\n");
 
 	platform_notify = mpc866ads_platform_notify;
@@ -366,11 +349,20 @@
 	ppc_sys_device_initfunc();
 	ppc_sys_device_disable_all();
 
-#ifdef MPC8xx_SECOND_ETH_SCC1
+#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
 	ppc_sys_device_enable(MPC8xx_CPM_SCC1);
 #endif
 	ppc_sys_device_enable(MPC8xx_CPM_FEC1);
 
+	ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+	fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+		&mpc8xx_mdio_fec_pdata;
+
+	fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+	/* No PHY interrupt line here */
+	fmpi->irq[0xf] = -1;
+
 /* Since either of the uarts could be used as console, they need to ready */
 #ifdef CONFIG_SERIAL_CPM_SMC1
 	ppc_sys_device_enable(MPC8xx_CPM_SMC1);
@@ -381,6 +373,14 @@
 	ppc_sys_device_enable(MPC8xx_CPM_SMC2);
 	ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
 #endif
+	ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+
+	fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+		&mpc8xx_mdio_fec_pdata;
+
+	fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+	/* No PHY interrupt line here */
+	fmpi->irq[0xf] = -1;
 
 	return 0;
 }
diff --git a/arch/ppc/platforms/mpc885ads_setup.c b/arch/ppc/platforms/mpc885ads_setup.c
index c1fc4a1..5dfa4e6 100644
--- a/arch/ppc/platforms/mpc885ads_setup.c
+++ b/arch/ppc/platforms/mpc885ads_setup.c
@@ -38,7 +38,10 @@
 static void setup_smc1_ioports(void);
 static void setup_smc2_ioports(void);
 
-static void __init mpc885ads_scc_phy_init(char);
+static struct fs_mii_fec_platform_info	mpc8xx_mdio_fec_pdata;
+static void setup_fec1_ioports(void);
+static void setup_fec2_ioports(void);
+static void setup_scc3_ioports(void);
 
 static struct fs_uart_platform_info mpc885_uart_pdata[] = {
 	[fsid_smc1_uart] = {
@@ -61,23 +64,8 @@
  	},
 };
 
-static struct fs_mii_bus_info fec_mii_bus_info = {
-	.method = fsmii_fec,
-	.id = 0,
-};
-
-static struct fs_mii_bus_info scc_mii_bus_info = {
-#ifdef CONFIG_SCC_ENET_8xx_FIXED
-	.method = fsmii_fixed,
-#else
-	.method = fsmii_fec,
-#endif
-
-	.id = 0,
-};
-
-static struct fs_platform_info mpc8xx_fec_pdata[] = {
-	{
+static struct fs_platform_info mpc8xx_enet_pdata[] = {
+	[fsid_fec1] = {
 	 .rx_ring = 128,
 	 .tx_ring = 16,
 	 .rx_copybreak = 240,
@@ -85,11 +73,12 @@
 	 .use_napi = 1,
 	 .napi_weight = 17,
 
-	 .phy_addr = 0,
-	 .phy_irq = SIU_IRQ7,
+	 .init_ioports = setup_fec1_ioports,
 
-	 .bus_info = &fec_mii_bus_info,
-	 }, {
+          .bus_id = "0:00",
+          .has_phy = 1,
+	 },
+	[fsid_fec2] = {
 	     .rx_ring = 128,
 	     .tx_ring = 16,
 	     .rx_copybreak = 240,
@@ -97,35 +86,32 @@
 	     .use_napi = 1,
 	     .napi_weight = 17,
 
-	     .phy_addr = 1,
-	     .phy_irq = SIU_IRQ7,
+	     .init_ioports = setup_fec2_ioports,
 
-	     .bus_info = &fec_mii_bus_info,
-	     }
-};
+ 	     .bus_id = "0:01",
+ 	     .has_phy = 1,
+	     },
+	[fsid_scc3] = {
+		.rx_ring = 64,
+		.tx_ring = 8,
+		.rx_copybreak = 240,
 
-static struct fs_platform_info mpc8xx_scc_pdata = {
-	.rx_ring = 64,
-	.tx_ring = 8,
-	.rx_copybreak = 240,
+		.use_napi = 1,
+		.napi_weight = 17,
 
-	.use_napi = 1,
-	.napi_weight = 17,
-
-	.phy_addr = 2,
-#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
-	.phy_irq = -1,
+		.init_ioports = setup_scc3_ioports,
+#ifdef CONFIG_FIXED_MII_10_FDX
+		.bus_id = "fixed@100:1",
 #else
-	.phy_irq = SIU_IRQ7,
-#endif
-
-	.bus_info = &scc_mii_bus_info,
+		.bus_id = "0:02",
+ #endif
+	},
 };
 
 void __init board_init(void)
 {
-	volatile cpm8xx_t *cp = cpmp;
-	unsigned int *bcsr_io;
+	cpm8xx_t *cp = cpmp;
+ 	unsigned int *bcsr_io;
 
 #ifdef CONFIG_FS_ENET
 	immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -164,6 +150,14 @@
 	/* use MDC for MII (common) */
 	setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
 	clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
+	bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+	clrbits32(bcsr_io,BCSR5_MII1_EN);
+	clrbits32(bcsr_io,BCSR5_MII1_RST);
+#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
+	clrbits32(bcsr_io,BCSR5_MII2_EN);
+	clrbits32(bcsr_io,BCSR5_MII2_RST);
+#endif
+	iounmap(bcsr_io);
 #endif
 }
 
@@ -194,8 +188,8 @@
 	/* configure FEC2 pins */
 	setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
 	setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
-	setbits32(&immap->im_cpm.cp_peso, 0x00037800);
 	clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
+	setbits32(&immap->im_cpm.cp_peso, 0x00037800);
 	clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
 }
 
@@ -213,6 +207,8 @@
 
 	/* Enable the PHY.
 	 */
+	clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	udelay(1000);
 	setbits32(bcsr_io+4, BCSR4_ETH10_RST);
 	/* Configure port A pins for Txd and Rxd.
 	 */
@@ -254,37 +250,38 @@
 	clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
 	setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
 
-	setbits32(bcsr_io+1, BCSR1_ETHEN);
+	setbits32(bcsr_io+4, BCSR1_ETHEN);
 	iounmap(bcsr_io);
 }
 
+static int mac_count = 0;
+
 static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
 {
-	struct fs_platform_info *fpi = pdev->dev.platform_data;
-
-	volatile cpm8xx_t *cp;
+ 	struct fs_platform_info *fpi;
 	bd_t *bd = (bd_t *) __res;
 	char *e;
 	int i;
 
-	/* Get pointer to Communication Processor */
-	cp = cpmp;
+	if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
+		printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
+		return;
+	}
+
+	fpi = &mpc8xx_enet_pdata[fs_no];
+
 	switch (fs_no) {
 	case fsid_fec1:
-		fpi = &mpc8xx_fec_pdata[0];
 		fpi->init_ioports = &setup_fec1_ioports;
 		break;
 	case fsid_fec2:
-		fpi = &mpc8xx_fec_pdata[1];
 		fpi->init_ioports = &setup_fec2_ioports;
 		break;
 	case fsid_scc3:
-		fpi = &mpc8xx_scc_pdata;
 		fpi->init_ioports = &setup_scc3_ioports;
-		mpc885ads_scc_phy_init(fpi->phy_addr);
 		break;
 	default:
-    	        printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
+    	        printk(KERN_WARNING "Device %s is not supported!\n", pdev->name);
 	        return;
 	}
 
@@ -295,7 +292,7 @@
 	for (i = 0; i < 6; i++)
 		fpi->macaddr[i] = *e++;
 
-	fpi->macaddr[5 - pdev->id]++;
+	fpi->macaddr[5] += mac_count++;
 
 }
 
@@ -318,58 +315,6 @@
 	mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
 }
 
-/* SCC ethernet controller does not have MII management channel. FEC1 MII
- * channel is used to communicate with the 10Mbit PHY.
- */
-
-#define MII_ECNTRL_PINMUX        0x4
-#define FEC_ECNTRL_PINMUX        0x00000004
-#define FEC_RCNTRL_MII_MODE        0x00000004
-
-/* Make MII read/write commands.
- */
-#define mk_mii_write(REG, VAL, PHY_ADDR)    (0x50020000 | (((REG) & 0x1f) << 18) | \
-                ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
-
-static void mpc885ads_scc_phy_init(char phy_addr)
-{
-	volatile immap_t *immap;
-	volatile fec_t *fecp;
-	bd_t *bd;
-
-	bd = (bd_t *) __res;
-	immap = (immap_t *) IMAP_ADDR;	/* pointer to internal registers */
-	fecp = &(immap->im_cpm.cp_fec);
-
-	/* Enable MII pins of the FEC1
-	 */
-	setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
-	clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
-	/* Set MII speed to 2.5 MHz
-	 */
-	out_be32(&fecp->fec_mii_speed,
-		 ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
-
-	/* Enable FEC pin MUX
-	 */
-	setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
-	setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-
-	out_be32(&fecp->fec_mii_data,
-		 mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
-	udelay(100);
-	out_be32(&fecp->fec_mii_data,
-		 mk_mii_write(MII_ADVERTISE,
-			      ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
-	udelay(100);
-
-	/* Disable FEC MII settings
-	 */
-	clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
-	clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
-	out_be32(&fecp->fec_mii_speed, 0);
-}
-
 static void setup_smc1_ioports(void)
 {
         immap_t *immap = (immap_t *) IMAP_ADDR;
@@ -462,6 +407,9 @@
 
 int __init mpc885ads_init(void)
 {
+	struct fs_mii_fec_platform_info* fmpi;
+	bd_t *bd = (bd_t *) __res;
+
 	printk(KERN_NOTICE "mpc885ads: Init\n");
 
 	platform_notify = mpc885ads_platform_notify;
@@ -471,8 +419,17 @@
 
 	ppc_sys_device_enable(MPC8xx_CPM_FEC1);
 
+	ppc_sys_device_enable(MPC8xx_MDIO_FEC);
+	fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
+		&mpc8xx_mdio_fec_pdata;
+
+	fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+
+	/* No PHY interrupt line here */
+	fmpi->irq[0xf] = SIU_IRQ7;
+
 #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
-	ppc_sys_device_enable(MPC8xx_CPM_SCC1);
+	ppc_sys_device_enable(MPC8xx_CPM_SCC3);
 
 #endif
 #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
diff --git a/arch/ppc/platforms/pq2ads_pd.h b/arch/ppc/platforms/pq2ads_pd.h
index 8f14a43..672483d 100644
--- a/arch/ppc/platforms/pq2ads_pd.h
+++ b/arch/ppc/platforms/pq2ads_pd.h
@@ -29,86 +29,4 @@
 #define F3_RXCLK	13
 #define F3_TXCLK	14
 
-/* Automatically generates register configurations */
-#define PC_CLK(x)	((uint)(1<<(x-1)))	/* FCC CLK I/O ports */
-
-#define CMXFCR_RF1CS(x)	((uint)((x-5)<<27))	/* FCC1 Receive Clock Source */
-#define CMXFCR_TF1CS(x)	((uint)((x-5)<<24))	/* FCC1 Transmit Clock Source */
-#define CMXFCR_RF2CS(x)	((uint)((x-9)<<19))	/* FCC2 Receive Clock Source */
-#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16))	/* FCC2 Transmit Clock Source */
-#define CMXFCR_RF3CS(x)	((uint)((x-9)<<11))	/* FCC3 Receive Clock Source */
-#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8))	/* FCC3 Transmit Clock Source */
-
-#define PC_F1RXCLK	PC_CLK(F1_RXCLK)
-#define PC_F1TXCLK	PC_CLK(F1_TXCLK)
-#define CMX1_CLK_ROUTE	(CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
-#define CMX1_CLK_MASK	((uint)0xff000000)
-
-#define PC_F2RXCLK	PC_CLK(F2_RXCLK)
-#define PC_F2TXCLK	PC_CLK(F2_TXCLK)
-#define CMX2_CLK_ROUTE	(CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
-#define CMX2_CLK_MASK	((uint)0x00ff0000)
-
-#define PC_F3RXCLK	PC_CLK(F3_RXCLK)
-#define PC_F3TXCLK	PC_CLK(F3_TXCLK)
-#define CMX3_CLK_ROUTE	(CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
-#define CMX3_CLK_MASK	((uint)0x0000ff00)
-
-/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PA1_COL		0x00000001U
-#define PA1_CRS		0x00000002U
-#define PA1_TXER	0x00000004U
-#define PA1_TXEN	0x00000008U
-#define PA1_RXDV	0x00000010U
-#define PA1_RXER	0x00000020U
-#define PA1_TXDAT	0x00003c00U
-#define PA1_RXDAT	0x0003c000U
-#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
-#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
-		PA1_RXDV | PA1_RXER)
-#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
-#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
-
-
-/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB2_TXER	0x00000001U
-#define PB2_RXDV	0x00000002U
-#define PB2_TXEN	0x00000004U
-#define PB2_RXER	0x00000008U
-#define PB2_COL		0x00000010U
-#define PB2_CRS		0x00000020U
-#define PB2_TXDAT	0x000003c0U
-#define PB2_RXDAT	0x00003c00U
-#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
-		PB2_RXER | PB2_RXDV | PB2_TXER)
-#define PB2_PSORB1	(PB2_TXEN)
-#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
-#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
-
-
-/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
- * but there is little variation among the choices.
- */
-#define PB3_RXDV	0x00004000U
-#define PB3_RXER	0x00008000U
-#define PB3_TXER	0x00010000U
-#define PB3_TXEN	0x00020000U
-#define PB3_COL		0x00040000U
-#define PB3_CRS		0x00080000U
-#define PB3_TXDAT	0x0f000000U
-#define PB3_RXDAT	0x00f00000U
-#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
-		PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
-#define PB3_PSORB1	0
-#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
-#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
-
-#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
-#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
-#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
-
 #endif
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 2497bbc..dca23f2 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -93,7 +93,7 @@
 endif
 obj-$(CONFIG_RAPIDIO)		+= ppc85xx_rio.o
 obj-$(CONFIG_83xx)		+= ppc83xx_setup.o ppc_sys.o \
-					mpc83xx_sys.o mpc83xx_devices.o
+					mpc83xx_sys.o mpc83xx_devices.o ipic.o
 ifeq ($(CONFIG_83xx),y)
 obj-$(CONFIG_PCI)		+= pci_auto.o
 endif
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
new file mode 100644
index 0000000..46801f5
--- /dev/null
+++ b/arch/ppc/syslib/ipic.c
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * 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/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+	[9] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 24,
+		.prio_mask = 0,
+	},
+	[10] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 25,
+		.prio_mask = 1,
+	},
+	[11] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 26,
+		.prio_mask = 2,
+	},
+	[14] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 29,
+		.prio_mask = 5,
+	},
+	[15] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 30,
+		.prio_mask = 6,
+	},
+	[16] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 31,
+		.prio_mask = 7,
+	},
+	[17] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 1,
+		.prio_mask = 5,
+	},
+	[18] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 2,
+		.prio_mask = 6,
+	},
+	[19] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 3,
+		.prio_mask = 7,
+	},
+	[20] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[21] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[22] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[23] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[32] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[33] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[34] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[35] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[36] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[37] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[38] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[39] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[48] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 0,
+		.prio_mask = 4,
+	},
+	[64] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[65] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[66] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[67] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[68] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 4,
+		.prio_mask = 0,
+	},
+	[69] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 5,
+		.prio_mask = 1,
+	},
+	[70] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 6,
+		.prio_mask = 2,
+	},
+	[71] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 7,
+		.prio_mask = 3,
+	},
+	[72] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 8,
+	},
+	[73] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 9,
+	},
+	[74] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 10,
+	},
+	[75] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 11,
+	},
+	[76] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 12,
+	},
+	[77] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 13,
+	},
+	[78] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 14,
+	},
+	[79] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 15,
+	},
+	[80] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 16,
+	},
+	[84] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 20,
+	},
+	[85] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 21,
+	},
+	[90] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 26,
+	},
+	[91] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 27,
+	},
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+	return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+	out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+	return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp &= ~(1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	ipic_disable_irq(irq);
+
+	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+	.typename = " IPIC  ",
+	.enable = ipic_enable_irq,
+	.disable = ipic_disable_irq,
+	.ack = ipic_disable_irq_and_ack,
+	.end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+		unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses,
+		unsigned int senses_count)
+{
+	u32 i, temp = 0;
+
+	primary_ipic = &p_ipic;
+	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+	primary_ipic->irq_offset = irq_offset;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+	/* default priority scheme is grouped. If spread mode is required
+	 * configure SICFR accordingly */
+	if (flags & IPIC_SPREADMODE_GRP_A)
+		temp |= SICFR_IPSA;
+	if (flags & IPIC_SPREADMODE_GRP_D)
+		temp |= SICFR_IPSD;
+	if (flags & IPIC_SPREADMODE_MIX_A)
+		temp |= SICFR_MPSA;
+	if (flags & IPIC_SPREADMODE_MIX_B)
+		temp |= SICFR_MPSB;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+	/* handle MCP route */
+	temp = 0;
+	if (flags & IPIC_DISABLE_MCP_OUT)
+		temp = SERCR_MCPR;
+	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+	/* handle routing of IRQ0 to MCP */
+	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+	if (flags & IPIC_IRQ0_MCP)
+		temp |= SEMSR_SIRQ0;
+	else
+		temp &= ~SEMSR_SIRQ0;
+
+	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+		irq_desc[i+irq_offset].chip = &ipic;
+		irq_desc[i+irq_offset].status = IRQ_LEVEL;
+	}
+
+	temp = 0;
+	for (i = 0 ; i < senses_count ; i++) {
+		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+			temp |= 1 << (15 - i);
+			if (i != 0)
+				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+			else
+				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+		}
+	}
+	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+			senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	if (priority > 7)
+		return -EINVAL;
+	if (src > 127)
+		return -EINVAL;
+	if (ipic_info[src].prio == 0)
+		return -EINVAL;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+	if (priority < 4) {
+		temp &= ~(0x7 << (20 + (3 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+	} else {
+		temp &= ~(0x7 << (4 + (7 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+	}
+
+	ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+	return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+	/* clear and set HPI */
+	temp &= 0x7f000000;
+	temp |= (src & 0x7f) << 24;
+
+	ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+	ipic_set_priority(MPC83xx_IRQ_MU, 1);
+	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp |= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp &= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+	return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+	if (irq == 0)    /* 0 --> no irq is pending */
+		irq = -1;
+
+	return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+	set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+	.id		= 0,
+	.cls		= &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+	int rc;
+
+	if (!primary_ipic->regs)
+		return -ENODEV;
+	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+	rc = sysdev_class_register(&ipic_sysclass);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys class\n");
+		return -ENODEV;
+	}
+	rc = sysdev_register(&device_ipic);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys device\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
new file mode 100644
index 0000000..a60c9d1
--- /dev/null
+++ b/arch/ppc/syslib/ipic.h
@@ -0,0 +1,47 @@
+/*
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * 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.
+ */
+#ifndef __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE	(0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define	SICFR_IPSA	0x00010000
+#define	SICFR_IPSD	0x00080000
+#define	SICFR_MPSA	0x00200000
+#define	SICFR_MPSB	0x00400000
+
+/* System External Interrupt Mask Register */
+#define	SEMSR_SIRQ0	0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR	0x00000001
+
+struct ipic {
+	volatile u32 __iomem	*regs;
+	unsigned int		irq_offset;
+};
+
+struct ipic_info {
+	u8	pend;		/* pending register offset from base */
+	u8	mask;		/* mask register offset from base */
+	u8	prio;		/* priority register offset from base */
+	u8	force;		/* force register offset from base */
+	u8	bit;		/* register bit position (as per doc)
+				   bit mask = 1 << (31 - bit) */
+	u8	prio_mask;	/* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 7735336f..325136e 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -16,9 +16,11 @@
 #include <linux/device.h>
 #include <linux/serial_8250.h>
 #include <linux/fsl_devices.h>
+#include <linux/fs_enet_pd.h>
 #include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/ppc_sys.h>
+#include <asm/cpm2.h>
 
 /* We use offsets for IORESOURCE_MEM since we do not know at compile time
  * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup
@@ -82,6 +84,60 @@
 	.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
 };
 
+static struct fs_platform_info mpc85xx_fcc1_pdata = {
+	.fs_no          = fsid_fcc1,
+	.cp_page        = CPM_CR_FCC1_PAGE,
+	.cp_block       = CPM_CR_FCC1_SBLOCK,
+
+	.rx_ring        = 32,
+	.tx_ring        = 32,
+	.rx_copybreak   = 240,
+	.use_napi       = 0,
+	.napi_weight    = 17,
+
+	.clk_mask	= CMX1_CLK_MASK,
+	.clk_route	= CMX1_CLK_ROUTE,
+	.clk_trx	= (PC_F1RXCLK | PC_F1TXCLK),
+
+	.mem_offset     = FCC1_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc2_pdata = {
+	.fs_no          = fsid_fcc2,
+	.cp_page        = CPM_CR_FCC2_PAGE,
+	.cp_block       = CPM_CR_FCC2_SBLOCK,
+
+	.rx_ring        = 32,
+	.tx_ring        = 32,
+	.rx_copybreak   = 240,
+	.use_napi       = 0,
+	.napi_weight    = 17,
+
+	.clk_mask	= CMX2_CLK_MASK,
+	.clk_route	= CMX2_CLK_ROUTE,
+	.clk_trx	= (PC_F2RXCLK | PC_F2TXCLK),
+
+	.mem_offset     = FCC2_MEM_OFFSET,
+};
+
+static struct fs_platform_info mpc85xx_fcc3_pdata = {
+	.fs_no          = fsid_fcc3,
+	.cp_page        = CPM_CR_FCC3_PAGE,
+	.cp_block       = CPM_CR_FCC3_SBLOCK,
+
+	.rx_ring        = 32,
+	.tx_ring        = 32,
+	.rx_copybreak   = 240,
+	.use_napi       = 0,
+	.napi_weight    = 17,
+
+	.clk_mask	= CMX3_CLK_MASK,
+	.clk_route	= CMX3_CLK_ROUTE,
+	.clk_trx	= (PC_F3RXCLK | PC_F3TXCLK),
+
+	.mem_offset     = FCC3_MEM_OFFSET,
+};
+
 static struct plat_serial8250_port serial_platform_data[] = {
 	[0] = {
 		.mapbase	= 0x4500,
@@ -318,19 +374,28 @@
 	[MPC85xx_CPM_FCC1] = {
 		.name = "fsl-cpm-fcc",
 		.id	= 1,
-		.num_resources	 = 3,
+		.num_resources	 = 4,
+		.dev.platform_data = &mpc85xx_fcc1_pdata,
 		.resource = (struct resource[]) {
 			{
+				.name	= "fcc_regs",
 				.start	= 0x91300,
 				.end	= 0x9131F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name   = "fcc_regs_c",
 				.start	= 0x91380,
 				.end	= 0x9139F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name	= "fcc_pram",
+				.start	= 0x88400,
+				.end	= 0x884ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
 				.start	= SIU_INT_FCC1,
 				.end	= SIU_INT_FCC1,
 				.flags	= IORESOURCE_IRQ,
@@ -340,19 +405,28 @@
 	[MPC85xx_CPM_FCC2] = {
 		.name = "fsl-cpm-fcc",
 		.id	= 2,
-		.num_resources	 = 3,
+		.num_resources	 = 4,
+		.dev.platform_data = &mpc85xx_fcc2_pdata,
 		.resource = (struct resource[]) {
 			{
+				.name	= "fcc_regs",
 				.start	= 0x91320,
 				.end	= 0x9133F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name   = "fcc_regs_c",
 				.start	= 0x913A0,
 				.end	= 0x913CF,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name	= "fcc_pram",
+				.start	= 0x88500,
+				.end	= 0x885ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
 				.start	= SIU_INT_FCC2,
 				.end	= SIU_INT_FCC2,
 				.flags	= IORESOURCE_IRQ,
@@ -362,19 +436,28 @@
 	[MPC85xx_CPM_FCC3] = {
 		.name = "fsl-cpm-fcc",
 		.id	= 3,
-		.num_resources	 = 3,
+		.num_resources	 = 4,
+		.dev.platform_data = &mpc85xx_fcc3_pdata,
 		.resource = (struct resource[]) {
 			{
+				.name	= "fcc_regs",
 				.start	= 0x91340,
 				.end	= 0x9135F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name   = "fcc_regs_c",
 				.start	= 0x913D0,
 				.end	= 0x913FF,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
+				.name	= "fcc_pram",
+				.start	= 0x88600,
+				.end	= 0x886ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
 				.start	= SIU_INT_FCC3,
 				.end	= SIU_INT_FCC3,
 				.flags	= IORESOURCE_IRQ,
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c
index 6f53638..cf5ab47 100644
--- a/arch/ppc/syslib/mpc8xx_devices.c
+++ b/arch/ppc/syslib/mpc8xx_devices.c
@@ -218,6 +218,14 @@
 			},
 		},
 	},
+
+        [MPC8xx_MDIO_FEC] = {
+                .name = "fsl-cpm-fec-mdio",
+                .id = 0,
+                .num_resources = 0,
+
+        },
+
 };
 
 static int __init mach_mpc8xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c
index eee2132..18ba1d7 100644
--- a/arch/ppc/syslib/mpc8xx_sys.c
+++ b/arch/ppc/syslib/mpc8xx_sys.c
@@ -22,7 +22,7 @@
 		.ppc_sys_name	= "MPC86X",
 		.mask 		= 0xFFFFFFFF,
 		.value 		= 0x00000000,
-		.num_devices	= 7,
+		.num_devices	= 8,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC8xx_CPM_FEC1,
@@ -32,13 +32,14 @@
 			MPC8xx_CPM_SCC4,
 			MPC8xx_CPM_SMC1,
 			MPC8xx_CPM_SMC2,
+			MPC8xx_MDIO_FEC,
 		},
 	},
 	{
 		.ppc_sys_name	= "MPC885",
 		.mask 		= 0xFFFFFFFF,
 		.value 		= 0x00000000,
-		.num_devices	= 8,
+		.num_devices	= 9,
 		.device_list	= (enum ppc_sys_devices[])
 		{
 			MPC8xx_CPM_FEC1,
@@ -49,6 +50,7 @@
 			MPC8xx_CPM_SCC4,
 			MPC8xx_CPM_SMC1,
 			MPC8xx_CPM_SMC2,
+			MPC8xx_MDIO_FEC,
 		},
 	},
 	{	/* default match */
diff --git a/arch/ppc/syslib/pq2_devices.c b/arch/ppc/syslib/pq2_devices.c
index 8692d00c..fefbc21 100644
--- a/arch/ppc/syslib/pq2_devices.c
+++ b/arch/ppc/syslib/pq2_devices.c
@@ -369,6 +369,11 @@
 			},
 		},
 	},
+	[MPC82xx_MDIO_BB] = {
+		.name = "fsl-bb-mdio",
+		.id = 0,
+		.num_resources = 0,
+	},
 };
 
 static int __init mach_mpc82xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/pq2_sys.c b/arch/ppc/syslib/pq2_sys.c
index fee8948..f52600c 100644
--- a/arch/ppc/syslib/pq2_sys.c
+++ b/arch/ppc/syslib/pq2_sys.c
@@ -139,13 +139,14 @@
 		.ppc_sys_name	= "8272",
 		.mask		= 0x0000ff00,
 		.value		= 0x00000c00,
-		.num_devices	= 12,
+		.num_devices	= 13,
 		.device_list = (enum ppc_sys_devices[])
 		{
 			MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1,
 			MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4,
 			MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI,
 			MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1,
+			MPC82xx_MDIO_BB,
 		},
 	},
 	/* below is a list of the 8280 family of processors */
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index d0f82c9..a0a94e0 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -617,6 +617,7 @@
 	spin_unlock(&appldata_timer_lock);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit
 appldata_cpu_notify(struct notifier_block *self,
 		    unsigned long action, void *hcpu)
@@ -625,20 +626,19 @@
 	case CPU_ONLINE:
 		appldata_online_cpu((long) hcpu);
 		break;
-#ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 		appldata_offline_cpu((long) hcpu);
 		break;
-#endif
 	default:
 		break;
 	}
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata appldata_nb = {
+static struct notifier_block appldata_nb = {
 	.notifier_call = appldata_cpu_notify,
 };
+#endif
 
 /*
  * appldata_init()
@@ -662,7 +662,7 @@
 		appldata_online_cpu(i);
 
 	/* Register cpu hotplug notifier */
-	register_cpu_notifier(&appldata_nb);
+	register_hotcpu_notifier(&appldata_nb);
 
 	appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);
 #ifdef MODULE
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f4dfc10..f1d4591 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,13 +1,16 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Mon Apr  3 14:34:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Thu Jul 27 13:51:07 2006
 #
 CONFIG_MMU=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_S390=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
@@ -25,6 +28,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 CONFIG_AUDIT=y
 # CONFIG_AUDITSYSCALL is not set
@@ -43,10 +47,12 @@
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
+CONFIG_RT_MUTEXES=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -94,7 +100,6 @@
 CONFIG_DEFAULT_MIGRATION_COST=1000000
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
-CONFIG_BINFMT_ELF32=y
 
 #
 # Code generation options
@@ -115,6 +120,7 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
 
 #
 # I/O subsystem configuration
@@ -142,6 +148,7 @@
 # CONFIG_APPLDATA_BASE is not set
 CONFIG_NO_IDLE_HZ=y
 CONFIG_NO_IDLE_HZ_INIT=y
+CONFIG_S390_HYPFS_FS=y
 CONFIG_KEXEC=y
 
 #
@@ -174,6 +181,8 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -186,7 +195,10 @@
 # CONFIG_INET6_IPCOMP is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -263,6 +275,7 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -276,6 +289,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+CONFIG_SYS_HYPERVISOR=y
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -334,6 +348,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -359,9 +374,7 @@
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 # CONFIG_MD_RAID10 is not set
-CONFIG_MD_RAID5=m
-# CONFIG_MD_RAID5_RESHAPE is not set
-# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_RAID456 is not set
 CONFIG_MD_MULTIPATH=m
 # CONFIG_MD_FAULTY is not set
 CONFIG_BLK_DEV_DM=y
@@ -419,7 +432,8 @@
 #
 # Cryptographic devices
 #
-CONFIG_Z90CRYPT=m
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
 
 #
 # Network device support
@@ -509,6 +523,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -614,26 +629,36 @@
 # Instrumentation Support
 #
 # CONFIG_PROFILING is not set
-# CONFIG_STATISTICS is not set
+CONFIG_STATISTICS=y
+CONFIG_KPROBES=y
 
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_LOG_BUF_SHIFT=17
 # 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_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
@@ -688,3 +713,4 @@
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=m
 # CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 86601a9..9a33ed6 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -16,9 +16,11 @@
 obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
 obj-$(CONFIG_SMP)		+= smp.o
 
+obj-$(CONFIG_AUDIT)		+= audit.o
+compat-obj-$(CONFIG_AUDIT)	+= compat_audit.o
 obj-$(CONFIG_COMPAT)		+= compat_linux.o compat_signal.o \
 					compat_wrapper.o compat_exec_domain.o \
-					binfmt_elf32.o
+					binfmt_elf32.o $(compat-obj-y)
 
 obj-$(CONFIG_VIRT_TIMER)	+= vtime.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
new file mode 100644
index 0000000..0741d91
--- /dev/null
+++ b/arch/s390/kernel/audit.c
@@ -0,0 +1,66 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_COMPAT
+	extern int s390_classify_syscall(unsigned);
+	if (abi == AUDIT_ARCH_S390)
+		return s390_classify_syscall(syscall);
+#endif
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_COMPAT
+	extern __u32 s390_dir_class[];
+	extern __u32 s390_write_class[];
+	extern __u32 s390_read_class[];
+	extern __u32 s390_chattr_class[];
+	audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
+	audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
+#endif
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
new file mode 100644
index 0000000..16d9436
--- /dev/null
+++ b/arch/s390/kernel/compat_audit.c
@@ -0,0 +1,38 @@
+#undef __s390x__
+#include <asm/unistd.h>
+
+unsigned s390_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned s390_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+unsigned s390_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned s390_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int s390_classify_syscall(unsigned syscall)
+{
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 1;
+	}
+}
diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S
index 5d59e262..8372752 100644
--- a/arch/s390/lib/uaccess.S
+++ b/arch/s390/lib/uaccess.S
@@ -88,30 +88,31 @@
         .globl __copy_in_user_asm
 	# %r2 = from, %r3 = n, %r4 = to
 __copy_in_user_asm:
+	ahi	%r3,-1
+	jo	6f
 	sacf	256
-	bras	1,1f
-	mvc	0(1,%r4),0(%r2)
-0:	mvc	0(256,%r4),0(%r2)
-	la	%r2,256(%r2)
-	la	%r4,256(%r4)
-1:	ahi	%r3,-256
-	jnm	0b
-2:	ex	%r3,0(%r1)
-	sacf	0
-	slr	%r2,%r2
-	br	14
-3:	mvc	0(1,%r4),0(%r2)
+	bras	%r1,4f
+0:	ahi	%r3,257
+1:	mvc	0(1,%r4),0(%r2)
 	la	%r2,1(%r2)
 	la	%r4,1(%r4)
 	ahi	%r3,-1
+	jnz	1b
+2:	lr	%r2,%r3
+	br	%r14
+3:	mvc	0(256,%r4),0(%r2)
+	la	%r2,256(%r2)
+	la	%r4,256(%r4)
+4:	ahi	%r3,-256
 	jnm	3b
-4:	lr	%r2,%r3
+5:	ex	%r3,4(%r1)
 	sacf	0
+6:	slr	%r2,%r2
 	br	%r14
         .section __ex_table,"a"
-	.long	0b,3b
-	.long	2b,3b
-	.long	3b,4b
+	.long	1b,2b
+	.long	3b,0b
+	.long	5b,0b
         .previous
 
         .align 4
diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S
index 19b41a3..1f755be 100644
--- a/arch/s390/lib/uaccess64.S
+++ b/arch/s390/lib/uaccess64.S
@@ -88,30 +88,31 @@
         .globl __copy_in_user_asm
 	# %r2 = from, %r3 = n, %r4 = to
 __copy_in_user_asm:
+	aghi	%r3,-1
+	jo	6f
 	sacf	256
-	bras	1,1f
-	mvc	0(1,%r4),0(%r2)
-0:	mvc	0(256,%r4),0(%r2)
-	la	%r2,256(%r2)
-	la	%r4,256(%r4)
-1:	aghi	%r3,-256
-	jnm	0b
-2:	ex	%r3,0(%r1)
-	sacf	0
-	slgr	%r2,%r2
-	br	14
-3:	mvc	0(1,%r4),0(%r2)
+	bras	%r1,4f
+0:	aghi	%r3,257
+1:	mvc	0(1,%r4),0(%r2)
 	la	%r2,1(%r2)
 	la	%r4,1(%r4)
 	aghi	%r3,-1
-	jnm	3b
-4:	lgr	%r2,%r3
-	sacf	0
+	jnz	1b
+2:	lgr	%r2,%r3
 	br	%r14
+3:	mvc	0(256,%r4),0(%r2)
+	la	%r2,256(%r2)
+	la	%r4,256(%r4)
+4:	aghi	%r3,-256
+	jnm	3b
+5:	ex	%r3,4(%r1)
+	sacf	0
+6:	slgr	%r2,%r2
+	br	14
         .section __ex_table,"a"
-	.quad	0b,3b
-	.quad	2b,3b
-	.quad	3b,4b
+	.quad	1b,2b
+	.quad	3b,0b
+	.quad	5b,0b
         .previous
 
         .align 4
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index eb6ebfe..6e6b6de 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -129,7 +129,7 @@
                 /*
                  * pg_table is physical at this point
                  */
-		pg_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
 
                 pg_dir->pgd0 =  (_PAGE_TABLE | __pa(pg_table));
                 pg_dir->pgd1 =  (_PAGE_TABLE | (__pa(pg_table)+1024));
@@ -219,7 +219,7 @@
                         continue;
                 }          
         
-	        pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
+		pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4);
                 pgd_populate(&init_mm, pg_dir, pm_dir);
 
                 for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
@@ -228,7 +228,7 @@
                                 continue; 
                         }          
                         
-                        pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
                         pmd_populate_kernel(&init_mm, pm_dir, pt_dir);
 	
                         for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 781dbb1..b09805f 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -421,18 +421,22 @@
 
 static int __init sq_api_init(void)
 {
+	int ret;
 	printk(KERN_NOTICE "sq: Registering store queue API.\n");
 
-#ifdef CONFIG_PROC_FS
 	create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
-#endif
 
-	return misc_register(&sq_dev);
+	ret = misc_register(&sq_dev);
+	if (ret)
+		remove_proc_entry("sq_mapping", NULL);
+
+	return ret;
 }
 
 static void __exit sq_api_exit(void)
 {
 	misc_deregister(&sq_dev);
+	remove_proc_entry("sq_mapping", NULL);
 }
 
 module_init(sq_api_init);
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 35488d6..0251cab 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -348,9 +348,9 @@
 	init_mm.context = (unsigned long) NO_CONTEXT;
 	init_task.thread.kregs = &fake_swapper_regs;
 
-	smp_setup_cpu_possible_map();
-
 	paging_init();
+
+	smp_setup_cpu_possible_map();
 }
 
 static int __init set_preferred_console(void)
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index e311ade..276f228 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -34,7 +34,6 @@
 #include <asm/tlbflush.h>
 #include <asm/cpudata.h>
 
-volatile int smp_processors_ready = 0;
 int smp_num_cpus = 1;
 volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,};
 unsigned char boot_cpu_id = 0;
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index ba843f6..3ff4edd 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -42,7 +42,7 @@
 
 extern void calibrate_delay(void);
 
-extern volatile int smp_processors_ready;
+static volatile int smp_processors_ready = 0;
 static int smp_highest_cpu;
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 extern cpuinfo_sparc cpu_data[NR_CPUS];
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 3b32096..7d4a649 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -39,7 +39,6 @@
 
 extern void calibrate_delay(void);
 
-extern volatile int smp_processors_ready;
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 extern unsigned char boot_cpu_id;
 
@@ -217,7 +216,6 @@
 	}
 
 	/* Ok, they are spinning and ready to go. */
-	smp_processors_ready = 1;
 }
 
 /* At each hardware IRQ, we get this called to forward IRQ reception
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index a41c8a5..94ff58c 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -219,6 +219,21 @@
 	return err;
 }
 
+int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
+{
+	if (ARCH_SUN4C_SUN4 &&
+	    (len > 0x20000000 ||
+	     ((flags & MAP_FIXED) &&
+	      addr < 0xe0000000 && addr + len > 0x20000000)))
+		return -EINVAL;
+
+	/* See asm-sparc/uaccess.h */
+	if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
+		return -EINVAL;
+
+	return 0;
+}
+
 /* Linux version of mmap */
 static unsigned long do_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
@@ -233,25 +248,13 @@
 			goto out;
 	}
 
-	retval = -EINVAL;
 	len = PAGE_ALIGN(len);
-	if (ARCH_SUN4C_SUN4 &&
-	    (len > 0x20000000 ||
-	     ((flags & MAP_FIXED) &&
-	      addr < 0xe0000000 && addr + len > 0x20000000)))
-		goto out_putf;
-
-	/* See asm-sparc/uaccess.h */
-	if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
-		goto out_putf;
-
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
 	down_write(&current->mm->mmap_sem);
 	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 
-out_putf:
 	if (file)
 		fput(file);
 out:
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 04eb1ea..845081b0 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -225,6 +225,32 @@
 	return (data1 == data2);	/* Was the write blocked? */
 }
 
+static void __init mostek_set_system_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	struct mostek48t02 *mregs;
+
+	mregs = (struct mostek48t02 *)mstk48t02_regs;
+	if(!mregs) {
+		prom_printf("Something wrong, clock regs not mapped yet.\n");
+		prom_halt();
+	}		
+	spin_lock_irq(&mostek_lock);
+	mregs->creg |= MSTK_CREG_READ;
+	sec = MSTK_REG_SEC(mregs);
+	min = MSTK_REG_MIN(mregs);
+	hour = MSTK_REG_HOUR(mregs);
+	day = MSTK_REG_DOM(mregs);
+	mon = MSTK_REG_MONTH(mregs);
+	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+        set_normalized_timespec(&wall_to_monotonic,
+                                -xtime.tv_sec, -xtime.tv_nsec);
+	mregs->creg &= ~MSTK_CREG_READ;
+	spin_unlock_irq(&mostek_lock);
+}
+
 /* Probe for the real time clock chip on Sun4 */
 static __inline__ void sun4_clock_probe(void)
 {
@@ -273,6 +299,7 @@
 #endif
 }
 
+#ifndef CONFIG_SUN4
 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
@@ -307,6 +334,8 @@
 	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
 		kick_start_clock();
 
+	mostek_set_system_time();
+
 	return 0;
 }
 
@@ -325,56 +354,37 @@
 
 
 /* Probe for the mostek real time clock chip. */
-static void clock_init(void)
+static int __init clock_init(void)
 {
-	of_register_driver(&clock_driver, &of_bus_type);
+	return of_register_driver(&clock_driver, &of_bus_type);
 }
 
+/* Must be after subsys_initcall() so that busses are probed.  Must
+ * be before device_initcall() because things like the RTC driver
+ * need to see the clock registers.
+ */
+fs_initcall(clock_init);
+#endif /* !CONFIG_SUN4 */
+
 void __init sbus_time_init(void)
 {
-	unsigned int year, mon, day, hour, min, sec;
-	struct mostek48t02 *mregs;
-
-#ifdef CONFIG_SUN4
-	int temp;
-	struct intersil *iregs;
-#endif
 
 	BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
 	btfixup();
 
 	if (ARCH_SUN4)
 		sun4_clock_probe();
-	else
-		clock_init();
 
 	sparc_init_timers(timer_interrupt);
 	
 #ifdef CONFIG_SUN4
 	if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
-#endif
-	mregs = (struct mostek48t02 *)mstk48t02_regs;
-	if(!mregs) {
-		prom_printf("Something wrong, clock regs not mapped yet.\n");
-		prom_halt();
-	}		
-	spin_lock_irq(&mostek_lock);
-	mregs->creg |= MSTK_CREG_READ;
-	sec = MSTK_REG_SEC(mregs);
-	min = MSTK_REG_MIN(mregs);
-	hour = MSTK_REG_HOUR(mregs);
-	day = MSTK_REG_DOM(mregs);
-	mon = MSTK_REG_MONTH(mregs);
-	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
-	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
-	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
-        set_normalized_timespec(&wall_to_monotonic,
-                                -xtime.tv_sec, -xtime.tv_nsec);
-	mregs->creg &= ~MSTK_CREG_READ;
-	spin_unlock_irq(&mostek_lock);
-#ifdef CONFIG_SUN4
+		mostek_set_system_time();
 	} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
 		/* initialise the intersil on sun4 */
+		unsigned int year, mon, day, hour, min, sec;
+		int temp;
+		struct intersil *iregs;
 
 		iregs=intersil_clock;
 		if(!iregs) {
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 054d0ab..bf5f14e 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -548,6 +548,26 @@
 	return ret;
 }
 
+int sparc64_mmap_check(unsigned long addr, unsigned long len,
+		unsigned long flags)
+{
+	if (test_thread_flag(TIF_32BIT)) {
+		if (len >= STACK_TOP32)
+			return -EINVAL;
+
+		if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len)
+			return -EINVAL;
+	} else {
+		if (len >= VA_EXCLUDE_START)
+			return -EINVAL;
+
+		if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 /* Linux version of mmap */
 asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
@@ -563,27 +583,11 @@
 	}
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	len = PAGE_ALIGN(len);
-	retval = -EINVAL;
-
-	if (test_thread_flag(TIF_32BIT)) {
-		if (len >= STACK_TOP32)
-			goto out_putf;
-
-		if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len)
-			goto out_putf;
-	} else {
-		if (len >= VA_EXCLUDE_START)
-			goto out_putf;
-
-		if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len))
-			goto out_putf;
-	}
 
 	down_write(&current->mm->mmap_sem);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 	up_write(&current->mm->mmap_sem);
 
-out_putf:
 	if (file)
 		fput(file);
 out:
diff --git a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
index 8cb0620..af9d81d 100644
--- a/arch/sparc64/mm/generic.c
+++ b/arch/sparc64/mm/generic.c
@@ -69,6 +69,8 @@
 		} else
 			offset += PAGE_SIZE;
 
+		if (pte_write(entry))
+			entry = pte_mkdirty(entry);
 		do {
 			BUG_ON(!pte_none(*pte));
 			set_pte_at(mm, address, pte, entry);
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 2517ecb..68ed24d 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -26,6 +26,7 @@
 
   /* Read-only sections, merged into text segment: */
   .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
   .dynstr         : { *(.dynstr) }
   .gnu.version    : { *(.gnu.version) }
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 62bdb8d..1bf672a 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -1,8 +1,8 @@
 /*
  * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
  *
- *  Copyright (C) 2001,02,03,05  NEC Electronics Corporation
- *  Copyright (C) 2001,02,03,05  Miles Bader <miles@gnu.org>
+ *  Copyright (C) 2001,02,03,05,06  NEC Electronics Corporation
+ *  Copyright (C) 2001,02,03,05,06  Miles Bader <miles@gnu.org>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
@@ -190,7 +190,7 @@
 		for (addr = start; addr < end; addr += PAGE_SIZE) {
 			struct page *page = virt_to_page (addr);
 			ClearPageReserved (page);
-			set_page_count (page, 1);
+			init_page_count (page);
 			__free_page (page);
 			total_ram_pages++;
 		}
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index c03ad6e..67bc48e 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -21,9 +21,6 @@
 
 /* platform dependent support */
 EXPORT_SYMBOL (kernel_thread);
-EXPORT_SYMBOL (enable_irq);
-EXPORT_SYMBOL (disable_irq);
-EXPORT_SYMBOL (disable_irq_nosync);
 EXPORT_SYMBOL (__bug);
 
 /* Networking helper routines. */
@@ -33,22 +30,9 @@
 EXPORT_SYMBOL (ip_fast_csum);
 
 /* string / mem functions */
-EXPORT_SYMBOL (strcpy);
-EXPORT_SYMBOL (strncpy);
-EXPORT_SYMBOL (strcat);
-EXPORT_SYMBOL (strncat);
-EXPORT_SYMBOL (strcmp);
-EXPORT_SYMBOL (strncmp);
-EXPORT_SYMBOL (strchr);
-EXPORT_SYMBOL (strlen);
-EXPORT_SYMBOL (strnlen);
-EXPORT_SYMBOL (strrchr);
-EXPORT_SYMBOL (strstr);
 EXPORT_SYMBOL (memset);
 EXPORT_SYMBOL (memcpy);
 EXPORT_SYMBOL (memmove);
-EXPORT_SYMBOL (memcmp);
-EXPORT_SYMBOL (memscan);
 
 /* semaphores */
 EXPORT_SYMBOL (__down);
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 83d389b..5fb9707 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-git22
-# Tue Jul  4 14:24:40 2006
+# Linux kernel version: 2.6.18-rc4
+# Thu Aug 24 21:05:55 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -37,6 +37,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
@@ -200,7 +201,7 @@
 CONFIG_ACPI_NUMA=y
 # CONFIG_ACPI_ASUS is not set
 # CONFIG_ACPI_IBM is not set
-CONFIG_ACPI_TOSHIBA=y
+# CONFIG_ACPI_TOSHIBA is not set
 CONFIG_ACPI_BLACKLIST_YEAR=0
 # CONFIG_ACPI_DEBUG is not set
 CONFIG_ACPI_EC=y
@@ -215,7 +216,7 @@
 #
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_DEBUG=y
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
@@ -413,6 +414,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -493,8 +495,9 @@
 CONFIG_BLK_DEV_SD=y
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
 
 #
@@ -510,7 +513,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=y
 
 #
 # SCSI low-level drivers
@@ -536,7 +539,7 @@
 CONFIG_MEGARAID_SAS=y
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_AHCI=y
-# CONFIG_SCSI_SATA_SVW is not set
+CONFIG_SCSI_SATA_SVW=y
 CONFIG_SCSI_ATA_PIIX=y
 # CONFIG_SCSI_SATA_MV is not set
 CONFIG_SCSI_SATA_NV=y
@@ -587,7 +590,7 @@
 CONFIG_FUSION=y
 CONFIG_FUSION_SPI=y
 # CONFIG_FUSION_FC is not set
-# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_SAS=y
 CONFIG_FUSION_MAX_SGE=128
 # CONFIG_FUSION_CTL is not set
 
@@ -673,7 +676,7 @@
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
+CONFIG_B44=y
 CONFIG_FORCEDETH=y
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
@@ -710,7 +713,7 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
-# CONFIG_BNX2 is not set
+CONFIG_BNX2=y
 
 #
 # Ethernet (10000 Mbit)
@@ -840,44 +843,7 @@
 #
 # Watchdog Cards
 #
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-CONFIG_SOFT_WATCHDOG=y
-# CONFIG_ACQUIRE_WDT is not set
-# CONFIG_ADVANTECH_WDT is not set
-# CONFIG_ALIM1535_WDT is not set
-# CONFIG_ALIM7101_WDT is not set
-# CONFIG_SC520_WDT is not set
-# CONFIG_EUROTECH_WDT is not set
-# CONFIG_IB700_WDT is not set
-# CONFIG_IBMASR is not set
-# CONFIG_WAFER_WDT is not set
-# CONFIG_I6300ESB_WDT is not set
-# CONFIG_I8XX_TCO is not set
-# CONFIG_SC1200_WDT is not set
-# CONFIG_60XX_WDT is not set
-# CONFIG_SBC8360_WDT is not set
-# CONFIG_CPU5_WDT is not set
-# CONFIG_W83627HF_WDT is not set
-# CONFIG_W83877F_WDT is not set
-# CONFIG_W83977F_WDT is not set
-# CONFIG_MACHZ_WDT is not set
-# CONFIG_SBC_EPX_C3_WATCHDOG is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_INTEL=y
 CONFIG_HW_RANDOM_AMD=y
@@ -1054,6 +1020,7 @@
 CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256
 CONFIG_VIDEO_SELECT=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -1195,7 +1162,7 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -1299,7 +1266,7 @@
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
 
@@ -1373,7 +1340,6 @@
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1493,4 +1459,5 @@
 # CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
 CONFIG_PLIST=y
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 62bc5f5..cdae364 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -23,6 +23,7 @@
 # The DSO images are built using a special linker script
 quiet_cmd_syscall = SYSCALL $@
       cmd_syscall = $(CC) -m32 -nostdlib -shared -s \
+			  $(call ld-option, -Wl$(comma)--hash-style=sysv) \
 			   -Wl,-soname=linux-gate.so.1 -o $@ \
 			   -Wl,-T,$(filter-out FORCE,$^)
 
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
index ab94f2e..92d7d0c 100644
--- a/arch/x86_64/ia32/audit.c
+++ b/arch/x86_64/ia32/audit.c
@@ -9,3 +9,29 @@
 #include <asm-generic/audit_change_attr.h>
 ~0U
 };
+
+unsigned ia32_write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
+unsigned ia32_read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+int ia32_classify_syscall(unsigned syscall)
+{
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_socketcall:
+		return 4;
+	case __NR_execve:
+		return 5;
+	default:
+		return 1;
+	}
+}
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index a9dc0f3..2fd5a67 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -73,39 +73,44 @@
  * Dumping its extra ELF program headers includes all the other information
  * a debugger needs to easily find how the vsyscall DSO was being used.
  */
-#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL32_EHDR->e_phnum)
+#define ELF_CORE_EXTRA_PHDRS	(find_vma(current->mm, VSYSCALL32_BASE) ?     \
+    (VSYSCALL32_EHDR->e_phnum) : 0)
 #define ELF_CORE_WRITE_EXTRA_PHDRS					      \
 do {									      \
-	const struct elf32_phdr *const vsyscall_phdrs =			      \
-		(const struct elf32_phdr *) (VSYSCALL32_BASE		      \
-					   + VSYSCALL32_EHDR->e_phoff);	      \
-	int i;								      \
-	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {		      \
-		struct elf32_phdr phdr = vsyscall_phdrs[i];		      \
-		if (phdr.p_type == PT_LOAD) {				      \
-			BUG_ON(ofs != 0);				      \
-			ofs = phdr.p_offset = offset;			      \
-			phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);	      \
-			phdr.p_filesz = phdr.p_memsz;			      \
-			offset += phdr.p_filesz;			      \
+	if (find_vma(current->mm, VSYSCALL32_BASE)) { 			      \
+		const struct elf32_phdr *const vsyscall_phdrs =		      \
+			(const struct elf32_phdr *) (VSYSCALL32_BASE	      \
+						   + VSYSCALL32_EHDR->e_phoff);\
+		int i;							      \
+		Elf32_Off ofs = 0;					      \
+		for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {	      \
+			struct elf32_phdr phdr = vsyscall_phdrs[i];	      \
+			if (phdr.p_type == PT_LOAD) {			      \
+				BUG_ON(ofs != 0);			      \
+				ofs = phdr.p_offset = offset;		      \
+				phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);      \
+				phdr.p_filesz = phdr.p_memsz;		      \
+				offset += phdr.p_filesz;		      \
+			}						      \
+			else						      \
+				phdr.p_offset += ofs;			      \
+			phdr.p_paddr = 0; /* match other core phdrs */	      \
+			DUMP_WRITE(&phdr, sizeof(phdr));		      \
 		}							      \
-		else							      \
-			phdr.p_offset += ofs;				      \
-		phdr.p_paddr = 0; /* match other core phdrs */		      \
-		DUMP_WRITE(&phdr, sizeof(phdr));			      \
 	}								      \
 } while (0)
 #define ELF_CORE_WRITE_EXTRA_DATA					      \
 do {									      \
-	const struct elf32_phdr *const vsyscall_phdrs =			      \
-		(const struct elf32_phdr *) (VSYSCALL32_BASE		      \
-					   + VSYSCALL32_EHDR->e_phoff);	      \
-	int i;								      \
-	for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {		      \
-		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
-			DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,	      \
-				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));    \
+	if (find_vma(current->mm, VSYSCALL32_BASE)) { 			      \
+		const struct elf32_phdr *const vsyscall_phdrs =		      \
+			(const struct elf32_phdr *) (VSYSCALL32_BASE	      \
+						   + VSYSCALL32_EHDR->e_phoff);      \
+		int i;							      \
+		for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) {	      \
+			if (vsyscall_phdrs[i].p_type == PT_LOAD)	      \
+				DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\
+				    PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));   \
+		}							      \
 	}								      \
 } while (0)
 
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 9b5bb41..5d4a7d1 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -103,7 +103,7 @@
 	pushq	%rax
 	CFI_ADJUST_CFA_OFFSET 8
 	cld
-	SAVE_ARGS 0,0,1
+	SAVE_ARGS 0,0,0
  	/* no need to do an access_ok check here because rbp has been
  	   32bit zero extended */ 
 1:	movl	(%rbp),%r9d
diff --git a/arch/x86_64/ia32/vsyscall.lds b/arch/x86_64/ia32/vsyscall.lds
index f2e75ed..1dc86ff 100644
--- a/arch/x86_64/ia32/vsyscall.lds
+++ b/arch/x86_64/ia32/vsyscall.lds
@@ -11,6 +11,7 @@
   . = VSYSCALL_BASE + SIZEOF_HEADERS;
 
   .hash           : { *(.hash) }		:text
+  .gnu.hash       : { *(.gnu.hash) }
   .dynsym         : { *(.dynsym) }
   .dynstr         : { *(.dynstr) }
   .gnu.version    : { *(.gnu.version) }
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
index a067aa4..21f3338 100644
--- a/arch/x86_64/kernel/audit.c
+++ b/arch/x86_64/kernel/audit.c
@@ -8,19 +8,54 @@
 ~0U
 };
 
+static unsigned read_class[] = {
+#include <asm-generic/audit_read.h>
+~0U
+};
+
+static unsigned write_class[] = {
+#include <asm-generic/audit_write.h>
+~0U
+};
+
 static unsigned chattr_class[] = {
 #include <asm-generic/audit_change_attr.h>
 ~0U
 };
 
+int audit_classify_syscall(int abi, unsigned syscall)
+{
+#ifdef CONFIG_IA32_EMULATION
+	extern int ia32_classify_syscall(unsigned);
+	if (abi == AUDIT_ARCH_I386)
+		return ia32_classify_syscall(syscall);
+#endif
+	switch(syscall) {
+	case __NR_open:
+		return 2;
+	case __NR_openat:
+		return 3;
+	case __NR_execve:
+		return 5;
+	default:
+		return 0;
+	}
+}
+
 static int __init audit_classes_init(void)
 {
 #ifdef CONFIG_IA32_EMULATION
 	extern __u32 ia32_dir_class[];
+	extern __u32 ia32_write_class[];
+	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
+	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
 #endif
+	audit_register_class(AUDIT_CLASS_WRITE, write_class);
+	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
 	return 0;
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index e56c2ad..764bf23 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -71,7 +71,11 @@
 #endif
 	/* kernel code + 640k memory hole (later should not be needed, but 
 	   be paranoid for now) */
-	if (last >= 640*1024 && addr < __pa_symbol(&_end)) { 
+	if (last >= 640*1024 && addr < 1024*1024) {
+		*addrp = 1024*1024;
+		return 1;
+	}
+	if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
 		*addrp = __pa_symbol(&_end);
 		return 1;
 	}
@@ -104,35 +108,6 @@
 	return 0;
 }
 
-/*
- * This function checks if the entire range <start,end> is mapped with type.
- *
- * Note: this function only works correct if the e820 table is sorted and
- * not-overlapping, which is the case
- */
-int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
-{
-	int i;
-	for (i = 0; i < e820.nr_map; i++) {
-		struct e820entry *ei = &e820.map[i];
-		if (type && ei->type != type)
-			continue;
-		/* is the region (part) in overlap with the current region ?*/
-		if (ei->addr >= end || ei->addr + ei->size <= start)
-			continue;
-
-		/* if the region is at the beginning of <start,end> we move
-		 * start to the end of the region since it's ok until there
-		 */
-		if (ei->addr <= start)
-			start = ei->addr + ei->size;
-		/* if start is now at or beyond end, we're done, full coverage */
-		if (start >= end)
-			return 1; /* we're done */
-	}
-	return 0;
-}
-
 /* 
  * Find a free area in a specific range. 
  */ 
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index d464dde..aa8d893 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -513,6 +513,7 @@
 	swapgs	
 1:	incl	%gs:pda_irqcount	# RED-PEN should check preempt count
 	cmoveq %gs:pda_irqstackptr,%rsp
+	push    %rbp			# backlink for old unwinder
 	/*
 	 * We entered an interrupt context - irqs are off:
 	 */
@@ -972,6 +973,8 @@
 ENDPROC(kernel_thread)
 	
 child_rip:
+	pushq $0		# fake return address
+	CFI_STARTPROC
 	/*
 	 * Here we are in the child and the registers are set as they were
 	 * at kernel_thread() invocation in the parent.
@@ -982,6 +985,7 @@
 	# exit
 	xorl %edi, %edi
 	call do_exit
+	CFI_ENDPROC
 ENDPROC(child_rip)
 
 /*
@@ -1139,18 +1143,21 @@
 END(machine_check)
 #endif
 
+/* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
 	CFI_STARTPROC
-	movq %gs:pda_irqstackptr,%rax
-	movq %rsp,%rdx
-	CFI_DEF_CFA_REGISTER	rdx
+	push %rbp
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET rbp,0
+	mov  %rsp,%rbp
+	CFI_DEF_CFA_REGISTER rbp
 	incl %gs:pda_irqcount
-	cmove %rax,%rsp
-	pushq %rdx
-	/*todo CFI_DEF_CFA_EXPRESSION ...*/
+	cmove %gs:pda_irqstackptr,%rsp
+	push  %rbp			# backlink for old unwinder
 	call __do_softirq
-	popq %rsp
+	leaveq
 	CFI_DEF_CFA_REGISTER	rsp
+	CFI_ADJUST_CFA_OFFSET   -8
 	decl %gs:pda_irqcount
 	ret
 	CFI_ENDPROC
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 6df05e6..c9739ca 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -191,6 +191,7 @@
 	 * jump
 	 */
 	movq	initial_code(%rip),%rax
+	pushq	$0		# fake return address
 	jmp	*%rax
 
 	/* SMP bootup changes these two */
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index ce31d90..3dc5854 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -46,4 +46,9 @@
  */ 
 DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
 
+/* Copies of the original ist values from the tss are only accessed during
+ * debugging, no special alignment required.
+ */
+DEFINE_PER_CPU(struct orig_ist, orig_ist);
+
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
index 83fb24a..106076b 100644
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -207,14 +207,11 @@
 	__flush_tlb();
 
 
-	/* The segment registers are funny things, they are
-	 * automatically loaded from a table, in memory wherever you
-	 * set them to a specific selector, but this table is never
-	 * accessed again unless you set the segment to a different selector.
-	 *
-	 * The more common model are caches where the behide
-	 * the scenes work is done, but is also dropped at arbitrary
-	 * times.
+	/* The segment registers are funny things, they have both a
+	 * visible and an invisible part.  Whenever the visible part is
+	 * set to a specific selector, the invisible part is loaded
+	 * with from a table in memory.  At no other time is the
+	 * descriptor table in memory accessed.
 	 *
 	 * I take advantage of this here by force loading the
 	 * segments, before I zap the gdt with an invalid value.
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 8884567..4e017fb 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -615,7 +615,7 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static __cpuinit void mce_remove_device(unsigned int cpu)
+static void mce_remove_device(unsigned int cpu)
 {
 	int i;
 
@@ -626,10 +626,9 @@
 	sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval);
 	sysdev_unregister(&per_cpu(device_mce,cpu));
 }
-#endif
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static __cpuinit int
+static int
 mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
@@ -638,18 +637,17 @@
 	case CPU_ONLINE:
 		mce_create_device(cpu);
 		break;
-#ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 		mce_remove_device(cpu);
 		break;
-#endif
 	}
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __cpuinitdata mce_cpu_notifier = {
+static struct notifier_block mce_cpu_notifier = {
 	.notifier_call = mce_cpu_callback,
 };
+#endif
 
 static __init int mce_init_device(void)
 {
@@ -664,7 +662,7 @@
 		mce_create_device(i);
 	}
 
-	register_cpu_notifier(&mce_cpu_notifier);
+	register_hotcpu_notifier(&mce_cpu_notifier);
 	misc_register(&mce_log_device);
 	return err;
 }
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index db2acbf..883fe74 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -558,7 +558,7 @@
  *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
  */
 
-static __cpuinit void deallocate_threshold_block(unsigned int cpu,
+static void deallocate_threshold_block(unsigned int cpu,
 						 unsigned int bank)
 {
 	struct threshold_block *pos = NULL;
@@ -578,7 +578,7 @@
 	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
 }
 
-static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank)
+static void threshold_remove_bank(unsigned int cpu, int bank)
 {
 	int i = 0;
 	struct threshold_bank *b;
@@ -618,7 +618,7 @@
 	per_cpu(threshold_banks, cpu)[bank] = NULL;
 }
 
-static __cpuinit void threshold_remove_device(unsigned int cpu)
+static void threshold_remove_device(unsigned int cpu)
 {
 	unsigned int bank;
 
@@ -629,14 +629,8 @@
 	}
 }
 
-#else /* !CONFIG_HOTPLUG_CPU */
-static void threshold_remove_device(unsigned int cpu)
-{
-}
-#endif
-
 /* get notified when a cpu comes on/off */
-static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
+static int threshold_cpu_callback(struct notifier_block *nfb,
 					    unsigned long action, void *hcpu)
 {
 	/* cpu was unsigned int to begin with */
@@ -659,9 +653,10 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block threshold_cpu_notifier __cpuinitdata = {
+static struct notifier_block threshold_cpu_notifier = {
 	.notifier_call = threshold_cpu_callback,
 };
+#endif /* CONFIG_HOTPLUG_CPU */
 
 static __init int threshold_init_device(void)
 {
@@ -673,7 +668,7 @@
 		if (err)
 			return err;
 	}
-	register_cpu_notifier(&threshold_cpu_notifier);
+	register_hotcpu_notifier(&threshold_cpu_notifier);
 	return 0;
 }
 
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
index e71ed53..146924b 100644
--- a/arch/x86_64/kernel/pci-calgary.c
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -85,7 +85,8 @@
 #define CSR_AGENT_MASK		0xffe0ffff
 
 #define MAX_NUM_OF_PHBS		8 /* how many PHBs in total? */
-#define MAX_PHB_BUS_NUM		(MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */
+#define MAX_NUM_CHASSIS		8 /* max number of chassis */
+#define MAX_PHB_BUS_NUM		(MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
 #define PHBS_PER_CALGARY	4
 
 /* register offsets in Calgary's internal register space */
@@ -110,7 +111,8 @@
 	0xB000 /* PHB3 */
 };
 
-void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES];
+static char bus_to_phb[MAX_PHB_BUS_NUM];
+void* tce_table_kva[MAX_PHB_BUS_NUM];
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
@@ -119,7 +121,7 @@
  * the bitmap of PHBs the user requested that we disable
  * translation on.
  */
-static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM);
+static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
 
 static void tce_cache_blast(struct iommu_table *tbl);
 
@@ -452,7 +454,7 @@
 
 static inline int busno_to_phbid(unsigned char num)
 {
-	return bus_to_phb(num) % PHBS_PER_CALGARY;
+	return bus_to_phb[num];
 }
 
 static inline unsigned long split_queue_offset(unsigned char num)
@@ -812,7 +814,7 @@
 	int i, ret = -ENODEV;
 	struct pci_dev *dev = NULL;
 
-	for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) {
+	for (i = 0; i < MAX_PHB_BUS_NUM; i++) {
 		dev = pci_get_device(PCI_VENDOR_ID_IBM,
 				     PCI_DEVICE_ID_IBM_CALGARY,
 				     dev);
@@ -822,7 +824,7 @@
 			calgary_init_one_nontraslated(dev);
 			continue;
 		}
-		if (!tce_table_kva[i] && !translate_empty_slots) {
+		if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
 			pci_dev_put(dev);
 			continue;
 		}
@@ -842,7 +844,7 @@
 			pci_dev_put(dev);
 			continue;
 		}
-		if (!tce_table_kva[i] && !translate_empty_slots)
+		if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
 			continue;
 		calgary_disable_translation(dev);
 		calgary_free_tar(dev);
@@ -876,9 +878,10 @@
 void __init detect_calgary(void)
 {
 	u32 val;
-	int bus, table_idx;
+	int bus;
 	void *tbl;
-	int detected = 0;
+	int calgary_found = 0;
+	int phb = -1;
 
 	/*
 	 * if the user specified iommu=off or iommu=soft or we found
@@ -889,38 +892,46 @@
 
 	specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
 
-	for (bus = 0, table_idx = 0;
-	     bus <= num_online_nodes() * MAX_PHB_BUS_NUM;
-	     bus++) {
-		BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM);
+	for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
+		int dev;
+
+		tce_table_kva[bus] = NULL;
+		bus_to_phb[bus] = -1;
+
 		if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
 			continue;
+
+		/*
+		 * There are 4 PHBs per Calgary chip.  Set phb to which phb (0-3)
+		 * it is connected to releative to the clagary chip.
+		 */
+		phb = (phb + 1) % PHBS_PER_CALGARY;
+
 		if (test_bit(bus, translation_disabled)) {
 			printk(KERN_INFO "Calgary: translation is disabled for "
 			       "PHB 0x%x\n", bus);
 			/* skip this phb, don't allocate a tbl for it */
-			tce_table_kva[table_idx] = NULL;
-			table_idx++;
 			continue;
 		}
 		/*
-		 * scan the first slot of the PCI bus to see if there
-		 * are any devices present
+		 * Scan the slots of the PCI bus to see if there is a device present.
+		 * The parent bus will be the zero-ith device, so start at 1.
 		 */
-		val = read_pci_config(bus, 1, 0, 0);
-		if (val != 0xffffffff || translate_empty_slots) {
-			tbl = alloc_tce_table();
-			if (!tbl)
-				goto cleanup;
-			detected = 1;
-		} else
-			tbl = NULL;
-
-		tce_table_kva[table_idx] = tbl;
-		table_idx++;
+		for (dev = 1; dev < 8; dev++) {
+			val = read_pci_config(bus, dev, 0, 0);
+			if (val != 0xffffffff || translate_empty_slots) {
+				tbl = alloc_tce_table();
+				if (!tbl)
+					goto cleanup;
+				tce_table_kva[bus] = tbl;
+				bus_to_phb[bus] = phb;
+				calgary_found = 1;
+				break;
+			}
+		}
 	}
 
-	if (detected) {
+	if (calgary_found) {
 		iommu_detected = 1;
 		calgary_detected = 1;
 		printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
@@ -929,9 +940,9 @@
 	return;
 
 cleanup:
-	for (--table_idx; table_idx >= 0; --table_idx)
-		if (tce_table_kva[table_idx])
-			free_tce_table(tce_table_kva[table_idx]);
+	for (--bus; bus >= 0; --bus)
+		if (tce_table_kva[bus])
+			free_tce_table(tce_table_kva[bus]);
 }
 
 int __init calgary_iommu_init(void)
@@ -1002,7 +1013,7 @@
 			if (p == endp)
 				break;
 
-			if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) {
+			if (bridge < MAX_PHB_BUS_NUM) {
 				printk(KERN_INFO "Calgary: disabling "
 				       "translation for PHB 0x%x\n", bridge);
 				set_bit(bridge, translation_disabled);
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index c4c3cc3..aad7609 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -92,5 +92,7 @@
 {
 	if (dma_ops)
 		return;
+
+	force_iommu = 0; /* no HW IOMMU */
 	dma_ops = &nommu_dma_ops;
 }
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index ebdb77f..6a55f87 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -31,9 +31,10 @@
 void pci_swiotlb_init(void)
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
-	if (!iommu_detected && !no_iommu &&
-	    (end_pfn > MAX_DMA32_PFN || force_iommu))
+	if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN)
 	       swiotlb = 1;
+	if (swiotlb_force)
+		swiotlb = 1;
 	if (swiotlb) {
 		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
 		swiotlb_init();
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 8a099ff..34afad7 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -521,8 +521,6 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	unsigned long kernel_end;
-
  	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  	screen_info = SCREEN_INFO;
 	edid_info = EDID_INFO;
@@ -596,8 +594,8 @@
 				(table_end - table_start) << PAGE_SHIFT);
 
 	/* reserve kernel */
-	kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE);
-	reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY);
+	reserve_bootmem_generic(__pa_symbol(&_text),
+				__pa_symbol(&_end) - __pa_symbol(&_text));
 
 	/*
 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 6fe58a6..417de56 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -189,6 +189,7 @@
 {
 	int cpu = stack_smp_processor_id();
 	struct tss_struct *t = &per_cpu(init_tss, cpu);
+	struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu);
 	unsigned long v; 
 	char *estacks = NULL; 
 	struct task_struct *me;
@@ -256,7 +257,7 @@
 			estacks += EXCEPTION_STKSZ;
 			break;
 		}
-		t->ist[v] = (unsigned long)estacks;
+		orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
 	}
 
 	t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 5a1c0a3..06af6ca 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -203,7 +203,7 @@
 {
 	int i;
 	for_each_cpu_mask(i, cpu_possible_map) {
-		spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i));
+		spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock);
 	}
 	return 0;
 }
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
index d3a9e79..5530dda 100644
--- a/arch/x86_64/kernel/tce.c
+++ b/arch/x86_64/kernel/tce.c
@@ -96,7 +96,6 @@
 static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
 {
 	unsigned int bitmapsz;
-	unsigned int tce_table_index;
 	unsigned long bmppages;
 	int ret;
 
@@ -105,8 +104,7 @@
 	/* set the tce table size - measured in entries */
 	tbl->it_size = table_size_to_number_of_entries(specified_table_size);
 
-	tce_table_index = bus_to_phb(tbl->it_busno);
-	tbl->it_base = (unsigned long)tce_table_kva[tce_table_index];
+	tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
 	if (!tbl->it_base) {
 		printk(KERN_ERR "Calgary: iommu_table_setparms: "
 		       "no table allocated?!\n");
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index b9ff759..7a9b182 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -28,6 +28,7 @@
 #include <linux/acpi.h>
 #ifdef CONFIG_ACPI
 #include <acpi/achware.h>	/* for PM timer frequency */
+#include <acpi/acpi_bus.h>
 #endif
 #include <asm/8253pit.h>
 #include <asm/pgtable.h>
@@ -193,7 +194,7 @@
 	   is just accounted to the spinlock function.
 	   Better would be to write these functions in assembler again
 	   and check exactly. */
-	if (in_lock_functions(pc)) {
+	if (!user_mode(regs) && in_lock_functions(pc)) {
 		char *v = *(char **)regs->rsp;
 		if ((v >= _stext && v <= _etext) ||
 			(v >= _sinittext && v <= _einittext) ||
@@ -953,11 +954,18 @@
 #ifdef CONFIG_SMP
 	if (apic_is_clustered_box())
 		return 1;
- 	/* Intel systems are normally all synchronized. Exceptions
- 	   are handled in the check above. */
- 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
- 		return 0;
 #endif
+	/* Most intel systems have synchronized TSCs except for
+	   multi node systems */
+ 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+#ifdef CONFIG_ACPI
+		/* But TSC doesn't tick in C3 so don't use it there */
+		if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100)
+			return 1;
+#endif
+ 		return 0;
+	}
+
  	/* Assume multi socket systems are not synchronized */
  	return num_present_cpus() > 1;
 }
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index eb39a27..b124977 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -107,7 +107,11 @@
 }
 
 static int kstack_depth_to_print = 12;
+#ifdef CONFIG_STACK_UNWIND
 static int call_trace = 1;
+#else
+#define call_trace (-1)
+#endif
 
 #ifdef CONFIG_KALLSYMS
 # include <linux/kallsyms.h>
@@ -174,7 +178,7 @@
 			break;
 #endif
 		default:
-			end = per_cpu(init_tss, cpu).ist[k];
+			end = per_cpu(orig_ist, cpu).ist[k];
 			break;
 		}
 		/*
@@ -254,7 +258,6 @@
 {
 	const unsigned cpu = safe_smp_processor_id();
 	unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
-	int i = 11;
 	unsigned used = 0;
 
 	printk("\nCall Trace:\n");
@@ -276,11 +279,20 @@
 				unw_ret = show_trace_unwind(&info, NULL);
 		}
 		if (unw_ret > 0) {
-			if (call_trace > 0)
+			if (call_trace == 1 && !arch_unw_user_mode(&info)) {
+				print_symbol("DWARF2 unwinder stuck at %s\n",
+					     UNW_PC(&info));
+				if ((long)UNW_SP(&info) < 0) {
+					printk("Leftover inexact backtrace:\n");
+					stack = (unsigned long *)UNW_SP(&info);
+				} else
+					printk("Full inexact backtrace again:\n");
+			} else if (call_trace >= 1)
 				return;
-			printk("Legacy call trace:");
-			i = 18;
-		}
+			else
+				printk("Full inexact backtrace again:\n");
+		} else
+			printk("Inexact backtrace:\n");
 	}
 
 	/*
@@ -521,7 +533,7 @@
 		/* Nest count reaches zero, release the lock. */
 		spin_unlock_irqrestore(&die_lock, flags);
 	if (panic_on_oops)
-		panic("Oops");
+		panic("Fatal exception");
 }
 
 void __kprobes __die(const char * str, struct pt_regs * regs, long err)
@@ -1112,14 +1124,18 @@
 }
 __setup("kstack=", kstack_setup);
 
+#ifdef CONFIG_STACK_UNWIND
 static int __init call_trace_setup(char *s)
 {
 	if (strcmp(s, "old") == 0)
 		call_trace = -1;
 	else if (strcmp(s, "both") == 0)
 		call_trace = 0;
-	else if (strcmp(s, "new") == 0)
+	else if (strcmp(s, "newfallback") == 0)
 		call_trace = 1;
+	else if (strcmp(s, "new") == 0)
+		call_trace = 2;
 	return 1;
 }
 __setup("call_trace=", call_trace_setup);
+#endif
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index b50a7c7..3acf60d 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -2,7 +2,6 @@
 #include <linux/pci.h>
 #include <asm/mpspec.h>
 #include <linux/cpumask.h>
-#include <asm/k8.h>
 
 /*
  * This discovers the pcibus <-> node mapping on AMD K8.
@@ -19,6 +18,7 @@
 #define NR_LDT_BUS_NUMBER_REGISTERS 3
 #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
 #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
+#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
 
 /**
  * fill_mp_bus_to_cpumask()
@@ -28,7 +28,8 @@
 __init static int
 fill_mp_bus_to_cpumask(void)
 {
-	int i, j, k;
+	struct pci_dev *nb_dev = NULL;
+	int i, j;
 	u32 ldtbus, nid;
 	static int lbnr[3] = {
 		LDT_BUS_NUMBER_REGISTER_0,
@@ -36,9 +37,8 @@
 		LDT_BUS_NUMBER_REGISTER_2
 	};
 
-	cache_k8_northbridges();
-	for (k = 0; k < num_k8_northbridges; k++) {
-		struct pci_dev *nb_dev = k8_northbridges[k];
+	while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+			PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
 		pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
 
 		for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index 3c55c76..2d48a79 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/bitmap.h>
+#include <linux/dmi.h>
 #include <asm/e820.h>
 
 #include "pci.h"
@@ -164,11 +165,33 @@
 	}
 }
 
+static int disable_mcfg(struct dmi_system_id *d)
+{
+	printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
+	pci_probe &= ~PCI_PROBE_MMCONF;
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
+	/* Has broken MCFG table that makes the system hang when used */
+        {
+         .callback = disable_mcfg,
+         .ident = "Intel D3C5105 SDV",
+         .matches = {
+                     DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
+                     DMI_MATCH(DMI_BOARD_NAME, "D26928"),
+                     },
+         },
+         {}
+};
+
 void __init pci_mmcfg_init(void)
 {
 	int i;
 
-	if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+	dmi_check_system(dmi_bad_mcfg);
+
+	if ((pci_probe & (PCI_PROBE_MMCONF|PCI_PROBE_MMCONF_FORCE)) == 0)
 		return;
 
 	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
@@ -177,15 +200,6 @@
 	    (pci_mmcfg_config[0].base_address == 0))
 		return;
 
-	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
-			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
-				pci_mmcfg_config[0].base_address);
-		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
-		return;
-	}
-
 	/* RED-PEN i386 doesn't do _nocache right now */
 	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
 	if (pci_mmcfg_virt == NULL) {
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
index 5064d93..9aea23c 100644
--- a/arch/xtensa/kernel/ptrace.c
+++ b/arch/xtensa/kernel/ptrace.c
@@ -212,7 +212,7 @@
 	 */
 	case PTRACE_KILL:
 		ret = 0;
-		if (child->state == EXIT_ZOMBIE)	/* already dead */
+		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
 			break;
 		child->exit_code = SIGKILL;
 		child->ptrace &= ~PT_SINGLESTEP;
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 27e4090..ce077d6 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -487,11 +487,9 @@
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
-	if (panic_on_oops) {
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
-		ssleep(5);
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
+
 	do_exit(err);
 }
 
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index aae3123..3a3aee0 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1561,7 +1561,7 @@
 		/* ->key must be copied to avoid race with cfq_exit_queue() */
 		k = __cic->key;
 		if (unlikely(!k)) {
-			cfq_drop_dead_cic(ioc, cic);
+			cfq_drop_dead_cic(ioc, __cic);
 			goto restart;
 		}
 
diff --git a/block/elevator.c b/block/elevator.c
index bc7baee..9b72dc7 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -765,7 +765,8 @@
 		read_lock(&tasklist_lock);
 		do_each_thread(g, p) {
 			task_lock(p);
-			e->ops.trim(p->io_context);
+			if (p->io_context)
+				e->ops.trim(p->io_context);
 			task_unlock(p);
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 61d6b3c..ddd9253 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -3628,6 +3628,8 @@
 		ret->nr_batch_requests = 0; /* because this is 0 */
 		ret->aic = NULL;
 		ret->cic_root.rb_node = NULL;
+		/* make sure set_task_ioprio() sees the settings above */
+		smp_wmb();
 		tsk->io_context = ret;
 	}
 
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 96309b9..11abc7b 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -285,6 +285,8 @@
 {
 	int result;
 
+	if (acpi_disabled)
+		return -ENODEV;
 
 	acpi_ac_dir = acpi_lock_ac_dir();
 	if (!acpi_ac_dir)
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 81e970a..1dda370 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -129,11 +129,15 @@
 	struct acpi_memory_info *info, *n;
 
 
+	if (!list_empty(&mem_device->res_list))
+		return 0;
+
 	status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
 				     acpi_memory_get_resource, mem_device);
 	if (ACPI_FAILURE(status)) {
 		list_for_each_entry_safe(info, n, &mem_device->res_list, list)
 			kfree(info);
+		INIT_LIST_HEAD(&mem_device->res_list);
 		return -EINVAL;
 	}
 
@@ -230,17 +234,10 @@
 	 * (i.e. memory-hot-remove function)
 	 */
 	list_for_each_entry(info, &mem_device->res_list, list) {
-		u64 start_pfn, end_pfn;
-
-		start_pfn = info->start_addr >> PAGE_SHIFT;
-		end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT;
-
-		if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) {
-			/* already enabled. try next area */
+		if (info->enabled) { /* just sanity check...*/
 			num_enabled++;
 			continue;
 		}
-
 		result = add_memory(node, info->start_addr, info->length);
 		if (result)
 			continue;
@@ -487,10 +484,8 @@
 
 
 	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status)){
-		ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+	if (ACPI_FAILURE(status))
 		return AE_OK;	/* continue */
-	}
 
 	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 					     acpi_memory_device_notify, NULL);
@@ -506,10 +501,8 @@
 
 
 	status = is_memory_device(handle);
-	if (ACPI_FAILURE(status)){
-		ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+	if (ACPI_FAILURE(status))
 		return AE_OK;	/* continue */
-	}
 
 	status = acpi_remove_notify_handler(handle,
 					    ACPI_SYSTEM_NOTIFY,
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 6e52217..9810e2a 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -757,6 +757,9 @@
 {
 	int result;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	acpi_battery_dir = acpi_lock_battery_dir();
 	if (!acpi_battery_dir)
 		return -ENODEV;
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index b297769..279c4ba 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/pm.h>
@@ -68,7 +69,8 @@
 
 	status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
 	if (ACPI_FAILURE(status) || !*device) {
-		ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle));
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+				  handle));
 		return -ENODEV;
 	}
 
@@ -192,7 +194,7 @@
 	/* Make sure this is a valid target state */
 
 	if (!device->flags.power_manageable) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable",
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
 				device->kobj.name));
 		return -ENODEV;
 	}
@@ -738,7 +740,10 @@
 		return -ENODEV;
 	}
 
-	firmware_register(&acpi_subsys);
+	result = firmware_register(&acpi_subsys);
+	if (result < 0)
+		printk(KERN_WARNING "%s: firmware_register error: %d\n",
+			__FUNCTION__, result);
 
 	result = acpi_bus_init();
 
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 1c0a39d..578b99b 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -58,8 +58,8 @@
 };
 
 #define DOCK_DOCKING	0x00000001
-#define DOCK_EVENT	KOBJ_DOCK
-#define UNDOCK_EVENT	KOBJ_UNDOCK
+#define DOCK_EVENT	3
+#define UNDOCK_EVENT	2
 
 static struct dock_station *dock_station;
 
@@ -322,11 +322,10 @@
 
 static void dock_event(struct dock_station *ds, u32 event, int num)
 {
-	struct acpi_device *device;
-
-	device = dock_create_acpi_device(ds->handle);
-	if (device)
-		kobject_uevent(&device->kobj, num);
+	/*
+	 * we don't do events until someone tells me that
+	 * they would like to have them.
+	 */
 }
 
 /**
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 32c9d88..1ba2db6 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -91,6 +91,14 @@
 	HK_EVENT_ENTERRING_S5,
 };
 
+enum conf_entry_enum {
+	bus_handle = 0,
+	bus_method = 1,
+	action_handle = 2,
+	method = 3,
+	LAST_CONF_ENTRY
+};
+
 /*  procdir we use */
 static struct proc_dir_entry *hotkey_proc_dir;
 static struct proc_dir_entry *hotkey_config;
@@ -244,19 +252,15 @@
 
 static char *format_result(union acpi_object *object)
 {
-	char *buf = NULL;
+	char *buf;
 
-	buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
-	if (buf)
-		memset(buf, 0, RESULT_STR_LEN);
-	else
-		goto do_fail;
-
+	buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
+	if (!buf)
+		return NULL;
 	/* Now, just support integer type */
 	if (object->type == ACPI_TYPE_INTEGER)
 		sprintf(buf, "%d\n", (u32) object->integer.value);
-      do_fail:
-	return (buf);
+	return buf;
 }
 
 static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
@@ -486,98 +490,102 @@
 
 static void free_hotkey_buffer(union acpi_hotkey *key)
 {
+	/* key would never be null, action method could be */
 	kfree(key->event_hotkey.action_method);
 }
 
 static void free_poll_hotkey_buffer(union acpi_hotkey *key)
 {
+	/* key would never be null, others could be*/
 	kfree(key->poll_hotkey.action_method);
 	kfree(key->poll_hotkey.poll_method);
 	kfree(key->poll_hotkey.poll_result);
 }
 static int
-init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
-		   char *method, int std_num, int external_num)
+init_hotkey_device(union acpi_hotkey *key, char **config_entry,
+		   int std_num, int external_num)
 {
 	acpi_handle tmp_handle;
 	acpi_status status = AE_OK;
 
-
 	if (std_num < 0 || IS_POLL(std_num) || !key)
 		goto do_fail;
 
-	if (!bus_str || !action_str || !method)
+	if (!config_entry[bus_handle] || !config_entry[action_handle]
+			|| !config_entry[method])
 		goto do_fail;
 
 	key->link.hotkey_type = ACPI_HOTKEY_EVENT;
 	key->link.hotkey_standard_num = std_num;
 	key->event_hotkey.flag = 0;
-	key->event_hotkey.action_method = method;
+	key->event_hotkey.action_method = config_entry[method];
 
-	status =
-	    acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle));
+	status = acpi_get_handle(NULL, config_entry[bus_handle],
+			   &(key->event_hotkey.bus_handle));
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	key->event_hotkey.external_hotkey_num = external_num;
-	status =
-	    acpi_get_handle(NULL, action_str,
+	status = acpi_get_handle(NULL, config_entry[action_handle],
 			    &(key->event_hotkey.action_handle));
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	status = acpi_get_handle(key->event_hotkey.action_handle,
-				 method, &tmp_handle);
+				 config_entry[method], &tmp_handle);
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	return AE_OK;
-      do_fail:
+do_fail_zero:
+	key->event_hotkey.action_method = NULL;
+do_fail:
 	return -ENODEV;
 }
 
 static int
-init_poll_hotkey_device(union acpi_hotkey *key,
-			char *poll_str,
-			char *poll_method,
-			char *action_str, char *action_method, int std_num)
+init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
+			int std_num)
 {
 	acpi_status status = AE_OK;
 	acpi_handle tmp_handle;
 
-
 	if (std_num < 0 || IS_EVENT(std_num) || !key)
 		goto do_fail;
-
-	if (!poll_str || !poll_method || !action_str || !action_method)
+	if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
+		!config_entry[action_handle] || !config_entry[method])
 		goto do_fail;
 
 	key->link.hotkey_type = ACPI_HOTKEY_POLLING;
 	key->link.hotkey_standard_num = std_num;
 	key->poll_hotkey.flag = 0;
-	key->poll_hotkey.poll_method = poll_method;
-	key->poll_hotkey.action_method = action_method;
+	key->poll_hotkey.poll_method = config_entry[bus_method];
+	key->poll_hotkey.action_method = config_entry[method];
 
-	status =
-	    acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle));
+	status = acpi_get_handle(NULL, config_entry[bus_handle],
+		      &(key->poll_hotkey.poll_handle));
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	status = acpi_get_handle(key->poll_hotkey.poll_handle,
-				 poll_method, &tmp_handle);
+				 config_entry[bus_method], &tmp_handle);
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	status =
-	    acpi_get_handle(NULL, action_str,
+	    acpi_get_handle(NULL, config_entry[action_handle],
 			    &(key->poll_hotkey.action_handle));
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	status = acpi_get_handle(key->poll_hotkey.action_handle,
-				 action_method, &tmp_handle);
+				 config_entry[method], &tmp_handle);
 	if (ACPI_FAILURE(status))
-		goto do_fail;
+		goto do_fail_zero;
 	key->poll_hotkey.poll_result =
 	    (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
 	if (!key->poll_hotkey.poll_result)
-		goto do_fail;
+		goto do_fail_zero;
 	return AE_OK;
-      do_fail:
+
+do_fail_zero:
+	key->poll_hotkey.poll_method = NULL;
+	key->poll_hotkey.action_method = NULL;
+do_fail:
 	return -ENODEV;
 }
 
@@ -652,17 +660,18 @@
 }
 
 static int
-get_parms(char *config_record,
-	  int *cmd,
-	  char **bus_handle,
-	  char **bus_method,
-	  char **action_handle,
-	  char **method, int *internal_event_num, int *external_event_num)
+get_parms(char *config_record, int *cmd, char **config_entry,
+	       int *internal_event_num, int *external_event_num)
 {
+/* the format of *config_record =
+ * "1:\d+:*" : "cmd:internal_event_num"
+ * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
+ * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
+ */
 	char *tmp, *tmp1, count;
+	int i;
 
 	sscanf(config_record, "%d", cmd);
-
 	if (*cmd == 1) {
 		if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
 		    2)
@@ -674,59 +683,27 @@
 	if (!tmp)
 		goto do_fail;
 	tmp++;
-	tmp1 = strchr(tmp, ':');
-	if (!tmp1)
-		goto do_fail;
-
-	count = tmp1 - tmp;
-	*bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
-	if (!*bus_handle)
-		goto do_fail;
-	strncpy(*bus_handle, tmp, count);
-	*(*bus_handle + count) = 0;
-
-	tmp = tmp1;
-	tmp++;
-	tmp1 = strchr(tmp, ':');
-	if (!tmp1)
-		goto do_fail;
-	count = tmp1 - tmp;
-	*bus_method = (char *)kmalloc(count + 1, GFP_KERNEL);
-	if (!*bus_method)
-		goto do_fail;
-	strncpy(*bus_method, tmp, count);
-	*(*bus_method + count) = 0;
-
-	tmp = tmp1;
-	tmp++;
-	tmp1 = strchr(tmp, ':');
-	if (!tmp1)
-		goto do_fail;
-	count = tmp1 - tmp;
-	*action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
-	if (!*action_handle)
-		goto do_fail;
-	strncpy(*action_handle, tmp, count);
-	*(*action_handle + count) = 0;
-
-	tmp = tmp1;
-	tmp++;
-	tmp1 = strchr(tmp, ':');
-	if (!tmp1)
-		goto do_fail;
-	count = tmp1 - tmp;
-	*method = (char *)kmalloc(count + 1, GFP_KERNEL);
-	if (!*method)
-		goto do_fail;
-	strncpy(*method, tmp, count);
-	*(*method + count) = 0;
-
-	if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <=
-	    0)
-		goto do_fail;
-
-	return 6;
-      do_fail:
+	for (i = 0; i < LAST_CONF_ENTRY; i++) {
+		tmp1 = strchr(tmp, ':');
+		if (!tmp1) {
+			goto do_fail;
+		}
+		count = tmp1 - tmp;
+		config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
+		if (!config_entry[i])
+			goto handle_failure;
+		strncpy(config_entry[i], tmp, count);
+		tmp = tmp1 + 1;
+	}
+	if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
+		goto handle_failure;
+	if (!IS_OTHERS(*internal_event_num)) {
+		return 6;
+	}
+handle_failure:
+	while (i-- > 0)
+		kfree(config_entry[i]);
+do_fail:
 	return -1;
 }
 
@@ -736,50 +713,34 @@
 				   size_t count, loff_t * data)
 {
 	char *config_record = NULL;
-	char *bus_handle = NULL;
-	char *bus_method = NULL;
-	char *action_handle = NULL;
-	char *method = NULL;
+	char *config_entry[LAST_CONF_ENTRY];
 	int cmd, internal_event_num, external_event_num;
 	int ret = 0;
-	union acpi_hotkey *key = NULL;
+	union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
 
-
-	config_record = (char *)kmalloc(count + 1, GFP_KERNEL);
-	if (!config_record)
+	if (!key)
 		return -ENOMEM;
 
+	config_record = kzalloc(count + 1, GFP_KERNEL);
+	if (!config_record) {
+		kfree(key);
+		return -ENOMEM;
+	}
+
 	if (copy_from_user(config_record, buffer, count)) {
 		kfree(config_record);
+		kfree(key);
 		printk(KERN_ERR PREFIX "Invalid data\n");
 		return -EINVAL;
 	}
-	config_record[count] = 0;
-
-	ret = get_parms(config_record,
-			&cmd,
-			&bus_handle,
-			&bus_method,
-			&action_handle,
-			&method, &internal_event_num, &external_event_num);
-
+	ret = get_parms(config_record, &cmd, config_entry,
+		       &internal_event_num, &external_event_num);
 	kfree(config_record);
-	if (IS_OTHERS(internal_event_num))
-		goto do_fail;
 	if (ret != 6) {
-	      do_fail:
-		kfree(bus_handle);
-		kfree(bus_method);
-		kfree(action_handle);
-		kfree(method);
 		printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
 		return -EINVAL;
 	}
 
-	key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-	if (!key)
-		goto do_fail;
-	memset(key, 0, sizeof(union acpi_hotkey));
 	if (cmd == 1) {
 		union acpi_hotkey *tmp = NULL;
 		tmp = get_hotkey_by_event(&global_hotkey_list,
@@ -791,34 +752,19 @@
 		goto cont_cmd;
 	}
 	if (IS_EVENT(internal_event_num)) {
-		kfree(bus_method);
-		ret = init_hotkey_device(key, bus_handle, action_handle, method,
-					 internal_event_num,
-					 external_event_num);
-	} else
-		ret = init_poll_hotkey_device(key, bus_handle, bus_method,
-					      action_handle, method,
-					      internal_event_num);
-	if (ret) {
-		kfree(bus_handle);
-		kfree(action_handle);
-		if (IS_EVENT(internal_event_num))
-			free_hotkey_buffer(key);
-		else
-			free_poll_hotkey_buffer(key);
-		kfree(key);
-		printk(KERN_ERR PREFIX "Invalid hotkey\n");
-		return -EINVAL;
+		if (init_hotkey_device(key, config_entry,
+			internal_event_num, external_event_num))
+			goto init_hotkey_fail;
+	} else {
+		if (init_poll_hotkey_device(key, config_entry,
+			       internal_event_num))
+			goto init_poll_hotkey_fail;
 	}
-
-      cont_cmd:
-	kfree(bus_handle);
-	kfree(action_handle);
-
+cont_cmd:
 	switch (cmd) {
 	case 0:
-		if (get_hotkey_by_event
-		    (&global_hotkey_list, key->link.hotkey_standard_num))
+		if (get_hotkey_by_event(&global_hotkey_list,
+				key->link.hotkey_standard_num))
 			goto fail_out;
 		else
 			hotkey_add(key);
@@ -827,6 +773,7 @@
 		hotkey_remove(key);
 		break;
 	case 2:
+		/* key is kfree()ed if matched*/
 		if (hotkey_update(key))
 			goto fail_out;
 		break;
@@ -835,11 +782,22 @@
 		break;
 	}
 	return count;
-      fail_out:
-	if (IS_EVENT(internal_event_num))
-		free_hotkey_buffer(key);
-	else
-		free_poll_hotkey_buffer(key);
+
+init_poll_hotkey_fail:		/* failed init_poll_hotkey_device */
+	kfree(config_entry[bus_method]);
+	config_entry[bus_method] = NULL;
+init_hotkey_fail:		/* failed init_hotkey_device */
+	kfree(config_entry[method]);
+fail_out:
+	kfree(config_entry[bus_handle]);
+	kfree(config_entry[action_handle]);
+	/* No double free since elements =NULL for error cases */
+	if (IS_EVENT(internal_event_num)) {
+		if (config_entry[bus_method])
+			kfree(config_entry[bus_method]);
+		free_hotkey_buffer(key);	/* frees [method] */
+	} else
+		free_poll_hotkey_buffer(key);  /* frees [bus_method]+[method] */
 	kfree(key);
 	printk(KERN_ERR PREFIX "invalid key\n");
 	return -EINVAL;
@@ -923,10 +881,9 @@
 	union acpi_hotkey *key;
 
 
-	arg = (char *)kmalloc(count + 1, GFP_KERNEL);
+	arg = kzalloc(count + 1, GFP_KERNEL);
 	if (!arg)
 		return -ENOMEM;
-	arg[count] = 0;
 
 	if (copy_from_user(arg, buffer, count)) {
 		kfree(arg);
diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c
index 84239d5..6809c28 100644
--- a/drivers/acpi/i2c_ec.c
+++ b/drivers/acpi/i2c_ec.c
@@ -330,7 +330,7 @@
 	status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
-		kfree(ec_hc->smbus);
+		kfree(ec_hc);
 		kfree(smbus);
 		return -EIO;
 	}
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index b7d1514..507f051 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -746,6 +746,16 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
 			  handle, units, timeout));
 
+	/*
+	 * This can be called during resume with interrupts off.
+	 * Like boot-time, we should be single threaded and will
+	 * always get the lock if we try -- timeout or not.
+	 * If this doesn't succeed, then we will oops courtesy of
+	 * might_sleep() in down().
+	 */
+	if (!down_trylock(sem))
+		return AE_OK;
+
 	switch (timeout) {
 		/*
 		 * No Wait:
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index db7b350..62bef0b 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1714,6 +1714,9 @@
 {
 	int result = 0;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	init_MUTEX(&sbs_sem);
 
 	if (capacity_mode != DEF_CAPACITY_UNIT
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5fcb50c..698a154 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -4,6 +4,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/acpi.h>
 
 #include <acpi/acpi_drivers.h>
@@ -113,6 +114,8 @@
 static void acpi_device_register(struct acpi_device *device,
 				 struct acpi_device *parent)
 {
+	int err;
+
 	/*
 	 * Linkage
 	 * -------
@@ -138,7 +141,10 @@
 		device->kobj.parent = &parent->kobj;
 	device->kobj.ktype = &ktype_acpi_ns;
 	device->kobj.kset = &acpi_namespace_kset;
-	kobject_register(&device->kobj);
+	err = kobject_register(&device->kobj);
+	if (err < 0)
+		printk(KERN_WARNING "%s: kobject_register error: %d\n",
+			__FUNCTION__, err);
 	create_sysfs_device_files(device);
 }
 
@@ -1450,7 +1456,9 @@
 	if (acpi_disabled)
 		return 0;
 
-	kset_register(&acpi_namespace_kset);
+	result = kset_register(&acpi_namespace_kset);
+	if (result < 0)
+		printk(KERN_ERR PREFIX "kset_register error: %d\n", result);
 
 	result = bus_register(&acpi_bus_type);
 	if (result) {
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index f48227f..d0d84c4 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -262,7 +262,7 @@
 	if (!data)
 		return AE_BAD_PARAMETER;
 
-	element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+	element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
 	if (!element)
 		return AE_NO_MEMORY;
 
diff --git a/drivers/base/node.c b/drivers/base/node.c
index d7de1753..e9b0957 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -64,7 +64,7 @@
 		       "Node %d Mapped:       %8lu kB\n"
 		       "Node %d AnonPages:    %8lu kB\n"
 		       "Node %d PageTables:   %8lu kB\n"
-		       "Node %d NFS Unstable: %8lu kB\n"
+		       "Node %d NFS_Unstable: %8lu kB\n"
 		       "Node %d Bounce:       %8lu kB\n"
 		       "Node %d Slab:         %8lu kB\n",
 		       nid, K(i.totalram),
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index c2d6216..3ef9d51 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -139,7 +139,7 @@
 				(void *)(long)i);
 	}
 
-	register_cpu_notifier(&topology_cpu_notifier);
+	register_hotcpu_notifier(&topology_cpu_notifier);
 
 	return 0;
 }
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 5109fa3..ad1d706 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4177,6 +4177,11 @@
 	int i, unit, drive;
 	int err, dr;
 
+#if defined(CONFIG_PPC_MERGE)
+	if (check_legacy_ioport(FDC1))
+		return -ENODEV;
+#endif
+
 	raw_cmd = NULL;
 
 	for (dr = 0; dr < N_DRIVE; dr++) {
@@ -4234,13 +4239,6 @@
 	}
 
 	use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC_MERGE)
-	if (check_legacy_ioport(FDC1)) {
-		del_timer(&fd_timeout);
-		err = -ENODEV;
-		goto out_unreg_region;
-	}
-#endif
 	fdc_state[0].address = FDC1;
 	if (fdc_state[0].address == -1) {
 		del_timer(&fd_timeout);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0a1b1ea..bdbade9 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -300,6 +300,15 @@
 				lo->disk->disk_name, result);
 		goto harderror;
 	}
+
+	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
+		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
+				lo->disk->disk_name,
+				(unsigned long)ntohl(reply.magic));
+		result = -EPROTO;
+		goto harderror;
+	}
+
 	req = nbd_find_request(lo, reply.handle);
 	if (unlikely(IS_ERR(req))) {
 		result = PTR_ERR(req);
@@ -312,13 +321,6 @@
 		goto harderror;
 	}
 
-	if (ntohl(reply.magic) != NBD_REPLY_MAGIC) {
-		printk(KERN_ERR "%s: Wrong magic (0x%lx)\n",
-				lo->disk->disk_name,
-				(unsigned long)ntohl(reply.magic));
-		result = -EPROTO;
-		goto harderror;
-	}
 	if (ntohl(reply.error)) {
 		printk(KERN_ERR "%s: Other side returned error (%d)\n",
 				lo->disk->disk_name, ntohl(reply.error));
@@ -339,7 +341,8 @@
 					printk(KERN_ERR "%s: Receive data failed (result %d)\n",
 							lo->disk->disk_name,
 							result);
-					goto harderror;
+					req->errors++;
+					return req;
 				}
 				dprintk(DBG_RX, "%s: request %p: got %d bytes data\n",
 					lo->disk->disk_name, req, bvec->bv_len);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index bde2c64..451b996 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2577,19 +2577,19 @@
 	case PKT_CTRL_CMD_SETUP:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		mutex_lock(&ctl_mutex);
+		mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 		ret = pkt_setup_dev(&ctrl_cmd);
 		mutex_unlock(&ctl_mutex);
 		break;
 	case PKT_CTRL_CMD_TEARDOWN:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		mutex_lock(&ctl_mutex);
+		mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 		ret = pkt_remove_dev(&ctrl_cmd);
 		mutex_unlock(&ctl_mutex);
 		break;
 	case PKT_CTRL_CMD_STATUS:
-		mutex_lock(&ctl_mutex);
+		mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 		pkt_get_status(&ctrl_cmd);
 		mutex_unlock(&ctl_mutex);
 		break;
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index b6ee50a..fa70824 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -266,7 +266,7 @@
 		goto out;
 
 	if (req->cmd != READ) {
-		printk("GSCD: bad cmd %lu\n", rq_data_dir(req));
+		printk("GSCD: bad cmd %u\n", rq_data_dir(req));
 		end_request(req, 0);
 		goto repeat;
 	}
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 5bb2234..39a7f68 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -175,6 +175,14 @@
 		}
 		break;
 
+	case R200_EMIT_VAP_CTL:{
+			RING_LOCALS;
+			BEGIN_RING(2);
+			OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+			ADVANCE_RING();
+		}
+		break;
+
 	case RADEON_EMIT_RB3D_COLORPITCH:
 	case RADEON_EMIT_RE_LINE_PATTERN:
 	case RADEON_EMIT_SE_LINE_WIDTH:
@@ -202,7 +210,6 @@
 	case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
 	case R200_EMIT_TFACTOR_0:
 	case R200_EMIT_VTX_FMT_0:
-	case R200_EMIT_VAP_CTL:
 	case R200_EMIT_MATRIX_SELECT_0:
 	case R200_EMIT_TEX_PROC_CTL_2:
 	case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 41db806..017f755 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -311,7 +311,8 @@
 				/* CD went away; no more connection */
 				pr_debug("hvsi%i: CD dropped\n", hp->index);
 				hp->mctrl &= TIOCM_CD;
-				if (!(hp->tty->flags & CLOCAL))
+				/* If userland hasn't done an open(2) yet, hp->tty is NULL. */
+				if (hp->tty && !(hp->tty->flags & CLOCAL))
 					*to_hangup = hp->tty;
 			}
 			break;
@@ -986,10 +987,7 @@
 		start_j = 0;
 #endif /* DEBUG */
 		wake_up_all(&hp->emptyq);
-		if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags)
-				&& hp->tty->ldisc.write_wakeup)
-			hp->tty->ldisc.write_wakeup(hp->tty);
-		wake_up_interruptible(&hp->tty->write_wait);
+		tty_wakeup(hp->tty);
 	}
 
 out:
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index be61f22..d37ced0 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -107,10 +107,14 @@
 	if (err) {
 		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
 		       err);
-		goto out;
+		goto err_unmap;
 	}
 out:
 	return err;
+
+err_unmap:
+	iounmap(mem);
+	goto out;
 }
 
 static void __exit mod_exit(void)
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 6594bd5..ccd7e71 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -164,7 +164,7 @@
 	if (err) {
 		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
 		       err);
-		goto out;
+		goto err_unmap;
 	}
 out:
 	return err;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 819516b..a01d796 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -25,12 +25,12 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/random.h>
+#include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/hw_random.h>
 
 #include <asm/io.h>
-#include <asm/hardware/clock.h>
 
 #define RNG_OUT_REG		0x00		/* Output register */
 #define RNG_STAT_REG		0x04		/* Status register
@@ -52,7 +52,7 @@
 
 static void __iomem *rng_base;
 static struct clk *rng_ick;
-static struct device *rng_dev;
+static struct platform_device *rng_dev;
 
 static u32 omap_rng_read_reg(int reg)
 {
@@ -83,9 +83,8 @@
 	.data_read	= omap_rng_data_read,
 };
 
-static int __init omap_rng_probe(struct device *dev)
+static int __init omap_rng_probe(struct platform_device *pdev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *res, *mem;
 	int ret;
 
@@ -95,16 +94,14 @@
 	 */
 	BUG_ON(rng_dev);
 
-    	if (cpu_is_omap24xx()) {
+	if (cpu_is_omap24xx()) {
 		rng_ick = clk_get(NULL, "rng_ick");
 		if (IS_ERR(rng_ick)) {
-			dev_err(dev, "Could not get rng_ick\n");
+			dev_err(&pdev->dev, "Could not get rng_ick\n");
 			ret = PTR_ERR(rng_ick);
 			return ret;
-		}
-		else {
-			clk_use(rng_ick);
-		}
+		} else
+			clk_enable(rng_ick);
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -117,7 +114,7 @@
 	if (mem == NULL)
 		return -EBUSY;
 
-	dev_set_drvdata(dev, mem);
+	dev_set_drvdata(&pdev->dev, mem);
 	rng_base = (u32 __iomem *)io_p2v(res->start);
 
 	ret = hwrng_register(&omap_rng_ops);
@@ -127,25 +124,25 @@
 		return ret;
 	}
 
-	dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
+	dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
 		omap_rng_read_reg(RNG_REV_REG));
 	omap_rng_write_reg(RNG_MASK_REG, 0x1);
 
-	rng_dev = dev;
+	rng_dev = pdev;
 
 	return 0;
 }
 
-static int __exit omap_rng_remove(struct device *dev)
+static int __exit omap_rng_remove(struct platform_device *pdev)
 {
-	struct resource *mem = dev_get_drvdata(dev);
+	struct resource *mem = dev_get_drvdata(&pdev->dev);
 
 	hwrng_unregister(&omap_rng_ops);
 
 	omap_rng_write_reg(RNG_MASK_REG, 0x0);
 
 	if (cpu_is_omap24xx()) {
-		clk_unuse(rng_ick);
+		clk_disable(rng_ick);
 		clk_put(rng_ick);
 	}
 
@@ -157,18 +154,16 @@
 
 #ifdef CONFIG_PM
 
-static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
 {
 	omap_rng_write_reg(RNG_MASK_REG, 0x0);
-
 	return 0;
 }
 
-static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
+static int omap_rng_resume(struct platform_device *pdev)
 {
 	omap_rng_write_reg(RNG_MASK_REG, 0x1);
-
-	return 1;
+	return 0;
 }
 
 #else
@@ -179,9 +174,11 @@
 #endif
 
 
-static struct device_driver omap_rng_driver = {
-	.name		= "omap_rng",
-	.bus		= &platform_bus_type,
+static struct platform_driver omap_rng_driver = {
+	.driver = {
+		.name		= "omap_rng",
+		.owner		= THIS_MODULE,
+	},
 	.probe		= omap_rng_probe,
 	.remove		= __exit_p(omap_rng_remove),
 	.suspend	= omap_rng_suspend,
@@ -193,12 +190,12 @@
 	if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
 		return -ENODEV;
 
-	return driver_register(&omap_rng_driver);
+	return platform_driver_register(&omap_rng_driver);
 }
 
 static void __exit omap_rng_exit(void)
 {
-	driver_unregister(&omap_rng_driver);
+	platform_driver_unregister(&omap_rng_driver);
 }
 
 module_init(omap_rng_init);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 0aa5d60..843d34c 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3428,6 +3428,7 @@
 
 	rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC);
 	if (rv) {
+		rv->user = NULL;
 		rv->done = free_recv_msg;
 		atomic_inc(&recv_msg_inuse_count);
 	}
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 056ebe8..3e90aac 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -107,7 +107,6 @@
 
 struct kbd_struct kbd_table[MAX_NR_CONSOLES];
 static struct kbd_struct *kbd = kbd_table;
-static struct kbd_struct kbd0;
 
 int spawnpid, spawnsig;
 
@@ -223,13 +222,13 @@
 {
 	struct list_head *node;
 
-	list_for_each(node,&kbd_handler.h_list) {
+	list_for_each(node, &kbd_handler.h_list) {
 		struct input_handle *handle = to_handle_h(node);
 		if (test_bit(EV_SND, handle->dev->evbit)) {
 			if (test_bit(SND_TONE, handle->dev->sndbit))
-				input_event(handle->dev, EV_SND, SND_TONE, 0);
+				input_inject_event(handle, EV_SND, SND_TONE, 0);
 			if (test_bit(SND_BELL, handle->dev->sndbit))
-				input_event(handle->dev, EV_SND, SND_BELL, 0);
+				input_inject_event(handle, EV_SND, SND_BELL, 0);
 		}
 	}
 }
@@ -247,11 +246,11 @@
 			struct input_handle *handle = to_handle_h(node);
 			if (test_bit(EV_SND, handle->dev->evbit)) {
 				if (test_bit(SND_TONE, handle->dev->sndbit)) {
-					input_event(handle->dev, EV_SND, SND_TONE, hz);
+					input_inject_event(handle, EV_SND, SND_TONE, hz);
 					break;
 				}
 				if (test_bit(SND_BELL, handle->dev->sndbit)) {
-					input_event(handle->dev, EV_SND, SND_BELL, 1);
+					input_inject_event(handle, EV_SND, SND_BELL, 1);
 					break;
 				}
 			}
@@ -272,15 +271,15 @@
 	unsigned int d = 0;
 	unsigned int p = 0;
 
-	list_for_each(node,&kbd_handler.h_list) {
+	list_for_each(node, &kbd_handler.h_list) {
 		struct input_handle *handle = to_handle_h(node);
 		struct input_dev *dev = handle->dev;
 
 		if (test_bit(EV_REP, dev->evbit)) {
 			if (rep->delay > 0)
-				input_event(dev, EV_REP, REP_DELAY, rep->delay);
+				input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
 			if (rep->period > 0)
-				input_event(dev, EV_REP, REP_PERIOD, rep->period);
+				input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
 			d = dev->rep[REP_DELAY];
 			p = dev->rep[REP_PERIOD];
 		}
@@ -988,7 +987,7 @@
  * interrupt routines for this thing allows us to easily mask
  * this when we don't want any of the above to happen.
  * This allows for easy and efficient race-condition prevention
- * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ...
+ * for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
  */
 
 static void kbd_bh(unsigned long dummy)
@@ -998,11 +997,11 @@
 
 	if (leds != ledstate) {
 		list_for_each(node, &kbd_handler.h_list) {
-			struct input_handle * handle = to_handle_h(node);
-			input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
-			input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
-			input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
-			input_sync(handle->dev);
+			struct input_handle *handle = to_handle_h(node);
+			input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+			input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
+			input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
+			input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
 		}
 	}
 
@@ -1011,23 +1010,6 @@
 
 DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
 
-/*
- * This allows a newly plugged keyboard to pick the LED state.
- */
-static void kbd_refresh_leds(struct input_handle *handle)
-{
-	unsigned char leds = ledstate;
-
-	tasklet_disable(&keyboard_tasklet);
-	if (leds != 0xff) {
-		input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01));
-		input_event(handle->dev, EV_LED, LED_NUML,    !!(leds & 0x02));
-		input_event(handle->dev, EV_LED, LED_CAPSL,   !!(leds & 0x04));
-		input_sync(handle->dev);
-	}
-	tasklet_enable(&keyboard_tasklet);
-}
-
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
     defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
     defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
@@ -1043,7 +1025,7 @@
 	 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
 	 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
 	 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92,
-	284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+	284,285,309,  0,312, 91,327,328,329,331,333,335,336,337,338,339,
 	367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
 	360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
 	103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
@@ -1065,38 +1047,55 @@
 static int emulate_raw(struct vc_data *vc, unsigned int keycode,
 		       unsigned char up_flag)
 {
-	if (keycode > 255 || !x86_keycodes[keycode])
-		return -1;
+	int code;
 
 	switch (keycode) {
 		case KEY_PAUSE:
 			put_queue(vc, 0xe1);
 			put_queue(vc, 0x1d | up_flag);
 			put_queue(vc, 0x45 | up_flag);
-			return 0;
+			break;
+
 		case KEY_HANGEUL:
 			if (!up_flag)
 				put_queue(vc, 0xf2);
-			return 0;
+			break;
+
 		case KEY_HANJA:
 			if (!up_flag)
 				put_queue(vc, 0xf1);
-			return 0;
-	}
+			break;
 
-	if (keycode == KEY_SYSRQ && sysrq_alt) {
-		put_queue(vc, 0x54 | up_flag);
-		return 0;
-	}
+		case KEY_SYSRQ:
+			/*
+			 * Real AT keyboards (that's what we're trying
+			 * to emulate here emit 0xe0 0x2a 0xe0 0x37 when
+			 * pressing PrtSc/SysRq alone, but simply 0x54
+			 * when pressing Alt+PrtSc/SysRq.
+			 */
+			if (sysrq_alt) {
+				put_queue(vc, 0x54 | up_flag);
+			} else {
+				put_queue(vc, 0xe0);
+				put_queue(vc, 0x2a | up_flag);
+				put_queue(vc, 0xe0);
+				put_queue(vc, 0x37 | up_flag);
+			}
+			break;
 
-	if (x86_keycodes[keycode] & 0x100)
-		put_queue(vc, 0xe0);
+		default:
+			if (keycode > 255)
+				return -1;
 
-	put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag);
+			code = x86_keycodes[keycode];
+			if (!code)
+				return -1;
 
-	if (keycode == KEY_SYSRQ) {
-		put_queue(vc, 0xe0);
-		put_queue(vc, 0x37 | up_flag);
+			if (code & 0x100)
+				put_queue(vc, 0xe0);
+			put_queue(vc, (code & 0x7f) | up_flag);
+
+			break;
 	}
 
 	return 0;
@@ -1298,16 +1297,15 @@
 	if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
 		return NULL;
 
-	if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
+	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+	if (!handle)
 		return NULL;
-	memset(handle, 0, sizeof(struct input_handle));
 
 	handle->dev = dev;
 	handle->handler = handler;
 	handle->name = "kbd";
 
 	input_open_device(handle);
-	kbd_refresh_leds(handle);
 
 	return handle;
 }
@@ -1318,6 +1316,24 @@
 	kfree(handle);
 }
 
+/*
+ * Start keyboard handler on the new keyboard by refreshing LED state to
+ * match the rest of the system.
+ */
+static void kbd_start(struct input_handle *handle)
+{
+	unsigned char leds = ledstate;
+
+	tasklet_disable(&keyboard_tasklet);
+	if (leds != 0xff) {
+		input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
+		input_inject_event(handle, EV_LED, LED_NUML,    !!(leds & 0x02));
+		input_inject_event(handle, EV_LED, LED_CAPSL,   !!(leds & 0x04));
+		input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
+	}
+	tasklet_enable(&keyboard_tasklet);
+}
+
 static struct input_device_id kbd_ids[] = {
 	{
                 .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
@@ -1338,6 +1354,7 @@
 	.event		= kbd_event,
 	.connect	= kbd_connect,
 	.disconnect	= kbd_disconnect,
+	.start		= kbd_start,
 	.name		= "kbd",
 	.id_table	= kbd_ids,
 };
@@ -1346,15 +1363,15 @@
 {
 	int i;
 
-        kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS;
-        kbd0.ledmode = LED_SHOW_FLAGS;
-        kbd0.lockstate = KBD_DEFLOCK;
-        kbd0.slockstate = 0;
-        kbd0.modeflags = KBD_DEFMODE;
-        kbd0.kbdmode = VC_XLATE;
-
-        for (i = 0 ; i < MAX_NR_CONSOLES ; i++)
-                kbd_table[i] = kbd0;
+        for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		kbd_table[i].ledflagstate = KBD_DEFLEDS;
+		kbd_table[i].default_ledflagstate = KBD_DEFLEDS;
+		kbd_table[i].ledmode = LED_SHOW_FLAGS;
+		kbd_table[i].lockstate = KBD_DEFLOCK;
+		kbd_table[i].slockstate = 0;
+		kbd_table[i].modeflags = KBD_DEFMODE;
+		kbd_table[i].kbdmode = VC_XLATE;
+	}
 
 	input_register_handler(&kbd_handler);
 
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 4ea7bd5..a369dd6 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -142,6 +142,7 @@
 
 static moxa_board_conf moxa_boards[MAX_BOARDS];
 static void __iomem *moxaBaseAddr[MAX_BOARDS];
+static int loadstat[MAX_BOARDS];
 
 struct moxa_str {
 	int type;
@@ -1688,6 +1689,8 @@
 	if (moxaCard == 0)
 		return (-1);
 	for (card = 0; card < MAX_BOARDS; card++) {
+	        if (loadstat[card] == 0)
+			continue;
 		if ((ports = moxa_boards[card].numPorts) == 0)
 			continue;
 		if (readb(moxaIntPend[card]) == 0xff) {
@@ -2903,6 +2906,7 @@
 		}
 		break;
 	}
+	loadstat[cardno] = 1;
 	return (0);
 }
 
@@ -2920,7 +2924,7 @@
 	len1 = len >> 1;
 	ptr = (ushort *) moxaBuff;
 	for (i = 0; i < len1; i++)
-		usum += *(ptr + i);
+		usum += le16_to_cpu(*(ptr + i));
 	retry = 0;
 	do {
 		len1 = len >> 1;
@@ -2992,7 +2996,7 @@
 	wlen = len >> 1;
 	uptr = (ushort *) moxaBuff;
 	for (i = 0; i < wlen; i++)
-		usum += uptr[i];
+		usum += le16_to_cpu(uptr[i]);
 	retry = 0;
 	j = 0;
 	do {
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 645eb81..84e5a68 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -221,7 +221,6 @@
 	.gpio_change	= pc8736x_gpio_change,
 	.gpio_current	= pc8736x_gpio_current
 };
-EXPORT_SYMBOL(pc8736x_gpio_ops);
 
 static int pc8736x_gpio_open(struct inode *inode, struct file *file)
 {
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index afc6eda..07e0b75 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -374,7 +374,12 @@
 	struct sysctl_data_s *scd;
 	void *salbuf;
 	dev_t first_dev, dev;
-	nasid_t event_nasid = ia64_sn_get_console_nasid();
+	nasid_t event_nasid;
+
+	if (!ia64_platform_is("sn2"))
+		return -ENODEV;
+
+	event_nasid = ia64_sn_get_console_nasid();
 
 	if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
 				SYSCTL_BASENAME) < 0) {
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index b2dbbdb..2f07b08 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -391,8 +391,8 @@
 #define DESC_LIST_SIZE 4096
 
 #define MASK_PARITY  BIT1
-#define MASK_FRAMING BIT2
-#define MASK_BREAK   BIT3
+#define MASK_FRAMING BIT0
+#define MASK_BREAK   BIT14
 #define MASK_OVERRUN BIT4
 
 #define GSR   0x00 /* global status */
@@ -1800,17 +1800,17 @@
 
 			stat = 0;
 
-			if ((status = *(p+1) & (BIT9 + BIT8))) {
-				if (status & BIT9)
+			if ((status = *(p+1) & (BIT1 + BIT0))) {
+				if (status & BIT1)
 					icount->parity++;
-				else if (status & BIT8)
+				else if (status & BIT0)
 					icount->frame++;
 				/* discard char if tty control flags say so */
 				if (status & info->ignore_status_mask)
 					continue;
-				if (status & BIT9)
+				if (status & BIT1)
 					stat = TTY_PARITY;
-				else if (status & BIT8)
+				else if (status & BIT0)
 					stat = TTY_FRAME;
 			}
 			if (tty) {
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index bfdb902..bb0d919 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -153,6 +153,15 @@
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_mem(struct tty_struct *tty, int idx);
 
+/**
+ *	alloc_tty_struct	-	allocate a tty object
+ *
+ *	Return a new empty tty structure. The data fields have not
+ *	been initialized in any way but has been zeroed
+ *
+ *	Locking: none
+ *	FIXME: use kzalloc
+ */
 
 static struct tty_struct *alloc_tty_struct(void)
 {
@@ -166,6 +175,15 @@
 
 static void tty_buffer_free_all(struct tty_struct *);
 
+/**
+ *	free_tty_struct		-	free a disused tty
+ *	@tty: tty struct to free
+ *
+ *	Free the write buffers, tty queue and tty memory itself.
+ *
+ *	Locking: none. Must be called after tty is definitely unused
+ */
+
 static inline void free_tty_struct(struct tty_struct *tty)
 {
 	kfree(tty->write_buf);
@@ -175,6 +193,17 @@
 
 #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
 
+/**
+ *	tty_name	-	return tty naming
+ *	@tty: tty structure
+ *	@buf: buffer for output
+ *
+ *	Convert a tty structure into a name. The name reflects the kernel
+ *	naming policy and if udev is in use may not reflect user space
+ *
+ *	Locking: none
+ */
+
 char *tty_name(struct tty_struct *tty, char *buf)
 {
 	if (!tty) /* Hmm.  NULL pointer.  That's fun. */
@@ -235,6 +264,28 @@
  * Tty buffer allocation management
  */
 
+
+/**
+ *	tty_buffer_free_all		-	free buffers used by a tty
+ *	@tty: tty to free from
+ *
+ *	Remove all the buffers pending on a tty whether queued with data
+ *	or in the free ring. Must be called when the tty is no longer in use
+ *
+ *	Locking: none
+ */
+
+
+/**
+ *	tty_buffer_free_all		-	free buffers used by a tty
+ *	@tty: tty to free from
+ *
+ *	Remove all the buffers pending on a tty whether queued with data
+ *	or in the free ring. Must be called when the tty is no longer in use
+ *
+ *	Locking: none
+ */
+
 static void tty_buffer_free_all(struct tty_struct *tty)
 {
 	struct tty_buffer *thead;
@@ -247,19 +298,47 @@
 		kfree(thead);
 	}
 	tty->buf.tail = NULL;
+	tty->buf.memory_used = 0;
 }
 
+/**
+ *	tty_buffer_init		-	prepare a tty buffer structure
+ *	@tty: tty to initialise
+ *
+ *	Set up the initial state of the buffer management for a tty device.
+ *	Must be called before the other tty buffer functions are used.
+ *
+ *	Locking: none
+ */
+
 static void tty_buffer_init(struct tty_struct *tty)
 {
 	spin_lock_init(&tty->buf.lock);
 	tty->buf.head = NULL;
 	tty->buf.tail = NULL;
 	tty->buf.free = NULL;
+	tty->buf.memory_used = 0;
 }
 
-static struct tty_buffer *tty_buffer_alloc(size_t size)
+/**
+ *	tty_buffer_alloc	-	allocate a tty buffer
+ *	@tty: tty device
+ *	@size: desired size (characters)
+ *
+ *	Allocate a new tty buffer to hold the desired number of characters.
+ *	Return NULL if out of memory or the allocation would exceed the
+ *	per device queue
+ *
+ *	Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
 {
-	struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+	struct tty_buffer *p;
+
+	if (tty->buf.memory_used + size > 65536)
+		return NULL;
+	p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
 	if(p == NULL)
 		return NULL;
 	p->used = 0;
@@ -269,17 +348,27 @@
 	p->read = 0;
 	p->char_buf_ptr = (char *)(p->data);
 	p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-/* 	printk("Flip create %p\n", p); */
+	tty->buf.memory_used += size;
 	return p;
 }
 
-/* Must be called with the tty_read lock held. This needs to acquire strategy
-   code to decide if we should kfree or relink a given expired buffer */
+/**
+ *	tty_buffer_free		-	free a tty buffer
+ *	@tty: tty owning the buffer
+ *	@b: the buffer to free
+ *
+ *	Free a tty buffer, or add it to the free list according to our
+ *	internal strategy
+ *
+ *	Locking: Caller must hold tty->buf.lock
+ */
 
 static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
 {
 	/* Dumb strategy for now - should keep some stats */
-/* 	printk("Flip dispose %p\n", b); */
+	tty->buf.memory_used -= b->size;
+	WARN_ON(tty->buf.memory_used < 0);
+
 	if(b->size >= 512)
 		kfree(b);
 	else {
@@ -288,6 +377,18 @@
 	}
 }
 
+/**
+ *	tty_buffer_find		-	find a free tty buffer
+ *	@tty: tty owning the buffer
+ *	@size: characters wanted
+ *
+ *	Locate an existing suitable tty buffer or if we are lacking one then
+ *	allocate a new one. We round our buffers off in 256 character chunks
+ *	to get better allocation behaviour.
+ *
+ *	Locking: Caller must hold tty->buf.lock
+ */
+
 static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
 {
 	struct tty_buffer **tbh = &tty->buf.free;
@@ -299,20 +400,28 @@
 			t->used = 0;
 			t->commit = 0;
 			t->read = 0;
-			/* DEBUG ONLY */
-/*			memset(t->data, '*', size); */
-/* 			printk("Flip recycle %p\n", t); */
+			tty->buf.memory_used += t->size;
 			return t;
 		}
 		tbh = &((*tbh)->next);
 	}
 	/* Round the buffer size out */
 	size = (size + 0xFF) & ~ 0xFF;
-	return tty_buffer_alloc(size);
+	return tty_buffer_alloc(tty, size);
 	/* Should possibly check if this fails for the largest buffer we
 	   have queued and recycle that ? */
 }
 
+/**
+ *	tty_buffer_request_room		-	grow tty buffer if needed
+ *	@tty: tty structure
+ *	@size: size desired
+ *
+ *	Make at least size bytes of linear space available for the tty
+ *	buffer. If we fail return the size we managed to find.
+ *
+ *	Locking: Takes tty->buf.lock
+ */
 int tty_buffer_request_room(struct tty_struct *tty, size_t size)
 {
 	struct tty_buffer *b, *n;
@@ -347,6 +456,18 @@
 }
 EXPORT_SYMBOL_GPL(tty_buffer_request_room);
 
+/**
+ *	tty_insert_flip_string	-	Add characters to the tty buffer
+ *	@tty: tty structure
+ *	@chars: characters
+ *	@size: size
+ *
+ *	Queue a series of bytes to the tty buffering. All the characters
+ *	passed are marked as without error. Returns the number added.
+ *
+ *	Locking: Called functions may take tty->buf.lock
+ */
+
 int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
 				size_t size)
 {
@@ -370,6 +491,20 @@
 }
 EXPORT_SYMBOL(tty_insert_flip_string);
 
+/**
+ *	tty_insert_flip_string_flags	-	Add characters to the tty buffer
+ *	@tty: tty structure
+ *	@chars: characters
+ *	@flags: flag bytes
+ *	@size: size
+ *
+ *	Queue a series of bytes to the tty buffering. For each character
+ *	the flags array indicates the status of the character. Returns the
+ *	number added.
+ *
+ *	Locking: Called functions may take tty->buf.lock
+ */
+
 int tty_insert_flip_string_flags(struct tty_struct *tty,
 		const unsigned char *chars, const char *flags, size_t size)
 {
@@ -394,6 +529,17 @@
 }
 EXPORT_SYMBOL(tty_insert_flip_string_flags);
 
+/**
+ *	tty_schedule_flip	-	push characters to ldisc
+ *	@tty: tty to push from
+ *
+ *	Takes any pending buffers and transfers their ownership to the
+ *	ldisc side of the queue. It then schedules those characters for
+ *	processing by the line discipline.
+ *
+ *	Locking: Takes tty->buf.lock
+ */
+
 void tty_schedule_flip(struct tty_struct *tty)
 {
 	unsigned long flags;
@@ -405,12 +551,19 @@
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
-/*
+/**
+ *	tty_prepare_flip_string		-	make room for characters
+ *	@tty: tty
+ *	@chars: return pointer for character write area
+ *	@size: desired size
+ *
  *	Prepare a block of space in the buffer for data. Returns the length
  *	available and buffer pointer to the space which is now allocated and
  *	accounted for as ready for normal characters. This is used for drivers
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
+ *
+ *	Locking: May call functions taking tty->buf.lock
  */
 
 int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
@@ -427,12 +580,20 @@
 
 EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
 
-/*
+/**
+ *	tty_prepare_flip_string_flags	-	make room for characters
+ *	@tty: tty
+ *	@chars: return pointer for character write area
+ *	@flags: return pointer for status flag write area
+ *	@size: desired size
+ *
  *	Prepare a block of space in the buffer for data. Returns the length
  *	available and buffer pointer to the space which is now allocated and
  *	accounted for as ready for characters. This is used for drivers
  *	that need their own block copy routines into the buffer. There is no
  *	guarantee the buffer is a DMA target!
+ *
+ *	Locking: May call functions taking tty->buf.lock
  */
 
 int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
@@ -451,10 +612,16 @@
 
 
 
-/*
+/**
+ *	tty_set_termios_ldisc		-	set ldisc field
+ *	@tty: tty structure
+ *	@num: line discipline number
+ *
  *	This is probably overkill for real world processors but
  *	they are not on hot paths so a little discipline won't do 
  *	any harm.
+ *
+ *	Locking: takes termios_sem
  */
  
 static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -474,6 +641,19 @@
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table */
 
+/**
+ *	tty_register_ldisc	-	install a line discipline
+ *	@disc: ldisc number
+ *	@new_ldisc: pointer to the ldisc object
+ *
+ *	Installs a new line discipline into the kernel. The discipline
+ *	is set up as unreferenced and then made available to the kernel
+ *	from this point onwards.
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
 {
 	unsigned long flags;
@@ -493,6 +673,18 @@
 }
 EXPORT_SYMBOL(tty_register_ldisc);
 
+/**
+ *	tty_unregister_ldisc	-	unload a line discipline
+ *	@disc: ldisc number
+ *	@new_ldisc: pointer to the ldisc object
+ *
+ *	Remove a line discipline from the kernel providing it is not
+ *	currently in use.
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
 int tty_unregister_ldisc(int disc)
 {
 	unsigned long flags;
@@ -512,6 +704,19 @@
 }
 EXPORT_SYMBOL(tty_unregister_ldisc);
 
+/**
+ *	tty_ldisc_get		-	take a reference to an ldisc
+ *	@disc: ldisc number
+ *
+ *	Takes a reference to a line discipline. Deals with refcounts and
+ *	module locking counts. Returns NULL if the discipline is not available.
+ *	Returns a pointer to the discipline and bumps the ref count if it is
+ *	available
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
 struct tty_ldisc *tty_ldisc_get(int disc)
 {
 	unsigned long flags;
@@ -540,6 +745,17 @@
 
 EXPORT_SYMBOL_GPL(tty_ldisc_get);
 
+/**
+ *	tty_ldisc_put		-	drop ldisc reference
+ *	@disc: ldisc number
+ *
+ *	Drop a reference to a line discipline. Manage refcounts and
+ *	module usage counts
+ *
+ *	Locking:
+ *		takes tty_ldisc_lock to guard against ldisc races
+ */
+
 void tty_ldisc_put(int disc)
 {
 	struct tty_ldisc *ld;
@@ -557,6 +773,19 @@
 	
 EXPORT_SYMBOL_GPL(tty_ldisc_put);
 
+/**
+ *	tty_ldisc_assign	-	set ldisc on a tty
+ *	@tty: tty to assign
+ *	@ld: line discipline
+ *
+ *	Install an instance of a line discipline into a tty structure. The
+ *	ldisc must have a reference count above zero to ensure it remains/
+ *	The tty instance refcount starts at zero.
+ *
+ *	Locking:
+ *		Caller must hold references
+ */
+
 static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
 {
 	tty->ldisc = *ld;
@@ -571,6 +800,8 @@
  *	the tty ldisc. Return 0 on failure or 1 on success. This is
  *	used to implement both the waiting and non waiting versions
  *	of tty_ldisc_ref
+ *
+ *	Locking: takes tty_ldisc_lock
  */
 
 static int tty_ldisc_try(struct tty_struct *tty)
@@ -602,6 +833,8 @@
  *	must also be careful not to hold other locks that will deadlock
  *	against a discipline change, such as an existing ldisc reference
  *	(which we check for)
+ *
+ *	Locking: call functions take tty_ldisc_lock
  */
  
 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
@@ -622,6 +855,8 @@
  *	Dereference the line discipline for the terminal and take a 
  *	reference to it. If the line discipline is in flux then 
  *	return NULL. Can be called from IRQ and timer functions.
+ *
+ *	Locking: called functions take tty_ldisc_lock
  */
  
 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
@@ -639,6 +874,8 @@
  *
  *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
  *	be called in IRQ context.
+ *
+ *	Locking: takes tty_ldisc_lock
  */
  
 void tty_ldisc_deref(struct tty_ldisc *ld)
@@ -683,6 +920,9 @@
  *
  *	Set the discipline of a tty line. Must be called from a process
  *	context.
+ *
+ *	Locking: takes tty_ldisc_lock.
+ *		called functions take termios_sem
  */
  
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -846,9 +1086,17 @@
 	return retval;
 }
 
-/*
- * This routine returns a tty driver structure, given a device number
+/**
+ *	get_tty_driver		-	find device of a tty
+ *	@dev_t: device identifier
+ *	@index: returns the index of the tty
+ *
+ *	This routine returns a tty driver structure, given a device number
+ *	and also passes back the index number.
+ *
+ *	Locking: caller must hold tty_mutex
  */
+
 static struct tty_driver *get_tty_driver(dev_t device, int *index)
 {
 	struct tty_driver *p;
@@ -863,11 +1111,17 @@
 	return NULL;
 }
 
-/*
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU.  If the signal is blocked or
- * ignored, go ahead and perform the operation.  (POSIX 7.2)
+/**
+ *	tty_check_change	-	check for POSIX terminal changes
+ *	@tty: tty to check
+ *
+ *	If we try to write to, or set the state of, a terminal and we're
+ *	not in the foreground, send a SIGTTOU.  If the signal is blocked or
+ *	ignored, go ahead and perform the operation.  (POSIX 7.2)
+ *
+ *	Locking: none
  */
+
 int tty_check_change(struct tty_struct * tty)
 {
 	if (current->signal->tty != tty)
@@ -1005,10 +1259,27 @@
 
 EXPORT_SYMBOL_GPL(tty_ldisc_flush);
 	
-/*
- * This can be called by the "eventd" kernel thread.  That is process synchronous,
- * but doesn't hold any locks, so we need to make sure we have the appropriate
- * locks for what we're doing..
+/**
+ *	do_tty_hangup		-	actual handler for hangup events
+ *	@data: tty device
+ *
+ *	This can be called by the "eventd" kernel thread.  That is process
+ *	synchronous but doesn't hold any locks, so we need to make sure we
+ *	have the appropriate locks for what we're doing.
+ *
+ *	The hangup event clears any pending redirections onto the hung up
+ *	device. It ensures future writes will error and it does the needed
+ *	line discipline hangup and signal delivery. The tty object itself
+ *	remains intact.
+ *
+ *	Locking:
+ *		BKL
+ *		redirect lock for undoing redirection
+ *		file list lock for manipulating list of ttys
+ *		tty_ldisc_lock from called functions
+ *		termios_sem resetting termios data
+ *		tasklist_lock to walk task list for hangup event
+ *
  */
 static void do_tty_hangup(void *data)
 {
@@ -1133,6 +1404,14 @@
 		fput(f);
 }
 
+/**
+ *	tty_hangup		-	trigger a hangup event
+ *	@tty: tty to hangup
+ *
+ *	A carrier loss (virtual or otherwise) has occurred on this like
+ *	schedule a hangup sequence to run after this event.
+ */
+
 void tty_hangup(struct tty_struct * tty)
 {
 #ifdef TTY_DEBUG_HANGUP
@@ -1145,6 +1424,15 @@
 
 EXPORT_SYMBOL(tty_hangup);
 
+/**
+ *	tty_vhangup		-	process vhangup
+ *	@tty: tty to hangup
+ *
+ *	The user has asked via system call for the terminal to be hung up.
+ *	We do this synchronously so that when the syscall returns the process
+ *	is complete. That guarantee is neccessary for security reasons.
+ */
+
 void tty_vhangup(struct tty_struct * tty)
 {
 #ifdef TTY_DEBUG_HANGUP
@@ -1156,6 +1444,14 @@
 }
 EXPORT_SYMBOL(tty_vhangup);
 
+/**
+ *	tty_hung_up_p		-	was tty hung up
+ *	@filp: file pointer of tty
+ *
+ *	Return true if the tty has been subject to a vhangup or a carrier
+ *	loss
+ */
+
 int tty_hung_up_p(struct file * filp)
 {
 	return (filp->f_op == &hung_up_tty_fops);
@@ -1163,19 +1459,28 @@
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
-/*
- * This function is typically called only by the session leader, when
- * it wants to disassociate itself from its controlling tty.
+/**
+ *	disassociate_ctty	-	disconnect controlling tty
+ *	@on_exit: true if exiting so need to "hang up" the session
  *
- * It performs the following functions:
+ *	This function is typically called only by the session leader, when
+ *	it wants to disassociate itself from its controlling tty.
+ *
+ *	It performs the following functions:
  * 	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
  * 	(2)  Clears the tty from being controlling the session
  * 	(3)  Clears the controlling tty for all processes in the
  * 		session group.
  *
- * The argument on_exit is set to 1 if called when a process is
- * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *	The argument on_exit is set to 1 if called when a process is
+ *	exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *
+ *	Locking: tty_mutex is taken to protect current->signal->tty
+ *		BKL is taken for hysterical raisins
+ *		Tasklist lock is taken (under tty_mutex) to walk process
+ *		lists for the session.
  */
+
 void disassociate_ctty(int on_exit)
 {
 	struct tty_struct *tty;
@@ -1222,6 +1527,25 @@
 	unlock_kernel();
 }
 
+
+/**
+ *	stop_tty	-	propogate flow control
+ *	@tty: tty to stop
+ *
+ *	Perform flow control to the driver. For PTY/TTY pairs we
+ *	must also propogate the TIOCKPKT status. May be called
+ *	on an already stopped device and will not re-call the driver
+ *	method.
+ *
+ *	This functionality is used by both the line disciplines for
+ *	halting incoming flow and by the driver. It may therefore be
+ *	called from any context, may be under the tty atomic_write_lock
+ *	but not always.
+ *
+ *	Locking:
+ *		Broken. Relies on BKL which is unsafe here.
+ */
+
 void stop_tty(struct tty_struct *tty)
 {
 	if (tty->stopped)
@@ -1238,6 +1562,19 @@
 
 EXPORT_SYMBOL(stop_tty);
 
+/**
+ *	start_tty	-	propogate flow control
+ *	@tty: tty to start
+ *
+ *	Start a tty that has been stopped if at all possible. Perform
+ *	any neccessary wakeups and propogate the TIOCPKT status. If this
+ *	is the tty was previous stopped and is being started then the
+ *	driver start method is invoked and the line discipline woken.
+ *
+ *	Locking:
+ *		Broken. Relies on BKL which is unsafe here.
+ */
+
 void start_tty(struct tty_struct *tty)
 {
 	if (!tty->stopped || tty->flow_stopped)
@@ -1258,6 +1595,23 @@
 
 EXPORT_SYMBOL(start_tty);
 
+/**
+ *	tty_read	-	read method for tty device files
+ *	@file: pointer to tty file
+ *	@buf: user buffer
+ *	@count: size of user buffer
+ *	@ppos: unused
+ *
+ *	Perform the read system call function on this terminal device. Checks
+ *	for hung up devices before calling the line discipline method.
+ *
+ *	Locking:
+ *		Locks the line discipline internally while needed
+ *		For historical reasons the line discipline read method is
+ *	invoked under the BKL. This will go away in time so do not rely on it
+ *	in new code. Multiple read calls may be outstanding in parallel.
+ */
+
 static ssize_t tty_read(struct file * file, char __user * buf, size_t count, 
 			loff_t *ppos)
 {
@@ -1302,6 +1656,7 @@
 	ssize_t ret = 0, written = 0;
 	unsigned int chunk;
 	
+	/* FIXME: O_NDELAY ... */
 	if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
 		return -ERESTARTSYS;
 	}
@@ -1318,6 +1673,9 @@
 	 * layer has problems with bigger chunks. It will
 	 * claim to be able to handle more characters than
 	 * it actually does.
+	 *
+	 * FIXME: This can probably go away now except that 64K chunks
+	 * are too likely to fail unless switched to vmalloc...
 	 */
 	chunk = 2048;
 	if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
@@ -1375,6 +1733,24 @@
 }
 
 
+/**
+ *	tty_write		-	write method for tty device file
+ *	@file: tty file pointer
+ *	@buf: user data to write
+ *	@count: bytes to write
+ *	@ppos: unused
+ *
+ *	Write data to a tty device via the line discipline.
+ *
+ *	Locking:
+ *		Locks the line discipline as required
+ *		Writes to the tty driver are serialized by the atomic_write_lock
+ *	and are then processed in chunks to the device. The line discipline
+ *	write method will not be involked in parallel for each device
+ *		The line discipline write method is called under the big
+ *	kernel lock for historical reasons. New code should not rely on this.
+ */
+
 static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
 			 loff_t *ppos)
 {
@@ -1422,7 +1798,18 @@
 
 static char ptychar[] = "pqrstuvwxyzabcde";
 
-static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ *	pty_line_name	-	generate name for a pty
+ *	@driver: the tty driver in use
+ *	@index: the minor number
+ *	@p: output buffer of at least 6 bytes
+ *
+ *	Generate a name from a driver reference and write it to the output
+ *	buffer.
+ *
+ *	Locking: None
+ */
+static void pty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	int i = index + driver->name_base;
 	/* ->name is initialized to "ttyp", but "tty" is expected */
@@ -1431,24 +1818,53 @@
 			ptychar[i >> 4 & 0xf], i & 0xf);
 }
 
-static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ *	pty_line_name	-	generate name for a tty
+ *	@driver: the tty driver in use
+ *	@index: the minor number
+ *	@p: output buffer of at least 7 bytes
+ *
+ *	Generate a name from a driver reference and write it to the output
+ *	buffer.
+ *
+ *	Locking: None
+ */
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	sprintf(p, "%s%d", driver->name, index + driver->name_base);
 }
 
-/*
+/**
+ *	init_dev		-	initialise a tty device
+ *	@driver: tty driver we are opening a device on
+ *	@idx: device index
+ *	@tty: returned tty structure
+ *
+ *	Prepare a tty device. This may not be a "new" clean device but
+ *	could also be an active device. The pty drivers require special
+ *	handling because of this.
+ *
+ *	Locking:
+ *		The function is called under the tty_mutex, which
+ *	protects us from the tty struct or driver itself going away.
+ *
+ *	On exit the tty device has the line discipline attached and
+ *	a reference count of 1. If a pair was created for pty/tty use
+ *	and the other was a pty master then it too has a reference count of 1.
+ *
  * WSH 06/09/97: Rewritten to remove races and properly clean up after a
  * failed open.  The new code protects the open with a mutex, so it's
  * really quite straightforward.  The mutex locking can probably be
  * relaxed for the (most common) case of reopening a tty.
  */
+
 static int init_dev(struct tty_driver *driver, int idx,
 	struct tty_struct **ret_tty)
 {
 	struct tty_struct *tty, *o_tty;
 	struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
 	struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
-	int retval=0;
+	int retval = 0;
 
 	/* check whether we're reopening an existing tty */
 	if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -1662,10 +2078,20 @@
 	goto end_init;
 }
 
-/*
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots.
+/**
+ *	release_mem		-	release tty structure memory
+ *
+ *	Releases memory associated with a tty structure, and clears out the
+ *	driver table slots. This function is called when a device is no longer
+ *	in use. It also gets called when setup of a device fails.
+ *
+ *	Locking:
+ *		tty_mutex - sometimes only
+ *		takes the file list lock internally when working on the list
+ *	of ttys that the driver keeps.
+ *		FIXME: should we require tty_mutex is held here ??
  */
+
 static void release_mem(struct tty_struct *tty, int idx)
 {
 	struct tty_struct *o_tty;
@@ -2006,18 +2432,27 @@
 
 }
 
-/*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
+/**
+ *	tty_open		-	open a tty device
+ *	@inode: inode of device file
+ *	@filp: file pointer to tty
  *
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now.  - Ted 1/27/92)
+ *	tty_open and tty_release keep up the tty count that contains the
+ *	number of opens done on a tty. We cannot use the inode-count, as
+ *	different inodes might point to the same tty.
  *
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
+ *	Open-counting is needed for pty masters, as well as for keeping
+ *	track of serial lines: DTR is dropped when the last close happens.
+ *	(This is not done solely through tty->count, now.  - Ted 1/27/92)
+ *
+ *	The termios state of a pty is reset on first open so that
+ *	settings don't persist across reuse.
+ *
+ *	Locking: tty_mutex protects current->signal->tty, get_tty_driver and
+ *		init_dev work. tty->count should protect the rest.
+ *		task_lock is held to update task details for sessions
  */
+
 static int tty_open(struct inode * inode, struct file * filp)
 {
 	struct tty_struct *tty;
@@ -2132,6 +2567,18 @@
 }
 
 #ifdef CONFIG_UNIX98_PTYS
+/**
+ *	ptmx_open		-	open a unix 98 pty master
+ *	@inode: inode of device file
+ *	@filp: file pointer to tty
+ *
+ *	Allocate a unix98 pty master device from the ptmx driver.
+ *
+ *	Locking: tty_mutex protects theinit_dev work. tty->count should
+ 		protect the rest.
+ *		allocated_ptys_lock handles the list of free pty numbers
+ */
+
 static int ptmx_open(struct inode * inode, struct file * filp)
 {
 	struct tty_struct *tty;
@@ -2191,6 +2638,18 @@
 }
 #endif
 
+/**
+ *	tty_release		-	vfs callback for close
+ *	@inode: inode of tty
+ *	@filp: file pointer for handle to tty
+ *
+ *	Called the last time each file handle is closed that references
+ *	this tty. There may however be several such references.
+ *
+ *	Locking:
+ *		Takes bkl. See release_dev
+ */
+
 static int tty_release(struct inode * inode, struct file * filp)
 {
 	lock_kernel();
@@ -2199,7 +2658,18 @@
 	return 0;
 }
 
-/* No kernel lock held - fine */
+/**
+ *	tty_poll	-	check tty status
+ *	@filp: file being polled
+ *	@wait: poll wait structures to update
+ *
+ *	Call the line discipline polling method to obtain the poll
+ *	status of the device.
+ *
+ *	Locking: locks called line discipline but ldisc poll method
+ *	may be re-entered freely by other callers.
+ */
+
 static unsigned int tty_poll(struct file * filp, poll_table * wait)
 {
 	struct tty_struct * tty;
@@ -2243,6 +2713,21 @@
 	return 0;
 }
 
+/**
+ *	tiocsti			-	fake input character
+ *	@tty: tty to fake input into
+ *	@p: pointer to character
+ *
+ *	Fake input to a tty device. Does the neccessary locking and
+ *	input management.
+ *
+ *	FIXME: does not honour flow control ??
+ *
+ *	Locking:
+ *		Called functions take tty_ldisc_lock
+ *		current->signal->tty check is safe without locks
+ */
+
 static int tiocsti(struct tty_struct *tty, char __user *p)
 {
 	char ch, mbz = 0;
@@ -2258,6 +2743,18 @@
 	return 0;
 }
 
+/**
+ *	tiocgwinsz		-	implement window query ioctl
+ *	@tty; tty
+ *	@arg: user buffer for result
+ *
+ *	Copies the kernel idea of the window size into the user buffer. No
+ *	locking is done.
+ *
+ *	FIXME: Returning random values racing a window size set is wrong
+ *	should lock here against that
+ */
+
 static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
 {
 	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
@@ -2265,6 +2762,24 @@
 	return 0;
 }
 
+/**
+ *	tiocswinsz		-	implement window size set ioctl
+ *	@tty; tty
+ *	@arg: user buffer for result
+ *
+ *	Copies the user idea of the window size to the kernel. Traditionally
+ *	this is just advisory information but for the Linux console it
+ *	actually has driver level meaning and triggers a VC resize.
+ *
+ *	Locking:
+ *		The console_sem is used to ensure we do not try and resize
+ *	the console twice at once.
+ *	FIXME: Two racing size sets may leave the console and kernel
+ *		parameters disagreeing. Is this exploitable ?
+ *	FIXME: Random values racing a window size get is wrong
+ *	should lock here against that
+ */
+
 static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
 	struct winsize __user * arg)
 {
@@ -2294,6 +2809,15 @@
 	return 0;
 }
 
+/**
+ *	tioccons	-	allow admin to move logical console
+ *	@file: the file to become console
+ *
+ *	Allow the adminstrator to move the redirected console device
+ *
+ *	Locking: uses redirect_lock to guard the redirect information
+ */
+
 static int tioccons(struct file *file)
 {
 	if (!capable(CAP_SYS_ADMIN))
@@ -2319,6 +2843,17 @@
 	return 0;
 }
 
+/**
+ *	fionbio		-	non blocking ioctl
+ *	@file: file to set blocking value
+ *	@p: user parameter
+ *
+ *	Historical tty interfaces had a blocking control ioctl before
+ *	the generic functionality existed. This piece of history is preserved
+ *	in the expected tty API of posix OS's.
+ *
+ *	Locking: none, the open fle handle ensures it won't go away.
+ */
 
 static int fionbio(struct file *file, int __user *p)
 {
@@ -2334,6 +2869,23 @@
 	return 0;
 }
 
+/**
+ *	tiocsctty	-	set controlling tty
+ *	@tty: tty structure
+ *	@arg: user argument
+ *
+ *	This ioctl is used to manage job control. It permits a session
+ *	leader to set this tty as the controlling tty for the session.
+ *
+ *	Locking:
+ *		Takes tasklist lock internally to walk sessions
+ *		Takes task_lock() when updating signal->tty
+ *
+ *	FIXME: tty_mutex is needed to protect signal->tty references.
+ *	FIXME: why task_lock on the signal->tty reference ??
+ *
+ */
+
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
 	struct task_struct *p;
@@ -2374,6 +2926,18 @@
 	return 0;
 }
 
+/**
+ *	tiocgpgrp		-	get process group
+ *	@tty: tty passed by user
+ *	@real_tty: tty side of the tty pased by the user if a pty else the tty
+ *	@p: returned pid
+ *
+ *	Obtain the process group of the tty. If there is no process group
+ *	return an error.
+ *
+ *	Locking: none. Reference to ->signal->tty is safe.
+ */
+
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
 	/*
@@ -2385,6 +2949,20 @@
 	return put_user(real_tty->pgrp, p);
 }
 
+/**
+ *	tiocspgrp		-	attempt to set process group
+ *	@tty: tty passed by user
+ *	@real_tty: tty side device matching tty passed by user
+ *	@p: pid pointer
+ *
+ *	Set the process group of the tty to the session passed. Only
+ *	permitted where the tty session is our session.
+ *
+ *	Locking: None
+ *
+ *	FIXME: current->signal->tty referencing is unsafe.
+ */
+
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
 	pid_t pgrp;
@@ -2408,6 +2986,18 @@
 	return 0;
 }
 
+/**
+ *	tiocgsid		-	get session id
+ *	@tty: tty passed by user
+ *	@real_tty: tty side of the tty pased by the user if a pty else the tty
+ *	@p: pointer to returned session id
+ *
+ *	Obtain the session id of the tty. If there is no session
+ *	return an error.
+ *
+ *	Locking: none. Reference to ->signal->tty is safe.
+ */
+
 static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
 	/*
@@ -2421,6 +3011,16 @@
 	return put_user(real_tty->session, p);
 }
 
+/**
+ *	tiocsetd	-	set line discipline
+ *	@tty: tty device
+ *	@p: pointer to user data
+ *
+ *	Set the line discipline according to user request.
+ *
+ *	Locking: see tty_set_ldisc, this function is just a helper
+ */
+
 static int tiocsetd(struct tty_struct *tty, int __user *p)
 {
 	int ldisc;
@@ -2430,6 +3030,21 @@
 	return tty_set_ldisc(tty, ldisc);
 }
 
+/**
+ *	send_break	-	performed time break
+ *	@tty: device to break on
+ *	@duration: timeout in mS
+ *
+ *	Perform a timed break on hardware that lacks its own driver level
+ *	timed break functionality.
+ *
+ *	Locking:
+ *		None
+ *
+ *	FIXME:
+ *		What if two overlap
+ */
+
 static int send_break(struct tty_struct *tty, unsigned int duration)
 {
 	tty->driver->break_ctl(tty, -1);
@@ -2442,8 +3057,19 @@
 	return 0;
 }
 
-static int
-tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
+/**
+ *	tiocmget		-	get modem status
+ *	@tty: tty device
+ *	@file: user file pointer
+ *	@p: pointer to result
+ *
+ *	Obtain the modem status bits from the tty driver if the feature
+ *	is supported. Return -EINVAL if it is not available.
+ *
+ *	Locking: none (up to the driver)
+ */
+
+static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
 {
 	int retval = -EINVAL;
 
@@ -2456,8 +3082,20 @@
 	return retval;
 }
 
-static int
-tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
+/**
+ *	tiocmset		-	set modem status
+ *	@tty: tty device
+ *	@file: user file pointer
+ *	@cmd: command - clear bits, set bits or set all
+ *	@p: pointer to desired bits
+ *
+ *	Set the modem status bits from the tty driver if the feature
+ *	is supported. Return -EINVAL if it is not available.
+ *
+ *	Locking: none (up to the driver)
+ */
+
+static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
 	     unsigned __user *p)
 {
 	int retval = -EINVAL;
@@ -2573,6 +3211,7 @@
 			clear_bit(TTY_EXCLUSIVE, &tty->flags);
 			return 0;
 		case TIOCNOTTY:
+			/* FIXME: taks lock or tty_mutex ? */
 			if (current->signal->tty != tty)
 				return -ENOTTY;
 			if (current->signal->leader)
@@ -2753,9 +3392,16 @@
 
 EXPORT_SYMBOL(do_SAK);
 
-/*
- * This routine is called out of the software interrupt to flush data
- * from the buffer chain to the line discipline.
+/**
+ *	flush_to_ldisc
+ *	@private_: tty structure passed from work queue.
+ *
+ *	This routine is called out of the software interrupt to flush data
+ *	from the buffer chain to the line discipline.
+ *
+ *	Locking: holds tty->buf.lock to guard buffer list. Drops the lock
+ *	while invoking the line discipline receive_buf method. The
+ *	receive_buf method is single threaded for each tty instance.
  */
  
 static void flush_to_ldisc(void *private_)
@@ -2831,6 +3477,8 @@
  *	Convert termios baud rate data into a speed. This should be called
  *	with the termios lock held if this termios is a terminal termios
  *	structure. May change the termios data.
+ *
+ *	Locking: none
  */
  
 int tty_termios_baud_rate(struct termios *termios)
@@ -2859,6 +3507,8 @@
  *	Returns the baud rate as an integer for this terminal. The
  *	termios lock must be held by the caller and the terminal bit
  *	flags may be updated.
+ *
+ *	Locking: none
  */
  
 int tty_get_baud_rate(struct tty_struct *tty)
@@ -2888,6 +3538,8 @@
  *
  *	In the event of the queue being busy for flipping the work will be
  *	held off and retried later.
+ *
+ *	Locking: tty buffer lock. Driver locks in low latency mode.
  */
 
 void tty_flip_buffer_push(struct tty_struct *tty)
@@ -2907,9 +3559,16 @@
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
 
-/*
- * This subroutine initializes a tty structure.
+/**
+ *	initialize_tty_struct
+ *	@tty: tty to initialize
+ *
+ *	This subroutine initializes a tty structure that has been newly
+ *	allocated.
+ *
+ *	Locking: none - tty in question must not be exposed at this point
  */
+
 static void initialize_tty_struct(struct tty_struct *tty)
 {
 	memset(tty, 0, sizeof(struct tty_struct));
@@ -2935,6 +3594,7 @@
 /*
  * The default put_char routine if the driver did not define one.
  */
+
 static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	tty->driver->write(tty, &ch, 1);
@@ -2943,19 +3603,23 @@
 static struct class *tty_class;
 
 /**
- * tty_register_device - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- *	This field is optional, if there is no known struct device for this
- *	tty device it can be set to NULL safely.
+ *	tty_register_device - register a tty device
+ *	@driver: the tty driver that describes the tty device
+ *	@index: the index in the tty driver for this tty device
+ *	@device: a struct device that is associated with this tty device.
+ *		This field is optional, if there is no known struct device
+ *		for this tty device it can be set to NULL safely.
  *
- * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
+ *	Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
  *
- * This call is required to be made to register an individual tty device if
- * the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set.  If that
- * bit is not set, this function should not be called by a tty driver.
+ *	This call is required to be made to register an individual tty device
+ *	if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set.  If
+ *	that bit is not set, this function should not be called by a tty
+ *	driver.
+ *
+ *	Locking: ??
  */
+
 struct class_device *tty_register_device(struct tty_driver *driver,
 					 unsigned index, struct device *device)
 {
@@ -2977,13 +3641,16 @@
 }
 
 /**
- * tty_unregister_device - unregister a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
+ * 	tty_unregister_device - unregister a tty device
+ * 	@driver: the tty driver that describes the tty device
+ * 	@index: the index in the tty driver for this tty device
  *
- * If a tty device is registered with a call to tty_register_device() then
- * this function must be made when the tty device is gone.
+ * 	If a tty device is registered with a call to tty_register_device() then
+ *	this function must be called when the tty device is gone.
+ *
+ *	Locking: ??
  */
+
 void tty_unregister_device(struct tty_driver *driver, unsigned index)
 {
 	class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
@@ -3094,7 +3761,6 @@
 	driver->cdev.owner = driver->owner;
 	error = cdev_add(&driver->cdev, dev, driver->num);
 	if (error) {
-		cdev_del(&driver->cdev);
 		unregister_chrdev_region(dev, driver->num);
 		driver->ttys = NULL;
 		driver->termios = driver->termios_locked = NULL;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index f19cf9d..4ad47d3 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -36,6 +36,18 @@
 #define TERMIOS_WAIT	2
 #define TERMIOS_TERMIO	4
 
+
+/**
+ *	tty_wait_until_sent	-	wait for I/O to finish
+ *	@tty: tty we are waiting for
+ *	@timeout: how long we will wait
+ *
+ *	Wait for characters pending in a tty driver to hit the wire, or
+ *	for a timeout to occur (eg due to flow control)
+ *
+ *	Locking: none
+ */
+
 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -94,6 +106,18 @@
 			old->c_cc[i] : termios->c_cc[i];
 }
 
+/**
+ *	change_termios		-	update termios values
+ *	@tty: tty to update
+ *	@new_termios: desired new value
+ *
+ *	Perform updates to the termios values set on this terminal. There
+ *	is a bit of layering violation here with n_tty in terms of the
+ *	internal knowledge of this function.
+ *
+ *	Locking: termios_sem
+ */
+
 static void change_termios(struct tty_struct * tty, struct termios * new_termios)
 {
 	int canon_change;
@@ -155,6 +179,19 @@
 	up(&tty->termios_sem);
 }
 
+/**
+ *	set_termios		-	set termios values for a tty
+ *	@tty: terminal device
+ *	@arg: user data
+ *	@opt: option information
+ *
+ *	Helper function to prepare termios data and run neccessary other
+ *	functions before using change_termios to do the actual changes.
+ *
+ *	Locking:
+ *		Called functions take ldisc and termios_sem locks
+ */
+
 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
 {
 	struct termios tmp_termios;
@@ -284,6 +321,17 @@
 	}
 }
 
+/**
+ *	set_sgttyb		-	set legacy terminal values
+ *	@tty: tty structure
+ *	@sgttyb: pointer to old style terminal structure
+ *
+ *	Updates a terminal from the legacy BSD style terminal information
+ *	structure.
+ *
+ *	Locking: termios_sem
+ */
+
 static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 {
 	int retval;
@@ -369,9 +417,16 @@
 }
 #endif
 
-/*
- * Send a high priority character to the tty.
+/**
+ *	send_prio_char		-	send priority character
+ *
+ *	Send a high priority character to the tty even if stopped
+ *
+ *	Locking: none
+ *
+ *	FIXME: overlapping calls with start/stop tty lose state of tty
  */
+
 static void send_prio_char(struct tty_struct *tty, char ch)
 {
 	int	was_stopped = tty->stopped;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index eccffaf..a5628a8 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1011,6 +1011,8 @@
 		   return -EPERM;
 		vt_dont_switch = 0;
 		return 0;
+	case VT_GETHIFONTMASK:
+		return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index d53f664..fff89c2 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -45,7 +45,7 @@
 comment "Watchdog Device Drivers"
 	depends on WATCHDOG
 
-# Architecture Independant
+# Architecture Independent
 
 config SOFT_WATCHDOG
 	tristate "Software watchdog"
@@ -127,7 +127,7 @@
 	  enabled.
 
 	  The driver is limited by the speed of the system's PCLK
-	  signal, so with reasonbaly fast systems (PCLK around 50-66MHz)
+	  signal, so with reasonably fast systems (PCLK around 50-66MHz)
 	  then watchdog intervals of over approximately 20seconds are
 	  unavailable.
 
@@ -423,7 +423,7 @@
 	  is no way to know if writing to its IO address will corrupt
 	  your system or have any real effect.  The only way to be sure
 	  that this driver does what you want is to make sure you
-	  are runnning it on an EPX-C3 from Winsystems with the watchdog
+	  are running it on an EPX-C3 from Winsystems with the watchdog
 	  timer at IO address 0x1ee and 0x1ef.  It will write to both those
 	  IO ports.  Basically, the assumption is made that if you compile
 	  this driver into your kernel and/or load it as a module, that you
@@ -472,7 +472,7 @@
 	tristate "Indy/I2 Hardware Watchdog"
 	depends on WATCHDOG && SGI_IP22
 	help
-	  Hardwaredriver for the Indy's/I2's watchdog. This is a
+	  Hardware driver for the Indy's/I2's watchdog. This is a
 	  watchdog timer that will reboot the machine after a 60 second
 	  timer expired and no process has written to /dev/watchdog during
 	  that time.
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
index 1035be5..41fc6f8 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/char/watchdog/sbc8360.c
@@ -200,7 +200,7 @@
 static int wd_multiplier = 2;
 static int nowayout = WATCHDOG_NOWAYOUT;
 
-module_param(timeout, int, 27);
+module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout,
@@ -407,7 +407,7 @@
 MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
 MODULE_DESCRIPTION("SBC8360 watchdog driver");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("1.01");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 /* end of sbc8360.c */
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 498aa37..3ece692 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -51,6 +51,7 @@
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE];
+	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -58,7 +59,8 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_FORK;
 	ev->event_data.fork.parent_pid = task->real_parent->pid;
 	ev->event_data.fork.parent_tgid = task->real_parent->tgid;
@@ -76,6 +78,7 @@
 {
 	struct cn_msg *msg;
 	struct proc_event *ev;
+	struct timespec ts;
 	__u8 buffer[CN_PROC_MSG_SIZE];
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
@@ -84,7 +87,8 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ev->timestamp);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_EXEC;
 	ev->event_data.exec.process_pid = task->pid;
 	ev->event_data.exec.process_tgid = task->tgid;
@@ -100,6 +104,7 @@
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE];
+	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -118,7 +123,8 @@
 	} else
 	     	return;
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ev->timestamp);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	ev->timestamp_ns = timespec_to_ns(&ts);
 
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
@@ -131,6 +137,7 @@
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE];
+	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -138,7 +145,8 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	get_seq(&msg->seq, &ev->cpu);
-	ktime_get_ts(&ev->timestamp);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->what = PROC_EVENT_EXIT;
 	ev->event_data.exit.process_pid = task->pid;
 	ev->event_data.exit.process_tgid = task->tgid;
@@ -164,6 +172,7 @@
 	struct cn_msg *msg;
 	struct proc_event *ev;
 	__u8 buffer[CN_PROC_MSG_SIZE];
+	struct timespec ts;
 
 	if (atomic_read(&proc_event_num_listeners) < 1)
 		return;
@@ -171,7 +180,8 @@
 	msg = (struct cn_msg*)buffer;
 	ev = (struct proc_event*)msg->data;
 	msg->seq = rcvd_seq;
-	ktime_get_ts(&ev->timestamp);
+	ktime_get_ts(&ts); /* get high res monotonic timestamp */
+	ev->timestamp_ns = timespec_to_ns(&ts);
 	ev->cpu = -1;
 	ev->what = PROC_EVENT_NONE;
 	ev->event_data.ack.err = err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index bc1088d..b3df613 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -284,39 +284,69 @@
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
 
+static struct cpufreq_governor *__find_governor(const char *str_governor)
+{
+	struct cpufreq_governor *t;
+
+	list_for_each_entry(t, &cpufreq_governor_list, governor_list)
+		if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN))
+			return t;
+
+	return NULL;
+}
+
 /**
  * cpufreq_parse_governor - parse a governor string
  */
 static int cpufreq_parse_governor (char *str_governor, unsigned int *policy,
 				struct cpufreq_governor **governor)
 {
+	int err = -EINVAL;
+
 	if (!cpufreq_driver)
-		return -EINVAL;
+		goto out;
+
 	if (cpufreq_driver->setpolicy) {
 		if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_PERFORMANCE;
-			return 0;
+			err = 0;
 		} else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
 			*policy = CPUFREQ_POLICY_POWERSAVE;
-			return 0;
+			err = 0;
 		}
-		return -EINVAL;
-	} else {
+	} else if (cpufreq_driver->target) {
 		struct cpufreq_governor *t;
+
 		mutex_lock(&cpufreq_governor_mutex);
-		if (!cpufreq_driver || !cpufreq_driver->target)
-			goto out;
-		list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-			if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) {
-				*governor = t;
+
+		t = __find_governor(str_governor);
+
+		if (t == NULL) {
+			char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor);
+
+			if (name) {
+				int ret;
+
 				mutex_unlock(&cpufreq_governor_mutex);
-				return 0;
+				ret = request_module(name);
+				mutex_lock(&cpufreq_governor_mutex);
+
+				if (ret == 0)
+					t = __find_governor(str_governor);
 			}
+
+			kfree(name);
 		}
-out:
+
+		if (t != NULL) {
+			*governor = t;
+			err = 0;
+		}
+
 		mutex_unlock(&cpufreq_governor_mutex);
 	}
-	return -EINVAL;
+  out:
+	return err;
 }
 
 
@@ -1265,23 +1295,21 @@
 
 int cpufreq_register_governor(struct cpufreq_governor *governor)
 {
-	struct cpufreq_governor *t;
+	int err;
 
 	if (!governor)
 		return -EINVAL;
 
 	mutex_lock(&cpufreq_governor_mutex);
 
-	list_for_each_entry(t, &cpufreq_governor_list, governor_list) {
-		if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) {
-			mutex_unlock(&cpufreq_governor_mutex);
-			return -EBUSY;
-		}
+	err = -EBUSY;
+	if (__find_governor(governor->name) == NULL) {
+		err = 0;
+		list_add(&governor->governor_list, &cpufreq_governor_list);
 	}
-	list_add(&governor->governor_list, &cpufreq_governor_list);
 
 	mutex_unlock(&cpufreq_governor_mutex);
-	return 0;
+	return err;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_governor);
 
@@ -1343,6 +1371,11 @@
 
 	memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo));
 
+	if (policy->min > data->min && policy->min > policy->max) {
+		ret = -EINVAL;
+		goto error_out;
+	}
+
 	/* verify the cpu speed can be set within this limit */
 	ret = cpufreq_driver->verify(policy);
 	if (ret)
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index bf6ab8a..a1cfd4e 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -29,6 +29,7 @@
 #include <linux/rcupdate.h>
 #include <linux/completion.h>
 #include <linux/kobject.h>
+#include <linux/platform_device.h>
 
 #define EDAC_MC_LABEL_LEN	31
 #define MC_PROC_NAME_MAX_LEN 7
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index cc15c4f..35ad1b0 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -26,6 +26,7 @@
 #include <linux/jiffies.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
@@ -64,17 +65,17 @@
 #define ABIT_UGURU_IN_SENSOR			0
 #define ABIT_UGURU_TEMP_SENSOR			1
 #define ABIT_UGURU_NC				2
-/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
-   convert them to params. */
-/* 250 was determined by trial and error, 200 works most of the time, but not
-   always. I assume this is cpu-speed independent, since the ISA-bus and not
-   the CPU should be the bottleneck. Note that 250 sometimes is still not
-   enough (only reported on AN7 mb) this is handled by a higher layer. */
-#define ABIT_UGURU_WAIT_TIMEOUT			250
+/* In many cases we need to wait for the uGuru to reach a certain status, most
+   of the time it will reach this status within 30 - 90 ISA reads, and thus we
+   can best busy wait. This define gives the total amount of reads to try. */
+#define ABIT_UGURU_WAIT_TIMEOUT			125
+/* However sometimes older versions of the uGuru seem to be distracted and they
+   do not respond for a long time. To handle this we sleep before each of the
+   last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */
+#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP		5
 /* Normally all expected status in abituguru_ready, are reported after the
-   first read, but sometimes not and we need to poll, 5 polls was not enough
-   50 sofar is. */
-#define ABIT_UGURU_READY_TIMEOUT		50
+   first read, but sometimes not and we need to poll. */
+#define ABIT_UGURU_READY_TIMEOUT		5
 /* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
 #define ABIT_UGURU_MAX_RETRIES			3
 #define ABIT_UGURU_RETRY_DELAY			(HZ/5)
@@ -226,6 +227,10 @@
 		timeout--;
 		if (timeout == 0)
 			return -EBUSY;
+		/* sleep a bit before our last few tries, see the comment on
+		   this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */
+		if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP)
+			msleep(0);
 	}
 	return 0;
 }
@@ -256,6 +261,7 @@
 			   "CMD reg does not hold 0xAC after ready command\n");
 			return -EIO;
 		}
+		msleep(0);
 	}
 
 	/* After this the ABIT_UGURU_DATA port should contain
@@ -268,6 +274,7 @@
 				"state != more input after ready command\n");
 			return -EIO;
 		}
+		msleep(0);
 	}
 
 	data->uguru_ready = 1;
@@ -331,7 +338,8 @@
 	/* And read the data */
 	for (i = 0; i < count; i++) {
 		if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
-			ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+			ABIT_UGURU_DEBUG(retries ? 1 : 3,
+				"timeout exceeded waiting for "
 				"read state (bank: %d, sensor: %d)\n",
 				(int)bank_addr, (int)sensor_addr);
 			break;
@@ -350,7 +358,9 @@
 static int abituguru_write(struct abituguru_data *data,
 	u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
 {
-	int i;
+	/* We use the ready timeout as we have to wait for 0xAC just like the
+	   ready function */
+	int i, timeout = ABIT_UGURU_READY_TIMEOUT;
 
 	/* Send the address */
 	i = abituguru_send_address(data, bank_addr, sensor_addr,
@@ -370,7 +380,8 @@
 	}
 
 	/* Now we need to wait till the chip is ready to be read again,
-	   don't ask why */
+	   so that we can read 0xAC as confirmation that our write has
+	   succeeded. */
 	if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
 		ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state "
 			"after write (bank: %d, sensor: %d)\n", (int)bank_addr,
@@ -379,11 +390,15 @@
 	}
 
 	/* Cmd port MUST be read now and should contain 0xAC */
-	if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
-		ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write "
-			"(bank: %d, sensor: %d)\n", (int)bank_addr,
-			(int)sensor_addr);
-		return -EIO;
+	while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+		timeout--;
+		if (timeout == 0) {
+			ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after "
+				"write (bank: %d, sensor: %d)\n",
+				(int)bank_addr, (int)sensor_addr);
+			return -EIO;
+		}
+		msleep(0);
 	}
 
 	/* Last put the chip back in ready state */
@@ -403,7 +418,7 @@
 				   u8 sensor_addr)
 {
 	u8 val, buf[3];
-	int ret = ABIT_UGURU_NC;
+	int i, ret = -ENODEV; /* error is the most common used retval :| */
 
 	/* If overriden by the user return the user selected type */
 	if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR &&
@@ -439,7 +454,7 @@
 	buf[2] = 250;
 	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
 			buf, 3) != 3)
-		return -ENODEV;
+		goto abituguru_detect_bank1_sensor_type_exit;
 	/* Now we need 20 ms to give the uguru time to read the sensors
 	   and raise a voltage alarm */
 	set_current_state(TASK_UNINTERRUPTIBLE);
@@ -447,21 +462,16 @@
 	/* Check for alarm and check the alarm is a volt low alarm. */
 	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
 			ABIT_UGURU_MAX_RETRIES) != 3)
-		return -ENODEV;
+		goto abituguru_detect_bank1_sensor_type_exit;
 	if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
 		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
 				sensor_addr, buf, 3,
 				ABIT_UGURU_MAX_RETRIES) != 3)
-			return -ENODEV;
+			goto abituguru_detect_bank1_sensor_type_exit;
 		if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
-			/* Restore original settings */
-			if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
-					sensor_addr,
-					data->bank1_settings[sensor_addr],
-					3) != 3)
-				return -ENODEV;
 			ABIT_UGURU_DEBUG(2, "  found volt sensor\n");
-			return ABIT_UGURU_IN_SENSOR;
+			ret = ABIT_UGURU_IN_SENSOR;
+			goto abituguru_detect_bank1_sensor_type_exit;
 		} else
 			ABIT_UGURU_DEBUG(2, "  alarm raised during volt "
 				"sensor test, but volt low flag not set\n");
@@ -477,7 +487,7 @@
 	buf[2] = 10;
 	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
 			buf, 3) != 3)
-		return -ENODEV;
+		goto abituguru_detect_bank1_sensor_type_exit;
 	/* Now we need 50 ms to give the uguru time to read the sensors
 	   and raise a temp alarm */
 	set_current_state(TASK_UNINTERRUPTIBLE);
@@ -485,15 +495,16 @@
 	/* Check for alarm and check the alarm is a temp high alarm. */
 	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
 			ABIT_UGURU_MAX_RETRIES) != 3)
-		return -ENODEV;
+		goto abituguru_detect_bank1_sensor_type_exit;
 	if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
 		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
 				sensor_addr, buf, 3,
 				ABIT_UGURU_MAX_RETRIES) != 3)
-			return -ENODEV;
+			goto abituguru_detect_bank1_sensor_type_exit;
 		if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) {
-			ret = ABIT_UGURU_TEMP_SENSOR;
 			ABIT_UGURU_DEBUG(2, "  found temp sensor\n");
+			ret = ABIT_UGURU_TEMP_SENSOR;
+			goto abituguru_detect_bank1_sensor_type_exit;
 		} else
 			ABIT_UGURU_DEBUG(2, "  alarm raised during temp "
 				"sensor test, but temp high flag not set\n");
@@ -501,11 +512,23 @@
 		ABIT_UGURU_DEBUG(2, "  alarm not raised during temp sensor "
 			"test\n");
 
-	/* Restore original settings */
-	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
-			data->bank1_settings[sensor_addr], 3) != 3)
+	ret = ABIT_UGURU_NC;
+abituguru_detect_bank1_sensor_type_exit:
+	/* Restore original settings, failing here is really BAD, it has been
+	   reported that some BIOS-es hang when entering the uGuru menu with
+	   invalid settings present in the uGuru, so we try this 3 times. */
+	for (i = 0; i < 3; i++)
+		if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+				sensor_addr, data->bank1_settings[sensor_addr],
+				3) == 3)
+			break;
+	if (i == 3) {
+		printk(KERN_ERR ABIT_UGURU_NAME
+			": Fatal error could not restore original settings. "
+			"This should never happen please report this to the "
+			"abituguru maintainer (see MAINTAINERS)\n");
 		return -ENODEV;
-
+	}
 	return ret;
 }
 
@@ -1305,7 +1328,7 @@
 		data->update_timeouts = 0;
 LEAVE_UPDATE:
 		/* handle timeout condition */
-		if (err == -EBUSY) {
+		if (!success && (err == -EBUSY || err >= 0)) {
 			/* No overflow please */
 			if (data->update_timeouts < 255u)
 				data->update_timeouts++;
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index ced309f..eae9e81 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -232,7 +232,7 @@
 	unsigned long timeout;
 
 	timeout = jiffies + POLL_TIMEOUT;
-	while (time_before(jiffies, timeout)) {
+	while (1) {
 		status = inb(ACBST);
 
 		/* Reset the status register to avoid the hang */
@@ -242,7 +242,10 @@
 			scx200_acb_machine(iface, status);
 			return;
 		}
-		yield();
+		if (time_after(jiffies, timeout))
+			break;
+		cpu_relax();
+		cond_resched();
 	}
 
 	dev_err(&iface->adapter.dev, "timeout in state %s\n",
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
index e7e2704..0be6fd6 100644
--- a/drivers/i2c/chips/tps65010.c
+++ b/drivers/i2c/chips/tps65010.c
@@ -43,13 +43,12 @@
 /*-------------------------------------------------------------------------*/
 
 #define	DRIVER_VERSION	"2 May 2005"
-#define	DRIVER_NAME	(tps65010_driver.name)
+#define	DRIVER_NAME	(tps65010_driver.driver.name)
 
 MODULE_DESCRIPTION("TPS6501x Power Management Driver");
 MODULE_LICENSE("GPL");
 
 static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
@@ -100,7 +99,7 @@
 	/* not currently tracking GPIO state */
 };
 
-#define	POWER_POLL_DELAY	msecs_to_jiffies(800)
+#define	POWER_POLL_DELAY	msecs_to_jiffies(5000)
 
 /*-------------------------------------------------------------------------*/
 
@@ -520,8 +519,11 @@
 		goto fail1;
 	}
 
+	/* the IRQ is active low, but many gpio lines can't support that
+	 * so this driver can use falling-edge triggers instead.
+	 */
+	irqflags = IRQF_SAMPLE_RANDOM;
 #ifdef	CONFIG_ARM
-	irqflags = IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_LOW;
 	if (machine_is_omap_h2()) {
 		tps->model = TPS65010;
 		omap_cfg_reg(W4_GPIO58);
@@ -543,8 +545,6 @@
 
 		// FIXME set up this board's IRQ ...
 	}
-#else
-	irqflags = IRQF_SAMPLE_RANDOM;
 #endif
 
 	if (tps->irq > 0) {
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index d1266fe2..b6fb167 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -682,6 +682,7 @@
 config BLK_DEV_SGIIOC4
 	tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
 	depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
+	select IDEPCI_SHARE_IRQ
 	help
 	  This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
 	  chipset, which has one channel and can support two devices.
@@ -773,20 +774,6 @@
 	  to transfer data to and from memory.  Saying Y is safe and improves
 	  performance.
 
-config BLK_DEV_IDE_PMAC_BLINK
-	bool "Blink laptop LED on drive activity (DEPRECATED)"
-	depends on BLK_DEV_IDE_PMAC && ADB_PMU
-	select ADB_PMU_LED
-	select LEDS_TRIGGERS
-	select LEDS_TRIGGER_IDE_DISK
-	help
-	  This option enables the use of the sleep LED as a hard drive
-	  activity LED.
-	  This option is deprecated, it only selects ADB_PMU_LED and
-	  LEDS_TRIGGER_IDE_DISK and changes the code in the new led class
-	  device to default to the ide-disk trigger (which should be set
-	  from userspace via sysfs).
-
 config BLK_DEV_IDE_SWARM
 	tristate "IDE for Sibyte evaluation boards"
 	depends on SIBYTE_SB1xxx_SOC
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index f712e4c..7cf3eb0 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -776,7 +776,7 @@
 		 * not available so we don't need to recheck that.
 		 */
 		capacity = idedisk_capacity(drive);
-		barrier = ide_id_has_flush_cache(id) &&
+		barrier = ide_id_has_flush_cache(id) && !drive->noflush &&
 			(drive->addressing == 0 || capacity <= (1ULL << 28) ||
 			 ide_id_has_flush_cache_ext(id));
 
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 98918fb..7c3a13e 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -750,7 +750,7 @@
 			goto bug_dma_off;
 		printk(", DMA");
 	} else if (id->field_valid & 1) {
-		printk(", BUG");
+		goto bug_dma_off;
 	}
 	return;
 bug_dma_off:
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 6571652..77703ac 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -23,6 +23,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
+#include <linux/nmi.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -1243,6 +1244,7 @@
 		if (stat == 0xff)
 			return -ENODEV;
 		touch_softlockup_watchdog();
+		touch_nmi_watchdog();
 	}
 	return -EBUSY;
 }
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index c12f1b7..41b74b1 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -376,6 +376,8 @@
 				break;
 		case ide_floppy:media = "floppy\n";
 				break;
+		case ide_optical:media = "optical\n";
+				break;
 		default:	media = "UNKNOWN\n";
 				break;
 	}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 05fbd92..defd4b4 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1539,7 +1539,7 @@
 		const char *hd_words[] = {
 			"none", "noprobe", "nowerr", "cdrom", "serialize",
 			"autotune", "noautotune", "minus8", "swapdata", "bswap",
-			"minus11", "remap", "remap63", "scsi", NULL };
+			"noflush", "remap", "remap63", "scsi", NULL };
 		unit = s[2] - 'a';
 		hw   = unit / MAX_DRIVES;
 		unit = unit % MAX_DRIVES;
@@ -1578,6 +1578,9 @@
 			case -10: /* "bswap" */
 				drive->bswap = 1;
 				goto done;
+			case -11: /* noflush */
+				drive->noflush = 1;
+				goto done;
 			case -12: /* "remap" */
 				drive->remap_0_to_1 = 1;
 				goto done;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index a7c725f..f286079 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -425,12 +425,12 @@
 	return d->init_setup(dev, d);
 }
 
-static const struct pci_device_id aec62xx_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 },
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 },
+static struct pci_device_id aec62xx_pci_tbl[] = {
+	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 2f962cf..78810ba 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -180,6 +180,36 @@
 		.channels	= 2,
 		.autodma	= AUTODMA,
 		.bootable	= OFF_BOARD,
+	},{	/* 15 */
+		.name		= "JMB361",
+		.init_hwif	= init_hwif_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= OFF_BOARD,
+	},{	/* 16 */
+		.name		= "JMB363",
+		.init_hwif	= init_hwif_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= OFF_BOARD,
+	},{	/* 17 */
+		.name		= "JMB365",
+		.init_hwif	= init_hwif_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= OFF_BOARD,
+	},{	/* 18 */
+		.name		= "JMB366",
+		.init_hwif	= init_hwif_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= OFF_BOARD,
+	},{	/* 19 */
+		.name		= "JMB368",
+		.init_hwif	= init_hwif_generic,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.bootable	= OFF_BOARD,
 	}
 };
 
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 3cb0442..e9bad18 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -498,9 +498,14 @@
 {
 	u8 speed	= ide_dma_speed(drive, it821x_ratemask(drive));
 
-	config_it821x_chipset_for_pio(drive, !speed);
-	it821x_tune_chipset(drive, speed);
-	return ide_dma_enable(drive);
+	if (speed) {
+		config_it821x_chipset_for_pio(drive, 0);
+		it821x_tune_chipset(drive, speed);
+
+		return ide_dma_enable(drive);
+	}
+
+	return 0;
 }
 
 /**
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 03677bf..f063d95 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -649,11 +649,11 @@
 }
 
 static struct pci_device_id svwks_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0},
-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1},
-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2},
-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3},
-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4},
+	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
+	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index e125032..d8a0d87 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -367,12 +367,13 @@
 static void __devinit
 ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
 {
+	void __iomem *virt_dma_base;
 	int num_ports = sizeof (ioc4_dma_regs_t);
 
 	printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
 	       dma_base, dma_base + num_ports - 1);
 
-	if (!request_region(dma_base, num_ports, hwif->name)) {
+	if (!request_mem_region(dma_base, num_ports, hwif->name)) {
 		printk(KERN_ERR
 		       "%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
 		       "ALREADY in use\n",
@@ -381,13 +382,21 @@
 		goto dma_alloc_failure;
 	}
 
-	hwif->dma_base = dma_base;
+	virt_dma_base = ioremap(dma_base, num_ports);
+	if (virt_dma_base == NULL) {
+		printk(KERN_ERR
+		       "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
+		       __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
+		goto dma_remap_failure;
+	}
+	hwif->dma_base = (unsigned long) virt_dma_base;
+
 	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
 					  IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
 					  &hwif->dmatable_dma);
 
 	if (!hwif->dmatable_cpu)
-		goto dma_alloc_failure;
+		goto dma_pci_alloc_failure;
 
 	hwif->sg_max_nents = IOC4_PRD_ENTRIES;
 
@@ -411,6 +420,12 @@
 	printk(KERN_INFO
 	       "Changing from DMA to PIO mode for Drive %s\n", hwif->name);
 
+dma_pci_alloc_failure:
+	iounmap(virt_dma_base);
+
+dma_remap_failure:
+	release_mem_region(dma_base, num_ports);
+
 dma_alloc_failure:
 	/* Disable DMA because we couldnot allocate any DMA maps */
 	hwif->autodma = 0;
@@ -607,18 +622,15 @@
 	hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &__ide_dma_timeout;
 
-	/*
-	 * The IOC4 uses MMIO rather than Port IO.
-	 * It also needs special workarounds for INB.
-	 */
-	default_hwif_mmiops(hwif);
 	hwif->INB = &sgiioc4_INB;
 }
 
 static int __devinit
 sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
 {
-	unsigned long base, ctl, dma_base, irqport;
+	unsigned long cmd_base, dma_base, irqport;
+	unsigned long bar0, cmd_phys_base, ctl;
+	void __iomem *virt_base;
 	ide_hwif_t *hwif;
 	int h;
 
@@ -636,23 +648,32 @@
 	}
 
 	/*  Get the CmdBlk and CtrlBlk Base Registers */
-	base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
-	ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
-	irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
+	bar0 = pci_resource_start(dev, 0);
+	virt_base = ioremap(bar0, pci_resource_len(dev, 0));
+	if (virt_base == NULL) {
+		printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
+			d->name, bar0);
+		return -ENOMEM;
+	}
+	cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
+	ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
+	irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
 	dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;
 
-	if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
+	cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
+	if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
+	    hwif->name)) {
 		printk(KERN_ERR
-			"%s : %s -- ERROR, Port Addresses "
+			"%s : %s -- ERROR, Addresses "
 			"0x%p to 0x%p ALREADY in use\n",
-		       __FUNCTION__, hwif->name, (void *) base,
-		       (void *) base + IOC4_CMD_CTL_BLK_SIZE);
+		       __FUNCTION__, hwif->name, (void *) cmd_phys_base,
+		       (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
 		return -ENOMEM;
 	}
 
-	if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
+	if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
 		/* Initialize the IO registers */
-		sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
+		sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
 		memcpy(hwif->io_ports, hwif->hw.io_ports,
 		       sizeof (hwif->io_ports));
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
@@ -665,6 +686,9 @@
 	hwif->cds = (struct ide_pci_device_s *) d;
 	hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
 
+	/* The IOC4 uses MMIO rather than Port IO. */
+	default_hwif_mmiops(hwif);
+
 	/* Initializing chipset IRQ Registers */
 	hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);
 
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 25ceb4a..20b3929 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -1082,10 +1082,10 @@
 }
 
 static struct pci_device_id siimage_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680), 0},
+	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112), 1},
-	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA), 2},
+	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
 #endif
 	{ 0, },
 };
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 8a6c23a..f03196c 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -86,6 +86,8 @@
 	u8 chipset_family;
 	u8 flags;
 } SiSHostChipInfo[] = {
+	{ "SiS968",	PCI_DEVICE_ID_SI_968,	ATA_133  },
+	{ "SiS966",	PCI_DEVICE_ID_SI_966,	ATA_133  },
 	{ "SiS965",	PCI_DEVICE_ID_SI_965,	ATA_133  },
 	{ "SiS745",	PCI_DEVICE_ID_SI_745,	ATA_100  },
 	{ "SiS735",	PCI_DEVICE_ID_SI_735,	ATA_100  },
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index afdaee3..9b7589e 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -6,7 +6,7 @@
  *
  *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
  *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a,
- *   vt8235, vt8237
+ *   vt8235, vt8237, vt8237a
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -81,6 +81,7 @@
 	{ "vt6410",	PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8251",	PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8237",	PCI_DEVICE_ID_VIA_8237,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+	{ "vt8237a",	PCI_DEVICE_ID_VIA_8237A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8235",	PCI_DEVICE_ID_VIA_8235,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8233a",	PCI_DEVICE_ID_VIA_8233A,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
 	{ "vt8233c",	PCI_DEVICE_ID_VIA_8233C_0,  0x00, 0x2f, VIA_UDMA_100 },
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index d4bad67..448df27 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -3552,6 +3552,8 @@
 
 static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 {
+	pci_save_state(pdev);
+
 #ifdef CONFIG_PPC_PMAC
 	if (machine_is(powermac)) {
 		struct device_node *of_node;
@@ -3563,8 +3565,6 @@
 	}
 #endif
 
-	pci_save_state(pdev);
-
 	return 0;
 }
 
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index aaa74f2..b08755e 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -2515,6 +2515,9 @@
 		sdev->skip_ms_page_8 = 1;
 	if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
 		sdev->fix_capacity = 1;
+	if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
+	    (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
+		sdev->allow_restart = 1;
 	return 0;
 }
 
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index d294bbc..1205e80 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -35,6 +35,7 @@
 #include <net/arp.h>
 #include <net/neighbour.h>
 #include <net/route.h>
+#include <net/netevent.h>
 #include <rdma/ib_addr.h>
 
 MODULE_AUTHOR("Sean Hefty");
@@ -326,25 +327,22 @@
 }
 EXPORT_SYMBOL(rdma_addr_cancel);
 
-static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev,
-			 struct packet_type *pkt, struct net_device *orig_dev)
+static int netevent_callback(struct notifier_block *self, unsigned long event, 
+	void *ctx)
 {
-	struct arphdr *arp_hdr;
+	if (event == NETEVENT_NEIGH_UPDATE) {  
+		struct neighbour *neigh = ctx;
 
-	arp_hdr = (struct arphdr *) skb->nh.raw;
-
-	if (arp_hdr->ar_op == htons(ARPOP_REQUEST) ||
-	    arp_hdr->ar_op == htons(ARPOP_REPLY))
-		set_timeout(jiffies);
-
-	kfree_skb(skb);
+		if (neigh->dev->type == ARPHRD_INFINIBAND &&
+		    (neigh->nud_state & NUD_VALID)) {
+			set_timeout(jiffies);
+		}
+	}
 	return 0;
 }
 
-static struct packet_type addr_arp = {
-	.type           = __constant_htons(ETH_P_ARP),
-	.func           = addr_arp_recv,
-	.af_packet_priv = (void*) 1,
+static struct notifier_block nb = {
+	.notifier_call = netevent_callback
 };
 
 static int addr_init(void)
@@ -353,13 +351,13 @@
 	if (!addr_wq)
 		return -ENOMEM;
 
-	dev_add_pack(&addr_arp);
+	register_netevent_notifier(&nb);
 	return 0;
 }
 
 static void addr_cleanup(void)
 {
-	dev_remove_pack(&addr_arp);
+	unregister_netevent_notifier(&nb);
 	destroy_workqueue(addr_wq);
 }
 
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index e05ca2c..75313ad 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -301,7 +301,8 @@
 	    event->event == IB_EVENT_PORT_ACTIVE ||
 	    event->event == IB_EVENT_LID_CHANGE  ||
 	    event->event == IB_EVENT_PKEY_CHANGE ||
-	    event->event == IB_EVENT_SM_CHANGE) {
+	    event->event == IB_EVENT_SM_CHANGE   ||
+	    event->event == IB_EVENT_CLIENT_REREGISTER) {
 		work = kmalloc(sizeof *work, GFP_ATOMIC);
 		if (work) {
 			INIT_WORK(&work->work, ib_cache_task, work);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index f85c97f..0de335b 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -975,8 +975,10 @@
 
 	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
 							    id.local_id);
-	if (IS_ERR(cm_id_priv->timewait_info))
+	if (IS_ERR(cm_id_priv->timewait_info)) {
+		ret = PTR_ERR(cm_id_priv->timewait_info);
 		goto out;
+	}
 
 	ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av);
 	if (ret)
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index aeda484..d6b8422 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -405,7 +405,8 @@
 	    event->event == IB_EVENT_PORT_ACTIVE ||
 	    event->event == IB_EVENT_LID_CHANGE  ||
 	    event->event == IB_EVENT_PKEY_CHANGE ||
-	    event->event == IB_EVENT_SM_CHANGE) {
+	    event->event == IB_EVENT_SM_CHANGE   ||
+	    event->event == IB_EVENT_CLIENT_REREGISTER) {
 		struct ib_sa_device *sa_dev;
 		sa_dev = container_of(handler, typeof(*sa_dev), event_handler);
 
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index bb9bee5..102a59c 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -42,6 +42,7 @@
 #include <linux/kref.h>
 #include <linux/idr.h>
 #include <linux/mutex.h>
+#include <linux/completion.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_user_verbs.h>
@@ -69,6 +70,7 @@
 
 struct ib_uverbs_device {
 	struct kref				ref;
+	struct completion			comp;
 	int					devnum;
 	struct cdev			       *dev;
 	struct class_device		       *class_dev;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index e725ccc..4e16314 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -122,7 +122,7 @@
 	struct ib_uverbs_device *dev =
 		container_of(ref, struct ib_uverbs_device, ref);
 
-	kfree(dev);
+	complete(&dev->comp);
 }
 
 void ib_uverbs_release_ucq(struct ib_uverbs_file *file,
@@ -740,6 +740,7 @@
 		return;
 
 	kref_init(&uverbs_dev->ref);
+	init_completion(&uverbs_dev->comp);
 
 	spin_lock(&map_lock);
 	uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -793,6 +794,8 @@
 
 err:
 	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+	wait_for_completion(&uverbs_dev->comp);
+	kfree(uverbs_dev);
 	return;
 }
 
@@ -812,7 +815,10 @@
 	spin_unlock(&map_lock);
 
 	clear_bit(uverbs_dev->devnum, dev_map);
+
 	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
+	wait_for_completion(&uverbs_dev->comp);
+	kfree(uverbs_dev);
 }
 
 static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index 9ba3211..f930e55 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -41,9 +41,11 @@
 /* Trivial bitmap-based allocator */
 u32 mthca_alloc(struct mthca_alloc *alloc)
 {
+	unsigned long flags;
 	u32 obj;
 
-	spin_lock(&alloc->lock);
+	spin_lock_irqsave(&alloc->lock, flags);
+
 	obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
 	if (obj >= alloc->max) {
 		alloc->top = (alloc->top + alloc->max) & alloc->mask;
@@ -56,19 +58,24 @@
 	} else
 		obj = -1;
 
-	spin_unlock(&alloc->lock);
+	spin_unlock_irqrestore(&alloc->lock, flags);
 
 	return obj;
 }
 
 void mthca_free(struct mthca_alloc *alloc, u32 obj)
 {
+	unsigned long flags;
+
 	obj &= alloc->max - 1;
-	spin_lock(&alloc->lock);
+
+	spin_lock_irqsave(&alloc->lock, flags);
+
 	clear_bit(obj, alloc->table);
 	alloc->last = min(alloc->last, obj);
 	alloc->top = (alloc->top + alloc->max) & alloc->mask;
-	spin_unlock(&alloc->lock);
+
+	spin_unlock_irqrestore(&alloc->lock, flags);
 }
 
 int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask,
@@ -108,14 +115,15 @@
  * serialize access to the array.
  */
 
+#define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1)
+
 void *mthca_array_get(struct mthca_array *array, int index)
 {
 	int p = (index * sizeof (void *)) >> PAGE_SHIFT;
 
-	if (array->page_list[p].page) {
-		int i = index & (PAGE_SIZE / sizeof (void *) - 1);
-		return array->page_list[p].page[i];
-	} else
+	if (array->page_list[p].page)
+		return array->page_list[p].page[index & MTHCA_ARRAY_MASK];
+	else
 		return NULL;
 }
 
@@ -130,8 +138,7 @@
 	if (!array->page_list[p].page)
 		return -ENOMEM;
 
-	array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] =
-		value;
+	array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value;
 	++array->page_list[p].used;
 
 	return 0;
@@ -144,7 +151,8 @@
 	if (--array->page_list[p].used == 0) {
 		free_page((unsigned long) array->page_list[p].page);
 		array->page_list[p].page = NULL;
-	}
+	} else
+		array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL;
 
 	if (array->page_list[p].used < 0)
 		pr_debug("Array %p index %d page %d with ref count %d < 0\n",
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 557cde3..7b82c19 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -967,12 +967,12 @@
 } mthca_hca_table[] = {
 	[TAVOR]        = { .latest_fw = MTHCA_FW_VER(3, 4, 0),
 			   .flags     = 0 },
-	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 400),
+	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 600),
 			   .flags     = MTHCA_FLAG_PCIE },
-	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0),
+	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 400),
 			   .flags     = MTHCA_FLAG_MEMFREE |
 					MTHCA_FLAG_PCIE },
-	[SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 0, 800),
+	[SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 1, 0),
 			   .flags     = MTHCA_FLAG_MEMFREE |
 					MTHCA_FLAG_PCIE    |
 					MTHCA_FLAG_SINAI_OPT }
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 230ae21..265b1d1 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1287,11 +1287,7 @@
 		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
 		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|
 		(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)	|
-		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST)	|
-		(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
-		(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+		(1ull << IB_USER_VERBS_CMD_DETACH_MCAST);
 	dev->ib_dev.node_type            = IB_NODE_CA;
 	dev->ib_dev.phys_port_cnt        = dev->limits.num_ports;
 	dev->ib_dev.dma_device           = &dev->pdev->dev;
@@ -1316,6 +1312,11 @@
 		dev->ib_dev.modify_srq           = mthca_modify_srq;
 		dev->ib_dev.query_srq            = mthca_query_srq;
 		dev->ib_dev.destroy_srq          = mthca_destroy_srq;
+		dev->ib_dev.uverbs_cmd_mask	|=
+			(1ull << IB_USER_VERBS_CMD_CREATE_SRQ)		|
+			(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ)		|
+			(1ull << IB_USER_VERBS_CMD_QUERY_SRQ)		|
+			(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
 
 		if (mthca_is_memfree(dev))
 			dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 8de2887..9a5bece 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -136,8 +136,8 @@
  * We have one global lock that protects dev->cq/qp_table.  Each
  * struct mthca_cq/qp also has its own lock.  An individual qp lock
  * may be taken inside of an individual cq lock.  Both cqs attached to
- * a qp may be locked, with the send cq locked first.  No other
- * nesting should be done.
+ * a qp may be locked, with the cq with the lower cqn locked first.
+ * No other nesting should be done.
  *
  * 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
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index cd8b672..2e8f6f3 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -99,6 +99,10 @@
 	MTHCA_QP_BIT_RSC = 1 <<  3
 };
 
+enum {
+	MTHCA_SEND_DOORBELL_FENCE = 1 << 5
+};
+
 struct mthca_qp_path {
 	__be32 port_pkey;
 	u8     rnr_retry;
@@ -1259,6 +1263,32 @@
 	return 0;
 }
 
+static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
+{
+	if (send_cq == recv_cq)
+		spin_lock_irq(&send_cq->lock);
+	else if (send_cq->cqn < recv_cq->cqn) {
+		spin_lock_irq(&send_cq->lock);
+		spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING);
+	} else {
+		spin_lock_irq(&recv_cq->lock);
+		spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING);
+	}
+}
+
+static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq)
+{
+	if (send_cq == recv_cq)
+		spin_unlock_irq(&send_cq->lock);
+	else if (send_cq->cqn < recv_cq->cqn) {
+		spin_unlock(&recv_cq->lock);
+		spin_unlock_irq(&send_cq->lock);
+	} else {
+		spin_unlock(&send_cq->lock);
+		spin_unlock_irq(&recv_cq->lock);
+	}
+}
+
 int mthca_alloc_sqp(struct mthca_dev *dev,
 		    struct mthca_pd *pd,
 		    struct mthca_cq *send_cq,
@@ -1311,17 +1341,13 @@
 	 * Lock CQs here, so that CQ polling code can do QP lookup
 	 * without taking a lock.
 	 */
-	spin_lock_irq(&send_cq->lock);
-	if (send_cq != recv_cq)
-		spin_lock(&recv_cq->lock);
+	mthca_lock_cqs(send_cq, recv_cq);
 
 	spin_lock(&dev->qp_table.lock);
 	mthca_array_clear(&dev->qp_table.qp, mqpn);
 	spin_unlock(&dev->qp_table.lock);
 
-	if (send_cq != recv_cq)
-		spin_unlock(&recv_cq->lock);
-	spin_unlock_irq(&send_cq->lock);
+	mthca_unlock_cqs(send_cq, recv_cq);
 
  err_out:
 	dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
@@ -1355,9 +1381,7 @@
 	 * Lock CQs here, so that CQ polling code can do QP lookup
 	 * without taking a lock.
 	 */
-	spin_lock_irq(&send_cq->lock);
-	if (send_cq != recv_cq)
-		spin_lock(&recv_cq->lock);
+	mthca_lock_cqs(send_cq, recv_cq);
 
 	spin_lock(&dev->qp_table.lock);
 	mthca_array_clear(&dev->qp_table.qp,
@@ -1365,9 +1389,7 @@
 	--qp->refcount;
 	spin_unlock(&dev->qp_table.lock);
 
-	if (send_cq != recv_cq)
-		spin_unlock(&recv_cq->lock);
-	spin_unlock_irq(&send_cq->lock);
+	mthca_unlock_cqs(send_cq, recv_cq);
 
 	wait_event(qp->wait, !get_qp_refcount(dev, qp));
 
@@ -1502,7 +1524,7 @@
 	int i;
 	int size;
 	int size0 = 0;
-	u32 f0 = 0;
+	u32 f0;
 	int ind;
 	u8 op0 = 0;
 
@@ -1686,6 +1708,8 @@
 		if (!size0) {
 			size0 = size;
 			op0   = mthca_opcode[wr->opcode];
+			f0    = wr->send_flags & IB_SEND_FENCE ?
+				MTHCA_SEND_DOORBELL_FENCE : 0;
 		}
 
 		++ind;
@@ -1843,7 +1867,7 @@
 	int i;
 	int size;
 	int size0 = 0;
-	u32 f0 = 0;
+	u32 f0;
 	int ind;
 	u8 op0 = 0;
 
@@ -2051,6 +2075,8 @@
 		if (!size0) {
 			size0 = size;
 			op0   = mthca_opcode[wr->opcode];
+			f0    = wr->send_flags & IB_SEND_FENCE ?
+				MTHCA_SEND_DOORBELL_FENCE : 0;
 		}
 
 		++ind;
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index 13d6d01..d74653d 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -6,8 +6,7 @@
 	  transports IP packets over InfiniBand so you can use your IB
 	  device as a fancy NIC.
 
-	  The IPoIB protocol is defined by the IETF ipoib working
-	  group: <http://www.ietf.org/html.charters/ipoib-charter.html>.
+	  See Documentation/infiniband/ipoib.txt for more information
 
 config INFINIBAND_IPOIB_DEBUG
 	bool "IP-over-InfiniBand debugging" if EMBEDDED
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 34b0da5..1437d7e 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -378,21 +378,6 @@
 	return iser_conn_set_full_featured_mode(conn);
 }
 
-static void
-iscsi_iser_conn_terminate(struct iscsi_conn *conn)
-{
-	struct iscsi_iser_conn *iser_conn = conn->dd_data;
-	struct iser_conn *ib_conn = iser_conn->ib_conn;
-
-	BUG_ON(!ib_conn);
-	/* starts conn teardown process, waits until all previously   *
-	 * posted buffers get flushed, deallocates all conn resources */
-	iser_conn_terminate(ib_conn);
-	iser_conn->ib_conn = NULL;
-	conn->recv_lock = NULL;
-}
-
-
 static struct iscsi_transport iscsi_iser_transport;
 
 static struct iscsi_cls_session *
@@ -555,13 +540,13 @@
 static void
 iscsi_iser_ep_disconnect(__u64 ep_handle)
 {
-	struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+	struct iser_conn *ib_conn;
 
+	ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
 	if (!ib_conn)
 		return;
 
 	iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
-
 	iser_conn_terminate(ib_conn);
 }
 
@@ -614,9 +599,6 @@
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn             = iscsi_iser_conn_start,
 	.stop_conn              = iscsi_conn_stop,
-	/* these are called as part of conn recovery */
-	.suspend_conn_recv	= NULL, /* FIXME is/how this relvant to iser? */
-	.terminate_conn		= iscsi_iser_conn_terminate,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
 	.get_stats		= iscsi_iser_conn_get_stats,
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 8f472e7..8257d5a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -77,6 +77,14 @@
 
 static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad };
 
+static int mellanox_workarounds = 1;
+
+module_param(mellanox_workarounds, int, 0444);
+MODULE_PARM_DESC(mellanox_workarounds,
+		 "Enable workarounds for Mellanox SRP target bugs if != 0");
+
+static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 };
+
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device);
 static void srp_completion(struct ib_cq *cq, void *target_ptr);
@@ -526,8 +534,10 @@
 	while (ib_poll_cq(target->cq, 1, &wc) > 0)
 		; /* nothing */
 
+	spin_lock_irq(target->scsi_host->host_lock);
 	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
 		srp_reset_req(target, req);
+	spin_unlock_irq(target->scsi_host->host_lock);
 
 	target->rx_head	 = 0;
 	target->tx_head	 = 0;
@@ -567,7 +577,7 @@
 	return ret;
 }
 
-static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
+static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
 		       int sg_cnt, struct srp_request *req,
 		       struct srp_direct_buf *buf)
 {
@@ -577,10 +587,15 @@
 	int page_cnt;
 	int i, j;
 	int ret;
+	struct srp_device *dev = target->srp_host->dev;
 
 	if (!dev->fmr_pool)
 		return -ENODEV;
 
+	if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) &&
+	    mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3))
+		return -EINVAL;
+
 	len = page_cnt = 0;
 	for (i = 0; i < sg_cnt; ++i) {
 		if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
@@ -683,7 +698,7 @@
 		buf->va  = cpu_to_be64(sg_dma_address(scat));
 		buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
 		buf->len = cpu_to_be32(sg_dma_len(scat));
-	} else if (srp_map_fmr(target->srp_host->dev, scat, count, req,
+	} else if (srp_map_fmr(target, scat, count, req,
 			       (void *) cmd->add_data)) {
 		/*
 		 * FMR mapping failed, and the scatterlist has more
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index a29d5ce..4bf4818 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -127,14 +127,10 @@
 {
 	struct evdev_list *list;
 	int i = iminor(inode) - EVDEV_MINOR_BASE;
-	int accept_err;
 
 	if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
 		return -ENODEV;
 
-	if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
-		return accept_err;
-
 	if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
 		return -ENOMEM;
 
@@ -260,7 +256,7 @@
 
 		if (evdev_event_from_user(buffer + retval, &event))
 			return -EFAULT;
-		input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+		input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
 		retval += evdev_event_size();
 	}
 
@@ -428,8 +424,8 @@
 			if (get_user(v, ip + 1))
 				return -EFAULT;
 
-			input_event(dev, EV_REP, REP_DELAY, u);
-			input_event(dev, EV_REP, REP_PERIOD, v);
+			input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+			input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
 
 			return 0;
 
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 47e93da..90de5af 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -106,10 +106,10 @@
 	gp->gameport = port;
 	gp->res_port = request_region(port->io, 0x10, "FM801 GP");
 	if (!gp->res_port) {
-		kfree(gp);
-		gameport_free_port(port);
 		printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
 			port->io, port->io + 0x0f);
+		gameport_free_port(port);
+		kfree(gp);
 		return -EBUSY;
 	}
 
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 36644bf..3f47ae5 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -53,6 +53,7 @@
 
 static struct bus_type gameport_bus;
 
+static void gameport_add_driver(struct gameport_driver *drv);
 static void gameport_add_port(struct gameport *gameport);
 static void gameport_destroy_port(struct gameport *gameport);
 static void gameport_reconnect_port(struct gameport *gameport);
@@ -211,8 +212,14 @@
 
 static void gameport_find_driver(struct gameport *gameport)
 {
+	int error;
+
 	down_write(&gameport_bus.subsys.rwsem);
-	device_attach(&gameport->dev);
+	error = device_attach(&gameport->dev);
+	if (error < 0)
+		printk(KERN_WARNING
+			"gameport: device_attach() failed for %s (%s), error: %d\n",
+			gameport->phys, gameport->name, error);
 	up_write(&gameport_bus.subsys.rwsem);
 }
 
@@ -316,7 +323,6 @@
 	spin_unlock_irqrestore(&gameport_event_lock, flags);
 }
 
-
 static struct gameport_event *gameport_get_event(void)
 {
 	struct gameport_event *event;
@@ -342,7 +348,6 @@
 static void gameport_handle_event(void)
 {
 	struct gameport_event *event;
-	struct gameport_driver *gameport_drv;
 
 	mutex_lock(&gameport_mutex);
 
@@ -369,8 +374,7 @@
 				break;
 
 			case GAMEPORT_REGISTER_DRIVER:
-				gameport_drv = event->object;
-				driver_register(&gameport_drv->driver);
+				gameport_add_driver(event->object);
 				break;
 
 			default:
@@ -532,6 +536,7 @@
 	if (gameport->parent)
 		gameport->dev.parent = &gameport->parent->dev;
 
+	INIT_LIST_HEAD(&gameport->node);
 	spin_lock_init(&gameport->timer_lock);
 	init_timer(&gameport->poll_timer);
 	gameport->poll_timer.function = gameport_run_poll_handler;
@@ -544,6 +549,8 @@
  */
 static void gameport_add_port(struct gameport *gameport)
 {
+	int error;
+
 	if (gameport->parent)
 		gameport->parent->child = gameport;
 
@@ -558,8 +565,13 @@
 		printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
 			gameport->name, gameport->phys, gameport->speed);
 
-	device_add(&gameport->dev);
-	gameport->registered = 1;
+	error = device_add(&gameport->dev);
+	if (error)
+		printk(KERN_ERR
+			"gameport: device_add() failed for %s (%s), error: %d\n",
+			gameport->phys, gameport->name, error);
+	else
+		gameport->registered = 1;
 }
 
 /*
@@ -583,10 +595,11 @@
 
 	if (gameport->registered) {
 		device_del(&gameport->dev);
-		list_del_init(&gameport->node);
 		gameport->registered = 0;
 	}
 
+	list_del_init(&gameport->node);
+
 	gameport_remove_pending_events(gameport);
 	put_device(&gameport->dev);
 }
@@ -704,11 +717,22 @@
 }
 
 static struct bus_type gameport_bus = {
-	.name =	"gameport",
-	.probe = gameport_driver_probe,
-	.remove = gameport_driver_remove,
+	.name	= "gameport",
+	.probe	= gameport_driver_probe,
+	.remove	= gameport_driver_remove,
 };
 
+static void gameport_add_driver(struct gameport_driver *drv)
+{
+	int error;
+
+	error = driver_register(&drv->driver);
+	if (error)
+		printk(KERN_ERR
+			"gameport: driver_register() failed for %s, error: %d\n",
+			drv->driver.name, error);
+}
+
 void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
 {
 	drv->driver.bus = &gameport_bus;
@@ -778,16 +802,24 @@
 
 static int __init gameport_init(void)
 {
-	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
-	if (IS_ERR(gameport_task)) {
-		printk(KERN_ERR "gameport: Failed to start kgameportd\n");
-		return PTR_ERR(gameport_task);
-	}
+	int error;
 
 	gameport_bus.dev_attrs = gameport_device_attrs;
 	gameport_bus.drv_attrs = gameport_driver_attrs;
 	gameport_bus.match = gameport_bus_match;
-	bus_register(&gameport_bus);
+	error = bus_register(&gameport_bus);
+	if (error) {
+		printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
+		return error;
+	}
+
+	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
+	if (IS_ERR(gameport_task)) {
+		bus_unregister(&gameport_bus);
+		error = PTR_ERR(gameport_task);
+		printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
+		return error;
+	}
 
 	return 0;
 }
diff --git a/drivers/input/input.c b/drivers/input/input.c
index a90486f..9cb4b9a 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -35,6 +35,16 @@
 
 static struct input_handler *input_table[8];
 
+/**
+ * input_event() - report new input event
+ * @handle: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct input_handle *handle;
@@ -183,6 +193,23 @@
 }
 EXPORT_SYMBOL(input_event);
 
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+	if (!handle->dev->grab || handle->dev->grab == handle)
+		input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
 static void input_repeat_key(unsigned long data)
 {
 	struct input_dev *dev = (void *) data;
@@ -197,15 +224,6 @@
 		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
 }
 
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
-	if (handle->dev->accept)
-		return handle->dev->accept(handle->dev, file);
-
-	return 0;
-}
-EXPORT_SYMBOL(input_accept_process);
-
 int input_grab_device(struct input_handle *handle)
 {
 	if (handle->dev->grab)
@@ -218,8 +236,15 @@
 
 void input_release_device(struct input_handle *handle)
 {
-	if (handle->dev->grab == handle)
-		handle->dev->grab = NULL;
+	struct input_dev *dev = handle->dev;
+
+	if (dev->grab == handle) {
+		dev->grab = NULL;
+
+		list_for_each_entry(handle, &dev->h_list, d_node)
+			if (handle->handler->start)
+				handle->handler->start(handle);
+	}
 }
 EXPORT_SYMBOL(input_release_device);
 
@@ -963,8 +988,11 @@
 	list_for_each_entry(handler, &input_handler_list, node)
 		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
 			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id)))
+				if ((handle = handler->connect(handler, dev, id))) {
 					input_link_handle(handle);
+					if (handler->start)
+						handler->start(handle);
+				}
 
 	input_wakeup_procfs_readers();
 
@@ -1028,8 +1056,11 @@
 	list_for_each_entry(dev, &input_dev_list, node)
 		if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
 			if ((id = input_match_device(handler->id_table, dev)))
-				if ((handle = handler->connect(handler, dev, id)))
+				if ((handle = handler->connect(handler, dev, id))) {
 					input_link_handle(handle);
+					if (handler->start)
+						handler->start(handle);
+				}
 
 	input_wakeup_procfs_readers();
 }
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 6d99e3c..b4914e7 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -79,6 +79,7 @@
 	{ 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",	btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel",	btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x06f8, 0x0004, "Gullemot Jet Leader 3D",			btn_joystick, abs_joystick, ff_iforce }, //?
+	{ 0x06d6, 0x29bc, "Trust Force Feedback Race Master",		btn_wheel, abs_wheel, ff_iforce },
 	{ 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]",		btn_joystick, abs_joystick, ff_iforce }
 };
 
@@ -222,22 +223,22 @@
 	int err = 0;
 	struct iforce_core_effect* core_effect;
 
-	/* Check who is trying to erase this effect */
-	if (iforce->core_effects[effect_id].owner != current->pid) {
-		printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
-		return -EACCES;
-	}
-
 	if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
 		return -EINVAL;
 
-	core_effect = iforce->core_effects + effect_id;
+	core_effect = &iforce->core_effects[effect_id];
+
+	/* Check who is trying to erase this effect */
+	if (core_effect->owner != current->pid) {
+		printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner);
+		return -EACCES;
+	}
 
 	if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
-		err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
+		err = release_resource(&core_effect->mod1_chunk);
 
 	if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
-		err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
+		err = release_resource(&core_effect->mod2_chunk);
 
 	/*TODO: remember to change that if more FF_MOD* bits are added */
 	core_effect->flags[0] = 0;
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index 75eb5ca..7a19ee0 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -50,7 +50,7 @@
  */
 
 #define SPACEBALL_MAX_LENGTH	128
-#define SPACEBALL_MAX_ID	8
+#define SPACEBALL_MAX_ID	9
 
 #define SPACEBALL_1003      1
 #define SPACEBALL_2003B     3
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ce1f10e..a86afd0 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -482,6 +482,55 @@
 	return IRQ_HANDLED;
 }
 
+static int atkbd_set_repeat_rate(struct atkbd *atkbd)
+{
+	const short period[32] =
+		{ 33,  37,  42,  46,  50,  54,  58,  63,  67,  75,  83,  92, 100, 109, 116, 125,
+		 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
+	const short delay[4] =
+		{ 250, 500, 750, 1000 };
+
+	struct input_dev *dev = atkbd->dev;
+	unsigned char param;
+	int i = 0, j = 0;
+
+	while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
+		i++;
+	dev->rep[REP_PERIOD] = period[i];
+
+	while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY])
+		j++;
+	dev->rep[REP_DELAY] = delay[j];
+
+	param = i | (j << 5);
+	return ps2_command(&atkbd->ps2dev, &param, ATKBD_CMD_SETREP);
+}
+
+static int atkbd_set_leds(struct atkbd *atkbd)
+{
+	struct input_dev *dev = atkbd->dev;
+	unsigned char param[2];
+
+	param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
+		 | (test_bit(LED_NUML,    dev->led) ? 2 : 0)
+		 | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
+	if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
+		return -1;
+
+	if (atkbd->extra) {
+		param[0] = 0;
+		param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
+			 | (test_bit(LED_SLEEP,   dev->led) ? 0x02 : 0)
+			 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
+			 | (test_bit(LED_MISC,    dev->led) ? 0x10 : 0)
+			 | (test_bit(LED_MUTE,    dev->led) ? 0x20 : 0);
+		if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS))
+			return -1;
+	}
+
+	return 0;
+}
+
 /*
  * atkbd_event_work() is used to complete processing of events that
  * can not be processed by input_event() which is often called from
@@ -490,47 +539,15 @@
 
 static void atkbd_event_work(void *data)
 {
-	const short period[32] =
-		{ 33,  37,  42,  46,  50,  54,  58,  63,  67,  75,  83,  92, 100, 109, 116, 125,
-		 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
-	const short delay[4] =
-		{ 250, 500, 750, 1000 };
-
 	struct atkbd *atkbd = data;
-	struct input_dev *dev = atkbd->dev;
-	unsigned char param[2];
-	int i, j;
 
 	mutex_lock(&atkbd->event_mutex);
 
-	if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) {
-		param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
-			 | (test_bit(LED_NUML,    dev->led) ? 2 : 0)
-			 | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
-		ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS);
+	if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+		atkbd_set_leds(atkbd);
 
-		if (atkbd->extra) {
-			param[0] = 0;
-			param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0)
-				 | (test_bit(LED_SLEEP,   dev->led) ? 0x02 : 0)
-				 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
-				 | (test_bit(LED_MISC,    dev->led) ? 0x10 : 0)
-				 | (test_bit(LED_MUTE,    dev->led) ? 0x20 : 0);
-			ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS);
-		}
-	}
-
-	if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) {
-		i = j = 0;
-		while (i < 31 && period[i] < dev->rep[REP_PERIOD])
-			i++;
-		while (j < 3 && delay[j] < dev->rep[REP_DELAY])
-			j++;
-		dev->rep[REP_PERIOD] = period[i];
-		dev->rep[REP_DELAY] = delay[j];
-		param[0] = i | (j << 5);
-		ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP);
-	}
+	if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+		atkbd_set_repeat_rate(atkbd);
 
 	mutex_unlock(&atkbd->event_mutex);
 }
@@ -975,7 +992,6 @@
 {
 	struct atkbd *atkbd = serio_get_drvdata(serio);
 	struct serio_driver *drv = serio->drv;
-	unsigned char param[1];
 
 	if (!atkbd || !drv) {
 		printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
@@ -985,10 +1001,6 @@
 	atkbd_disable(atkbd);
 
 	if (atkbd->write) {
-		param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0)
-		         | (test_bit(LED_NUML,    atkbd->dev->led) ? 2 : 0)
-		         | (test_bit(LED_CAPSL,   atkbd->dev->led) ? 4 : 0);
-
 		if (atkbd_probe(atkbd))
 			return -1;
 		if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
@@ -996,8 +1008,13 @@
 
 		atkbd_activate(atkbd);
 
-		if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS))
-			return -1;
+/*
+ * Restore repeat rate and LEDs (that were reset by atkbd_activate)
+ * to pre-resume state
+ */
+		if (!atkbd->softrepeat)
+			atkbd_set_repeat_rate(atkbd);
+		atkbd_set_leds(atkbd);
 	}
 
 	atkbd_enable(atkbd);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index ccf0fae..de0f46d 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -94,7 +94,7 @@
 
 static ssize_t __init locate_wistron_bios(void __iomem *base)
 {
-	static const unsigned char __initdata signature[] =
+	static unsigned char __initdata signature[] =
 		{ 0x42, 0x21, 0x55, 0x30 };
 	ssize_t offset;
 
@@ -343,7 +343,7 @@
  * a list of buttons and their key codes (reported when loading this module
  * with force=1) and the output of dmidecode to $MODULE_AUTHOR.
  */
-static struct dmi_system_id dmi_ids[] = {
+static struct dmi_system_id dmi_ids[] __initdata = {
 	{
 		.callback = dmi_matched,
 		.ident = "Fujitsu-Siemens Amilo Pro V2000",
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 2f0d288..54b696c 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -238,8 +238,7 @@
 		{ 100,	PS2PP_KIND_MX,					/* MX510 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
 				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
-		{ 111,  PS2PP_KIND_MX,					/* MX300 */
-				PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+		{ 111,  PS2PP_KIND_MX,	PS2PP_WHEEL | PS2PP_SIDE_BTN },	/* MX300 reports task button as side */
 		{ 112,	PS2PP_KIND_MX,					/* MX500 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
 				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 8bc9f51..343afa3 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -485,13 +485,6 @@
 	param[0] =  40;
 	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
 
-	param[0] = 200;
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
-	param[0] = 200;
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
-	param[0] =  60;
-	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
-
 	if (set_properties) {
 		set_bit(BTN_MIDDLE, psmouse->dev->keybit);
 		set_bit(REL_WHEEL, psmouse->dev->relbit);
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 6d9ec9a..ae5871a 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -183,21 +183,26 @@
 	.attrs = trackpoint_attrs,
 };
 
-static void trackpoint_disconnect(struct psmouse *psmouse)
+static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id)
 {
-	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+	unsigned char param[2] = { 0 };
 
-	kfree(psmouse->private);
-	psmouse->private = NULL;
+	if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
+		return -1;
+
+	if (param[0] != TP_MAGIC_IDENT)
+		return -1;
+
+	if (firmware_id)
+		*firmware_id = param[1];
+
+	return 0;
 }
 
 static int trackpoint_sync(struct psmouse *psmouse)
 {
-	unsigned char toggle;
 	struct trackpoint_data *tp = psmouse->private;
-
-	if (!tp)
-		return -1;
+	unsigned char toggle;
 
 	/* Disable features that may make device unusable with this driver */
 	trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle);
@@ -263,27 +268,38 @@
 	tp->ext_dev = TP_DEF_EXT_DEV;
 }
 
+static void trackpoint_disconnect(struct psmouse *psmouse)
+{
+	sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group);
+
+	kfree(psmouse->private);
+	psmouse->private = NULL;
+}
+
+static int trackpoint_reconnect(struct psmouse *psmouse)
+{
+	if (trackpoint_start_protocol(psmouse, NULL))
+		return -1;
+
+	if (trackpoint_sync(psmouse))
+		return -1;
+
+	return 0;
+}
+
 int trackpoint_detect(struct psmouse *psmouse, int set_properties)
 {
 	struct trackpoint_data *priv;
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
 	unsigned char firmware_id;
 	unsigned char button_info;
-	unsigned char param[2];
 
-	param[0] = param[1] = 0;
-
-	if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
-		return -1;
-
-	if (param[0] != TP_MAGIC_IDENT)
+	if (trackpoint_start_protocol(psmouse, &firmware_id))
 		return -1;
 
 	if (!set_properties)
 		return 0;
 
-	firmware_id = param[1];
-
 	if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
 		printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
 		button_info = 0;
@@ -296,7 +312,7 @@
 	psmouse->vendor = "IBM";
 	psmouse->name = "TrackPoint";
 
-	psmouse->reconnect = trackpoint_sync;
+	psmouse->reconnect = trackpoint_reconnect;
 	psmouse->disconnect = trackpoint_disconnect;
 
 	trackpoint_defaults(priv);
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 61a6f97..ed202f2 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -177,6 +177,11 @@
 		return -1;
 	}
 
+	if (send && !param) {
+		WARN_ON(1);
+		return -1;
+	}
+
 	mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING);
 
 	serio_pause_rx(ps2dev->serio);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 6521034..3e76ad7 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -62,6 +62,7 @@
 
 static struct bus_type serio_bus;
 
+static void serio_add_driver(struct serio_driver *drv);
 static void serio_add_port(struct serio *serio);
 static void serio_destroy_port(struct serio *serio);
 static void serio_reconnect_port(struct serio *serio);
@@ -140,8 +141,14 @@
 
 static void serio_find_driver(struct serio *serio)
 {
+	int error;
+
 	down_write(&serio_bus.subsys.rwsem);
-	device_attach(&serio->dev);
+	error = device_attach(&serio->dev);
+	if (error < 0)
+		printk(KERN_WARNING
+			"serio: device_attach() failed for %s (%s), error: %d\n",
+			serio->phys, serio->name, error);
 	up_write(&serio_bus.subsys.rwsem);
 }
 
@@ -272,7 +279,6 @@
 static void serio_handle_event(void)
 {
 	struct serio_event *event;
-	struct serio_driver *serio_drv;
 
 	mutex_lock(&serio_mutex);
 
@@ -304,8 +310,7 @@
 				break;
 
 			case SERIO_REGISTER_DRIVER:
-				serio_drv = event->object;
-				driver_register(&serio_drv->driver);
+				serio_add_driver(event->object);
 				break;
 
 			default:
@@ -525,6 +530,7 @@
 
 	__module_get(THIS_MODULE);
 
+	INIT_LIST_HEAD(&serio->node);
 	spin_lock_init(&serio->lock);
 	mutex_init(&serio->drv_mutex);
 	device_initialize(&serio->dev);
@@ -542,6 +548,8 @@
  */
 static void serio_add_port(struct serio *serio)
 {
+	int error;
+
 	if (serio->parent) {
 		serio_pause_rx(serio->parent);
 		serio->parent->child = serio;
@@ -551,9 +559,19 @@
 	list_add_tail(&serio->node, &serio_list);
 	if (serio->start)
 		serio->start(serio);
-	device_add(&serio->dev);
-	sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
-	serio->registered = 1;
+	error = device_add(&serio->dev);
+	if (error)
+		printk(KERN_ERR
+			"serio: device_add() failed for %s (%s), error: %d\n",
+			serio->phys, serio->name, error);
+	else {
+		serio->registered = 1;
+		error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
+		if (error)
+			printk(KERN_ERR
+				"serio: sysfs_create_group() failed for %s (%s), error: %d\n",
+				serio->phys, serio->name, error);
+	}
 }
 
 /*
@@ -583,10 +601,10 @@
 	if (serio->registered) {
 		sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
 		device_del(&serio->dev);
-		list_del_init(&serio->node);
 		serio->registered = 0;
 	}
 
+	list_del_init(&serio->node);
 	serio_remove_pending_events(serio);
 	put_device(&serio->dev);
 }
@@ -756,6 +774,17 @@
 	.remove = serio_driver_remove,
 };
 
+static void serio_add_driver(struct serio_driver *drv)
+{
+	int error;
+
+	error = driver_register(&drv->driver);
+	if (error)
+		printk(KERN_ERR
+			"serio: driver_register() failed for %s, error: %d\n",
+			drv->driver.name, error);
+}
+
 void __serio_register_driver(struct serio_driver *drv, struct module *owner)
 {
 	drv->driver.bus = &serio_bus;
@@ -903,18 +932,26 @@
 
 static int __init serio_init(void)
 {
-	serio_task = kthread_run(serio_thread, NULL, "kseriod");
-	if (IS_ERR(serio_task)) {
-		printk(KERN_ERR "serio: Failed to start kseriod\n");
-		return PTR_ERR(serio_task);
-	}
+	int error;
 
 	serio_bus.dev_attrs = serio_device_attrs;
 	serio_bus.drv_attrs = serio_driver_attrs;
 	serio_bus.match = serio_bus_match;
 	serio_bus.uevent = serio_uevent;
 	serio_bus.resume = serio_resume;
-	bus_register(&serio_bus);
+	error = bus_register(&serio_bus);
+	if (error) {
+		printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
+		return error;
+	}
+
+	serio_task = kthread_run(serio_thread, NULL, "kseriod");
+	if (IS_ERR(serio_task)) {
+		bus_unregister(&serio_bus);
+		error = PTR_ERR(serio_task);
+		printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
+		return error;
+	}
 
 	return 0;
 }
diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
index 0a5be7f..af3eb9e 100644
--- a/drivers/isdn/hardware/eicon/divasync.h
+++ b/drivers/isdn/hardware/eicon/divasync.h
@@ -256,7 +256,6 @@
 #define NO_ORDER_CHECK_MASK 0x00000010
 #define LOW_CHANNEL_MASK 0x00000020
 #define NO_HSCX30_MASK  0x00000040
-#define MODE_MASK   0x00000080
 #define SET_BOARD   0x00001000
 #define SET_CRC4   0x00030000
 #define SET_L1_TRISTATE  0x00040000
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
index a4f7288..3ef567b 100644
--- a/drivers/isdn/i4l/Kconfig
+++ b/drivers/isdn/i4l/Kconfig
@@ -5,6 +5,7 @@
 config ISDN_PPP
 	bool "Support synchronous PPP"
 	depends on INET
+	select SLHC
 	help
 	  Over digital connections such as ISDN, there is no need to
 	  synchronize sender and recipient's clocks with start and stop bits
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index f5fe7fb..d5d649f 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -90,6 +90,15 @@
 	  and the ide-disk LED trigger and configure appropriately through
 	  sysfs.
 
+config ADB_PMU_LED_IDE
+	bool "Use front LED as IDE LED by default"
+	depends on ADB_PMU_LED
+	select LEDS_TRIGGERS
+	select LEDS_TRIGGER_IDE_DISK
+	help
+	  This option makes the front LED default to the IDE trigger
+	  so that it blinks on IDE activity.
+
 config PMAC_SMU
 	bool "Support for SMU  based PowerMacs"
 	depends on PPC_PMAC64
@@ -100,7 +109,7 @@
 
 config PMAC_APM_EMU
 	tristate "APM emulation"
-	depends on PPC_PMAC && PPC32 && PM
+	depends on PPC_PMAC && PPC32 && PM && ADB_PMU
 
 config PMAC_MEDIABAY
 	bool "Support PowerBook hotswap media bay"
@@ -115,8 +124,6 @@
 	bool "Backlight control for LCD screens"
 	depends on ADB_PMU && FB = y && (BROKEN || !PPC64)
 	select FB_BACKLIGHT
-	select BACKLIGHT_CLASS_DEVICE
-	select BACKLIGHT_LCD_SUPPORT
 	help
 	  Say Y here to enable Macintosh specific extensions of the generic
 	  backlight code. With this enabled, the brightness keys on older
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 545be1e..c69d23b 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -45,14 +45,11 @@
 #include <linux/pmu.h>
 
 #include <asm/machdep.h>
+#include <asm/backlight.h>
 #ifdef CONFIG_PPC_PMAC
 #include <asm/pmac_feature.h>
 #endif
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
 MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");
 
 #define KEYB_KEYREG	0	/* register # for key up/down data */
@@ -237,11 +234,6 @@
 static struct adb_ids mouse_ids;
 static struct adb_ids buttons_ids;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-/* Exported to via-pmu.c */
-int disable_kernel_backlight = 0;
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 /* Kind of keyboard, see Apple technote 1152  */
 #define ADB_KEYBOARD_UNKNOWN	0
 #define ADB_KEYBOARD_ANSI	0x0100
@@ -527,7 +519,7 @@
 
 		case 0xa:	/* brightness decrease */
 #ifdef CONFIG_PMAC_BACKLIGHT
-			if (!disable_kernel_backlight && down)
+			if (down)
 				pmac_backlight_key_down();
 #endif
 			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
@@ -535,7 +527,7 @@
 
 		case 0x9:	/* brightness increase */
 #ifdef CONFIG_PMAC_BACKLIGHT
-			if (!disable_kernel_backlight && down)
+			if (down)
 				pmac_backlight_key_up();
 #endif
 			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index c1fe0b3..20bf672 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -95,6 +95,17 @@
  *	- Use min/max macros here or there
  *	- Latest darwin updated U3H min fan speed to 20% PWM
  *
+ *  July. 06, 2006 : 1.3
+ *	- Fix setting of RPM fans on Xserve G5 (they were going too fast)
+ *      - Add missing slots fan control loop for Xserve G5
+ *	- Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
+ *        still can't properly implement the control loop for these, so let's
+ *        reduce the noise a little bit, it appears that 40% still gives us
+ *        a pretty good air flow
+ *	- Add code to "tickle" the FCU regulary so it doesn't think that
+ *        we are gone while in fact, the machine just didn't need any fan
+ *        speed change lately
+ *
  */
 
 #include <linux/types.h>
@@ -121,7 +132,7 @@
 
 #include "therm_pm72.h"
 
-#define VERSION "1.2b2"
+#define VERSION "1.3"
 
 #undef DEBUG
 
@@ -146,6 +157,7 @@
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
 static struct dimm_pid_state		dimms_state;
+static struct slots_pid_state		slots_state;
 static int				state;
 static int				cpu_count;
 static int				cpu_pid_type;
@@ -154,7 +166,8 @@
 static int				critical_state;
 static int				rackmac;
 static s32				dimm_output_clamp;
-
+static int 				fcu_rpm_shift;
+static int				fcu_tickle_ticks;
 static DECLARE_MUTEX(driver_lock);
 
 /*
@@ -495,13 +508,20 @@
 	rc = fan_write_reg(0x2e, &buf, 1);
 	if (rc < 0)
 		return -EIO;
+	rc = fan_read_reg(0, &buf, 1);
+	if (rc < 0)
+		return -EIO;
+	fcu_rpm_shift = (buf == 1) ? 2 : 3;
+	printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
+	       fcu_rpm_shift);
+
 	return 0;
 }
 
 static int set_rpm_fan(int fan_index, int rpm)
 {
 	unsigned char buf[2];
-	int rc, id;
+	int rc, id, min, max;
 
 	if (fcu_fans[fan_index].type != FCU_FAN_RPM)
 		return -EINVAL;
@@ -509,12 +529,15 @@
 	if (id == FCU_FAN_ABSENT_ID)
 		return -EINVAL;
 
-	if (rpm < 300)
-		rpm = 300;
-	else if (rpm > 8191)
-		rpm = 8191;
-	buf[0] = rpm >> 5;
-	buf[1] = rpm << 3;
+	min = 2400 >> fcu_rpm_shift;
+	max = 56000 >> fcu_rpm_shift;
+
+	if (rpm < min)
+		rpm = min;
+	else if (rpm > max)
+		rpm = max;
+	buf[0] = rpm >> (8 - fcu_rpm_shift);
+	buf[1] = rpm << fcu_rpm_shift;
 	rc = fan_write_reg(0x10 + (id * 2), buf, 2);
 	if (rc < 0)
 		return -EIO;
@@ -551,7 +574,7 @@
 	if (rc != 2)
 		return -EIO;
 
-	return (buf[0] << 5) | buf[1] >> 3;
+	return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -609,6 +632,26 @@
 	return (buf[0] * 1000) / 2559;
 }
 
+static void tickle_fcu(void)
+{
+	int pwm;
+
+	pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+
+	DBG("FCU Tickle, slots fan is: %d\n", pwm);
+	if (pwm < 0)
+		pwm = 100;
+
+	if (!rackmac) {
+		pwm = SLOTS_FAN_DEFAULT_PWM;
+	} else if (pwm < SLOTS_PID_OUTPUT_MIN)
+		pwm = SLOTS_PID_OUTPUT_MIN;
+
+	/* That is hopefully enough to make the FCU happy */
+	set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
+}
+
+
 /*
  * Utility routine to read the CPU calibration EEPROM data
  * from the device-tree
@@ -715,6 +758,9 @@
 BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
 BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
 
+BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
+BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
+
 BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
 
 static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -735,6 +781,9 @@
 static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
 static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
 
+static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
+static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
+
 static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
 
 /*
@@ -1076,6 +1125,9 @@
 	fan_min = dimm_output_clamp;
 	fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
 
+	DBG(" CPU min mpu = %d, min dimm = %d\n",
+	    state->mpu.rminn_intake_fan, dimm_output_clamp);
+
 	state->rpm = max(state->rpm, (int)fan_min);
 	state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
 	state->intake_rpm = state->rpm;
@@ -1374,7 +1426,8 @@
 	DBG("  current rpm: %d\n", state->rpm);
 
 	/* Get some sensor readings */
-	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
 	state->last_temp = temp;
 	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
 	    FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1575,7 +1628,7 @@
 }
 
 /*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1588,6 +1641,127 @@
 	state->monitor = NULL;
 }
 
+/*
+ * Slots fan control loop
+ */
+static void do_monitor_slots(struct slots_pid_state *state)
+{
+	s32 temp, integral, derivative;
+	s64 integ_p, deriv_p, prop_p, sum;
+	int i, rc;
+
+	if (--state->ticks != 0)
+		return;
+	state->ticks = SLOTS_PID_INTERVAL;
+
+	DBG("slots:\n");
+
+	/* Check fan status */
+	rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
+	if (rc < 0) {
+		printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
+		/* XXX What do we do now ? */
+	} else
+		state->pwm = rc;
+	DBG("  current pwm: %d\n", state->pwm);
+
+	/* Get some sensor readings */
+	temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
+						    DS1775_TEMP)) << 8;
+	state->last_temp = temp;
+	DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
+	    FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
+
+	/* Store temperature and error in history array */
+	state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
+	state->sample_history[state->cur_sample] = temp;
+	state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
+
+	/* If first loop, fill the history table */
+	if (state->first) {
+		for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
+			state->cur_sample = (state->cur_sample + 1) %
+				SLOTS_PID_HISTORY_SIZE;
+			state->sample_history[state->cur_sample] = temp;
+			state->error_history[state->cur_sample] =
+				temp - SLOTS_PID_INPUT_TARGET;
+		}
+		state->first = 0;
+	}
+
+	/* Calculate the integral term */
+	sum = 0;
+	integral = 0;
+	for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
+		integral += state->error_history[i];
+	integral *= SLOTS_PID_INTERVAL;
+	DBG("  integral: %08x\n", integral);
+	integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
+	DBG("   integ_p: %d\n", (int)(integ_p >> 36));
+	sum += integ_p;
+
+	/* Calculate the derivative term */
+	derivative = state->error_history[state->cur_sample] -
+		state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
+				    % SLOTS_PID_HISTORY_SIZE];
+	derivative /= SLOTS_PID_INTERVAL;
+	deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
+	DBG("   deriv_p: %d\n", (int)(deriv_p >> 36));
+	sum += deriv_p;
+
+	/* Calculate the proportional term */
+	prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
+	DBG("   prop_p: %d\n", (int)(prop_p >> 36));
+	sum += prop_p;
+
+	/* Scale sum */
+	sum >>= 36;
+
+	DBG("   sum: %d\n", (int)sum);
+	state->pwm = (s32)sum;
+
+	state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
+	state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
+
+	DBG("** DRIVES PWM: %d\n", (int)state->pwm);
+	set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
+}
+
+/*
+ * Initialize the state structure for the slots bay fan control loop
+ */
+static int init_slots_state(struct slots_pid_state *state)
+{
+	state->ticks = 1;
+	state->first = 1;
+	state->pwm = 50;
+
+	state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
+	if (state->monitor == NULL)
+		return -ENODEV;
+
+	device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	return 0;
+}
+
+/*
+ * Dispose of the state data for the slots control loop
+ */
+static void dispose_slots_state(struct slots_pid_state *state)
+{
+	if (state->monitor == NULL)
+		return;
+
+	device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
+	device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
+
+	detach_i2c_chip(state->monitor);
+	state->monitor = NULL;
+}
+
+
 static int call_critical_overtemp(void)
 {
 	char *argv[] = { critical_overtemp_path, NULL };
@@ -1617,14 +1791,17 @@
 		goto out;
 	}
 
-	/* Set the PCI fan once for now */
-	set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+	/* Set the PCI fan once for now on non-RackMac */
+	if (!rackmac)
+		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
 	initialize_adc(&cpu_state[0]);
 	if (cpu_state[1].monitor != NULL)
 		initialize_adc(&cpu_state[1]);
 
+	fcu_tickle_ticks = FCU_TICKLE_TICKS;
+
 	up(&driver_lock);
 
 	while (state == state_attached) {
@@ -1634,6 +1811,12 @@
 
 		down(&driver_lock);
 
+		/* Tickle the FCU just in case */
+		if (--fcu_tickle_ticks < 0) {
+			fcu_tickle_ticks = FCU_TICKLE_TICKS;
+			tickle_fcu();
+		}
+
 		/* First, we always calculate the new DIMMs state on an Xserve */
 		if (rackmac)
 			do_monitor_dimms(&dimms_state);
@@ -1654,7 +1837,9 @@
 		}
 		/* Then, the rest */
 		do_monitor_backside(&backside_state);
-		if (!rackmac)
+		if (rackmac)
+			do_monitor_slots(&slots_state);
+		else
 			do_monitor_drives(&drives_state);
 		up(&driver_lock);
 
@@ -1696,6 +1881,7 @@
 	dispose_cpu_state(&cpu_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
+	dispose_slots_state(&slots_state);
 	dispose_dimms_state(&dimms_state);
 }
 
@@ -1745,6 +1931,8 @@
 		goto fail;
 	if (rackmac && init_dimms_state(&dimms_state))
 		goto fail;
+	if (rackmac && init_slots_state(&slots_state))
+		goto fail;
 	if (!rackmac && init_drives_state(&drives_state))
 		goto fail;
 
diff --git a/drivers/macintosh/therm_pm72.h b/drivers/macintosh/therm_pm72.h
index fc7e9b7..393cc9d 100644
--- a/drivers/macintosh/therm_pm72.h
+++ b/drivers/macintosh/therm_pm72.h
@@ -105,6 +105,7 @@
 #define DRIVES_DALLAS_ID	0x94
 #define BACKSIDE_MAX_ID		0x98
 #define XSERVE_DIMMS_LM87	0x25a
+#define XSERVE_SLOTS_LM75	0x290
 
 /*
  * Some MAX6690, DS1775, LM87 register definitions
@@ -198,7 +199,7 @@
 
 #define SLOTS_FAN_PWM_DEFAULT_ID	2
 #define SLOTS_FAN_PWM_INDEX		2
-#define	SLOTS_FAN_DEFAULT_PWM		50 /* Do better here ! */
+#define	SLOTS_FAN_DEFAULT_PWM		40 /* Do better here ! */
 
 
 /*
@@ -206,7 +207,7 @@
  */
 #define DIMM_PID_G_d			0
 #define DIMM_PID_G_p			0
-#define DIMM_PID_G_r			0x6553600
+#define DIMM_PID_G_r			0x06553600
 #define DIMM_PID_INPUT_TARGET		3276800
 #define DIMM_PID_INTERVAL    		1
 #define DIMM_PID_OUTPUT_MAX		14000
@@ -226,6 +227,31 @@
 };
 
 
+/*
+ * PID factors for the Xserve Slots control loop
+ */
+#define SLOTS_PID_G_d			0
+#define SLOTS_PID_G_p			0
+#define SLOTS_PID_G_r			0x00100000
+#define SLOTS_PID_INPUT_TARGET		3200000
+#define SLOTS_PID_INTERVAL    		1
+#define SLOTS_PID_OUTPUT_MAX		100
+#define SLOTS_PID_OUTPUT_MIN		20
+#define SLOTS_PID_HISTORY_SIZE		20
+
+struct slots_pid_state
+{
+	int			ticks;
+	struct i2c_client *	monitor;
+	s32	       		sample_history[SLOTS_PID_HISTORY_SIZE];
+	s32			error_history[SLOTS_PID_HISTORY_SIZE];
+	int			cur_sample;
+	s32			last_temp;
+	int			first;
+	int			pwm;
+};
+
+
 
 /* Desktops */
 
@@ -283,6 +309,9 @@
 	s32			pump_max;
 };
 
+/* Tickle FCU every 10 seconds */
+#define FCU_TICKLE_TICKS	10
+
 /*
  * Driver state
  */
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index b42d05f..a82f313 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -15,19 +15,51 @@
 
 #define MAX_PMU_LEVEL 0xFF
 
-static struct device_node *vias;
 static struct backlight_properties pmu_backlight_data;
+static spinlock_t pmu_backlight_lock;
+static int sleeping;
+static u8 bl_curve[FB_BACKLIGHT_LEVELS];
 
-static int pmu_backlight_get_level_brightness(struct fb_info *info,
-		int level)
+static void pmu_backlight_init_curve(u8 off, u8 min, u8 max)
+{
+	unsigned int i, flat, count, range = (max - min);
+
+	bl_curve[0] = off;
+
+	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+		bl_curve[flat] = min;
+
+	count = FB_BACKLIGHT_LEVELS * 15 / 16;
+	for (i = 0; i < count; ++i)
+		bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+
+static int pmu_backlight_curve_lookup(int value)
+{
+	int level = (FB_BACKLIGHT_LEVELS - 1);
+	int i, max = 0;
+
+	/* Look for biggest value */
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
+		max = max((int)bl_curve[i], max);
+
+	/* Look for nearest value */
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
+		int diff = abs(bl_curve[i] - value);
+		if (diff < max) {
+			max = diff;
+			level = i;
+		}
+	}
+	return level;
+}
+
+static int pmu_backlight_get_level_brightness(int level)
 {
 	int pmulevel;
 
 	/* Get and convert the value */
-	mutex_lock(&info->bl_mutex);
-	pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
-	mutex_unlock(&info->bl_mutex);
-
+	pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
 	if (pmulevel < 0)
 		pmulevel = 0;
 	else if (pmulevel > MAX_PMU_LEVEL)
@@ -38,25 +70,37 @@
 
 static int pmu_backlight_update_status(struct backlight_device *bd)
 {
-	struct fb_info *info = class_get_devdata(&bd->class_dev);
 	struct adb_request req;
-	int pmulevel, level = bd->props->brightness;
+	unsigned long flags;
+	int level = bd->props->brightness;
 
-	if (vias == NULL)
-		return -ENODEV;
+	spin_lock_irqsave(&pmu_backlight_lock, flags);
+
+	/* Don't update brightness when sleeping */
+	if (sleeping)
+		goto out;
 
 	if (bd->props->power != FB_BLANK_UNBLANK ||
 	    bd->props->fb_blank != FB_BLANK_UNBLANK)
 		level = 0;
 
-	pmulevel = pmu_backlight_get_level_brightness(info, level);
+	if (level > 0) {
+		int pmulevel = pmu_backlight_get_level_brightness(level);
 
-	pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
-	pmu_wait_complete(&req);
+		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+		pmu_wait_complete(&req);
 
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-		PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
-	pmu_wait_complete(&req);
+		pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+			PMU_POW_BACKLIGHT | PMU_POW_ON);
+		pmu_wait_complete(&req);
+	} else {
+		pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+			PMU_POW_BACKLIGHT | PMU_POW_OFF);
+		pmu_wait_complete(&req);
+	}
+
+out:
+	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
 
 	return 0;
 }
@@ -73,15 +117,23 @@
 	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
 };
 
-void __init pmu_backlight_init(struct device_node *in_vias)
+#ifdef CONFIG_PM
+void pmu_backlight_set_sleep(int sleep)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pmu_backlight_lock, flags);
+	sleeping = sleep;
+	spin_unlock_irqrestore(&pmu_backlight_lock, flags);
+}
+#endif /* CONFIG_PM */
+
+void __init pmu_backlight_init()
 {
 	struct backlight_device *bd;
-	struct fb_info *info;
 	char name[10];
 	int level, autosave;
 
-	vias = in_vias;
-
 	/* Special case for the old PowerBook since I can't test on it */
 	autosave =
 		machine_is_compatible("AAPL,3400/2400") ||
@@ -93,27 +145,14 @@
 	    !machine_is_compatible("PowerBook1,1"))
 		return;
 
-	/* Actually, this is a hack, but I don't know of a better way
-	 * to get the first framebuffer device.
-	 */
-	info = registered_fb[0];
-	if (!info) {
-		printk("pmubl: No framebuffer found\n");
-		goto error;
-	}
+	snprintf(name, sizeof(name), "pmubl");
 
-	snprintf(name, sizeof(name), "pmubl%d", info->node);
-
-	bd = backlight_device_register(name, info, &pmu_backlight_data);
+	bd = backlight_device_register(name, NULL, &pmu_backlight_data);
 	if (IS_ERR(bd)) {
 		printk("pmubl: Backlight registration failed\n");
 		goto error;
 	}
-
-	mutex_lock(&info->bl_mutex);
-	info->bl_dev = bd;
-	fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
-	mutex_unlock(&info->bl_mutex);
+	pmu_backlight_init_curve(0x7F, 0x46, 0x0E);
 
 	level = pmu_backlight_data.max_brightness;
 
@@ -123,18 +162,16 @@
 		pmu_request(&req, NULL, 2, 0xd9, 0);
 		pmu_wait_complete(&req);
 
-		mutex_lock(&info->bl_mutex);
-		level = pmac_backlight_curve_lookup(info,
+		level = pmu_backlight_curve_lookup(
 				(req.reply[0] >> 4) *
 				pmu_backlight_data.max_brightness / 15);
-		mutex_unlock(&info->bl_mutex);
 	}
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = level;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 	mutex_lock(&pmac_backlight_mutex);
 	if (!pmac_backlight)
diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c
index af8375ed..5189d54 100644
--- a/drivers/macintosh/via-pmu-led.c
+++ b/drivers/macintosh/via-pmu-led.c
@@ -74,7 +74,7 @@
 
 static struct led_classdev pmu_led = {
 	.name = "pmu-front-led",
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
+#ifdef CONFIG_ADB_PMU_LED_IDE
 	.default_trigger = "ide-disk",
 #endif
 	.brightness_set = pmu_led_set,
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 06ca80b..14610a6 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -16,7 +16,6 @@
  *    a sleep or a freq. switch
  *  - Move sleep code out of here to pmac_pm, merge into new
  *    common PM infrastructure
- *  - Move backlight code out as well
  *  - Save/Restore PCI space properly
  *
  */
@@ -60,9 +59,7 @@
 #include <asm/mmu_context.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
-#endif
 
 #include "via-pmu-event.h"
 
@@ -177,10 +174,6 @@
 static struct adb_request batt_req;
 static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES];
 
-#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
-extern int disable_kernel_backlight;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
-
 int __fake_sleep;
 int asleep;
 BLOCKING_NOTIFIER_HEAD(sleep_notifier_list);
@@ -466,7 +459,7 @@
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	/* Initialize backlight */
-	pmu_backlight_init(vias);
+	pmu_backlight_init();
 #endif
 
 #ifdef CONFIG_PPC32
@@ -1403,11 +1396,8 @@
 	else if ((1 << pirq) & PMU_INT_SNDBRT) {
 #ifdef CONFIG_PMAC_BACKLIGHT
 		if (len == 3)
-#ifdef CONFIG_INPUT_ADBHID
-			if (!disable_kernel_backlight)
-#endif /* CONFIG_INPUT_ADBHID */
-				pmac_backlight_set_legacy_brightness(data[1] >> 4);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+			pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4);
+#endif
 	}
 	/* Tick interrupt */
 	else if ((1 << pirq) & PMU_INT_TICK) {
@@ -2005,6 +1995,8 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 }
 
+extern void pmu_backlight_set_sleep(int sleep);
+
 static int
 pmac_suspend_devices(void)
 {
@@ -2042,6 +2034,11 @@
 		return -EBUSY;
 	}
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code not to muck around with the chip anymore */
+	pmu_backlight_set_sleep(1);
+#endif
+
 	/* Call platform functions marked "on sleep" */
 	pmac_pfunc_i2c_suspend();
 	pmac_pfunc_base_suspend();
@@ -2100,6 +2097,11 @@
 {
 	mdelay(100);
 
+#ifdef CONFIG_PMAC_BACKLIGHT
+	/* Tell backlight code it can use the chip again */
+	pmu_backlight_set_sleep(0);
+#endif
+
 	/* Power back up system devices (including the PIC) */
 	device_power_up();
 
@@ -2414,7 +2416,7 @@
 	spinlock_t lock;
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 	int	backlight_locker;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */	
+#endif
 };
 
 static LIST_HEAD(all_pmu_pvt);
@@ -2464,7 +2466,7 @@
 	spin_lock_irqsave(&all_pvt_lock, flags);
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
 	pp->backlight_locker = 0;
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */	
+#endif
 	list_add(&pp->list, &all_pmu_pvt);
 	spin_unlock_irqrestore(&all_pvt_lock, flags);
 	file->private_data = pp;
@@ -2559,13 +2561,12 @@
 		spin_lock_irqsave(&all_pvt_lock, flags);
 		list_del(&pp->list);
 		spin_unlock_irqrestore(&all_pvt_lock, flags);
+
 #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT)
-		if (pp->backlight_locker) {
-			spin_lock_irqsave(&pmu_lock, flags);
-			disable_kernel_backlight--;
-			spin_unlock_irqrestore(&pmu_lock, flags);
-		}
-#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */
+		if (pp->backlight_locker)
+			pmac_backlight_enable();
+#endif
+
 		kfree(pp);
 	}
 	unlock_kernel();
@@ -2642,18 +2643,18 @@
 #ifdef CONFIG_INPUT_ADBHID
 	case PMU_IOC_GRAB_BACKLIGHT: {
 		struct pmu_private *pp = filp->private_data;
-		unsigned long flags;
 
 		if (pp->backlight_locker)
 			return 0;
+
 		pp->backlight_locker = 1;
-		spin_lock_irqsave(&pmu_lock, flags);
-		disable_kernel_backlight++;
-		spin_unlock_irqrestore(&pmu_lock, flags);
+		pmac_backlight_disable();
+
 		return 0;
 	}
 #endif /* CONFIG_INPUT_ADBHID */
 #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
+
 	case PMU_IOC_GET_MODEL:
 	    	return put_user(pmu_kind, argp);
 	case PMU_IOC_HAS_ADB:
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 217615b..93f701e 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -710,6 +710,8 @@
 		return -EINVAL;
 	}
 
+	m->ti = ti;
+
 	r = parse_features(&as, m, ti);
 	if (r)
 		goto bad;
@@ -751,7 +753,6 @@
 	}
 
 	ti->private = m;
-	m->ti = ti;
 
 	return 0;
 
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index be48ced..c54de98 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -255,7 +255,9 @@
 	struct region *reg, *nreg;
 
 	read_unlock(&rh->hash_lock);
-	nreg = mempool_alloc(rh->region_pool, GFP_NOIO);
+	nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
+	if (unlikely(!nreg))
+		nreg = kmalloc(sizeof(struct region), GFP_NOIO);
 	nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
 		RH_CLEAN : RH_NOSYNC;
 	nreg->rh = rh;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index ff83c9b..b99c19c 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -162,7 +162,7 @@
 		goto out;
 	}
 
-	min_spacing = mddev->array_size;
+	min_spacing = conf->array_size;
 	sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *));
 
 	/* min_spacing is the minimum spacing that will fit the hash
@@ -171,7 +171,7 @@
 	 * that is larger than min_spacing as use the size of that as
 	 * the actual spacing
 	 */
-	conf->hash_spacing = mddev->array_size;
+	conf->hash_spacing = conf->array_size;
 	for (i=0; i < cnt-1 ; i++) {
 		sector_t sz = 0;
 		int j;
@@ -228,7 +228,7 @@
 	curr_offset = 0;
 	i = 0;
 	for (curr_offset = 0;
-	     curr_offset < mddev->array_size;
+	     curr_offset < conf->array_size;
 	     curr_offset += conf->hash_spacing) {
 
 		while (i < mddev->raid_disks-1 &&
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b6d1602..8dbab2e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1597,6 +1597,19 @@
 
 repeat:
 	spin_lock_irq(&mddev->write_lock);
+
+	if (mddev->degraded && mddev->sb_dirty == 3)
+		/* If the array is degraded, then skipping spares is both
+		 * dangerous and fairly pointless.
+		 * Dangerous because a device that was removed from the array
+		 * might have a event_count that still looks up-to-date,
+		 * so it can be re-added without a resync.
+		 * Pointless because if there are any spares to skip,
+		 * then a recovery will happen and soon that array won't
+		 * be degraded any more and the spare can go back to sleep then.
+		 */
+		mddev->sb_dirty = 1;
+
 	sync_req = mddev->in_sync;
 	mddev->utime = get_seconds();
 	if (mddev->sb_dirty == 3)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1efe22a..3b4d69c 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -930,10 +930,13 @@
 
 	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
 						conf->working_disks);
-	for (i = 0; i < conf->raid_disks; i++)
+	rcu_read_lock();
+	for (i = 0; i < conf->raid_disks; i++) {
+		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
 		seq_printf(seq, "%s",
-			      conf->mirrors[i].rdev &&
-			      test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_");
+			   rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_");
+	}
+	rcu_read_unlock();
 	seq_printf(seq, "]");
 }
 
@@ -975,7 +978,6 @@
 static void print_conf(conf_t *conf)
 {
 	int i;
-	mirror_info_t *tmp;
 
 	printk("RAID1 conf printout:\n");
 	if (!conf) {
@@ -985,14 +987,17 @@
 	printk(" --- wd:%d rd:%d\n", conf->working_disks,
 		conf->raid_disks);
 
+	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
 		char b[BDEVNAME_SIZE];
-		tmp = conf->mirrors + i;
-		if (tmp->rdev)
+		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		if (rdev)
 			printk(" disk %d, wo:%d, o:%d, dev:%s\n",
-				i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags),
-				bdevname(tmp->rdev->bdev,b));
+			       i, !test_bit(In_sync, &rdev->flags),
+			       !test_bit(Faulty, &rdev->flags),
+			       bdevname(rdev->bdev,b));
 	}
+	rcu_read_unlock();
 }
 
 static void close_sync(conf_t *conf)
@@ -1008,20 +1013,20 @@
 {
 	int i;
 	conf_t *conf = mddev->private;
-	mirror_info_t *tmp;
 
 	/*
 	 * Find all failed disks within the RAID1 configuration 
-	 * and mark them readable
+	 * and mark them readable.
+	 * Called under mddev lock, so rcu protection not needed.
 	 */
 	for (i = 0; i < conf->raid_disks; i++) {
-		tmp = conf->mirrors + i;
-		if (tmp->rdev 
-		    && !test_bit(Faulty, &tmp->rdev->flags)
-		    && !test_bit(In_sync, &tmp->rdev->flags)) {
+		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		if (rdev
+		    && !test_bit(Faulty, &rdev->flags)
+		    && !test_bit(In_sync, &rdev->flags)) {
 			conf->working_disks++;
 			mddev->degraded--;
-			set_bit(In_sync, &tmp->rdev->flags);
+			set_bit(In_sync, &rdev->flags);
 		}
 	}
 
@@ -1237,7 +1242,7 @@
 		/* ouch - failed to read all of that.
 		 * Try some synchronous reads of other devices to get
 		 * good data, much like with normal read errors.  Only
-		 * read into the pages we already have so they we don't
+		 * read into the pages we already have so we don't
 		 * need to re-issue the read request.
 		 * We don't need to freeze the array, because being in an
 		 * active sync request, there is no normal IO, and
@@ -1257,6 +1262,10 @@
 				s = PAGE_SIZE >> 9;
 			do {
 				if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
+					/* No rcu protection needed here devices
+					 * can only be removed when no resync is
+					 * active, and resync is currently active
+					 */
 					rdev = conf->mirrors[d].rdev;
 					if (sync_page_io(rdev->bdev,
 							 sect + rdev->data_offset,
@@ -1463,6 +1472,11 @@
 					s = PAGE_SIZE >> 9;
 
 				do {
+					/* Note: no rcu protection needed here
+					 * as this is synchronous in the raid1d thread
+					 * which is the thread that might remove
+					 * a device.  If raid1d ever becomes multi-threaded....
+					 */
 					rdev = conf->mirrors[d].rdev;
 					if (rdev &&
 					    test_bit(In_sync, &rdev->flags) &&
@@ -1486,7 +1500,6 @@
 							d = conf->raid_disks;
 						d--;
 						rdev = conf->mirrors[d].rdev;
-						atomic_add(s, &rdev->corrected_errors);
 						if (rdev &&
 						    test_bit(In_sync, &rdev->flags)) {
 							if (sync_page_io(rdev->bdev,
@@ -1509,9 +1522,11 @@
 									 s<<9, conf->tmppage, READ) == 0)
 								/* Well, this device is dead */
 								md_error(mddev, rdev);
-							else
+							else {
+								atomic_add(s, &rdev->corrected_errors);
 								printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
 								       mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b));
+							}
 						}
 					}
 				} else {
@@ -1625,15 +1640,16 @@
 		return 0;
 	}
 
-	/* before building a request, check if we can skip these blocks..
-	 * This call the bitmap_start_sync doesn't actually record anything
-	 */
 	if (mddev->bitmap == NULL &&
 	    mddev->recovery_cp == MaxSector &&
+	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
 	    conf->fullsync == 0) {
 		*skipped = 1;
 		return max_sector - sector_nr;
 	}
+	/* before building a request, check if we can skip these blocks..
+	 * This call the bitmap_start_sync doesn't actually record anything
+	 */
 	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
 	    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
 		/* We can skip this block, and probably several more */
@@ -1786,19 +1802,17 @@
 		for (i=0; i<conf->raid_disks; i++) {
 			bio = r1_bio->bios[i];
 			if (bio->bi_end_io == end_sync_read) {
-				md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors);
+				md_sync_acct(bio->bi_bdev, nr_sectors);
 				generic_make_request(bio);
 			}
 		}
 	} else {
 		atomic_set(&r1_bio->remaining, 1);
 		bio = r1_bio->bios[r1_bio->read_disk];
-		md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev,
-			     nr_sectors);
+		md_sync_acct(bio->bi_bdev, nr_sectors);
 		generic_make_request(bio);
 
 	}
-
 	return nr_sectors;
 }
 
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index d687a14..06ac899 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -393,7 +393,7 @@
 	state->bandwidth = bandwidth;
 
 	if (state->dst_type != DST_TYPE_IS_TERR)
-		return 0;
+		return -EOPNOTSUPP;
 
 	switch (bandwidth) {
 	case BANDWIDTH_6_MHZ:
@@ -462,7 +462,7 @@
 
 	state->symbol_rate = srate;
 	if (state->dst_type == DST_TYPE_IS_TERR) {
-		return 0;
+		return -EOPNOTSUPP;
 	}
 	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 	srate /= 1000;
@@ -504,7 +504,7 @@
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
 	if (state->dst_type != DST_TYPE_IS_CABLE)
-		return 0;
+		return -EOPNOTSUPP;
 
 	state->modulation = modulation;
 	switch (modulation) {
@@ -1234,7 +1234,7 @@
 		goto error;
 	}
 	if (write_dst(state, data, len)) {
-		dprintk(verbose, DST_INFO, 1, "Tring to recover.. ");
+		dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
 		if ((dst_error_recovery(state)) < 0) {
 			dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
 			goto error;
@@ -1328,15 +1328,13 @@
 {
 	u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
 
-	if (state->dst_type == DST_TYPE_IS_TERR)
-		return 0;
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
 	paket[4] = state->tx_tuna[4];
 	paket[2] = state->tx_tuna[2];
 	paket[3] = state->tx_tuna[3];
 	paket[7] = dst_check_sum (paket, 7);
-	dst_command(state, paket, 8);
-
-	return 0;
+	return dst_command(state, paket, 8);
 }
 
 static int dst_get_tuna(struct dst_state *state)
@@ -1465,7 +1463,7 @@
 	u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
 
 	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
+		return -EOPNOTSUPP;
 	if (cmd->msg_len > 0 && cmd->msg_len < 5)
 		memcpy(&paket[3], cmd->msg, cmd->msg_len);
 	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
@@ -1473,18 +1471,17 @@
 	else
 		return -EINVAL;
 	paket[7] = dst_check_sum(&paket[0], 7);
-	dst_command(state, paket, 8);
-	return 0;
+	return dst_command(state, paket, 8);
 }
 
 static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-	int need_cmd;
+	int need_cmd, retval = 0;
 	struct dst_state *state = fe->demodulator_priv;
 
 	state->voltage = voltage;
 	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
+		return -EOPNOTSUPP;
 
 	need_cmd = 0;
 
@@ -1506,9 +1503,9 @@
 	}
 
 	if (need_cmd)
-		dst_tone_power_cmd(state);
+		retval = dst_tone_power_cmd(state);
 
-	return 0;
+	return retval;
 }
 
 static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
@@ -1517,7 +1514,7 @@
 
 	state->tone = tone;
 	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
+		return -EOPNOTSUPP;
 
 	switch (tone) {
 	case SEC_TONE_OFF:
@@ -1533,9 +1530,7 @@
 	default:
 		return -EINVAL;
 	}
-	dst_tone_power_cmd(state);
-
-	return 0;
+	return dst_tone_power_cmd(state);
 }
 
 static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
@@ -1543,7 +1538,7 @@
 	struct dst_state *state = fe->demodulator_priv;
 
 	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
+		return -EOPNOTSUPP;
 	state->minicmd = minicmd;
 	switch (minicmd) {
 	case SEC_MINI_A:
@@ -1553,9 +1548,7 @@
 		state->tx_tuna[3] = 0xff;
 		break;
 	}
-	dst_tone_power_cmd(state);
-
-	return 0;
+	return dst_tone_power_cmd(state);
 }
 
 
@@ -1608,28 +1601,31 @@
 {
 	struct dst_state *state = fe->demodulator_priv;
 
-	dst_get_signal(state);
+	int retval = dst_get_signal(state);
 	*strength = state->decode_strength;
 
-	return 0;
+	return retval;
 }
 
 static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	struct dst_state *state = fe->demodulator_priv;
 
-	dst_get_signal(state);
+	int retval = dst_get_signal(state);
 	*snr = state->decode_snr;
 
-	return 0;
+	return retval;
 }
 
 static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
+	int retval = -EINVAL;
 	struct dst_state *state = fe->demodulator_priv;
 
 	if (p != NULL) {
-		dst_set_freq(state, p->frequency);
+		retval = dst_set_freq(state, p->frequency);
+		if(retval != 0)
+			return retval;
 		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
 
 		if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1647,10 +1643,10 @@
 			dst_set_symbolrate(state, p->u.qam.symbol_rate);
 			dst_set_modulation(state, p->u.qam.modulation);
 		}
-		dst_write_tuna(fe);
+		retval = dst_write_tuna(fe);
 	}
 
-	return 0;
+	return retval;
 }
 
 static int dst_tune_frontend(struct dvb_frontend* fe,
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index 1105465..0b51828 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB device drivers.
 #
 
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
-		dvb_ca_en50221.o dvb_frontend.o 		\
-		dvb_net.o dvb_ringbuffer.o dvb_math.o
+dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
+		 dvb_ca_en50221.o dvb_frontend.o 		\
+		 dvb_net.o dvb_ringbuffer.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 59ac35d..57b34cd 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -526,7 +526,9 @@
 	fepriv->delay = 3*HZ;
 	fepriv->status = 0;
 	fepriv->wakeup = 0;
-	fepriv->reinitialise = 1;
+	fepriv->reinitialise = 0;
+
+	dvb_frontend_init(fe);
 
 	while (1) {
 		up(&fepriv->sem);	    /* is locked when we enter the thread... */
@@ -1013,17 +1015,18 @@
 		return ret;
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+
+		/* normal tune mode when opened R/W */
+		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+		fepriv->tone = -1;
+		fepriv->voltage = -1;
+
 		ret = dvb_frontend_start (fe);
 		if (ret)
 			dvb_generic_release (inode, file);
 
 		/*  empty event queue */
 		fepriv->events.eventr = fepriv->events.eventw = 0;
-
-		/* normal tune mode when opened R/W */
-		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
-		fepriv->tone = -1;
-		fepriv->voltage = -1;
 	}
 
 	return ret;
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index a189683..2be33f2 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -194,11 +194,11 @@
 		{  253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
 		{  383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
 		{  443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
-		{  444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0  11 */ },
-		{  583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0  11 */ },
-		{  793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0  11 */ },
-		{  444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0  11 */ },
-		{  861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0  11 */ },
+		{  444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
+		{  583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1  00 */ },
+		{  793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1  00 */ },
+		{  444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
+		{  861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1  00 */ },
 	}
 };
 EXPORT_SYMBOL(dvb_pll_tda665x);
@@ -613,7 +613,21 @@
 
 int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
 {
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 };
 	struct dvb_pll_priv *priv = NULL;
+	int ret;
+
+	if (i2c != NULL) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = i2c_transfer (i2c, &msg, 1);
+		if (ret != 1)
+			return -1;
+		if (fe->ops.i2c_gate_ctrl)
+			     fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
 	if (priv == NULL)
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 500f15c..4506165 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -2203,8 +2203,8 @@
 				av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
 
 				/* set TDA9819 into DVB mode */
-				saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
-				saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+				saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+				saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
 
 				/* tuner on this needs a slower i2c bus speed */
 				av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 6405546..6ffe53f 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -272,8 +272,8 @@
 				if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
 					dprintk(1, "setting band in demodulator failed.\n");
 			} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-				saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD)
-				saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF)
+				saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
+				saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
 			}
 			if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
 				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
@@ -308,8 +308,8 @@
 			if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
 				dprintk(1, "setting band in demodulator failed.\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
 		}
 	}
 
@@ -750,8 +750,8 @@
 			if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
 				dprintk(1, "setting band in demodulator failed.\n");
 		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
-			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
+			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
+			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
 		}
 
 		/* init the saa7113 */
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 5f111d4..2d21fec 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -1303,6 +1303,9 @@
 	budget_av->budget.dvb_adapter.priv = budget_av;
 	frontend_init(budget_av);
 	ciintf_init(budget_av);
+
+	ttpci_budget_init_hooks(&budget_av->budget);
+
 	return 0;
 }
 
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 4b966ee..ffbbb3e 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -1101,6 +1101,8 @@
 	budget_ci->budget.dvb_adapter.priv = budget_ci;
 	frontend_init(budget_ci);
 
+	ttpci_budget_init_hooks(&budget_ci->budget);
+
 	return 0;
 }
 
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index e4cf777..e15562f 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -63,9 +63,6 @@
 {
 	dprintk(2, "budget: %p\n", budget);
 
-	if (--budget->feeding)
-		return budget->feeding;
-
 	saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
 	SAA7146_IER_DISABLE(budget->dev, MASK_10);
 	return 0;
@@ -77,8 +74,8 @@
 
 	dprintk(2, "budget: %p\n", budget);
 
-	if (budget->feeding)
-		return ++budget->feeding;
+	if (!budget->feeding || !budget->fe_synced)
+		return 0;
 
 	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
 
@@ -139,7 +136,33 @@
 	SAA7146_IER_ENABLE(budget->dev, MASK_10);	/* VPE */
 	saa7146_write(dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
 
-	return ++budget->feeding;
+	return 0;
+}
+
+static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	int synced;
+	int ret;
+
+	if (budget->read_fe_status)
+		ret = budget->read_fe_status(fe, status);
+	else
+		ret = -EINVAL;
+
+	if (!ret) {
+		synced = (*status & FE_HAS_LOCK);
+		if (synced != budget->fe_synced) {
+			budget->fe_synced = synced;
+			spin_lock(&budget->feedlock);
+			if (synced)
+				start_ts_capture(budget);
+			else
+				stop_ts_capture(budget);
+			spin_unlock(&budget->feedlock);
+		}
+	}
+	return ret;
 }
 
 static void vpeirq(unsigned long data)
@@ -267,7 +290,7 @@
 {
 	struct dvb_demux *demux = feed->demux;
 	struct budget *budget = (struct budget *) demux->priv;
-	int status;
+	int status = 0;
 
 	dprintk(2, "budget: %p\n", budget);
 
@@ -276,7 +299,8 @@
 
 	spin_lock(&budget->feedlock);
 	feed->pusi_seen = 0; /* have a clean section start */
-	status = start_ts_capture(budget);
+	if (budget->feeding++ == 0)
+		status = start_ts_capture(budget);
 	spin_unlock(&budget->feedlock);
 	return status;
 }
@@ -285,12 +309,13 @@
 {
 	struct dvb_demux *demux = feed->demux;
 	struct budget *budget = (struct budget *) demux->priv;
-	int status;
+	int status = 0;
 
 	dprintk(2, "budget: %p\n", budget);
 
 	spin_lock(&budget->feedlock);
-	status = stop_ts_capture(budget);
+	if (--budget->feeding == 0)
+		status = stop_ts_capture(budget);
 	spin_unlock(&budget->feedlock);
 	return status;
 }
@@ -470,6 +495,14 @@
 	return ret;
 }
 
+void ttpci_budget_init_hooks(struct budget *budget)
+{
+	if (budget->dvb_frontend && !budget->read_fe_status) {
+		budget->read_fe_status = budget->dvb_frontend->ops.read_status;
+		budget->dvb_frontend->ops.read_status = budget_read_fe_status;
+	}
+}
+
 int ttpci_budget_deinit(struct budget *budget)
 {
 	struct saa7146_dev *dev = budget->dev;
@@ -508,11 +541,8 @@
 	spin_lock(&budget->feedlock);
 	budget->video_port = video_port;
 	if (budget->feeding) {
-		int oldfeeding = budget->feeding;
-		budget->feeding = 1;
 		stop_ts_capture(budget);
 		start_ts_capture(budget);
-		budget->feeding = oldfeeding;
 	}
 	spin_unlock(&budget->feedlock);
 }
@@ -520,6 +550,7 @@
 EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
 EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
 EXPORT_SYMBOL_GPL(ttpci_budget_init);
+EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
 EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
 EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
 EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index ee60ce9..5722744 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -617,6 +617,8 @@
 	budget->dvb_adapter.priv = budget;
 	frontend_init(budget);
 
+	ttpci_budget_init_hooks(budget);
+
 	return 0;
 }
 
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 35761f1..863dffb 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -375,9 +375,6 @@
 		if (budget->dvb_frontend) {
 			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
 			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops.set_tone = budget_set_tone;
 			break;
 		}
 		break;
@@ -474,6 +471,8 @@
 	budget->dvb_adapter.priv = budget;
 	frontend_init(budget);
 
+	ttpci_budget_init_hooks(budget);
+
 	return 0;
 }
 
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index ecea3a1..e8a5c79 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -52,9 +52,6 @@
 	struct dmx_frontend hw_frontend;
 	struct dmx_frontend mem_frontend;
 
-	int fe_synced;
-	struct mutex pid_mutex;
-
 	int ci_present;
 	int video_port;
 
@@ -74,6 +71,9 @@
 
 	struct dvb_adapter dvb_adapter;
 	struct dvb_frontend *dvb_frontend;
+	int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+	int fe_synced;
+
 	void *priv;
 };
 
@@ -106,6 +106,7 @@
 extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
 			     struct saa7146_pci_extension_data *info,
 			     struct module *owner);
+extern void ttpci_budget_init_hooks(struct budget *budget);
 extern int ttpci_budget_deinit(struct budget *budget);
 extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
 extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index de3128a..220076b 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -350,5 +350,15 @@
 	help
 	  Enter the I/O port of your Zoltrix radio card.
 
-endmenu
+config USB_DSBR
+	tristate "D-Link USB FM radio support (EXPERIMENTAL)"
+	depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+	---help---
+	  Say Y here if you want to connect this type of radio to your
+	  computer's USB port. Note that the audio is not digital, and
+	  you must connect the line out connector to a sound card or a
+	  set of speakers.
 
+	  To compile this driver as a module, choose M here: the
+	  module will be called dsbr100.
+endmenu
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index e95b680..cf55a18 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -20,5 +20,6 @@
 obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
+obj-$(CONFIG_USB_DSBR) += dsbr100.o
 
 EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/video/dsbr100.c b/drivers/media/radio/dsbr100.c
similarity index 100%
rename from drivers/media/video/dsbr100.c
rename to drivers/media/radio/dsbr100.c
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6d532f1..732bf1e 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -145,7 +145,7 @@
 
 config VIDEO_SAA5249
 	tristate "SAA5249 Teletext processor"
-	depends on VIDEO_DEV && I2C
+	depends on VIDEO_DEV && I2C && VIDEO_V4L1
 	help
 	  Support for I2C bus based teletext using the SAA5249 chip. At the
 	  moment this is only useful on some European WinTV cards.
@@ -155,7 +155,7 @@
 
 config TUNER_3036
 	tristate "SAB3036 tuner"
-	depends on VIDEO_DEV && I2C
+	depends on VIDEO_DEV && I2C && VIDEO_V4L1
 	help
 	  Say Y here to include support for Philips SAB3036 compatible tuners.
 	  If in doubt, say N.
@@ -449,18 +449,6 @@
 
 source "drivers/media/video/em28xx/Kconfig"
 
-config USB_DSBR
-	tristate "D-Link USB FM radio support (EXPERIMENTAL)"
-	depends on USB && VIDEO_V4L1 && EXPERIMENTAL
-	---help---
-	  Say Y here if you want to connect this type of radio to your
-	  computer's USB port. Note that the audio is not digital, and
-	  you must connect the line out connector to a sound card or a
-	  set of speakers.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called dsbr100.
-
 source "drivers/media/video/usbvideo/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 353d61c..e82e511 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -77,7 +77,6 @@
 obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
-obj-$(CONFIG_USB_DSBR)          += dsbr100.o
 obj-$(CONFIG_USB_OV511)         += ov511.o
 obj-$(CONFIG_USB_SE401)         += se401.o
 obj-$(CONFIG_USB_STV680)        += stv680.o
@@ -91,6 +90,7 @@
 obj-$(CONFIG_USB_IBMCAM)        += usbvideo/
 obj-$(CONFIG_USB_KONICAWC)      += usbvideo/
 obj-$(CONFIG_USB_VICAM)         += usbvideo/
+obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= usbvideo/
 
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
index 153f6a4..cdcf556 100644
--- a/drivers/media/video/bt8xx/Kconfig
+++ b/drivers/media/video/bt8xx/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_BT848
 	tristate "BT848 Video For Linux"
-	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1
 	select I2C_ALGOBIT
 	select FW_LOADER
 	select VIDEO_BTCX
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 5764a89..20dff7c 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -3923,7 +3923,12 @@
 		goto err;
 	printk(KERN_INFO "bttv%d: registered device video%d\n",
 	       btv->c.nr,btv->video_dev->minor & 0x1f);
-	video_device_create_file(btv->video_dev, &class_device_attr_card);
+	if (class_device_create_file(&btv->video_dev->class_dev,
+				     &class_device_attr_card)<0) {
+		printk(KERN_ERR "bttv%d: class_device_create_file 'card' "
+		       "failed\n", btv->c.nr);
+		goto err;
+	}
 
 	/* vbi */
 	btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi");
@@ -4287,6 +4292,8 @@
 
 static int bttv_init_module(void)
 {
+	int ret;
+
 	bttv_num = 0;
 
 	printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
@@ -4308,7 +4315,11 @@
 
 	bttv_check_chipset();
 
-	bus_register(&bttv_sub_bus_type);
+	ret = bus_register(&bttv_sub_bus_type);
+	if (ret < 0) {
+		printk(KERN_WARNING "bttv: bus_register error: %d\n", ret);
+		return ret;
+	}
 	return pci_register_driver(&bttv_pci_driver);
 }
 
diff --git a/drivers/media/video/bt8xx/bttv-vbi.c b/drivers/media/video/bt8xx/bttv-vbi.c
index 8c9f0f7..63676e7 100644
--- a/drivers/media/video/bt8xx/bttv-vbi.c
+++ b/drivers/media/video/bt8xx/bttv-vbi.c
@@ -31,11 +31,16 @@
 #include <asm/io.h>
 #include "bttvp.h"
 
-/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate:
-   bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC
-   HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge
-   of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */
-#define VBI_OFFSET ((64 + 0) * 2)
+/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
+   in fCLKx2 pixels.  According to the datasheet, VBI capture starts
+   VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
+   is 64 fCLKx1 pixels wide.  VBI_HDELAY is set to 0, so this should be
+   (64 + 0) * 2 = 128 fCLKx2 pixels.  But it's not!  The datasheet is
+   Just Plain Wrong.  The real value appears to be different for
+   different revisions of the bt8x8 chips, and to be affected by the
+   horizontal scaling factor.  Experimentally, the value is measured
+   to be about 244.  */
+#define VBI_OFFSET 244
 
 #define VBI_DEFLINES 16
 #define VBI_MAXLINES 32
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c
index 353d02b..b69ee11 100644
--- a/drivers/media/video/compat_ioctl32.c
+++ b/drivers/media/video/compat_ioctl32.c
@@ -21,7 +21,7 @@
 
 #ifdef CONFIG_COMPAT
 
-
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 struct video_tuner32 {
 	compat_int_t tuner;
 	char name[32];
@@ -107,6 +107,7 @@
 	compat_caddr_t clips;
 	compat_int_t clipcount;
 };
+#endif
 
 static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -124,6 +125,7 @@
 }
 
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 /* You get back everything except the clips... */
 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
 {
@@ -138,6 +140,7 @@
 			return -EFAULT;
 	return 0;
 }
+#endif
 
 struct v4l2_clip32
 {
@@ -490,6 +493,24 @@
 	return 0;
 }
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+struct video_code32
+{
+	char		loadwhat[16];	/* name or tag of file being passed */
+	compat_int_t	datasize;
+	unsigned char	*data;
+};
+
+static inline int microcode32(struct video_code *kp, struct video_code32 __user *up)
+{
+	if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
+		copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) ||
+		get_user(kp->datasize, &up->datasize) ||
+		copy_from_user(kp->data, up->data, up->datasize))
+			return -EFAULT;
+	return 0;
+}
+
 #define VIDIOCGTUNER32		_IOWR('v',4, struct video_tuner32)
 #define VIDIOCSTUNER32		_IOW('v',5, struct video_tuner32)
 #define VIDIOCGWIN32		_IOR('v',9, struct video_window32)
@@ -498,6 +519,9 @@
 #define VIDIOCSFBUF32		_IOW('v',12, struct video_buffer32)
 #define VIDIOCGFREQ32		_IOR('v',14, u32)
 #define VIDIOCSFREQ32		_IOW('v',15, u32)
+#define VIDIOCSMICROCODE32	_IOW('v',27, struct video_code32)
+
+#endif
 
 /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
 #define VIDIOC_ENUMINPUT32	VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
@@ -519,6 +543,7 @@
 #define VIDIOC_S_INPUT32	_IOWR ('V', 39, compat_int_t)
 #define VIDIOC_TRY_FMT32      	_IOWR ('V', 64, struct v4l2_format32)
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 enum {
 	MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
 };
@@ -583,13 +608,17 @@
 
 	return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
 }
+#endif
 
 static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	union {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 		struct video_tuner vt;
 		struct video_buffer vb;
 		struct video_window vw;
+		struct video_code vc;
+#endif
 		struct v4l2_format v2f;
 		struct v4l2_buffer v2b;
 		struct v4l2_framebuffer v2fb;
@@ -605,6 +634,7 @@
 
 	/* First, convert the command. */
 	switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
 	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
 	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
@@ -612,6 +642,8 @@
 	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
 	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
 	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+	case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
+#endif
 	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
 	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
 	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
@@ -631,6 +663,7 @@
 	};
 
 	switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCSTUNER:
 	case VIDIOCGTUNER:
 		err = get_video_tuner32(&karg.vt, up);
@@ -644,6 +677,7 @@
 		break;
 
 	case VIDIOCSFREQ:
+#endif
 	case VIDIOC_S_INPUT:
 	case VIDIOC_OVERLAY:
 	case VIDIOC_STREAMON:
@@ -697,14 +731,21 @@
 		compatible_arg = 0;
 		break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCGWIN:
 	case VIDIOCGFBUF:
 	case VIDIOCGFREQ:
+#endif
 	case VIDIOC_G_FBUF:
 	case VIDIOC_G_INPUT:
 		compatible_arg = 0;
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+	case VIDIOCSMICROCODE:
+		err = microcode32(&karg.vc, up);
+		compatible_arg = 0;
+		break;
+#endif
 	};
-
 	if(err)
 		goto out;
 
@@ -719,6 +760,7 @@
 	}
 	if(err == 0) {
 		switch(cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 		case VIDIOCGTUNER:
 			err = put_video_tuner32(&karg.vt, up);
 			break;
@@ -730,7 +772,7 @@
 		case VIDIOCGFBUF:
 			err = put_video_buffer32(&karg.vb, up);
 			break;
-
+#endif
 		case VIDIOC_G_FBUF:
 			err = put_v4l2_framebuffer32(&karg.v2fb, up);
 			break;
@@ -768,7 +810,9 @@
 			err = put_v4l2_input32(&karg.v2i, up);
 			break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 		case VIDIOCGFREQ:
+#endif
 		case VIDIOC_G_INPUT:
 			err = put_user(((u32)karg.vx), (u32 __user *)up);
 			break;
@@ -786,6 +830,7 @@
 		return ret;
 
 	switch (cmd) {
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCSWIN32:
 		ret = do_set_window(file, cmd, arg);
 		break;
@@ -796,6 +841,7 @@
 	case VIDIOCSFBUF32:
 	case VIDIOCGFREQ32:
 	case VIDIOCSFREQ32:
+#endif
 	case VIDIOC_QUERYCAP:
 	case VIDIOC_ENUM_FMT:
 	case VIDIOC_G_FMT32:
@@ -827,6 +873,7 @@
 		ret = do_video_ioctl(file, cmd, arg);
 		break;
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	/* Little v, the video4linux ioctls (conflict?) */
 	case VIDIOCGCAP:
 	case VIDIOCGCHAN:
@@ -855,6 +902,7 @@
 	case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
 		ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
 		break;
+#endif
 	default:
 		v4l_print_ioctl("compat_ioctl32", cmd);
 	}
diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig
index 513cc09..e39a961 100644
--- a/drivers/media/video/cpia2/Kconfig
+++ b/drivers/media/video/cpia2/Kconfig
@@ -1,6 +1,6 @@
 config VIDEO_CPIA2
 	tristate "CPiA2 Video For Linux"
-	depends on VIDEO_DEV && USB
+	depends on VIDEO_DEV && USB && VIDEO_V4L1
 	---help---
 	  This is the video4linux driver for cameras based on Vision's CPiA2
 	  (Colour Processor Interface ASIC), such as the Digital Blue QX5
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index 5c2036b..7bb7589 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -104,8 +104,8 @@
 	if (i2c_master_recv(client, buffer, 4) < 4)
 		return 0;
 
-	return (buffer[0] << 24) | (buffer[1] << 16) |
-	    (buffer[2] << 8) | buffer[3];
+	return (buffer[3] << 24) | (buffer[2] << 16) |
+	    (buffer[1] << 8) | buffer[0];
 }
 
 int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 72b630a..c255646 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -89,7 +89,7 @@
 
 		auxgpio = cx_read(MO_GP1_IO);
 		/* Take out the parity part */
-		gpio+=(gpio & 0x7fd) + (auxgpio & 0xef);
+		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
 	} else
 		auxgpio = gpio;
 
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 2225d4b..94c92ba 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1180,7 +1180,6 @@
 			V4L2_CAP_READWRITE     |
 			V4L2_CAP_STREAMING     |
 			V4L2_CAP_VBI_CAPTURE   |
-			V4L2_CAP_VIDEO_OVERLAY |
 			0;
 		if (UNSET != core->tuner_type)
 			cap->capabilities |= V4L2_CAP_TUNER;
@@ -1226,7 +1225,7 @@
 		struct v4l2_format *f = arg;
 		return cx8800_try_fmt(dev,fh,f);
 	}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	/* --- streaming capture ------------------------------------- */
 	case VIDIOCGMBUF:
 	{
@@ -1585,7 +1584,7 @@
 		*id = 0;
 		return 0;
 	}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCSTUNER:
 	{
 		struct video_tuner *v = arg;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index dbb75a7..56246b8 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -362,7 +362,7 @@
 }
 
 /* ------------------------------------------------------------------------ */
-
+#ifdef CONFIG_VIDEO_V4L1
 static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode)
 {
 	if (rxsubchans == V4L2_TUNER_SUB_MONO)
@@ -384,6 +384,7 @@
 		return V4L2_TUNER_MODE_LANG1;
 	return V4L2_TUNER_MODE_MONO;
 }
+#endif
 
 static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
 {
@@ -509,6 +510,7 @@
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
+#ifdef CONFIG_VIDEO_V4L1
 	case VIDIOCGAUDIO:
 	{
 		struct video_audio *va = arg;
@@ -577,6 +579,12 @@
 	}
 
 	case VIDIOCSFREQ:
+	{
+		/* new channel -- kick audio carrier scan */
+		msp_wake_thread(client);
+		break;
+	}
+#endif
 	case VIDIOC_S_FREQUENCY:
 	{
 		/* new channel -- kick audio carrier scan */
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index f2fd919..ed02ff8 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -961,10 +961,10 @@
 		/* setup the chip*/
 		msp34xxg_reset(client);
 		state->std = state->radio ? 0x40 : msp_standard;
-		if (state->std != 1)
-			goto unmute;
 		/* start autodetect */
 		msp_write_dem(client, 0x20, state->std);
+		if (state->std != 1)
+			goto unmute;
 
 		/* watch autodetect */
 		v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n");
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 9b48abc..be1e5cc 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -852,7 +852,6 @@
 	return hdw->serial_number;
 }
 
-
 int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
 {
 	return hdw->unit_number;
@@ -2318,7 +2317,6 @@
 	}
 }
 
-
 /* Return name for this driver instance */
 const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
 {
@@ -2542,6 +2540,10 @@
 }
 
 
+/* Issue a command and get a response from the device.  This extended
+   version includes a probe flag (which if set means that device errors
+   should not be logged or treated as fatal) and a timeout in jiffies.
+   This can be used to non-lethally probe the health of endpoint 1. */
 static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
 				unsigned int timeout,int probe_fl,
 				void *write_data,unsigned int write_len,
@@ -2970,6 +2972,7 @@
 }
 
 
+/* Stop / start video stream transport */
 static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
 {
 	int status;
@@ -3068,6 +3071,7 @@
 }
 
 
+/* Find I2C address of eeprom */
 static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
 {
 	int result;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
index 681f79c..1e39376 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -26,6 +26,8 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
 #define BUFFER_SIG 0x47653271
 
 // #define SANITY_CHECK_BUFFERS
@@ -515,6 +517,10 @@
 }
 
 /* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+	return sp->buffer_target_count;
+}
 
 int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
 {
@@ -553,7 +559,6 @@
 	return sp->r_count;
 }
 
-
 void pvr2_stream_kill(struct pvr2_stream *sp)
 {
 	struct pvr2_buffer *bp;
@@ -607,7 +612,6 @@
 	return ret;
 }
 
-
 int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
 {
 	int ret = 0;
@@ -646,7 +650,6 @@
 	return bp->status;
 }
 
-
 int pvr2_buffer_get_id(struct pvr2_buffer *bp)
 {
 	return bp->id;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
index 96285ad..93279cc 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-io.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -47,6 +47,7 @@
 			      void *data);
 
 /* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
 int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
 
 /* Get a pointer to a buffer that is either idle, ready, or is specified
@@ -58,6 +59,7 @@
 /* Find out how many buffers are idle or ready */
 int pvr2_stream_get_ready_count(struct pvr2_stream *);
 
+
 /* Kill all pending buffers and throw away any ready buffers as well */
 void pvr2_stream_kill(struct pvr2_stream *);
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
index f7a2e22..b71f9a9 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-ioread.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -213,7 +213,9 @@
 				   " pvr2_ioread_setup (tear-down) id=%p",cp);
 			pvr2_ioread_stop(cp);
 			pvr2_stream_kill(cp->stream);
-			pvr2_stream_set_buffer_count(cp->stream,0);
+			if (pvr2_stream_get_buffer_count(cp->stream)) {
+				pvr2_stream_set_buffer_count(cp->stream,0);
+			}
 			cp->stream = NULL;
 		}
 		if (sp) {
@@ -251,7 +253,6 @@
 	return ret;
 }
 
-
 static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
 {
 	int stat;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
index 6af55a8..d1dda5c 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -44,12 +44,16 @@
 	struct kobj_type ktype;
 	struct class_device_attribute attr_v4l_minor_number;
 	struct class_device_attribute attr_unit_number;
+	int v4l_minor_number_created_ok;
+	int unit_number_created_ok;
 };
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
 struct pvr2_sysfs_debugifc {
 	struct class_device_attribute attr_debugcmd;
 	struct class_device_attribute attr_debuginfo;
+	int debugcmd_created_ok;
+	int debuginfo_created_ok;
 };
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 
@@ -67,6 +71,7 @@
 	struct pvr2_sysfs_ctl_item *item_next;
 	struct attribute *attr_gen[7];
 	struct attribute_group grp;
+	int created_ok;
 	char name[80];
 };
 
@@ -487,6 +492,7 @@
 	struct pvr2_sysfs_func_set *fp;
 	struct pvr2_ctrl *cptr;
 	unsigned int cnt,acnt;
+	int ret;
 
 	if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
 		return;
@@ -589,7 +595,13 @@
 	cip->grp.name = cip->name;
 	cip->grp.attrs = cip->attr_gen;
 
-	sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+	ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+	if (ret) {
+		printk(KERN_WARNING "%s: sysfs_create_group error: %d\n",
+		       __FUNCTION__, ret);
+		return;
+	}
+	cip->created_ok = !0;
 }
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
@@ -600,6 +612,8 @@
 static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
 {
 	struct pvr2_sysfs_debugifc *dip;
+	int ret;
+
 	dip = kmalloc(sizeof(*dip),GFP_KERNEL);
 	if (!dip) return;
 	memset(dip,0,sizeof(*dip));
@@ -613,17 +627,34 @@
 	dip->attr_debuginfo.attr.mode = S_IRUGO;
 	dip->attr_debuginfo.show = debuginfo_show;
 	sfp->debugifc = dip;
-	class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
-	class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+	ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+		       __FUNCTION__, ret);
+	} else {
+		dip->debugcmd_created_ok = !0;
+	}
+	ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+		       __FUNCTION__, ret);
+	} else {
+		dip->debuginfo_created_ok = !0;
+	}
 }
 
 
 static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
 {
 	if (!sfp->debugifc) return;
-	class_device_remove_file(sfp->class_dev,
-				 &sfp->debugifc->attr_debuginfo);
-	class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+	if (sfp->debugifc->debuginfo_created_ok) {
+		class_device_remove_file(sfp->class_dev,
+					 &sfp->debugifc->attr_debuginfo);
+	}
+	if (sfp->debugifc->debugcmd_created_ok) {
+		class_device_remove_file(sfp->class_dev,
+					 &sfp->debugifc->attr_debugcmd);
+	}
 	kfree(sfp->debugifc);
 	sfp->debugifc = NULL;
 }
@@ -645,7 +676,9 @@
 	struct pvr2_sysfs_ctl_item *cip1,*cip2;
 	for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
 		cip2 = cip1->item_next;
-		sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+		if (cip1->created_ok) {
+			sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+		}
 		pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
 		kfree(cip1);
 	}
@@ -675,8 +708,14 @@
 	pvr2_sysfs_tear_down_debugifc(sfp);
 #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
 	pvr2_sysfs_tear_down_controls(sfp);
-	class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
-	class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+	if (sfp->v4l_minor_number_created_ok) {
+		class_device_remove_file(sfp->class_dev,
+					 &sfp->attr_v4l_minor_number);
+	}
+	if (sfp->unit_number_created_ok) {
+		class_device_remove_file(sfp->class_dev,
+					 &sfp->attr_unit_number);
+	}
 	pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
 	sfp->class_dev->class_data = NULL;
 	class_device_unregister(sfp->class_dev);
@@ -709,6 +748,8 @@
 {
 	struct usb_device *usb_dev;
 	struct class_device *class_dev;
+	int ret;
+
 	usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
 	if (!usb_dev) return;
 	class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
@@ -733,20 +774,40 @@
 
 	sfp->class_dev = class_dev;
 	class_dev->class_data = sfp;
-	class_device_register(class_dev);
+	ret = class_device_register(class_dev);
+	if (ret) {
+		printk(KERN_ERR "%s: class_device_register failed\n",
+		       __FUNCTION__);
+		kfree(class_dev);
+		return;
+	}
 
 	sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
 	sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
 	sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
 	sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
 	sfp->attr_v4l_minor_number.store = NULL;
-	class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+	ret = class_device_create_file(sfp->class_dev,
+				       &sfp->attr_v4l_minor_number);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+		       __FUNCTION__, ret);
+	} else {
+		sfp->v4l_minor_number_created_ok = !0;
+	}
+
 	sfp->attr_unit_number.attr.owner = THIS_MODULE;
 	sfp->attr_unit_number.attr.name = "unit_number";
 	sfp->attr_unit_number.attr.mode = S_IRUGO;
 	sfp->attr_unit_number.show = unit_number_show;
 	sfp->attr_unit_number.store = NULL;
-	class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+	ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+	if (ret < 0) {
+		printk(KERN_WARNING "%s: class_device_create_file error: %d\n",
+		       __FUNCTION__, ret);
+	} else {
+		sfp->unit_number_created_ok = !0;
+	}
 
 	pvr2_sysfs_add_controls(sfp);
 #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
index 697145e..8fdf710 100644
--- a/drivers/media/video/pwc/Kconfig
+++ b/drivers/media/video/pwc/Kconfig
@@ -30,7 +30,7 @@
 
 config USB_PWC_DEBUG
 	bool "USB Philips Cameras verbose debug"
-	depends USB_PWC
+	depends on USB_PWC
 	help
 	  Say Y here in order to have the pwc driver generate verbose debugging
 	  messages.
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 47d0d83..d470394 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -160,6 +160,7 @@
 	.poll =		pwc_video_poll,
 	.mmap =		pwc_video_mmap,
 	.ioctl =        pwc_video_ioctl,
+	.compat_ioctl = v4l_compat_ioctl32,
 	.llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index f1fd69e..d73cff1 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -997,9 +997,9 @@
 	struct saa7134_dev *dev = NULL;
 	struct list_head *list;
 
-	if (!dmasound_init && !dmasound_exit) {
-		dmasound_init = alsa_device_init;
-		dmasound_exit = alsa_device_exit;
+	if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+		saa7134_dmasound_init = alsa_device_init;
+		saa7134_dmasound_exit = alsa_device_exit;
 	} else {
 		printk(KERN_WARNING "saa7134 ALSA: can't load, DMA sound handler already assigned (probably to OSS)\n");
 		return -EBUSY;
@@ -1036,8 +1036,8 @@
 		snd_card_free(snd_saa7134_cards[idx]);
 	}
 
-	dmasound_init = NULL;
-	dmasound_exit = NULL;
+	saa7134_dmasound_init = NULL;
+	saa7134_dmasound_exit = NULL;
 	printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
 
 	return;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 6e97cc8..be3a81f 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -95,8 +95,8 @@
 static LIST_HEAD(mops_list);
 static unsigned int saa7134_devcount;
 
-int (*dmasound_init)(struct saa7134_dev *dev);
-int (*dmasound_exit)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
 
 #define dprintk(fmt, arg...)	if (core_debug) \
 	printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
@@ -1008,8 +1008,8 @@
 	/* check for signal */
 	saa7134_irq_video_intl(dev);
 
-	if (dmasound_init && !dev->dmasound.priv_data) {
-		dmasound_init(dev);
+	if (saa7134_dmasound_init && !dev->dmasound.priv_data) {
+		saa7134_dmasound_init(dev);
 	}
 
 	return 0;
@@ -1036,8 +1036,8 @@
 	struct saa7134_mpeg_ops *mops;
 
 	/* Release DMA sound modules if present */
-	if (dmasound_exit && dev->dmasound.priv_data) {
-		dmasound_exit(dev);
+	if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
+		saa7134_dmasound_exit(dev);
 	}
 
 	/* debugging ... */
@@ -1169,8 +1169,8 @@
 
 /* ----------------- for the DMA sound modules --------------- */
 
-EXPORT_SYMBOL(dmasound_init);
-EXPORT_SYMBOL(dmasound_exit);
+EXPORT_SYMBOL(saa7134_dmasound_init);
+EXPORT_SYMBOL(saa7134_dmasound_exit);
 EXPORT_SYMBOL(saa7134_pgtable_free);
 EXPORT_SYMBOL(saa7134_pgtable_build);
 EXPORT_SYMBOL(saa7134_pgtable_alloc);
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 3895d05..2e3ba5f 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -993,9 +993,9 @@
 	struct saa7134_dev *dev = NULL;
 	struct list_head *list;
 
-	if (!dmasound_init && !dmasound_exit) {
-		dmasound_init = oss_device_init;
-		dmasound_exit = oss_device_exit;
+	if (!saa7134_dmasound_init && !saa7134_dmasound_exit) {
+		saa7134_dmasound_init = oss_device_init;
+		saa7134_dmasound_exit = oss_device_exit;
 	} else {
 		printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n");
 		return -EBUSY;
@@ -1037,8 +1037,8 @@
 
 	}
 
-	dmasound_init = NULL;
-	dmasound_exit = NULL;
+	saa7134_dmasound_init = NULL;
+	saa7134_dmasound_exit = NULL;
 
 	printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
 
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index e4156ec..2c171af 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -40,7 +40,7 @@
 
 static unsigned int video_debug   = 0;
 static unsigned int gbuffers      = 8;
-static unsigned int noninterlaced = 0;
+static unsigned int noninterlaced = 1;
 static unsigned int gbufsize      = 720*576*4;
 static unsigned int gbufsize_max  = 720*576*4;
 module_param(video_debug, int, 0644);
@@ -48,7 +48,7 @@
 module_param(gbuffers, int, 0444);
 MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
 module_param(noninterlaced, int, 0644);
-MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced");
+MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");
 
 #define dprintk(fmt, arg...)	if (video_debug) \
 	printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
@@ -2087,7 +2087,7 @@
 		struct v4l2_format *f = arg;
 		return saa7134_try_fmt(dev,fh,f);
 	}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCGMBUF:
 	{
 		struct video_mbuf *mbuf = arg;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index d5ee99c..c04ce61 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -586,8 +586,8 @@
 
 int saa7134_set_dmabits(struct saa7134_dev *dev);
 
-extern int (*dmasound_init)(struct saa7134_dev *dev);
-extern int (*dmasound_exit)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
 
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index b36ba9f..5686547 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -2181,7 +2181,6 @@
 	{ 0 }
 };
 
-MODULE_DEVICE_TABLE(pci, stradis_pci_tbl);
 
 static struct pci_driver stradis_driver = {
 	.name = "stradis",
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index f7eb402..40590ba 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -196,14 +196,6 @@
 		i2c_master_send(c, buffer, 4);
 		default_tuner_init(c);
 		break;
-	case TUNER_LG_TDVS_H06XF:
-		/* Set the Auxiliary Byte. */
-		buffer[2] &= ~0x20;
-		buffer[2] |= 0x18;
-		buffer[3] = 0x20;
-		i2c_master_send(c, buffer, 4);
-		default_tuner_init(c);
-		break;
 	case TUNER_PHILIPS_TD1316:
 		buffer[0] = 0x0b;
 		buffer[1] = 0xdc;
@@ -598,6 +590,7 @@
 		if (t->standby)
 			t->standby (client);
 		break;
+#ifdef CONFIG_VIDEO_V4L1
 	case VIDIOCSAUDIO:
 		if (check_mode(t, "VIDIOCSAUDIO") == EINVAL)
 			return 0;
@@ -607,17 +600,6 @@
 		/* Should be implemented, since bttv calls it */
 		tuner_dbg("VIDIOCSAUDIO not implemented.\n");
 		break;
-	case TDA9887_SET_CONFIG:
-		if (t->type == TUNER_TDA9887) {
-			int *i = arg;
-
-			t->tda9887_config = *i;
-			set_freq(client, t->tv_freq);
-		}
-		break;
-	/* --- v4l ioctls --- */
-	/* take care: bttv does userspace copying, we'll get a
-	   kernel pointer here... */
 	case VIDIOCSCHAN:
 		{
 			static const v4l2_std_id map[] = {
@@ -701,7 +683,18 @@
 				    ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
 			return 0;
 		}
+#endif
+	case TDA9887_SET_CONFIG:
+		if (t->type == TUNER_TDA9887) {
+			int *i = arg;
 
+			t->tda9887_config = *i;
+			set_freq(client, t->tv_freq);
+		}
+		break;
+	/* --- v4l ioctls --- */
+	/* take care: bttv does userspace copying, we'll get a
+	   kernel pointer here... */
 	case VIDIOC_S_STD:
 		{
 			v4l2_std_id *id = arg;
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index d071c5c..abe37cf 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -339,7 +339,20 @@
 	if (4 != (rc = i2c_master_send(c,buffer,4)))
 		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
 
-	if (t->type == TUNER_MICROTUNE_4042FI5) {
+	switch (t->type) {
+	case TUNER_LG_TDVS_H06XF:
+		/* Set the Auxiliary Byte. */
+		buffer[0] = buffer[2];
+		buffer[0] &= ~0x20;
+		buffer[0] |= 0x18;
+		buffer[1] = 0x20;
+		tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);
+
+		if (2 != (rc = i2c_master_send(c,buffer,2)))
+			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);
+		break;
+	case TUNER_MICROTUNE_4042FI5:
+	{
 		// FIXME - this may also work for other tuners
 		unsigned long timeout = jiffies + msecs_to_jiffies(1);
 		u8 status_byte = 0;
@@ -364,10 +377,12 @@
 		buffer[2] = config;
 		buffer[3] = cb;
 		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		       buffer[0],buffer[1],buffer[2],buffer[3]);
+			  buffer[0],buffer[1],buffer[2],buffer[3]);
 
 		if (4 != (rc = i2c_master_send(c,buffer,4)))
 			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+		break;
+	}
 	}
 }
 
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index a167e17..d7eadc2 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -1027,10 +1027,11 @@
 /* 70-79 */
 /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
 
+/* '+ 4' turns on the Low Noise Amplifier */
 static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
-	{ 16 * 130.00 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 364.50 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x08, },
+	{ 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
+	{ 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
+	{ 16 * 999.99        , 0xce, 0x08 + 4, },
 };
 
 static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
@@ -1060,10 +1061,11 @@
 
 /* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
 
+/* '+ 4' turns on the Low Noise Amplifier */
 static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
-	{ 16 * 146.25 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 428.50 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x08, },
+	{ 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
+	{ 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
+	{ 16 * 999.99        , 0xce, 0x08 + 4, },
 };
 
 static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
index 59fb899..a0fd82b 100644
--- a/drivers/media/video/usbvideo/Kconfig
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -3,7 +3,7 @@
 
 config USB_VICAM
 	tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)"
-	depends on USB && VIDEO_V4L1 && EXPERIMENTAL
+	depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you have 3com homeconnect camera (vicam).
@@ -13,7 +13,7 @@
 
 config USB_IBMCAM
 	tristate "USB IBM (Xirlink) C-it Camera support"
-	depends on USB && VIDEO_V4L1
+	depends on USB && VIDEO_DEV && VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you want to connect a IBM "C-It" camera, also known as
@@ -28,7 +28,7 @@
 
 config USB_KONICAWC
 	tristate "USB Konica Webcam support"
-	depends on USB && VIDEO_V4L1
+	depends on USB && VIDEO_DEV && VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y here if you want support for webcams based on a Konica
@@ -39,7 +39,7 @@
 
 config USB_QUICKCAM_MESSENGER
 	tristate "USB Logitech Quickcam Messenger"
-	depends on USB && VIDEO_DEV
+	depends on USB && VIDEO_DEV && VIDEO_V4L1
 	select VIDEO_USBVIDEO
 	---help---
 	  Say Y or M here to enable support for the USB Logitech Quickcam
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index d83a2c8..d7c3fcb 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -599,6 +599,10 @@
 			dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
 			break;
 		}
+
+		pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
+				 + (fmt2->fmt.pix.width-1) )
+				 /fmt2->fmt.pix.width;
 		pict->palette = pixelformat_to_palette(
 			fmt2->fmt.pix.pixelformat);
 		break;
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index f06dc19..8d972ffd 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -202,7 +202,7 @@
 /* ------------------------------------------------------------------ */
 /* debug help functions                                               */
 
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 static const char *v4l1_ioctls[] = {
 	[_IOC_NR(VIDIOCGCAP)]       = "VIDIOCGCAP",
 	[_IOC_NR(VIDIOCGCHAN)]      = "VIDIOCGCHAN",
@@ -301,7 +301,7 @@
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
 static const char *v4l2_int_ioctls[] = {
-#ifdef HAVE_VIDEO_DECODER
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	[_IOC_NR(DECODER_GET_CAPABILITIES)]    = "DECODER_GET_CAPABILITIES",
 	[_IOC_NR(DECODER_GET_STATUS)]          = "DECODER_GET_STATUS",
 	[_IOC_NR(DECODER_SET_NORM)]            = "DECODER_SET_NORM",
@@ -367,7 +367,7 @@
 		       (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ?
 		       v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd);
 		break;
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case 'v':
 		printk("v4l1 ioctl %s, dir=%s (0x%08x)\n",
 		       (_IOC_NR(cmd) < V4L1_IOCTLS) ?
@@ -414,6 +414,7 @@
 		printk ("%s: tuner type=%d\n", s, *p);
 		break;
 	}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case DECODER_SET_VBI_BYPASS:
 	case DECODER_ENABLE_OUTPUT:
 	case DECODER_GET_STATUS:
@@ -424,6 +425,7 @@
 	case VIDIOCCAPTURE:
 	case VIDIOCSYNC:
 	case VIDIOCSWRITEMODE:
+#endif
 	case TUNER_SET_TYPE_ADDR:
 	case TUNER_SET_STANDBY:
 	case TDA9887_SET_CONFIG:
@@ -755,6 +757,7 @@
 				p->afc);
 		break;
 	}
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	case VIDIOCGVBIFMT:
 	case VIDIOCSVBIFMT:
 	{
@@ -924,6 +927,14 @@
 				p->clipcount);
 		break;
 	}
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
+	{
+		unsigned long *p=arg;
+		printk ("%s: value=%lu\n", s, *p);
+		break;
+	}
+#endif
 	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
 	case VIDIOC_INT_I2S_CLOCK_FREQ:
 	case VIDIOC_INT_S_STANDBY:
@@ -933,13 +944,6 @@
 		printk ("%s: value=%d\n", s, *p);
 		break;
 	}
-	case VIDIOCGFREQ:
-	case VIDIOCSFREQ:
-	{
-		unsigned long *p=arg;
-		printk ("%s: value=%lu\n", s, *p);
-		break;
-	}
 	case VIDIOC_G_STD:
 	case VIDIOC_S_STD:
 	case VIDIOC_QUERYSTD:
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index b26ebaf..88bf2af 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -760,7 +760,7 @@
 		ret=vfd->vidioc_overlay(file, fh, *i);
 		break;
 	}
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	/* --- streaming capture ------------------------------------- */
 	case VIDIOCGMBUF:
 	{
@@ -1512,6 +1512,7 @@
 	int i=0;
 	int base;
 	int end;
+	int ret;
 	char *name_base;
 
 	switch(type)
@@ -1537,6 +1538,8 @@
 			name_base = "radio";
 			break;
 		default:
+			printk(KERN_ERR "%s called with unknown type: %d\n",
+			       __FUNCTION__, type);
 			return -1;
 	}
 
@@ -1571,9 +1574,18 @@
 	vfd->class_dev.class       = &video_class;
 	vfd->class_dev.devt        = MKDEV(VIDEO_MAJOR, vfd->minor);
 	sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base);
-	class_device_register(&vfd->class_dev);
-	class_device_create_file(&vfd->class_dev,
-				&class_device_attr_name);
+	ret = class_device_register(&vfd->class_dev);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: class_device_register failed\n",
+		       __FUNCTION__);
+		goto fail_minor;
+	}
+	ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: class_device_create_file 'name' failed\n",
+		       __FUNCTION__);
+		goto fail_classdev;
+	}
 
 #if 1
 	/* needed until all drivers are fixed */
@@ -1583,6 +1595,15 @@
 		       "http://lwn.net/Articles/36850/\n", vfd->name);
 #endif
 	return 0;
+
+fail_classdev:
+	class_device_unregister(&vfd->class_dev);
+fail_minor:
+	mutex_lock(&videodev_lock);
+	video_device[vfd->minor] = NULL;
+	vfd->minor = -1;
+	mutex_unlock(&videodev_lock);
+	return ret;
 }
 
 /**
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 41d23c8..841884a 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -986,7 +986,7 @@
 				file->f_flags & O_NONBLOCK));
 }
 
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
 {
 	struct vivi_fh  *fh=priv;
@@ -1328,7 +1328,7 @@
 	.vidioc_s_ctrl        = vidioc_s_ctrl,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
-#ifdef HAVE_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 	.vidiocgmbuf          = vidiocgmbuf,
 #endif
 	.tvnorms              = tvnorms,
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index d4cb144..c537d71 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -640,7 +640,6 @@
 	struct work_struct	 fc_setup_reset_work;
 	struct list_head	 fc_rports;
 	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;
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 90da7d6..85696f3 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -669,7 +669,10 @@
 			 * if still doing discovery,
 			 * hang loose a while until finished
 			 */
-			if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+			if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) ||
+			    (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE &&
+			     (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK)
+			      == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) {
 				if (count-- > 0) {
 					msleep(100);
 					goto try_again;
@@ -895,59 +898,45 @@
 {
 	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 */
-		list_for_each_entry(ri, &ioc->fc_rports, list) {
-			if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
-				ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
-			}
+	/* start by tagging all ports as missing */
+	list_for_each_entry(ri, &ioc->fc_rports, list) {
+		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+			ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
 		}
+	}
 
-		/*
-		 * now rescan devices known to adapter,
-		 * will reregister existing rports
-		 */
-		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-			(void) mptfc_GetFcPortPage0(ioc, ii);
-			mptfc_init_host_attr(ioc,ii);	/* refresh */
-			mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+	/*
+	 * now rescan devices known to adapter,
+	 * will reregister existing rports
+	 */
+	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+		(void) mptfc_GetFcPortPage0(ioc, ii);
+		mptfc_init_host_attr(ioc, ii);	/* refresh */
+		mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev);
+	}
+
+	/* delete devices still missing */
+	list_for_each_entry(ri, &ioc->fc_rports, list) {
+		/* if newly missing, delete it */
+		if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
+
+			ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+				       MPT_RPORT_INFO_FLAGS_MISSING);
+			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,
+				(unsigned long long)pn));
 		}
-
-		/* delete devices still missing */
-		list_for_each_entry(ri, &ioc->fc_rports, list) {
-			/* if newly missing, delete it */
-			if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) {
-
-				ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
-					       MPT_RPORT_INFO_FLAGS_MISSING);
-				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,
-					(unsigned long long)pn));
-			}
-		}
-
-		/*
-		 * allow multiple passes as target state
-		 * might have changed during scan
-		 */
-		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-		if (ioc->fc_rescan_work_count > 2) 	/* only need one more */
-			ioc->fc_rescan_work_count = 2;
-		work_to_do = --ioc->fc_rescan_work_count;
-		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-	} while (work_to_do);
+	}
 }
 
 static int
@@ -1159,7 +1148,6 @@
 	 *	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);
 
@@ -1202,10 +1190,8 @@
 	case MPI_EVENT_RESCAN:
 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
 		if (ioc->fc_rescan_work_q) {
-			if (ioc->fc_rescan_work_count++ == 0) {
-				queue_work(ioc->fc_rescan_work_q,
-					   &ioc->fc_rescan_work);
-			}
+			queue_work(ioc->fc_rescan_work_q,
+				   &ioc->fc_rescan_work);
 		}
 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
 		break;
@@ -1248,10 +1234,8 @@
 		mptfc_SetFcPortPage1_defaults(ioc);
 		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
 		if (ioc->fc_rescan_work_q) {
-			if (ioc->fc_rescan_work_count++ == 0) {
-				queue_work(ioc->fc_rescan_work_q,
-					   &ioc->fc_rescan_work);
-			}
+			queue_work(ioc->fc_rescan_work_q,
+				   &ioc->fc_rescan_work);
 		}
 		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
 	}
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index 7ca9e95..fb6565b 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -91,6 +91,8 @@
 	int			dma_allocated;
 
 	unsigned char		actual_bus_width;
+
+	int			prev_cmd_code;
 };
 
 #define IMXMCI_PEND_IRQ_b	0
@@ -248,16 +250,14 @@
 	 * partial FIFO fills and reads. The length has to be rounded up to burst size multiple.
 	 * This is required for SCR read at least.
 	 */
-	if (datasz < 64) {
+	if (datasz < 512) {
 		host->dma_size = datasz;
 		if (data->flags & MMC_DATA_READ) {
 			host->dma_dir = DMA_FROM_DEVICE;
 
 			/* Hack to enable read SCR */
-			if(datasz < 16) {
-				MMC_NOB = 1;
-				MMC_BLK_LEN = 16;
-			}
+			MMC_NOB = 1;
+			MMC_BLK_LEN = 512;
 		} else {
 			host->dma_dir = DMA_TO_DEVICE;
 		}
@@ -409,6 +409,9 @@
 
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	if(req && req->cmd)
+		host->prev_cmd_code = req->cmd->opcode;
+
 	host->req = NULL;
 	host->cmd = NULL;
 	host->data = NULL;
@@ -553,7 +556,6 @@
 {
 	int i;
 	int burst_len;
-	int flush_len;
 	int trans_done = 0;
 	unsigned int stat = *pstat;
 
@@ -566,44 +568,43 @@
 	dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n",
 		stat);
 
+	udelay(20);	/* required for clocks < 8MHz*/
+
 	if(host->dma_dir == DMA_FROM_DEVICE) {
 		imxmci_busy_wait_for_status(host, &stat,
 				STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE,
-				20, "imxmci_cpu_driven_data read");
+				50, "imxmci_cpu_driven_data read");
 
 		while((stat & (STATUS_APPL_BUFF_FF |  STATUS_DATA_TRANS_DONE)) &&
-		      (host->data_cnt < host->dma_size)) {
-			if(burst_len >= host->dma_size - host->data_cnt) {
-				flush_len = burst_len;
-				burst_len = host->dma_size - host->data_cnt;
-				flush_len -= burst_len;
-				host->data_cnt = host->dma_size;
-				trans_done = 1;
-			} else {
-				flush_len = 0;
-				host->data_cnt += burst_len;
-			}
+		      (host->data_cnt < 512)) {
+
+			udelay(20);	/* required for clocks < 8MHz*/
 
 			for(i = burst_len; i>=2 ; i-=2) {
-				*(host->data_ptr++) = MMC_BUFFER_ACCESS;
-				udelay(20);	/* required for clocks < 8MHz*/
+				u16 data;
+				data = MMC_BUFFER_ACCESS;
+				udelay(10);	/* required for clocks < 8MHz*/
+				if(host->data_cnt+2 <= host->dma_size) {
+					*(host->data_ptr++) = data;
+				} else {
+					if(host->data_cnt < host->dma_size)
+						*(u8*)(host->data_ptr) = data;
+				}
+				host->data_cnt += 2;
 			}
 
-			if(i == 1)
-				*(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS;
-
 			stat = MMC_STATUS;
 
-			/* Flush extra bytes from FIFO */
-			while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){
-				i = MMC_BUFFER_ACCESS;
-				stat = MMC_STATUS;
-				stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */
-			}
-
-			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n",
-				burst_len, stat);
+			dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n",
+				host->data_cnt, burst_len, stat);
 		}
+
+		if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512))
+			trans_done = 1;
+
+		if(host->dma_size & 0x1ff)
+			stat &= ~STATUS_CRC_READ_ERR;
+
 	} else {
 		imxmci_busy_wait_for_status(host, &stat,
 				STATUS_APPL_BUFF_FE,
@@ -692,8 +693,8 @@
 		       what, stat, MMC_INT_MASK);
 		dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n",
 		       MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma));
-		dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n",
-		       host->cmd?host->cmd->opcode:0, 1<<host->actual_bus_width, host->dma_size);
+		dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n",
+		       host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<<host->actual_bus_width, host->dma_size);
 	}
 
 	if(!host->present || timeout)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 33525bd..74eaaee 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -247,6 +247,55 @@
 
 EXPORT_SYMBOL(mmc_wait_for_app_cmd);
 
+/**
+ *	mmc_set_data_timeout - set the timeout for a data command
+ *	@data: data phase for command
+ *	@card: the MMC card associated with the data transfer
+ *	@write: flag to differentiate reads from writes
+ */
+void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
+			  int write)
+{
+	unsigned int mult;
+
+	/*
+	 * SD cards use a 100 multiplier rather than 10
+	 */
+	mult = mmc_card_sd(card) ? 100 : 10;
+
+	/*
+	 * Scale up the multiplier (and therefore the timeout) by
+	 * the r2w factor for writes.
+	 */
+	if (write)
+		mult <<= card->csd.r2w_factor;
+
+	data->timeout_ns = card->csd.tacc_ns * mult;
+	data->timeout_clks = card->csd.tacc_clks * mult;
+
+	/*
+	 * SD cards also have an upper limit on the timeout.
+	 */
+	if (mmc_card_sd(card)) {
+		unsigned int timeout_us, limit_us;
+
+		timeout_us = data->timeout_ns / 1000;
+		timeout_us += data->timeout_clks * 1000 /
+			(card->host->ios.clock / 1000);
+
+		if (write)
+			limit_us = 250000;
+		else
+			limit_us = 100000;
+
+		if (timeout_us > limit_us) {
+			data->timeout_ns = limit_us * 1000;
+			data->timeout_clks = 0;
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_set_data_timeout);
+
 static int mmc_select_card(struct mmc_host *host, struct mmc_card *card);
 
 /**
@@ -908,11 +957,9 @@
 {
 	int err;
 	struct mmc_card *card;
-
 	struct mmc_request mrq;
 	struct mmc_command cmd;
 	struct mmc_data data;
-
 	struct scatterlist sg;
 
 	list_for_each_entry(card, &host->cards, node) {
@@ -947,8 +994,8 @@
 
 		memset(&data, 0, sizeof(struct mmc_data));
 
-		data.timeout_ns = card->csd.tacc_ns * 10;
-		data.timeout_clks = card->csd.tacc_clks * 10;
+		mmc_set_data_timeout(&data, card, 0);
+
 		data.blksz_bits = 3;
 		data.blksz = 1 << 3;
 		data.blocks = 1;
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index 115cc21..a0e0dad 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -30,6 +30,7 @@
 #include <linux/mutex.h>
 
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/protocol.h>
 
 #include <asm/system.h>
@@ -171,8 +172,6 @@
 
 		brq.cmd.arg = req->sector << 9;
 		brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-		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);
@@ -180,6 +179,8 @@
 		brq.stop.arg = 0;
 		brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
+		mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
+
 		if (rq_data_dir(req) == READ) {
 			brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK;
 			brq.data.flags |= MMC_DATA_READ;
@@ -187,12 +188,6 @@
 			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) {
@@ -324,52 +319,11 @@
 	md->read_only = mmc_blk_readonly(card);
 
 	/*
-	 * Figure out a workable block size.  MMC cards have:
-	 *  - two block sizes, one for read and one for write.
-	 *  - may support partial reads and/or writes
-	 *    (allows block sizes smaller than specified)
+	 * Both SD and MMC specifications state (although a bit
+	 * unclearly in the MMC case) that a block size of 512
+	 * bytes must always be supported by the card.
 	 */
-	md->block_bits = card->csd.read_blkbits;
-	if (card->csd.write_blkbits != card->csd.read_blkbits) {
-		if (card->csd.write_blkbits < card->csd.read_blkbits &&
-		    card->csd.read_partial) {
-			/*
-			 * write block size is smaller than read block
-			 * size, but we support partial reads, so choose
-			 * the smaller write block size.
-			 */
-			md->block_bits = card->csd.write_blkbits;
-		} else if (card->csd.write_blkbits > card->csd.read_blkbits &&
-			   card->csd.write_partial) {
-			/*
-			 * read block size is smaller than write block
-			 * size, but we support partial writes.  Use read
-			 * block size.
-			 */
-		} else {
-			/*
-			 * We don't support this configuration for writes.
-			 */
-			printk(KERN_ERR "%s: unable to select block size for "
-				"writing (rb%u wb%u rp%u wp%u)\n",
-				mmc_card_id(card),
-				1 << card->csd.read_blkbits,
-				1 << card->csd.write_blkbits,
-				card->csd.read_partial,
-				card->csd.write_partial);
-			md->read_only = 1;
-		}
-	}
-
-	/*
-	 * Refuse to allow block sizes smaller than 512 bytes.
-	 */
-	if (md->block_bits < 9) {
-		printk(KERN_ERR "%s: unable to support block size %u\n",
-			mmc_card_id(card), 1 << md->block_bits);
-		ret = -EINVAL;
-		goto err_kfree;
-	}
+	md->block_bits = 9;
 
 	md->disk = alloc_disk(1 << MMC_SHIFT);
 	if (md->disk == NULL) {
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c
index 0b9682e..74f8cde 100644
--- a/drivers/mmc/mmc_queue.c
+++ b/drivers/mmc/mmc_queue.c
@@ -79,7 +79,8 @@
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (!blk_queue_plugged(q))
-			mq->req = req = elv_next_request(q);
+			req = elv_next_request(q);
+		mq->req = req;
 		spin_unlock_irq(q->queue_lock);
 
 		if (!req) {
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 8a30ef3..c351c6d 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -41,7 +41,7 @@
 #include "wbsd.h"
 
 #define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.5"
+#define DRIVER_VERSION "1.6"
 
 #define DBG(x...) \
 	pr_debug(DRIVER_NAME ": " x)
@@ -1439,13 +1439,13 @@
 
 static int __devinit wbsd_request_region(struct wbsd_host *host, int base)
 {
-	if (io & 0x7)
+	if (base & 0x7)
 		return -EINVAL;
 
 	if (!request_region(base, 8, DRIVER_NAME))
 		return -EIO;
 
-	host->base = io;
+	host->base = base;
 
 	return 0;
 }
@@ -1773,7 +1773,7 @@
 	/*
 	 * Request resources.
 	 */
-	ret = wbsd_request_resources(host, io, irq, dma);
+	ret = wbsd_request_resources(host, base, irq, dma);
 	if (ret) {
 		wbsd_release_resources(host);
 		wbsd_free_mmc(dev);
@@ -1861,6 +1861,7 @@
 
 static int __devinit wbsd_probe(struct platform_device *dev)
 {
+	/* Use the module parameters for resources */
 	return wbsd_init(&dev->dev, io, irq, dma, 0);
 }
 
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index d7897dc..a0ba07c 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -130,11 +130,13 @@
 	if (ctrl & NAND_CTRL_CHANGE) {
 		unsigned long bits;
 
-		bits = (~ctrl & NAND_NCE) << 2;
-		bits |= (ctrl & NAND_CLE) << 7;
-		bits |= (ctrl & NAND_ALE) << 6;
+		bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0;
+		bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0;
+		bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0;
 
-		ams_delta_latch2_write(0xC2, bits);
+		ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE |
+				AMS_DELTA_LATCH2_NAND_ALE |
+				AMS_DELTA_LATCH2_NAND_NCE, bits);
 	}
 
 	if (cmd != NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 62b8613..c8cbc00 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1093,9 +1093,10 @@
 
 	ret = nand_do_read_ops(mtd, from, &chip->ops);
 
+	*retlen = chip->ops.retlen;
+
 	nand_release_device(mtd);
 
-	*retlen = chip->ops.retlen;
 	return ret;
 }
 
@@ -1691,9 +1692,10 @@
 
 	ret = nand_do_write_ops(mtd, to, &chip->ops);
 
+	*retlen = chip->ops.retlen;
+
 	nand_release_device(mtd);
 
-	*retlen = chip->ops.retlen;
 	return ret;
 }
 
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 07136ec..d7b115a 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -120,7 +120,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/config.h>	/* for CONFIG_IP_MULTICAST */
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index 4532b17..aedfddf 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -1003,7 +1003,8 @@
 		/* Calculate the next Tx descriptor entry. */
 		int entry = vp->cur_tx % TX_RING_SIZE;
 		struct boom_tx_desc *prev_entry;
-		unsigned long flags, i;
+		unsigned long flags;
+		int i;
 
 		if (vp->tx_full)	/* No room to transmit with */
 			return 1;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 80e8ca0..415d081 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2928,7 +2928,7 @@
 	int new_mode;
 
 	if (dev->flags & IFF_PROMISC) {
-		if (vortex_debug > 0)
+		if (vortex_debug > 3)
 			printk(KERN_NOTICE "%s: Setting promiscuous mode.\n", dev->name);
 		new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm;
 	} else	if ((dev->mc_list)  ||  (dev->flags & IFF_ALLMULTI)) {
@@ -3169,7 +3169,7 @@
 {
 	int pci_rc, eisa_rc;
 
-	pci_rc = pci_module_init(&vortex_driver);
+	pci_rc = pci_register_driver(&vortex_driver);
 	eisa_rc = vortex_eisa_init();
 
 	if (pci_rc == 0)
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 1428bb7..488241c 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -48,7 +48,7 @@
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"1.2"
+#define DRV_VERSION		"1.3"
 #define DRV_RELDATE		"Mar 22, 2004"
 
 
@@ -314,12 +314,6 @@
 	u64		addr;
 };
 
-struct ring_info {
-	struct sk_buff		*skb;
-	dma_addr_t		mapping;
-	u32			len;
-};
-
 struct cp_dma_stats {
 	u64			tx_ok;
 	u64			rx_ok;
@@ -353,23 +347,23 @@
 	struct net_device_stats net_stats;
 	struct cp_extra_stats	cp_stats;
 
-	unsigned		rx_tail		____cacheline_aligned;
+	unsigned		rx_head		____cacheline_aligned;
+	unsigned		rx_tail;
 	struct cp_desc		*rx_ring;
-	struct ring_info	rx_skb[CP_RX_RING_SIZE];
-	unsigned		rx_buf_sz;
+	struct sk_buff		*rx_skb[CP_RX_RING_SIZE];
 
 	unsigned		tx_head		____cacheline_aligned;
 	unsigned		tx_tail;
-
 	struct cp_desc		*tx_ring;
-	struct ring_info	tx_skb[CP_TX_RING_SIZE];
-	dma_addr_t		ring_dma;
+	struct sk_buff		*tx_skb[CP_TX_RING_SIZE];
+
+	unsigned		rx_buf_sz;
+	unsigned		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
 
 #if CP_VLAN_TAG_USED
 	struct vlan_group	*vlgrp;
 #endif
-
-	unsigned int		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
+	dma_addr_t		ring_dma;
 
 	struct mii_if_info	mii_if;
 };
@@ -407,10 +401,8 @@
 			 struct ethtool_eeprom *eeprom, u8 *data);
 
 static struct pci_device_id cp_pci_tbl[] = {
-	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-	{ PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	PCI_DEVICE_ID_REALTEK_8139), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_TTTECH,	PCI_DEVICE_ID_TTTECH_MC322), },
 	{ },
 };
 MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
@@ -542,7 +534,7 @@
 		struct cp_desc *desc;
 		unsigned buflen;
 
-		skb = cp->rx_skb[rx_tail].skb;
+		skb = cp->rx_skb[rx_tail];
 		BUG_ON(!skb);
 
 		desc = &cp->rx_ring[rx_tail];
@@ -551,7 +543,7 @@
 			break;
 
 		len = (status & 0x1fff) - 4;
-		mapping = cp->rx_skb[rx_tail].mapping;
+		mapping = le64_to_cpu(desc->addr);
 
 		if ((status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag)) {
 			/* we don't support incoming fragmented frames.
@@ -572,7 +564,7 @@
 
 		if (netif_msg_rx_status(cp))
 			printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
-			       cp->dev->name, rx_tail, status, len);
+			       dev->name, rx_tail, status, len);
 
 		buflen = cp->rx_buf_sz + RX_OFFSET;
 		new_skb = dev_alloc_skb (buflen);
@@ -582,7 +574,7 @@
 		}
 
 		skb_reserve(new_skb, RX_OFFSET);
-		new_skb->dev = cp->dev;
+		new_skb->dev = dev;
 
 		pci_unmap_single(cp->pdev, mapping,
 				 buflen, PCI_DMA_FROMDEVICE);
@@ -595,11 +587,9 @@
 
 		skb_put(skb, len);
 
-		mapping =
-		cp->rx_skb[rx_tail].mapping =
-			pci_map_single(cp->pdev, new_skb->data,
-				       buflen, PCI_DMA_FROMDEVICE);
-		cp->rx_skb[rx_tail].skb = new_skb;
+		mapping = pci_map_single(cp->pdev, new_skb->data, buflen,
+					 PCI_DMA_FROMDEVICE);
+		cp->rx_skb[rx_tail] = new_skb;
 
 		cp_rx_skb(cp, skb, desc);
 		rx++;
@@ -717,19 +707,21 @@
 	unsigned tx_tail = cp->tx_tail;
 
 	while (tx_tail != tx_head) {
+		struct cp_desc *txd = cp->tx_ring + tx_tail;
 		struct sk_buff *skb;
 		u32 status;
 
 		rmb();
-		status = le32_to_cpu(cp->tx_ring[tx_tail].opts1);
+		status = le32_to_cpu(txd->opts1);
 		if (status & DescOwn)
 			break;
 
-		skb = cp->tx_skb[tx_tail].skb;
+		skb = cp->tx_skb[tx_tail];
 		BUG_ON(!skb);
 
-		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
+		pci_unmap_single(cp->pdev, le64_to_cpu(txd->addr),
+				 le32_to_cpu(txd->opts1) & 0xffff,
+				 PCI_DMA_TODEVICE);
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -756,7 +748,7 @@
 			dev_kfree_skb_irq(skb);
 		}
 
-		cp->tx_skb[tx_tail].skb = NULL;
+		cp->tx_skb[tx_tail] = NULL;
 
 		tx_tail = NEXT_TX(tx_tail);
 	}
@@ -826,9 +818,7 @@
 		txd->opts1 = cpu_to_le32(flags);
 		wmb();
 
-		cp->tx_skb[entry].skb = skb;
-		cp->tx_skb[entry].mapping = mapping;
-		cp->tx_skb[entry].len = len;
+		cp->tx_skb[entry] = skb;
 		entry = NEXT_TX(entry);
 	} else {
 		struct cp_desc *txd;
@@ -844,9 +834,7 @@
 		first_len = skb_headlen(skb);
 		first_mapping = pci_map_single(cp->pdev, skb->data,
 					       first_len, PCI_DMA_TODEVICE);
-		cp->tx_skb[entry].skb = skb;
-		cp->tx_skb[entry].mapping = first_mapping;
-		cp->tx_skb[entry].len = first_len;
+		cp->tx_skb[entry] = skb;
 		entry = NEXT_TX(entry);
 
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -887,9 +875,7 @@
 			txd->opts1 = cpu_to_le32(ctrl);
 			wmb();
 
-			cp->tx_skb[entry].skb = skb;
-			cp->tx_skb[entry].mapping = mapping;
-			cp->tx_skb[entry].len = len;
+			cp->tx_skb[entry] = skb;
 			entry = NEXT_TX(entry);
 		}
 
@@ -942,8 +928,6 @@
 	/* Note: do not reorder, GCC is clever about common statements. */
 	if (dev->flags & IFF_PROMISC) {
 		/* Unconditionally log net taps. */
-		printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-			dev->name);
 		rx_mode =
 		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 		    AcceptAllPhys;
@@ -1091,6 +1075,7 @@
 
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
+		dma_addr_t mapping;
 
 		skb = dev_alloc_skb(cp->rx_buf_sz + RX_OFFSET);
 		if (!skb)
@@ -1099,12 +1084,12 @@
 		skb->dev = cp->dev;
 		skb_reserve(skb, RX_OFFSET);
 
-		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
-			skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-		cp->rx_skb[i].skb = skb;
+		mapping = pci_map_single(cp->pdev, skb->data, cp->rx_buf_sz,
+					 PCI_DMA_FROMDEVICE);
+		cp->rx_skb[i] = skb;
 
 		cp->rx_ring[i].opts2 = 0;
-		cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
+		cp->rx_ring[i].addr = cpu_to_le64(mapping);
 		if (i == (CP_RX_RING_SIZE - 1))
 			cp->rx_ring[i].opts1 =
 				cpu_to_le32(DescOwn | RingEnd | cp->rx_buf_sz);
@@ -1152,23 +1137,27 @@
 
 static void cp_clean_rings (struct cp_private *cp)
 {
+	struct cp_desc *desc;
 	unsigned i;
 
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
-		if (cp->rx_skb[i].skb) {
-			pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
+		if (cp->rx_skb[i]) {
+			desc = cp->rx_ring + i;
+			pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
 					 cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(cp->rx_skb[i].skb);
+			dev_kfree_skb(cp->rx_skb[i]);
 		}
 	}
 
 	for (i = 0; i < CP_TX_RING_SIZE; i++) {
-		if (cp->tx_skb[i].skb) {
-			struct sk_buff *skb = cp->tx_skb[i].skb;
+		if (cp->tx_skb[i]) {
+			struct sk_buff *skb = cp->tx_skb[i];
 
-			pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-				 	 cp->tx_skb[i].len, PCI_DMA_TODEVICE);
-			if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+			desc = cp->tx_ring + i;
+			pci_unmap_single(cp->pdev, le64_to_cpu(desc->addr),
+					 le32_to_cpu(desc->opts1) & 0xffff,
+					 PCI_DMA_TODEVICE);
+			if (le32_to_cpu(desc->opts1) & LastFrag)
 				dev_kfree_skb(skb);
 			cp->net_stats.tx_dropped++;
 		}
@@ -1177,8 +1166,8 @@
 	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
 	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
 
-	memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
-	memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
+	memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
+	memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
 }
 
 static void cp_free_rings (struct cp_private *cp)
@@ -2010,7 +1999,6 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct cp_private *cp = netdev_priv(dev);
 
-	BUG_ON(!dev);
 	unregister_netdev(dev);
 	iounmap(cp->regs);
 	if (cp->wol_enabled)
@@ -2025,14 +2013,12 @@
 #ifdef CONFIG_PM
 static int cp_suspend (struct pci_dev *pdev, pm_message_t state)
 {
-	struct net_device *dev;
-	struct cp_private *cp;
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct cp_private *cp = netdev_priv(dev);
 	unsigned long flags;
 
-	dev = pci_get_drvdata (pdev);
-	cp  = netdev_priv(dev);
-
-	if (!dev || !netif_running (dev)) return 0;
+	if (!netif_running(dev))
+		return 0;
 
 	netif_device_detach (dev);
 	netif_stop_queue (dev);
@@ -2098,7 +2084,7 @@
 #ifdef MODULE
 	printk("%s", version);
 #endif
-	return pci_module_init (&cp_driver);
+	return pci_register_driver(&cp_driver);
 }
 
 static void __exit cp_exit (void)
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index e4f4eaf..10301d3 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -90,7 +90,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.27"
+#define DRV_VERSION	"0.9.28"
 
 
 #include <linux/module.h>
@@ -2512,9 +2512,6 @@
 
 	/* Note: do not reorder, GCC is clever about common statements. */
 	if (dev->flags & IFF_PROMISC) {
-		/* Unconditionally log net taps. */
-		printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-			dev->name);
 		rx_mode =
 		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 		    AcceptAllPhys;
@@ -2629,7 +2626,7 @@
 	printk (KERN_INFO RTL8139_DRIVER_NAME "\n");
 #endif
 
-	return pci_module_init (&rtl8139_pci_driver);
+	return pci_register_driver(&rtl8139_pci_driver);
 }
 
 
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 7e2ca95..257d3bc 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -899,7 +899,7 @@
 }
 
 
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
 {
 	struct i596_cmd *ptr;
 
@@ -932,7 +932,8 @@
 	lp->scb.cmd = I596_NULL;
 }
 
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
+static void i596_reset(struct net_device *dev, struct i596_private *lp,
+			int ioaddr)
 {
 	unsigned long flags;
 
@@ -1578,7 +1579,7 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "i82596 debug mask");
 
-int init_module(void)
+int __init init_module(void)
 {
 	if (debug >= 0)
 		i596_debug = debug;
@@ -1588,7 +1589,7 @@
 	return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
 	unregister_netdev(dev_82596);
 #ifdef __mc68000__
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index d2935ae..3eb7048 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -299,7 +299,7 @@
 	 *	Slow phase with lock held.
 	 */
 	 
-	disable_irq_nosync(dev->irq);
+	disable_irq_nosync_lockdep(dev->irq);
 	
 	spin_lock(&ei_local->page_lock);
 	
@@ -338,7 +338,7 @@
 		netif_stop_queue(dev);
 		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 		spin_unlock(&ei_local->page_lock);
-		enable_irq(dev->irq);
+		enable_irq_lockdep(dev->irq);
 		ei_local->stat.tx_errors++;
 		return 1;
 	}
@@ -379,7 +379,7 @@
 	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
 	
 	spin_unlock(&ei_local->page_lock);
-	enable_irq(dev->irq);
+	enable_irq_lockdep(dev->irq);
 
 	dev_kfree_skb (skb);
 	ei_local->stat.tx_bytes += send_length;
@@ -505,9 +505,9 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 void ei_poll(struct net_device *dev)
 {
-	disable_irq(dev->irq);
+	disable_irq_lockdep(dev->irq);
 	ei_interrupt(dev->irq, dev, NULL);
-	enable_irq(dev->irq);
+	enable_irq_lockdep(dev->irq);
 }
 #endif
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3918990..de4f9e1 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1411,6 +1411,22 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will be
 	  called forcedeth.
 
+config FORCEDETH_NAPI
+	bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+	depends on FORCEDETH && EXPERIMENTAL
+	help
+	  NAPI is a new driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card. It is
+	  still somewhat experimental and thus not yet enabled by default.
+
+	  If your estimated Rx load is 10kpps or more, or if the card will be
+	  deployed on potentially unfriendly networks (e.g. in a firewall),
+	  then say Y here.
+
+	  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+	  information.
+
+	  If in doubt, say N.
 
 config CS89x0
 	tristate "CS89x0 support"
@@ -1724,6 +1740,20 @@
 
 	  If unsure, say Y.
 
+config VIA_RHINE_NAPI
+	bool "Use Rx Polling (NAPI)"
+	depends on VIA_RHINE
+	help
+	  NAPI is a new driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card.
+
+	  If your estimated Rx load is 10kpps or more, or if the card will be
+	  deployed on potentially unfriendly networks (e.g. in a firewall),
+	  then say Y here.
+
+	  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+	  information.
+
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
 	depends on NET_PCI && EXPERIMENTAL && MIPS
@@ -2219,6 +2249,33 @@
 	bool "NAPI Support"
 	depends on GIANFAR
 
+config UCC_GETH
+	tristate "Freescale QE UCC GETH"
+	depends on QUICC_ENGINE && UCC_FAST
+	help
+	  This driver supports the Gigabit Ethernet mode of QE UCC.
+	  QE can be found on MPC836x CPUs.
+
+config UGETH_NAPI
+	bool "NAPI Support"
+	depends on UCC_GETH
+
+config UGETH_MAGIC_PACKET
+	bool "Magic Packet detection support"
+	depends on UCC_GETH
+
+config UGETH_FILTERING
+	bool "Mac address filtering support"
+	depends on UCC_GETH
+
+config UGETH_TX_ON_DEMOND
+	bool "Transmit on Demond support"
+	depends on UCC_GETH
+
+config UGETH_HAS_GIGA
+	bool
+	depends on UCC_GETH && MPC836x
+
 config MV643XX_ETH
 	tristate "MV-643XX Ethernet support"
 	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM
@@ -2249,6 +2306,15 @@
 	  This enables support for Port 2 of the Marvell MV643XX Gigabit
 	  Ethernet.
 
+config QLA3XXX
+	tristate "QLogic QLA3XXX Network Driver Support"
+	depends on PCI
+	help
+	  This driver supports QLogic ISP3XXX gigabit Ethernet cards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called qla3xxx.
+
 endmenu
 
 #
@@ -2352,7 +2418,7 @@
 	  you will need a newer firmware image.
 	  You may get this image or more information, at:
 
-	  <http://www.myri.com/Myri-10G/>
+	  <http://www.myri.com/scs/download-Myri10GE.html>
 
 	  To compile this driver as a module, choose M here and read
 	  <file:Documentation/networking/net-modules.txt>.  The module
@@ -2509,6 +2575,7 @@
 
 config PPP
 	tristate "PPP (point-to-point protocol) support"
+	select SLHC
 	---help---
 	  PPP (Point to Point Protocol) is a newer and better SLIP.  It serves
 	  the same purpose: sending Internet traffic over telephone (and other
@@ -2689,6 +2756,7 @@
 config SLIP_COMPRESSED
 	bool "CSLIP compressed headers"
 	depends on SLIP
+	select SLHC
 	---help---
 	  This protocol is faster than SLIP because it uses compression on the
 	  TCP/IP headers (not on the data itself), but it has to be supported
@@ -2701,6 +2769,12 @@
 	  <http://www.tldp.org/docs.html#howto>, explains how to configure
 	  CSLIP. This won't enlarge your kernel.
 
+config SLHC
+	tristate
+	help
+	  This option enables Van Jacobsen serial line header compression
+	  routines.
+
 config SLIP_SMART
 	bool "Keepalive and linefill"
 	depends on SLIP
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index c91e951..6ff1764 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -2,10 +2,6 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
-ifeq ($(CONFIG_ISDN_PPP),y)
-  obj-$(CONFIG_ISDN) += slhc.o
-endif
-
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
@@ -18,6 +14,9 @@
 		gianfar_mii.o \
 		gianfar_sysfs.o
 
+obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
+ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
+
 #
 # link order important here
 #
@@ -110,8 +109,9 @@
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+obj-$(CONFIG_QLA3XXX) += qla3xxx.o
 
-obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
+obj-$(CONFIG_PPP) += ppp_generic.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
 obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
 obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
@@ -120,9 +120,7 @@
 obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
 
 obj-$(CONFIG_SLIP) += slip.o
-ifeq ($(CONFIG_SLIP_COMPRESSED),y)
-  obj-$(CONFIG_SLIP) += slhc.o
-endif
+obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 7952dc6..0fbbcb7 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -370,8 +370,7 @@
 MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 1c01e9b..c0f3574 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -725,7 +725,7 @@
 
 static int __init acenic_init(void)
 {
-	return pci_module_init(&acenic_pci_driver);
+	return pci_register_driver(&acenic_pci_driver);
 }
 
 static void __exit acenic_exit(void)
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index ed322a7..f83df12 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -101,9 +101,9 @@
 
 #include "amd8111e.h"
 #define MODULE_NAME	"amd8111e"
-#define MODULE_VERS	"3.0.5"
+#define MODULE_VERS	"3.0.6"
 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
-MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
+MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.6");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
 module_param_array(speed_duplex, int, NULL, 0);
@@ -1527,7 +1527,6 @@
 	u32 mc_filter[2] ;
 	int i,bit_num;
 	if(dev->flags & IFF_PROMISC){
-		printk(KERN_INFO "%s: Setting  promiscuous mode.\n",dev->name);
 		writel( VAL2 | PROM, lp->mmio + CMD2);
 		return;
 	}
@@ -2158,7 +2157,7 @@
 
 static int __init amd8111e_init(void)
 {
-	return pci_module_init(&amd8111e_driver);
+	return pci_register_driver(&amd8111e_driver);
 }
 
 static void __exit amd8111e_cleanup(void)
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index b14e890..0a0e0cd 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -29,7 +29,7 @@
 	  even politically correct people are allowed to say Y here.
 
 config DEV_APPLETALK
-	bool "Appletalk interfaces support"
+	tristate "Appletalk interfaces support"
 	depends on ATALK
 	help
 	  AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 1d01ac0..ae7f828 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -1030,7 +1030,7 @@
 module_param(irq, int, 0);
 module_param(board_type, int, 0);
 
-int init_module(void)
+int __init init_module(void)
 {
 	if (io == 0)
 		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index 979a33d..fc256c1 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -177,7 +177,7 @@
 static int __init com20020pci_init(void)
 {
 	BUGLVL(D_NORMAL) printk(VERSION);
-	return pci_module_init(&com20020pci_driver);
+	return pci_register_driver(&com20020pci_driver);
 }
 
 static void __exit com20020pci_cleanup(void)
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index cc721ad..3aef3c1 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -825,8 +825,6 @@
     ariadne_init_ring(dev);
 
     if (dev->flags & IFF_PROMISC) {
-	/* Log any net taps. */
-	printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 	lance->RAP = CSR15;		/* Mode Register */
 	lance->RDP = PROM;		/* Set promiscuous mode */
     } else {
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 5d7929c7..1a85451 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -58,7 +58,7 @@
 #include <asm/dma.h>
 
 static char version[] __initdata =
-	"at1700.c:v1.15 4/7/98  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+	"at1700.c:v1.16 9/11/06  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
 #define DRV_NAME "at1700"
 
@@ -851,8 +851,6 @@
 	int i;
 
 	if (dev->flags & IFF_PROMISC) {
-		/* Unconditionally log net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
 		outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
 	} else if (dev->mc_count > MC_FILTERBREAK
@@ -901,7 +899,7 @@
 MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
 MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	if (io == 0)
 		printk("at1700: You should not use auto-probing with insmod!\n");
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 91783a8..465efe7 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -1121,7 +1121,7 @@
 
 	if (dev->flags & IFF_PROMISC) {
 		/* Log any net taps. */
-		DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name ));
+		DPRINTK( 2, ( "%s: Promiscuous mode enabled.\n", dev->name ));
 		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
 	} else {
 		short multicast_table[4];
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 55f6e3f..85be0e6 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -72,7 +72,7 @@
 #endif
 
 #define DRV_NAME	"au1000_eth"
-#define DRV_VERSION	"1.5"
+#define DRV_VERSION	"1.6"
 #define DRV_AUTHOR	"Pete Popov <ppopov@embeddedalley.com>"
 #define DRV_DESC	"Au1xxx on-chip Ethernet driver"
 
@@ -1292,7 +1292,6 @@
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		aup->mac->control |= MAC_PROMISCUOUS;
-		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 	} else if ((dev->flags & IFF_ALLMULTI)  ||
 			   dev->mc_count > MULTICAST_FILTER_LIMIT) {
 		aup->mac->control |= MAC_PASS_ALL_MULTI;
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index bea0fc0..17eb291 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -2354,7 +2354,7 @@
 	dma_desc_align_mask = ~(dma_desc_align_size - 1);
 	dma_desc_sync_size = max_t(unsigned int, dma_desc_align_size, sizeof(struct dma_desc));
 
-	return pci_module_init(&b44_driver);
+	return pci_register_driver(&b44_driver);
 }
 
 static void __exit b44_cleanup(void)
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index db73de0..654b903 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -56,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.4.43"
-#define DRV_MODULE_RELDATE	"June 28, 2006"
+#define DRV_MODULE_VERSION	"1.4.44"
+#define DRV_MODULE_RELDATE	"August 10, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -209,8 +209,10 @@
 
 static inline u32 bnx2_tx_avail(struct bnx2 *bp)
 {
-	u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
+	u32 diff;
 
+	smp_mb();
+	diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons);
 	if (diff > MAX_TX_DESC_CNT)
 		diff = (diff & MAX_TX_DESC_CNT) - 1;
 	return (bp->tx_ring_size - diff);
@@ -1569,7 +1571,7 @@
 	struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
 	unsigned long align;
 
-	skb = dev_alloc_skb(bp->rx_buf_size);
+	skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
 	if (skb == NULL) {
 		return -ENOMEM;
 	}
@@ -1578,7 +1580,6 @@
 		skb_reserve(skb, 8 - align);
 	}
 
-	skb->dev = bp->dev;
 	mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
 		PCI_DMA_FROMDEVICE);
 
@@ -1686,15 +1687,20 @@
 	}
 
 	bp->tx_cons = sw_cons;
+	/* Need to make the tx_cons update visible to bnx2_start_xmit()
+	 * before checking for netif_queue_stopped().  Without the
+	 * memory barrier, there is a small possibility that bnx2_start_xmit()
+	 * will miss it and cause the queue to be stopped forever.
+	 */
+	smp_mb();
 
-	if (unlikely(netif_queue_stopped(bp->dev))) {
-		spin_lock(&bp->tx_lock);
+	if (unlikely(netif_queue_stopped(bp->dev)) &&
+		     (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) {
+		netif_tx_lock(bp->dev);
 		if ((netif_queue_stopped(bp->dev)) &&
-		    (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) {
-
+		    (bnx2_tx_avail(bp) > bp->tx_wake_thresh))
 			netif_wake_queue(bp->dev);
-		}
-		spin_unlock(&bp->tx_lock);
+		netif_tx_unlock(bp->dev);
 	}
 }
 
@@ -1786,7 +1792,7 @@
 		if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
 			struct sk_buff *new_skb;
 
-			new_skb = dev_alloc_skb(len + 2);
+			new_skb = netdev_alloc_skb(bp->dev, len + 2);
 			if (new_skb == NULL)
 				goto reuse_rx;
 
@@ -1797,7 +1803,6 @@
 
 			skb_reserve(new_skb, 2);
 			skb_put(new_skb, len);
-			new_skb->dev = bp->dev;
 
 			bnx2_reuse_rx_skb(bp, skb,
 				sw_ring_cons, sw_ring_prod);
@@ -3503,6 +3508,8 @@
 	struct tx_bd *txbd;
 	u32 val;
 
+	bp->tx_wake_thresh = bp->tx_ring_size / 2;
+
 	txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
 		
 	txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
@@ -3952,7 +3959,7 @@
 		return -EINVAL;
 
 	pkt_size = 1514;
-	skb = dev_alloc_skb(pkt_size);
+	skb = netdev_alloc_skb(bp->dev, pkt_size);
 	if (!skb)
 		return -ENOMEM;
 	packet = skb_put(skb, pkt_size);
@@ -4390,10 +4397,8 @@
 #endif
 
 /* Called with netif_tx_lock.
- * hard_start_xmit is pseudo-lockless - a lock is only required when
- * the tx queue is full. This way, we get the benefit of lockless
- * operations most of the time without the complexities to handle
- * netif_stop_queue/wake_queue race conditions.
+ * bnx2_tx_int() runs without netif_tx_lock unless it needs to call
+ * netif_wake_queue().
  */
 static int
 bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -4512,12 +4517,9 @@
 	dev->trans_start = jiffies;
 
 	if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) {
-		spin_lock(&bp->tx_lock);
 		netif_stop_queue(dev);
-		
-		if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)
+		if (bnx2_tx_avail(bp) > bp->tx_wake_thresh)
 			netif_wake_queue(dev);
-		spin_unlock(&bp->tx_lock);
 	}
 
 	return NETDEV_TX_OK;
@@ -5628,7 +5630,6 @@
 	bp->pdev = pdev;
 
 	spin_lock_init(&bp->phy_lock);
-	spin_lock_init(&bp->tx_lock);
 	INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
 
 	dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
@@ -5751,7 +5752,7 @@
 	bp->mac_addr[5] = (u8) reg;
 
 	bp->tx_ring_size = MAX_TX_DESC_CNT;
-	bnx2_set_rx_ring_size(bp, 100);
+	bnx2_set_rx_ring_size(bp, 255);
 
 	bp->rx_csum = 1;
 
@@ -6015,7 +6016,7 @@
 
 static int __init bnx2_init(void)
 {
-	return pci_module_init(&bnx2_pci_driver);
+	return pci_register_driver(&bnx2_pci_driver);
 }
 
 static void __exit bnx2_cleanup(void)
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 658c5ee..fe80476 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -3890,10 +3890,6 @@
 	u32		tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES)));
 	u16		tx_prod;
 
-	struct tx_bd	*tx_desc_ring;
-	struct sw_bd	*tx_buf_ring;
-	int		tx_ring_size;
-
 	u16		tx_cons __attribute__((aligned(L1_CACHE_BYTES)));
 	u16		hw_tx_cons;
 
@@ -3916,9 +3912,11 @@
 	struct sw_bd		*rx_buf_ring;
 	struct rx_bd		*rx_desc_ring[MAX_RX_RINGS];
 
-	/* Only used to synchronize netif_stop_queue/wake_queue when tx */
-	/* ring is full */
-	spinlock_t		tx_lock;
+	/* TX constants */
+	struct tx_bd	*tx_desc_ring;
+	struct sw_bd	*tx_buf_ring;
+	int		tx_ring_size;
+	u32		tx_wake_thresh;
 
 	/* End of fields used in the performance code paths. */
 
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index a31544c..26040ab 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -5245,7 +5245,7 @@
 	else
 		link_transition_timeout = 0;
 
-	return pci_module_init(&cas_driver);
+	return pci_register_driver(&cas_driver);
 }
 
 static void __exit cas_cleanup(void)
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index e678724..b6de184 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -1243,7 +1243,7 @@
 
 static int __init t1_init_module(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit t1_cleanup_module(void)
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 47eecce..2dcca79b 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -1905,8 +1905,7 @@
 
 */
 
-int
-init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
 	struct net_local *lp;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 91cc8cb..7d06ded 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -3444,7 +3444,7 @@
 {
 	int rc_pci, rc_eisa;
 
-	rc_pci = pci_module_init(&dfx_driver);
+	rc_pci = pci_register_driver(&dfx_driver);
 	if (rc_pci >= 0) dfx_have_pci = 1;
 	
 	rc_eisa = dfx_eisa_init();
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 402961e..a572c29 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -1815,7 +1815,7 @@
 static int __init
 rio_init (void)
 {
-	return pci_module_init (&rio_driver);
+	return pci_register_driver(&rio_driver);
 }
 
 static void __exit
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 1b758b7..a860ebb 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -339,6 +339,17 @@
 	spin_unlock_irqrestore(&db->lock,flags);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ *Used by netconsole
+ */
+static void dm9000_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	dm9000_interrupt(dev->irq,dev,NULL);
+	enable_irq(dev->irq);
+}
+#endif
 
 /* dm9000_release_board
  *
@@ -366,8 +377,8 @@
 		kfree(db->data_req);
 	}
 
-	if (db->addr_res != NULL) {
-		release_resource(db->addr_res);
+	if (db->addr_req != NULL) {
+		release_resource(db->addr_req);
 		kfree(db->addr_req);
 	}
 }
@@ -538,6 +549,9 @@
 	ndev->stop		 = &dm9000_stop;
 	ndev->get_stats		 = &dm9000_get_stats;
 	ndev->set_multicast_list = &dm9000_hash_table;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	ndev->poll_controller	 = &dm9000_poll_controller;
+#endif
 
 #ifdef DM9000_PROGRAM_EEPROM
 	program_eeprom(db);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 91ef5f2..47d9708 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
 
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
 
   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
@@ -158,10 +158,10 @@
 
 
 #define DRV_NAME		"e100"
-#define DRV_EXT		"-NAPI"
-#define DRV_VERSION		"3.5.10-k2"DRV_EXT
+#define DRV_EXT			"-NAPI"
+#define DRV_VERSION		"3.5.16-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
-#define DRV_COPYRIGHT		"Copyright(c) 1999-2005 Intel Corporation"
+#define DRV_COPYRIGHT		"Copyright(c) 1999-2006 Intel Corporation"
 #define PFX			DRV_NAME ": "
 
 #define E100_WATCHDOG_PERIOD	(2 * HZ)
@@ -173,8 +173,11 @@
 MODULE_VERSION(DRV_VERSION);
 
 static int debug = 3;
+static int eeprom_bad_csum_allow = 0;
 module_param(debug, int, 0);
+module_param(eeprom_bad_csum_allow, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
 #define DPRINTK(nlevel, klevel, fmt, args...) \
 	(void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
 	printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
@@ -756,7 +759,8 @@
 	checksum = le16_to_cpu(0xBABA - checksum);
 	if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
 		DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
-		return -EAGAIN;
+		if (!eeprom_bad_csum_allow)
+			return -EAGAIN;
 	}
 
 	return 0;
@@ -1391,15 +1395,11 @@
 	}
 
 	if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
-	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000))) {
-		/* enable/disable MDI/MDI-X auto-switching.
-		   MDI/MDI-X auto-switching is disabled for 82551ER/QM chips */
-		if((nic->mac == mac_82551_E) || (nic->mac == mac_82551_F) ||
-		   (nic->mac == mac_82551_10) || (nic->mii.force_media) ||
-		   !(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))
-			mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, 0);
-		else
-			mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, NCONFIG_AUTO_SWITCH);
+	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
+		!(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
+		/* enable/disable MDI/MDI-X auto-switching. */
+		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
+				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
 	}
 
 	return 0;
@@ -1763,11 +1763,10 @@
 #define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
 static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
 {
-	if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + NET_IP_ALIGN)))
+	if(!(rx->skb = netdev_alloc_skb(nic->netdev, RFD_BUF_LEN + NET_IP_ALIGN)))
 		return -ENOMEM;
 
 	/* Align, init, and map the RFD. */
-	rx->skb->dev = nic->netdev;
 	skb_reserve(rx->skb, NET_IP_ALIGN);
 	memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd));
 	rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
@@ -2143,7 +2142,7 @@
 
 	e100_start_receiver(nic, NULL);
 
-	if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) {
+	if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
 		err = -ENOMEM;
 		goto err_loopback_none;
 	}
@@ -2795,6 +2794,7 @@
 	/* Detach; put netif into state similar to hotplug unplug. */
 	netif_poll_enable(netdev);
 	netif_device_detach(netdev);
+	pci_disable_device(pdev);
 
 	/* Request a slot reset. */
 	return PCI_ERS_RESULT_NEED_RESET;
@@ -2873,7 +2873,7 @@
 		printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
 		printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
 	}
-	return pci_module_init(&e100_driver);
+	return pci_register_driver(&e100_driver);
 }
 
 static void __exit e100_cleanup_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index d304297..98afa9c 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -242,12 +242,10 @@
 	struct timer_list watchdog_timer;
 	struct timer_list phy_info_timer;
 	struct vlan_group *vlgrp;
-    	uint16_t mng_vlan_id;
+	uint16_t mng_vlan_id;
 	uint32_t bd_number;
 	uint32_t rx_buffer_len;
-	uint32_t part_num;
 	uint32_t wol;
-	uint32_t ksp3_port_a;
 	uint32_t smartspeed;
 	uint32_t en_mng_pt;
 	uint16_t link_speed;
@@ -342,7 +340,9 @@
 	boolean_t tso_force;
 #endif
 	boolean_t smart_power_down;	/* phy smart power down */
+	boolean_t quad_port_a;
 	unsigned long flags;
+	uint32_t eeprom_wol;
 };
 
 enum e1000_state_t {
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 88a82ba..3fccffd 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -183,6 +183,9 @@
 		return -EINVAL;
 	}
 
+	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+		msleep(1);
+
 	if (ecmd->autoneg == AUTONEG_ENABLE) {
 		hw->autoneg = 1;
 		if (hw->media_type == e1000_media_type_fiber)
@@ -199,16 +202,20 @@
 						  ADVERTISED_TP;
 		ecmd->advertising = hw->autoneg_advertised;
 	} else
-		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex))
+		if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
+			clear_bit(__E1000_RESETTING, &adapter->flags);
 			return -EINVAL;
+		}
 
 	/* reset the link */
 
-	if (netif_running(adapter->netdev))
-		e1000_reinit_locked(adapter);
-	else
+	if (netif_running(adapter->netdev)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
+	} else
 		e1000_reset(adapter);
 
+	clear_bit(__E1000_RESETTING, &adapter->flags);
 	return 0;
 }
 
@@ -238,9 +245,13 @@
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	int retval = 0;
 
 	adapter->fc_autoneg = pause->autoneg;
 
+	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
+		msleep(1);
+
 	if (pause->rx_pause && pause->tx_pause)
 		hw->fc = e1000_fc_full;
 	else if (pause->rx_pause && !pause->tx_pause)
@@ -253,15 +264,17 @@
 	hw->original_fc = hw->fc;
 
 	if (adapter->fc_autoneg == AUTONEG_ENABLE) {
-		if (netif_running(adapter->netdev))
-			e1000_reinit_locked(adapter);
-		else
+		if (netif_running(adapter->netdev)) {
+			e1000_down(adapter);
+			e1000_up(adapter);
+		} else
 			e1000_reset(adapter);
 	} else
-		return ((hw->media_type == e1000_media_type_fiber) ?
-			e1000_setup_link(hw) : e1000_force_mac_fc(hw));
+		retval = ((hw->media_type == e1000_media_type_fiber) ?
+			   e1000_setup_link(hw) : e1000_force_mac_fc(hw));
 
-	return 0;
+	clear_bit(__E1000_RESETTING, &adapter->flags);
+	return retval;
 }
 
 static uint32_t
@@ -415,12 +428,12 @@
 		regs_buff[23] = regs_buff[18]; /* mdix mode */
 		e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0);
 	} else {
-        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
 		regs_buff[13] = (uint32_t)phy_data; /* cable length */
 		regs_buff[14] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
 		regs_buff[15] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
 		regs_buff[16] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
-        	e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+		e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
 		regs_buff[17] = (uint32_t)phy_data; /* extended 10bt distance */
 		regs_buff[18] = regs_buff[13]; /* cable polarity */
 		regs_buff[19] = 0;  /* Dummy (to align w/ IGP phy reg dump) */
@@ -696,7 +709,6 @@
 	}
 
 	clear_bit(__E1000_RESETTING, &adapter->flags);
-
 	return 0;
 err_setup_tx:
 	e1000_free_all_rx_resources(adapter);
@@ -881,16 +893,17 @@
 
 	*data = 0;
 
+	/* NOTE: we don't test MSI interrupts here, yet */
 	/* Hook up test interrupt handler just for this test */
 	if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED,
-			 netdev->name, netdev)) {
- 		shared_int = FALSE;
- 	} else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
-			      netdev->name, netdev)){
+			 netdev->name, netdev))
+		shared_int = FALSE;
+	else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED,
+			      netdev->name, netdev)) {
 		*data = 1;
 		return -1;
 	}
-	DPRINTK(PROBE,INFO, "testing %s interrupt\n",
+	DPRINTK(HW, INFO, "testing %s interrupt\n",
 	        (shared_int ? "shared" : "unshared"));
 
 	/* Disable all the interrupts */
@@ -1256,11 +1269,10 @@
 		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x9140);
 		/* autoneg off */
 		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, 0x8140);
-	} else if (adapter->hw.phy_type == e1000_phy_gg82563) {
+	} else if (adapter->hw.phy_type == e1000_phy_gg82563)
 		e1000_write_phy_reg(&adapter->hw,
 		                    GG82563_PHY_KMRN_MODE_CTRL,
 		                    0x1CC);
-	}
 
 	ctrl_reg = E1000_READ_REG(&adapter->hw, CTRL);
 
@@ -1288,9 +1300,9 @@
 	}
 
 	if (adapter->hw.media_type == e1000_media_type_copper &&
-	   adapter->hw.phy_type == e1000_phy_m88) {
+	   adapter->hw.phy_type == e1000_phy_m88)
 		ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
-	} else {
+	else {
 		/* Set the ILOS bit on the fiber Nic is half
 		 * duplex link is detected. */
 		stat_reg = E1000_READ_REG(&adapter->hw, STATUS);
@@ -1426,11 +1438,10 @@
 	case e1000_82546_rev_3:
 	default:
 		hw->autoneg = TRUE;
-		if (hw->phy_type == e1000_phy_gg82563) {
+		if (hw->phy_type == e1000_phy_gg82563)
 			e1000_write_phy_reg(hw,
 					    GG82563_PHY_KMRN_MODE_CTRL,
 					    0x180);
-		}
 		e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg);
 		if (phy_reg & MII_CR_LOOPBACK) {
 			phy_reg &= ~MII_CR_LOOPBACK;
@@ -1590,6 +1601,8 @@
 	return E1000_TEST_LEN;
 }
 
+extern void e1000_power_up_phy(struct e1000_adapter *);
+
 static void
 e1000_diag_test(struct net_device *netdev,
 		   struct ethtool_test *eth_test, uint64_t *data)
@@ -1606,6 +1619,8 @@
 		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
 		uint8_t autoneg = adapter->hw.autoneg;
 
+		DPRINTK(HW, INFO, "offline testing starting\n");
+
 		/* Link test performed before hardware reset so autoneg doesn't
 		 * interfere with test result */
 		if (e1000_link_test(adapter, &data[4]))
@@ -1629,6 +1644,8 @@
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
 		e1000_reset(adapter);
+		/* make sure the phy is powered up */
+		e1000_power_up_phy(adapter);
 		if (e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
@@ -1642,6 +1659,7 @@
 		if (if_running)
 			dev_open(netdev);
 	} else {
+		DPRINTK(HW, INFO, "online testing starting\n");
 		/* Online tests */
 		if (e1000_link_test(adapter, &data[4]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -1657,14 +1675,12 @@
 	msleep_interruptible(4 * 1000);
 }
 
-static void
-e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
 {
-	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	int retval = 1; /* fail by default */
 
-	switch (adapter->hw.device_id) {
-	case E1000_DEV_ID_82542:
+	switch (hw->device_id) {
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
@@ -1672,52 +1688,87 @@
 	case E1000_DEV_ID_82545EM_FIBER:
 	case E1000_DEV_ID_82545EM_COPPER:
 	case E1000_DEV_ID_82546GB_QUAD_COPPER:
+	case E1000_DEV_ID_82546GB_PCIE:
+		/* these don't support WoL at all */
 		wol->supported = 0;
-		wol->wolopts   = 0;
+		break;
+	case E1000_DEV_ID_82546EB_FIBER:
+	case E1000_DEV_ID_82546GB_FIBER:
+	case E1000_DEV_ID_82571EB_FIBER:
+	case E1000_DEV_ID_82571EB_SERDES:
+	case E1000_DEV_ID_82571EB_COPPER:
+		/* Wake events not supported on port B */
+		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
+			wol->supported = 0;
+			break;
+		}
+		/* return success for non excluded adapter ports */
+		retval = 0;
+		break;
+	case E1000_DEV_ID_82571EB_QUAD_COPPER:
+	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+		/* quad port adapters only support WoL on port A */
+		if (!adapter->quad_port_a) {
+			wol->supported = 0;
+			break;
+		}
+		/* return success for non excluded adapter ports */
+		retval = 0;
+		break;
+	default:
+		/* dual port cards only support WoL on port A from now on
+		 * unless it was enabled in the eeprom for port B
+		 * so exclude FUNC_1 ports from having WoL enabled */
+		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1 &&
+		    !adapter->eeprom_wol) {
+			wol->supported = 0;
+			break;
+		}
+
+		retval = 0;
+	}
+
+	return retval;
+}
+
+static void
+e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	wol->supported = WAKE_UCAST | WAKE_MCAST |
+	                 WAKE_BCAST | WAKE_MAGIC;
+	wol->wolopts = 0;
+
+	/* this function will set ->supported = 0 and return 1 if wol is not
+	 * supported by this hardware */
+	if (e1000_wol_exclusion(adapter, wol))
 		return;
 
+	/* apply any specific unsupported masks here */
+	switch (adapter->hw.device_id) {
 	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* device id 10B5 port-A supports wol */
-		if (!adapter->ksp3_port_a) {
-			wol->supported = 0;
-			return;
-		}
-		/* KSP3 does not suppport UCAST wake-ups for any interface */
-		wol->supported = WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
+		/* KSP3 does not suppport UCAST wake-ups */
+		wol->supported &= ~WAKE_UCAST;
 
 		if (adapter->wol & E1000_WUFC_EX)
 			DPRINTK(DRV, ERR, "Interface does not support "
 		        "directed (unicast) frame wake-up packets\n");
-		wol->wolopts = 0;
-		goto do_defaults;
-
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546GB_FIBER:
-	case E1000_DEV_ID_82571EB_FIBER:
-		/* Wake events only supported on port A for dual fiber */
-		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) {
-			wol->supported = 0;
-			wol->wolopts   = 0;
-			return;
-		}
-		/* Fall Through */
-
+		break;
 	default:
-		wol->supported = WAKE_UCAST | WAKE_MCAST |
-				 WAKE_BCAST | WAKE_MAGIC;
-		wol->wolopts = 0;
-
-do_defaults:
-		if (adapter->wol & E1000_WUFC_EX)
-			wol->wolopts |= WAKE_UCAST;
-		if (adapter->wol & E1000_WUFC_MC)
-			wol->wolopts |= WAKE_MCAST;
-		if (adapter->wol & E1000_WUFC_BC)
-			wol->wolopts |= WAKE_BCAST;
-		if (adapter->wol & E1000_WUFC_MAG)
-			wol->wolopts |= WAKE_MAGIC;
-		return;
+		break;
 	}
+
+	if (adapter->wol & E1000_WUFC_EX)
+		wol->wolopts |= WAKE_UCAST;
+	if (adapter->wol & E1000_WUFC_MC)
+		wol->wolopts |= WAKE_MCAST;
+	if (adapter->wol & E1000_WUFC_BC)
+		wol->wolopts |= WAKE_BCAST;
+	if (adapter->wol & E1000_WUFC_MAG)
+		wol->wolopts |= WAKE_MAGIC;
+
+	return;
 }
 
 static int
@@ -1726,52 +1777,36 @@
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	switch (adapter->hw.device_id) {
-	case E1000_DEV_ID_82542:
-	case E1000_DEV_ID_82543GC_FIBER:
-	case E1000_DEV_ID_82543GC_COPPER:
-	case E1000_DEV_ID_82544EI_FIBER:
-	case E1000_DEV_ID_82546EB_QUAD_COPPER:
-	case E1000_DEV_ID_82546GB_QUAD_COPPER:
-	case E1000_DEV_ID_82545EM_FIBER:
-	case E1000_DEV_ID_82545EM_COPPER:
+	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
+		return -EOPNOTSUPP;
+
+	if (e1000_wol_exclusion(adapter, wol))
 		return wol->wolopts ? -EOPNOTSUPP : 0;
 
+	switch (hw->device_id) {
 	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
-		/* device id 10B5 port-A supports wol */
-		if (!adapter->ksp3_port_a)
-			return wol->wolopts ? -EOPNOTSUPP : 0;
-
 		if (wol->wolopts & WAKE_UCAST) {
 			DPRINTK(DRV, ERR, "Interface does not support "
 		        "directed (unicast) frame wake-up packets\n");
 			return -EOPNOTSUPP;
 		}
-
-	case E1000_DEV_ID_82546EB_FIBER:
-	case E1000_DEV_ID_82546GB_FIBER:
-	case E1000_DEV_ID_82571EB_FIBER:
-		/* Wake events only supported on port A for dual fiber */
-		if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
-			return wol->wolopts ? -EOPNOTSUPP : 0;
-		/* Fall Through */
-
+		break;
 	default:
-		if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
-			return -EOPNOTSUPP;
-
-		adapter->wol = 0;
-
-		if (wol->wolopts & WAKE_UCAST)
-			adapter->wol |= E1000_WUFC_EX;
-		if (wol->wolopts & WAKE_MCAST)
-			adapter->wol |= E1000_WUFC_MC;
-		if (wol->wolopts & WAKE_BCAST)
-			adapter->wol |= E1000_WUFC_BC;
-		if (wol->wolopts & WAKE_MAGIC)
-			adapter->wol |= E1000_WUFC_MAG;
+		break;
 	}
 
+	/* these settings will always override what we currently have */
+	adapter->wol = 0;
+
+	if (wol->wolopts & WAKE_UCAST)
+		adapter->wol |= E1000_WUFC_EX;
+	if (wol->wolopts & WAKE_MCAST)
+		adapter->wol |= E1000_WUFC_MC;
+	if (wol->wolopts & WAKE_BCAST)
+		adapter->wol |= E1000_WUFC_BC;
+	if (wol->wolopts & WAKE_MAGIC)
+		adapter->wol |= E1000_WUFC_MAG;
+
 	return 0;
 }
 
@@ -1895,8 +1930,8 @@
 	.get_regs               = e1000_get_regs,
 	.get_wol                = e1000_get_wol,
 	.set_wol                = e1000_set_wol,
-	.get_msglevel	        = e1000_get_msglevel,
-	.set_msglevel	        = e1000_set_msglevel,
+	.get_msglevel           = e1000_get_msglevel,
+	.set_msglevel           = e1000_set_msglevel,
 	.nway_reset             = e1000_nway_reset,
 	.get_link               = ethtool_op_get_link,
 	.get_eeprom_len         = e1000_get_eeprom_len,
@@ -1904,17 +1939,17 @@
 	.set_eeprom             = e1000_set_eeprom,
 	.get_ringparam          = e1000_get_ringparam,
 	.set_ringparam          = e1000_set_ringparam,
-	.get_pauseparam		= e1000_get_pauseparam,
-	.set_pauseparam		= e1000_set_pauseparam,
-	.get_rx_csum		= e1000_get_rx_csum,
-	.set_rx_csum		= e1000_set_rx_csum,
-	.get_tx_csum		= e1000_get_tx_csum,
-	.set_tx_csum		= e1000_set_tx_csum,
-	.get_sg			= ethtool_op_get_sg,
-	.set_sg			= ethtool_op_set_sg,
+	.get_pauseparam         = e1000_get_pauseparam,
+	.set_pauseparam         = e1000_set_pauseparam,
+	.get_rx_csum            = e1000_get_rx_csum,
+	.set_rx_csum            = e1000_set_rx_csum,
+	.get_tx_csum            = e1000_get_tx_csum,
+	.set_tx_csum            = e1000_set_tx_csum,
+	.get_sg                 = ethtool_op_get_sg,
+	.set_sg                 = ethtool_op_set_sg,
 #ifdef NETIF_F_TSO
-	.get_tso		= ethtool_op_get_tso,
-	.set_tso		= e1000_set_tso,
+	.get_tso                = ethtool_op_get_tso,
+	.set_tso                = e1000_set_tso,
 #endif
 	.self_test_count        = e1000_diag_test_count,
 	.self_test              = e1000_diag_test,
@@ -1922,7 +1957,7 @@
 	.phys_id                = e1000_phys_id,
 	.get_stats_count        = e1000_get_stats_count,
 	.get_ethtool_stats      = e1000_get_ethtool_stats,
-	.get_perm_addr		= ethtool_op_get_perm_addr,
+	.get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 void e1000_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 583518a..a6f8f4f 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -31,6 +31,7 @@
  * Shared functions for accessing and configuring the MAC
  */
 
+
 #include "e1000_hw.h"
 
 static int32_t e1000_set_phy_type(struct e1000_hw *hw);
@@ -105,6 +106,33 @@
                                                uint16_t duplex);
 static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw);
 
+static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw,
+					   uint32_t segment);
+static int32_t e1000_get_software_flag(struct e1000_hw *hw);
+static int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
+static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
+static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+				      uint16_t words, uint16_t *data);
+static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
+				    uint8_t* data);
+static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
+				    uint16_t *data);
+static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+				   uint16_t *data);
+static void e1000_release_software_flag(struct e1000_hw *hw);
+static void e1000_release_software_semaphore(struct e1000_hw *hw);
+static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw,
+					 uint32_t no_snoop);
+static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw,
+					    uint32_t index, uint8_t byte);
+static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
+				       uint16_t words, uint16_t *data);
+static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
+				     uint8_t data);
+static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr,
+				    uint16_t data);
+
 /* IGP cable length table */
 static const
 uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
@@ -139,10 +167,10 @@
 {
     DEBUGFUNC("e1000_set_phy_type");
 
-    if(hw->mac_type == e1000_undefined)
+    if (hw->mac_type == e1000_undefined)
         return -E1000_ERR_PHY_TYPE;
 
-    switch(hw->phy_id) {
+    switch (hw->phy_id) {
     case M88E1000_E_PHY_ID:
     case M88E1000_I_PHY_ID:
     case M88E1011_I_PHY_ID:
@@ -150,10 +178,10 @@
         hw->phy_type = e1000_phy_m88;
         break;
     case IGP01E1000_I_PHY_ID:
-        if(hw->mac_type == e1000_82541 ||
-           hw->mac_type == e1000_82541_rev_2 ||
-           hw->mac_type == e1000_82547 ||
-           hw->mac_type == e1000_82547_rev_2) {
+        if (hw->mac_type == e1000_82541 ||
+            hw->mac_type == e1000_82541_rev_2 ||
+            hw->mac_type == e1000_82547 ||
+            hw->mac_type == e1000_82547_rev_2) {
             hw->phy_type = e1000_phy_igp;
             break;
         }
@@ -180,6 +208,7 @@
     return E1000_SUCCESS;
 }
 
+
 /******************************************************************************
  * IGP phy init script - initializes the GbE PHY
  *
@@ -193,7 +222,7 @@
 
     DEBUGFUNC("e1000_phy_init_script");
 
-    if(hw->phy_init_script) {
+    if (hw->phy_init_script) {
         msec_delay(20);
 
         /* Save off the current value of register 0x2F5B to be restored at
@@ -209,7 +238,7 @@
 
         msec_delay(5);
 
-        switch(hw->mac_type) {
+        switch (hw->mac_type) {
         case e1000_82541:
         case e1000_82547:
             e1000_write_phy_reg(hw, 0x1F95, 0x0001);
@@ -246,22 +275,22 @@
         /* Now enable the transmitter */
         e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
 
-        if(hw->mac_type == e1000_82547) {
+        if (hw->mac_type == e1000_82547) {
             uint16_t fused, fine, coarse;
 
             /* Move to analog registers page */
             e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused);
 
-            if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
+            if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
                 e1000_read_phy_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS, &fused);
 
                 fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
                 coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
 
-                if(coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
+                if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
                     coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
                     fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
-                } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
+                } else if (coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
                     fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
 
                 fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
@@ -360,6 +389,7 @@
     case E1000_DEV_ID_82571EB_COPPER:
     case E1000_DEV_ID_82571EB_FIBER:
     case E1000_DEV_ID_82571EB_SERDES:
+    case E1000_DEV_ID_82571EB_QUAD_COPPER:
             hw->mac_type = e1000_82571;
         break;
     case E1000_DEV_ID_82572EI_COPPER:
@@ -391,7 +421,7 @@
         return -E1000_ERR_MAC_TYPE;
     }
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_ich8lan:
         hw->swfwhw_semaphore_present = TRUE;
         hw->asf_firmware_present = TRUE;
@@ -429,7 +459,7 @@
 
     DEBUGFUNC("e1000_set_media_type");
 
-    if(hw->mac_type != e1000_82543) {
+    if (hw->mac_type != e1000_82543) {
         /* tbi_compatibility is only valid on 82543 */
         hw->tbi_compatibility_en = FALSE;
     }
@@ -489,16 +519,16 @@
     DEBUGFUNC("e1000_reset_hw");
 
     /* For 82542 (rev 2.0), disable MWI before issuing a device reset */
-    if(hw->mac_type == e1000_82542_rev2_0) {
+    if (hw->mac_type == e1000_82542_rev2_0) {
         DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
         e1000_pci_clear_mwi(hw);
     }
 
-    if(hw->bus_type == e1000_bus_type_pci_express) {
+    if (hw->bus_type == e1000_bus_type_pci_express) {
         /* Prevent the PCI-E bus from sticking if there is no TLP connection
          * on the last TLP read/write transaction when MAC is reset.
          */
-        if(e1000_disable_pciex_master(hw) != E1000_SUCCESS) {
+        if (e1000_disable_pciex_master(hw) != E1000_SUCCESS) {
             DEBUGOUT("PCI-E Master disable polling has failed.\n");
         }
     }
@@ -526,14 +556,14 @@
     ctrl = E1000_READ_REG(hw, CTRL);
 
     /* Must reset the PHY before resetting the MAC */
-    if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+    if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
         E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
         msec_delay(5);
     }
 
     /* Must acquire the MDIO ownership before MAC reset.
      * Ownership defaults to firmware after a reset. */
-    if(hw->mac_type == e1000_82573) {
+    if (hw->mac_type == e1000_82573) {
         timeout = 10;
 
         extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
@@ -543,14 +573,14 @@
             E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
             extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
 
-            if(extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+            if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
                 break;
             else
                 extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
 
             msec_delay(2);
             timeout--;
-        } while(timeout);
+        } while (timeout);
     }
 
     /* Workaround for ICH8 bit corruption issue in FIFO memory */
@@ -568,7 +598,7 @@
      */
     DEBUGOUT("Issuing a global reset to MAC\n");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
         case e1000_82544:
         case e1000_82540:
         case e1000_82545:
@@ -607,7 +637,7 @@
      * device.  Later controllers reload the EEPROM automatically, so just wait
      * for reload to complete.
      */
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
         case e1000_82542_rev2_0:
         case e1000_82542_rev2_1:
         case e1000_82543:
@@ -642,7 +672,7 @@
         case e1000_ich8lan:
         case e1000_80003es2lan:
             ret_val = e1000_get_auto_rd_done(hw);
-            if(ret_val)
+            if (ret_val)
                 /* We don't want to continue accessing MAC registers. */
                 return ret_val;
             break;
@@ -653,13 +683,13 @@
     }
 
     /* Disable HW ARPs on ASF enabled adapters */
-    if(hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
+    if (hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
         manc = E1000_READ_REG(hw, MANC);
         manc &= ~(E1000_MANC_ARP_EN);
         E1000_WRITE_REG(hw, MANC, manc);
     }
 
-    if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+    if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
         e1000_phy_init_script(hw);
 
         /* Configure activity LED after PHY reset */
@@ -677,8 +707,8 @@
     icr = E1000_READ_REG(hw, ICR);
 
     /* If MWI was previously enabled, reenable it. */
-    if(hw->mac_type == e1000_82542_rev2_0) {
-        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+    if (hw->mac_type == e1000_82542_rev2_0) {
+        if (hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
             e1000_pci_set_mwi(hw);
     }
 
@@ -718,9 +748,20 @@
 
     DEBUGFUNC("e1000_init_hw");
 
+    /* force full DMA clock frequency for 10/100 on ICH8 A0-B0 */
+    if (hw->mac_type == e1000_ich8lan) {
+        reg_data = E1000_READ_REG(hw, TARC0);
+        reg_data |= 0x30000000;
+        E1000_WRITE_REG(hw, TARC0, reg_data);
+
+        reg_data = E1000_READ_REG(hw, STATUS);
+        reg_data &= ~0x80000000;
+        E1000_WRITE_REG(hw, STATUS, reg_data);
+    }
+
     /* Initialize Identification LED */
     ret_val = e1000_id_led_init(hw);
-    if(ret_val) {
+    if (ret_val) {
         DEBUGOUT("Error Initializing Identification LED\n");
         return ret_val;
     }
@@ -738,7 +779,7 @@
     }
 
     /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
-    if(hw->mac_type == e1000_82542_rev2_0) {
+    if (hw->mac_type == e1000_82542_rev2_0) {
         DEBUGOUT("Disabling MWI on 82542 rev 2.0\n");
         e1000_pci_clear_mwi(hw);
         E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST);
@@ -752,11 +793,11 @@
     e1000_init_rx_addrs(hw);
 
     /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
-    if(hw->mac_type == e1000_82542_rev2_0) {
+    if (hw->mac_type == e1000_82542_rev2_0) {
         E1000_WRITE_REG(hw, RCTL, 0);
         E1000_WRITE_FLUSH(hw);
         msec_delay(1);
-        if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
+        if (hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
             e1000_pci_set_mwi(hw);
     }
 
@@ -765,7 +806,7 @@
     mta_size = E1000_MC_TBL_SIZE;
     if (hw->mac_type == e1000_ich8lan)
         mta_size = E1000_MC_TBL_SIZE_ICH8LAN;
-    for(i = 0; i < mta_size; i++) {
+    for (i = 0; i < mta_size; i++) {
         E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
         /* use write flush to prevent Memory Write Block (MWB) from
          * occuring when accessing our register space */
@@ -777,18 +818,18 @@
      * gives equal priority to transmits and receives.  Valid only on
      * 82542 and 82543 silicon.
      */
-    if(hw->dma_fairness && hw->mac_type <= e1000_82543) {
+    if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
     }
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82545_rev_3:
     case e1000_82546_rev_3:
         break;
     default:
         /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
-        if(hw->bus_type == e1000_bus_type_pcix) {
+        if (hw->bus_type == e1000_bus_type_pcix) {
             e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word);
             e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI,
                 &pcix_stat_hi_word);
@@ -796,9 +837,9 @@
                 PCIX_COMMAND_MMRBC_SHIFT;
             stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >>
                 PCIX_STATUS_HI_MMRBC_SHIFT;
-            if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
+            if (stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K)
                 stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K;
-            if(cmd_mmrbc > stat_mmrbc) {
+            if (cmd_mmrbc > stat_mmrbc) {
                 pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK;
                 pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT;
                 e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER,
@@ -816,7 +857,7 @@
     ret_val = e1000_setup_link(hw);
 
     /* Set the transmit descriptor write-back policy */
-    if(hw->mac_type > e1000_82544) {
+    if (hw->mac_type > e1000_82544) {
         ctrl = E1000_READ_REG(hw, TXDCTL);
         ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
         switch (hw->mac_type) {
@@ -867,14 +908,13 @@
     case e1000_ich8lan:
         ctrl = E1000_READ_REG(hw, TXDCTL1);
         ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
-        if(hw->mac_type >= e1000_82571)
+        if (hw->mac_type >= e1000_82571)
             ctrl |= E1000_TXDCTL_COUNT_DESC;
         E1000_WRITE_REG(hw, TXDCTL1, ctrl);
         break;
     }
 
 
-
     if (hw->mac_type == e1000_82573) {
         uint32_t gcr = E1000_READ_REG(hw, GCR);
         gcr |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
@@ -918,10 +958,10 @@
 
     DEBUGFUNC("e1000_adjust_serdes_amplitude");
 
-    if(hw->media_type != e1000_media_type_internal_serdes)
+    if (hw->media_type != e1000_media_type_internal_serdes)
         return E1000_SUCCESS;
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82545_rev_3:
     case e1000_82546_rev_3:
         break;
@@ -934,11 +974,11 @@
         return ret_val;
     }
 
-    if(eeprom_data != EEPROM_RESERVED_WORD) {
+    if (eeprom_data != EEPROM_RESERVED_WORD) {
         /* Adjust SERDES output amplitude only. */
         eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
@@ -1006,10 +1046,10 @@
      * in case we get disconnected and then reconnected into a different
      * hub or switch with different Flow Control capabilities.
      */
-    if(hw->mac_type == e1000_82542_rev2_0)
+    if (hw->mac_type == e1000_82542_rev2_0)
         hw->fc &= (~e1000_fc_tx_pause);
 
-    if((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
+    if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
         hw->fc &= (~e1000_fc_rx_pause);
 
     hw->original_fc = hw->fc;
@@ -1024,12 +1064,12 @@
      * or e1000_phy_setup() is called.
      */
     if (hw->mac_type == e1000_82543) {
-		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
-									1, &eeprom_data);
-		if (ret_val) {
-			DEBUGOUT("EEPROM Read Error\n");
-			return -E1000_ERR_EEPROM;
-		}
+        ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
+                                    1, &eeprom_data);
+        if (ret_val) {
+            DEBUGOUT("EEPROM Read Error\n");
+            return -E1000_ERR_EEPROM;
+        }
         ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
                     SWDPIO__EXT_SHIFT);
         E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
@@ -1062,14 +1102,14 @@
      * ability to transmit pause frames in not enabled, then these
      * registers will be set to 0.
      */
-    if(!(hw->fc & e1000_fc_tx_pause)) {
+    if (!(hw->fc & e1000_fc_tx_pause)) {
         E1000_WRITE_REG(hw, FCRTL, 0);
         E1000_WRITE_REG(hw, FCRTH, 0);
     } else {
         /* We need to set up the Receive Threshold high and low water marks
          * as well as (optionally) enabling the transmission of XON frames.
          */
-        if(hw->fc_send_xon) {
+        if (hw->fc_send_xon) {
             E1000_WRITE_REG(hw, FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
             E1000_WRITE_REG(hw, FCRTH, hw->fc_high_water);
         } else {
@@ -1116,11 +1156,11 @@
      * the EEPROM.
      */
     ctrl = E1000_READ_REG(hw, CTRL);
-    if(hw->media_type == e1000_media_type_fiber)
+    if (hw->media_type == e1000_media_type_fiber)
         signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
 
     ret_val = e1000_adjust_serdes_amplitude(hw);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* Take the link out of reset */
@@ -1128,7 +1168,7 @@
 
     /* Adjust VCO speed to improve BER performance */
     ret_val = e1000_set_vco_speed(hw);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     e1000_config_collision_dist(hw);
@@ -1199,15 +1239,15 @@
      * less than 500 milliseconds even if the other end is doing it in SW).
      * For internal serdes, we just assume a signal is present, then poll.
      */
-    if(hw->media_type == e1000_media_type_internal_serdes ||
+    if (hw->media_type == e1000_media_type_internal_serdes ||
        (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) {
         DEBUGOUT("Looking for Link\n");
-        for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
+        for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
             msec_delay(10);
             status = E1000_READ_REG(hw, STATUS);
-            if(status & E1000_STATUS_LU) break;
+            if (status & E1000_STATUS_LU) break;
         }
-        if(i == (LINK_UP_TIMEOUT / 10)) {
+        if (i == (LINK_UP_TIMEOUT / 10)) {
             DEBUGOUT("Never got a valid link from auto-neg!!!\n");
             hw->autoneg_failed = 1;
             /* AutoNeg failed to achieve a link, so we'll call
@@ -1216,7 +1256,7 @@
              * non-autonegotiating link partners.
              */
             ret_val = e1000_check_for_link(hw);
-            if(ret_val) {
+            if (ret_val) {
                 DEBUGOUT("Error while checking for link\n");
                 return ret_val;
             }
@@ -1250,7 +1290,7 @@
      * the PHY speed and duplex configuration is. In addition, we need to
      * perform a hardware reset on the PHY to take it out of reset.
      */
-    if(hw->mac_type > e1000_82543) {
+    if (hw->mac_type > e1000_82543) {
         ctrl |= E1000_CTRL_SLU;
         ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
         E1000_WRITE_REG(hw, CTRL, ctrl);
@@ -1258,13 +1298,13 @@
         ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
         E1000_WRITE_REG(hw, CTRL, ctrl);
         ret_val = e1000_phy_hw_reset(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
     /* Make sure we have a valid PHY */
     ret_val = e1000_detect_gig_phy(hw);
-    if(ret_val) {
+    if (ret_val) {
         DEBUGOUT("Error, did not detect valid phy.\n");
         return ret_val;
     }
@@ -1272,19 +1312,19 @@
 
     /* Set PHY to class A mode (if necessary) */
     ret_val = e1000_set_phy_mode(hw);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
-    if((hw->mac_type == e1000_82545_rev_3) ||
+    if ((hw->mac_type == e1000_82545_rev_3) ||
        (hw->mac_type == e1000_82546_rev_3)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
         phy_data |= 0x00000008;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
     }
 
-    if(hw->mac_type <= e1000_82543 ||
-       hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
-       hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
+    if (hw->mac_type <= e1000_82543 ||
+        hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
+        hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
         hw->phy_reset_disable = FALSE;
 
    return E1000_SUCCESS;
@@ -1314,7 +1354,7 @@
         return ret_val;
     }
 
-    /* Wait 10ms for MAC to configure PHY from eeprom settings */
+    /* Wait 15ms for MAC to configure PHY from eeprom settings */
     msec_delay(15);
     if (hw->mac_type != e1000_ich8lan) {
     /* Configure activity LED after PHY reset */
@@ -1324,11 +1364,14 @@
     E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
     }
 
-    /* disable lplu d3 during driver init */
-    ret_val = e1000_set_d3_lplu_state(hw, FALSE);
-    if (ret_val) {
-        DEBUGOUT("Error Disabling LPLU D3\n");
-        return ret_val;
+    /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
+    if (hw->phy_type == e1000_phy_igp) {
+        /* disable lplu d3 during driver init */
+        ret_val = e1000_set_d3_lplu_state(hw, FALSE);
+        if (ret_val) {
+            DEBUGOUT("Error Disabling LPLU D3\n");
+            return ret_val;
+        }
     }
 
     /* disable lplu d0 during driver init */
@@ -1366,45 +1409,45 @@
         }
     }
     ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* set auto-master slave resolution settings */
-    if(hw->autoneg) {
+    if (hw->autoneg) {
         e1000_ms_type phy_ms_setting = hw->master_slave;
 
-        if(hw->ffe_config_state == e1000_ffe_config_active)
+        if (hw->ffe_config_state == e1000_ffe_config_active)
             hw->ffe_config_state = e1000_ffe_config_enabled;
 
-        if(hw->dsp_config_state == e1000_dsp_config_activated)
+        if (hw->dsp_config_state == e1000_dsp_config_activated)
             hw->dsp_config_state = e1000_dsp_config_enabled;
 
         /* when autonegotiation advertisment is only 1000Mbps then we
           * should disable SmartSpeed and enable Auto MasterSlave
           * resolution as hardware default. */
-        if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+        if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
             /* Disable SmartSpeed */
-            ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
-            if(ret_val)
+            ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                         &phy_data);
+            if (ret_val)
                 return ret_val;
             phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-            ret_val = e1000_write_phy_reg(hw,
-                                                  IGP01E1000_PHY_PORT_CONFIG,
-                                                  phy_data);
-            if(ret_val)
+            ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                          phy_data);
+            if (ret_val)
                 return ret_val;
             /* Set auto Master/Slave resolution process */
             ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
             phy_data &= ~CR_1000T_MS_ENABLE;
             ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         }
 
         ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* load defaults for future use */
@@ -1428,7 +1471,7 @@
             break;
         }
         ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
@@ -1449,12 +1492,12 @@
 
     DEBUGFUNC("e1000_copper_link_ggp_setup");
 
-    if(!hw->phy_reset_disable) {
+    if (!hw->phy_reset_disable) {
 
         /* Enable CRS on TX for half-duplex operation. */
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
@@ -1463,7 +1506,7 @@
 
         ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                       phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* Options:
@@ -1474,7 +1517,7 @@
          *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
          */
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
@@ -1499,11 +1542,11 @@
          *   1 - Enabled
          */
         phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
-        if(hw->disable_polarity_correction == 1)
+        if (hw->disable_polarity_correction == 1)
             phy_data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
         ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
 
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* SW Reset the PHY so all changes take effect */
@@ -1559,9 +1602,9 @@
                 return ret_val;
 
             phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
-
             ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
                                           phy_data);
+
             if (ret_val)
                 return ret_val;
         }
@@ -1596,12 +1639,12 @@
 
     DEBUGFUNC("e1000_copper_link_mgp_setup");
 
-    if(hw->phy_reset_disable)
+    if (hw->phy_reset_disable)
         return E1000_SUCCESS;
 
     /* Enable CRS on TX. This must be set for half-duplex operation. */
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
@@ -1638,7 +1681,7 @@
      *   1 - Enabled
      */
     phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
-    if(hw->disable_polarity_correction == 1)
+    if (hw->disable_polarity_correction == 1)
         phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
     if (ret_val)
@@ -1678,7 +1721,7 @@
 
     /* SW Reset the PHY so all changes take effect */
     ret_val = e1000_phy_reset(hw);
-    if(ret_val) {
+    if (ret_val) {
         DEBUGOUT("Error Resetting the PHY\n");
         return ret_val;
     }
@@ -1708,7 +1751,7 @@
     /* If autoneg_advertised is zero, we assume it was not defaulted
      * by the calling code so we set to advertise full capability.
      */
-    if(hw->autoneg_advertised == 0)
+    if (hw->autoneg_advertised == 0)
         hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
     /* IFE phy only supports 10/100 */
@@ -1717,7 +1760,7 @@
 
     DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
     ret_val = e1000_phy_setup_autoneg(hw);
-    if(ret_val) {
+    if (ret_val) {
         DEBUGOUT("Error Setting up Auto-Negotiation\n");
         return ret_val;
     }
@@ -1727,20 +1770,20 @@
      * the Auto Neg Restart bit in the PHY control register.
      */
     ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
     ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* Does the user want to wait for Auto-Neg to complete here, or
      * check at a later time (for example, callback routine).
      */
-    if(hw->wait_autoneg_complete) {
+    if (hw->wait_autoneg_complete) {
         ret_val = e1000_wait_autoneg(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error while waiting for autoneg to complete\n");
             return ret_val;
         }
@@ -1751,7 +1794,6 @@
     return E1000_SUCCESS;
 }
 
-
 /******************************************************************************
 * Config the MAC and the PHY after link is up.
 *   1) Set up the MAC to the current PHY speed/duplex
@@ -1770,25 +1812,25 @@
     int32_t ret_val;
     DEBUGFUNC("e1000_copper_link_postconfig");
 
-    if(hw->mac_type >= e1000_82544) {
+    if (hw->mac_type >= e1000_82544) {
         e1000_config_collision_dist(hw);
     } else {
         ret_val = e1000_config_mac_to_phy(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error configuring MAC to PHY settings\n");
             return ret_val;
         }
     }
     ret_val = e1000_config_fc_after_link_up(hw);
-    if(ret_val) {
+    if (ret_val) {
         DEBUGOUT("Error Configuring Flow Control\n");
         return ret_val;
     }
 
     /* Config DSP to improve Giga link quality */
-    if(hw->phy_type == e1000_phy_igp) {
+    if (hw->phy_type == e1000_phy_igp) {
         ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error Configuring DSP after link up\n");
             return ret_val;
         }
@@ -1834,7 +1876,7 @@
 
     /* Check if it is a valid PHY and set PHY mode if necessary. */
     ret_val = e1000_copper_link_preconfig(hw);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     switch (hw->mac_type) {
@@ -1855,30 +1897,30 @@
         hw->phy_type == e1000_phy_igp_3 ||
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_copper_link_igp_setup(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     } else if (hw->phy_type == e1000_phy_m88) {
         ret_val = e1000_copper_link_mgp_setup(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     } else if (hw->phy_type == e1000_phy_gg82563) {
         ret_val = e1000_copper_link_ggp_setup(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
-    if(hw->autoneg) {
+    if (hw->autoneg) {
         /* Setup autoneg and flow control advertisement
           * and perform autonegotiation */
         ret_val = e1000_copper_link_autoneg(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     } else {
         /* PHY will be set to 10H, 10F, 100H,or 100F
           * depending on value from forced_speed_duplex. */
         DEBUGOUT("Forcing speed and duplex\n");
         ret_val = e1000_phy_force_speed_duplex(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error Forcing Speed and Duplex\n");
             return ret_val;
         }
@@ -1887,18 +1929,18 @@
     /* Check link status. Wait up to 100 microseconds for link to become
      * valid.
      */
-    for(i = 0; i < 10; i++) {
+    for (i = 0; i < 10; i++) {
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if(phy_data & MII_SR_LINK_STATUS) {
+        if (phy_data & MII_SR_LINK_STATUS) {
             /* Config the MAC and PHY after link is up */
             ret_val = e1000_copper_link_postconfig(hw);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             DEBUGOUT("Valid link established!!!\n");
@@ -2000,7 +2042,7 @@
 
     /* Read the MII Auto-Neg Advertisement Register (Address 4). */
     ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     if (hw->phy_type != e1000_phy_ife) {
@@ -2028,36 +2070,36 @@
     DEBUGOUT1("autoneg_advertised %x\n", hw->autoneg_advertised);
 
     /* Do we want to advertise 10 Mb Half Duplex? */
-    if(hw->autoneg_advertised & ADVERTISE_10_HALF) {
+    if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
         DEBUGOUT("Advertise 10mb Half duplex\n");
         mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
     }
 
     /* Do we want to advertise 10 Mb Full Duplex? */
-    if(hw->autoneg_advertised & ADVERTISE_10_FULL) {
+    if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
         DEBUGOUT("Advertise 10mb Full duplex\n");
         mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
     }
 
     /* Do we want to advertise 100 Mb Half Duplex? */
-    if(hw->autoneg_advertised & ADVERTISE_100_HALF) {
+    if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
         DEBUGOUT("Advertise 100mb Half duplex\n");
         mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
     }
 
     /* Do we want to advertise 100 Mb Full Duplex? */
-    if(hw->autoneg_advertised & ADVERTISE_100_FULL) {
+    if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
         DEBUGOUT("Advertise 100mb Full duplex\n");
         mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
     }
 
     /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
-    if(hw->autoneg_advertised & ADVERTISE_1000_HALF) {
+    if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
         DEBUGOUT("Advertise 1000mb Half duplex requested, request denied!\n");
     }
 
     /* Do we want to advertise 1000 Mb Full Duplex? */
-    if(hw->autoneg_advertised & ADVERTISE_1000_FULL) {
+    if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
         DEBUGOUT("Advertise 1000mb Full duplex\n");
         mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
         if (hw->phy_type == e1000_phy_ife) {
@@ -2119,7 +2161,7 @@
     }
 
     ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
@@ -2167,7 +2209,7 @@
 
     /* Read the MII Control Register. */
     ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* We need to disable autoneg in order to force link and duplex. */
@@ -2175,8 +2217,8 @@
     mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
 
     /* Are we forcing Full or Half Duplex? */
-    if(hw->forced_speed_duplex == e1000_100_full ||
-       hw->forced_speed_duplex == e1000_10_full) {
+    if (hw->forced_speed_duplex == e1000_100_full ||
+        hw->forced_speed_duplex == e1000_10_full) {
         /* We want to force full duplex so we SET the full duplex bits in the
          * Device and MII Control Registers.
          */
@@ -2193,7 +2235,7 @@
     }
 
     /* Are we forcing 100Mbps??? */
-    if(hw->forced_speed_duplex == e1000_100_full ||
+    if (hw->forced_speed_duplex == e1000_100_full ||
        hw->forced_speed_duplex == e1000_100_half) {
         /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
         ctrl |= E1000_CTRL_SPD_100;
@@ -2216,7 +2258,7 @@
     if ((hw->phy_type == e1000_phy_m88) ||
         (hw->phy_type == e1000_phy_gg82563)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
@@ -2224,7 +2266,7 @@
          */
         phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
@@ -2248,20 +2290,20 @@
          * forced whenever speed or duplex are forced.
          */
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
         phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
 
         ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
     /* Write back the modified PHY MII control register. */
     ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     udelay(1);
@@ -2273,50 +2315,50 @@
      * only if the user has set wait_autoneg_complete to 1, which is
      * the default.
      */
-    if(hw->wait_autoneg_complete) {
+    if (hw->wait_autoneg_complete) {
         /* We will wait for autoneg to complete. */
         DEBUGOUT("Waiting for forced speed/duplex link.\n");
         mii_status_reg = 0;
 
         /* We will wait for autoneg to complete or 4.5 seconds to expire. */
-        for(i = PHY_FORCE_TIME; i > 0; i--) {
+        for (i = PHY_FORCE_TIME; i > 0; i--) {
             /* Read the MII Status Register and wait for Auto-Neg Complete bit
              * to be set.
              */
             ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
-            if(mii_status_reg & MII_SR_LINK_STATUS) break;
+            if (mii_status_reg & MII_SR_LINK_STATUS) break;
             msec_delay(100);
         }
-        if((i == 0) &&
+        if ((i == 0) &&
            ((hw->phy_type == e1000_phy_m88) ||
             (hw->phy_type == e1000_phy_gg82563))) {
             /* We didn't get link.  Reset the DSP and wait again for link. */
             ret_val = e1000_phy_reset_dsp(hw);
-            if(ret_val) {
+            if (ret_val) {
                 DEBUGOUT("Error Resetting PHY DSP\n");
                 return ret_val;
             }
         }
         /* This loop will early-out if the link condition has been met.  */
-        for(i = PHY_FORCE_TIME; i > 0; i--) {
-            if(mii_status_reg & MII_SR_LINK_STATUS) break;
+        for (i = PHY_FORCE_TIME; i > 0; i--) {
+            if (mii_status_reg & MII_SR_LINK_STATUS) break;
             msec_delay(100);
             /* Read the MII Status Register and wait for Auto-Neg Complete bit
              * to be set.
              */
             ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         }
     }
@@ -2327,32 +2369,31 @@
          * defaults back to a 2.5MHz clock when the PHY is reset.
          */
         ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data |= M88E1000_EPSCR_TX_CLK_25;
         ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* In addition, because of the s/w reset above, we need to enable CRS on
          * TX.  This must be set for both full and half duplex operation.
          */
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
-           (!hw->autoneg) &&
-           (hw->forced_speed_duplex == e1000_10_full ||
-            hw->forced_speed_duplex == e1000_10_half)) {
+        if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+            (!hw->autoneg) && (hw->forced_speed_duplex == e1000_10_full ||
+             hw->forced_speed_duplex == e1000_10_half)) {
             ret_val = e1000_polarity_reversal_workaround(hw);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         }
     } else if (hw->phy_type == e1000_phy_gg82563) {
@@ -2443,10 +2484,10 @@
      * registers depending on negotiated values.
      */
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
-    if(phy_data & M88E1000_PSSR_DPLX)
+    if (phy_data & M88E1000_PSSR_DPLX)
         ctrl |= E1000_CTRL_FD;
     else
         ctrl &= ~E1000_CTRL_FD;
@@ -2456,9 +2497,9 @@
     /* Set up speed in the Device Control register depending on
      * negotiated values.
      */
-    if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+    if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
         ctrl |= E1000_CTRL_SPD_1000;
-    else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+    else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
         ctrl |= E1000_CTRL_SPD_100;
 
     /* Write the configured values back to the Device Control Reg. */
@@ -2526,7 +2567,7 @@
     }
 
     /* Disable TX Flow Control for 82542 (rev 2.0) */
-    if(hw->mac_type == e1000_82542_rev2_0)
+    if (hw->mac_type == e1000_82542_rev2_0)
         ctrl &= (~E1000_CTRL_TFCE);
 
     E1000_WRITE_REG(hw, CTRL, ctrl);
@@ -2560,11 +2601,12 @@
      * so we had to force link.  In this case, we need to force the
      * configuration of the MAC to match the "fc" parameter.
      */
-    if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
-       ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) ||
-       ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {
+    if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
+        ((hw->media_type == e1000_media_type_internal_serdes) &&
+         (hw->autoneg_failed)) ||
+        ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {
         ret_val = e1000_force_mac_fc(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error forcing flow control settings\n");
             return ret_val;
         }
@@ -2575,19 +2617,19 @@
      * has completed, and if so, how the PHY and link partner has
      * flow control configured.
      */
-    if((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
+    if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
         /* Read the MII Status Register and check to see if AutoNeg
          * has completed.  We read this twice because this reg has
          * some "sticky" (latched) bits.
          */
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
+        if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
             /* The AutoNeg process has completed, so we now need to
              * read both the Auto Negotiation Advertisement Register
              * (Address 4) and the Auto_Negotiation Base Page Ability
@@ -2596,11 +2638,11 @@
              */
             ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
                                          &mii_nway_adv_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
             ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
                                          &mii_nway_lp_ability_reg);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             /* Two bits in the Auto Negotiation Advertisement Register
@@ -2637,15 +2679,15 @@
              *   1   |   DC    |   1   |   DC    | e1000_fc_full
              *
              */
-            if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-               (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+            if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
                 /* Now we need to check if the user selected RX ONLY
                  * of pause frames.  In this case, we had to advertise
                  * FULL flow control because we could not advertise RX
                  * ONLY. Hence, we must now check to see if we need to
                  * turn OFF  the TRANSMISSION of PAUSE frames.
                  */
-                if(hw->original_fc == e1000_fc_full) {
+                if (hw->original_fc == e1000_fc_full) {
                     hw->fc = e1000_fc_full;
                     DEBUGOUT("Flow Control = FULL.\n");
                 } else {
@@ -2661,10 +2703,10 @@
              *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
              *
              */
-            else if(!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+            else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                     (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                     (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_tx_pause;
                 DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
             }
@@ -2676,10 +2718,10 @@
              *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
              *
              */
-            else if((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
-                    (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
-                    !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
-                    (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+            else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+                     (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+                     !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_rx_pause;
                 DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
@@ -2703,9 +2745,9 @@
              * be asked to delay transmission of packets than asking
              * our link partner to pause transmission of frames.
              */
-            else if((hw->original_fc == e1000_fc_none ||
-                     hw->original_fc == e1000_fc_tx_pause) ||
-                    hw->fc_strict_ieee) {
+            else if ((hw->original_fc == e1000_fc_none ||
+                      hw->original_fc == e1000_fc_tx_pause) ||
+                      hw->fc_strict_ieee) {
                 hw->fc = e1000_fc_none;
                 DEBUGOUT("Flow Control = NONE.\n");
             } else {
@@ -2718,19 +2760,19 @@
              * enabled per IEEE 802.3 spec.
              */
             ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
-            if(ret_val) {
+            if (ret_val) {
                 DEBUGOUT("Error getting link speed and duplex\n");
                 return ret_val;
             }
 
-            if(duplex == HALF_DUPLEX)
+            if (duplex == HALF_DUPLEX)
                 hw->fc = e1000_fc_none;
 
             /* Now we call a subroutine to actually force the MAC
              * controller to use the correct flow control settings.
              */
             ret_val = e1000_force_mac_fc(hw);
-            if(ret_val) {
+            if (ret_val) {
                 DEBUGOUT("Error forcing flow control settings\n");
                 return ret_val;
             }
@@ -2769,13 +2811,13 @@
      * set when the optics detect a signal. On older adapters, it will be
      * cleared when there is a signal.  This applies to fiber media only.
      */
-    if((hw->media_type == e1000_media_type_fiber) ||
-       (hw->media_type == e1000_media_type_internal_serdes)) {
+    if ((hw->media_type == e1000_media_type_fiber) ||
+        (hw->media_type == e1000_media_type_internal_serdes)) {
         rxcw = E1000_READ_REG(hw, RXCW);
 
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
-            if(status & E1000_STATUS_LU)
+            if (status & E1000_STATUS_LU)
                 hw->get_link_status = FALSE;
         }
     }
@@ -2786,20 +2828,20 @@
      * receive a Link Status Change interrupt or we have Rx Sequence
      * Errors.
      */
-    if((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
+    if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
         /* First we want to see if the MII Status Register reports
          * link.  If so, then we want to get the current speed/duplex
          * of the PHY.
          * Read the register twice since the link bit is sticky.
          */
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if(phy_data & MII_SR_LINK_STATUS) {
+        if (phy_data & MII_SR_LINK_STATUS) {
             hw->get_link_status = FALSE;
             /* Check if there was DownShift, must be checked immediately after
              * link-up */
@@ -2813,10 +2855,10 @@
              * happen due to the execution of this workaround.
              */
 
-            if((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
-               (!hw->autoneg) &&
-               (hw->forced_speed_duplex == e1000_10_full ||
-                hw->forced_speed_duplex == e1000_10_half)) {
+            if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) &&
+                (!hw->autoneg) &&
+                (hw->forced_speed_duplex == e1000_10_full ||
+                 hw->forced_speed_duplex == e1000_10_half)) {
                 E1000_WRITE_REG(hw, IMC, 0xffffffff);
                 ret_val = e1000_polarity_reversal_workaround(hw);
                 icr = E1000_READ_REG(hw, ICR);
@@ -2833,7 +2875,7 @@
         /* If we are forcing speed/duplex, then we simply return since
          * we have already determined whether we have link or not.
          */
-        if(!hw->autoneg) return -E1000_ERR_CONFIG;
+        if (!hw->autoneg) return -E1000_ERR_CONFIG;
 
         /* optimize the dsp settings for the igp phy */
         e1000_config_dsp_after_link_change(hw, TRUE);
@@ -2846,11 +2888,11 @@
          * speed/duplex on the MAC to the current PHY speed/duplex
          * settings.
          */
-        if(hw->mac_type >= e1000_82544)
+        if (hw->mac_type >= e1000_82544)
             e1000_config_collision_dist(hw);
         else {
             ret_val = e1000_config_mac_to_phy(hw);
-            if(ret_val) {
+            if (ret_val) {
                 DEBUGOUT("Error configuring MAC to PHY settings\n");
                 return ret_val;
             }
@@ -2861,7 +2903,7 @@
          * have had to re-autoneg with a different link partner.
          */
         ret_val = e1000_config_fc_after_link_up(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error configuring flow control\n");
             return ret_val;
         }
@@ -2873,7 +2915,7 @@
          * at gigabit speed, then TBI compatibility is not needed.  If we are
          * at gigabit speed, we turn on TBI compatibility.
          */
-        if(hw->tbi_compatibility_en) {
+        if (hw->tbi_compatibility_en) {
             uint16_t speed, duplex;
             ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
             if (ret_val) {
@@ -2884,7 +2926,7 @@
                 /* If link speed is not set to gigabit speed, we do not need
                  * to enable TBI compatibility.
                  */
-                if(hw->tbi_compatibility_on) {
+                if (hw->tbi_compatibility_on) {
                     /* If we previously were in the mode, turn it off. */
                     rctl = E1000_READ_REG(hw, RCTL);
                     rctl &= ~E1000_RCTL_SBP;
@@ -2897,7 +2939,7 @@
                  * packets. Some frames have an additional byte on the end and
                  * will look like CRC errors to to the hardware.
                  */
-                if(!hw->tbi_compatibility_on) {
+                if (!hw->tbi_compatibility_on) {
                     hw->tbi_compatibility_on = TRUE;
                     rctl = E1000_READ_REG(hw, RCTL);
                     rctl |= E1000_RCTL_SBP;
@@ -2913,12 +2955,12 @@
      * auto-negotiation time to complete, in case the cable was just plugged
      * in. The autoneg_failed flag does this.
      */
-    else if((((hw->media_type == e1000_media_type_fiber) &&
+    else if ((((hw->media_type == e1000_media_type_fiber) &&
               ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
-             (hw->media_type == e1000_media_type_internal_serdes)) &&
-            (!(status & E1000_STATUS_LU)) &&
-            (!(rxcw & E1000_RXCW_C))) {
-        if(hw->autoneg_failed == 0) {
+              (hw->media_type == e1000_media_type_internal_serdes)) &&
+              (!(status & E1000_STATUS_LU)) &&
+              (!(rxcw & E1000_RXCW_C))) {
+        if (hw->autoneg_failed == 0) {
             hw->autoneg_failed = 1;
             return 0;
         }
@@ -2934,7 +2976,7 @@
 
         /* Configure Flow Control after forcing link up. */
         ret_val = e1000_config_fc_after_link_up(hw);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error configuring flow control\n");
             return ret_val;
         }
@@ -2944,9 +2986,9 @@
      * Device Control register in an attempt to auto-negotiate with our link
      * partner.
      */
-    else if(((hw->media_type == e1000_media_type_fiber) ||
-             (hw->media_type == e1000_media_type_internal_serdes)) &&
-            (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
+    else if (((hw->media_type == e1000_media_type_fiber) ||
+              (hw->media_type == e1000_media_type_internal_serdes)) &&
+              (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
         DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -2956,12 +2998,12 @@
     /* If we force link for non-auto-negotiation switch, check link status
      * based on MAC synchronization for internal serdes media type.
      */
-    else if((hw->media_type == e1000_media_type_internal_serdes) &&
-            !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+    else if ((hw->media_type == e1000_media_type_internal_serdes) &&
+             !(E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
         /* SYNCH bit and IV bit are sticky. */
         udelay(10);
-        if(E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
-            if(!(rxcw & E1000_RXCW_IV)) {
+        if (E1000_RXCW_SYNCH & E1000_READ_REG(hw, RXCW)) {
+            if (!(rxcw & E1000_RXCW_IV)) {
                 hw->serdes_link_down = FALSE;
                 DEBUGOUT("SERDES: Link is up.\n");
             }
@@ -2970,8 +3012,8 @@
             DEBUGOUT("SERDES: Link is down.\n");
         }
     }
-    if((hw->media_type == e1000_media_type_internal_serdes) &&
-       (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
+    if ((hw->media_type == e1000_media_type_internal_serdes) &&
+        (E1000_TXCW_ANE & E1000_READ_REG(hw, TXCW))) {
         hw->serdes_link_down = !(E1000_STATUS_LU & E1000_READ_REG(hw, STATUS));
     }
     return E1000_SUCCESS;
@@ -2995,12 +3037,12 @@
 
     DEBUGFUNC("e1000_get_speed_and_duplex");
 
-    if(hw->mac_type >= e1000_82543) {
+    if (hw->mac_type >= e1000_82543) {
         status = E1000_READ_REG(hw, STATUS);
-        if(status & E1000_STATUS_SPEED_1000) {
+        if (status & E1000_STATUS_SPEED_1000) {
             *speed = SPEED_1000;
             DEBUGOUT("1000 Mbs, ");
-        } else if(status & E1000_STATUS_SPEED_100) {
+        } else if (status & E1000_STATUS_SPEED_100) {
             *speed = SPEED_100;
             DEBUGOUT("100 Mbs, ");
         } else {
@@ -3008,7 +3050,7 @@
             DEBUGOUT("10 Mbs, ");
         }
 
-        if(status & E1000_STATUS_FD) {
+        if (status & E1000_STATUS_FD) {
             *duplex = FULL_DUPLEX;
             DEBUGOUT("Full Duplex\n");
         } else {
@@ -3025,18 +3067,18 @@
      * if it is operating at half duplex.  Here we set the duplex settings to
      * match the duplex in the link partner's capabilities.
      */
-    if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
+    if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
         ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if(!(phy_data & NWAY_ER_LP_NWAY_CAPS))
+        if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
             *duplex = HALF_DUPLEX;
         else {
             ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
-            if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
+            if ((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
                (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
                 *duplex = HALF_DUPLEX;
         }
@@ -3077,17 +3119,17 @@
     DEBUGOUT("Waiting for Auto-Neg to complete.\n");
 
     /* We will wait for autoneg to complete or 4.5 seconds to expire. */
-    for(i = PHY_AUTO_NEG_TIME; i > 0; i--) {
+    for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
         /* Read the MII Status Register and wait for Auto-Neg
          * Complete bit to be set.
          */
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
-        if(phy_data & MII_SR_AUTONEG_COMPLETE) {
+        if (phy_data & MII_SR_AUTONEG_COMPLETE) {
             return E1000_SUCCESS;
         }
         msec_delay(100);
@@ -3160,14 +3202,16 @@
     /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
     ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
 
-    while(mask) {
+    while (mask) {
         /* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
          * then raising and lowering the Management Data Clock. A "0" is
          * shifted out to the PHY by setting the MDIO bit to "0" and then
          * raising and lowering the clock.
          */
-        if(data & mask) ctrl |= E1000_CTRL_MDIO;
-        else ctrl &= ~E1000_CTRL_MDIO;
+        if (data & mask)
+            ctrl |= E1000_CTRL_MDIO;
+        else
+            ctrl &= ~E1000_CTRL_MDIO;
 
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
@@ -3218,12 +3262,13 @@
     e1000_raise_mdi_clk(hw, &ctrl);
     e1000_lower_mdi_clk(hw, &ctrl);
 
-    for(data = 0, i = 0; i < 16; i++) {
+    for (data = 0, i = 0; i < 16; i++) {
         data = data << 1;
         e1000_raise_mdi_clk(hw, &ctrl);
         ctrl = E1000_READ_REG(hw, CTRL);
         /* Check to see if we shifted in a "1". */
-        if(ctrl & E1000_CTRL_MDIO) data |= 1;
+        if (ctrl & E1000_CTRL_MDIO)
+            data |= 1;
         e1000_lower_mdi_clk(hw, &ctrl);
     }
 
@@ -3233,7 +3278,7 @@
     return data;
 }
 
-int32_t
+static int32_t
 e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask)
 {
     uint32_t swfw_sync = 0;
@@ -3249,7 +3294,7 @@
     if (!hw->swfw_sync_present)
         return e1000_get_hw_eeprom_semaphore(hw);
 
-    while(timeout) {
+    while (timeout) {
             if (e1000_get_hw_eeprom_semaphore(hw))
                 return -E1000_ERR_SWFW_SYNC;
 
@@ -3277,7 +3322,7 @@
     return E1000_SUCCESS;
 }
 
-void
+static void
 e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask)
 {
     uint32_t swfw_sync;
@@ -3338,7 +3383,7 @@
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
-        if(ret_val) {
+        if (ret_val) {
             e1000_swfw_sync_release(hw, swfw);
             return ret_val;
         }
@@ -3383,12 +3428,12 @@
 
     DEBUGFUNC("e1000_read_phy_reg_ex");
 
-    if(reg_addr > MAX_PHY_REG_ADDRESS) {
+    if (reg_addr > MAX_PHY_REG_ADDRESS) {
         DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
         return -E1000_ERR_PARAM;
     }
 
-    if(hw->mac_type > e1000_82543) {
+    if (hw->mac_type > e1000_82543) {
         /* Set up Op-code, Phy Address, and register address in the MDI
          * Control register.  The MAC will take care of interfacing with the
          * PHY to retrieve the desired data.
@@ -3400,16 +3445,16 @@
         E1000_WRITE_REG(hw, MDIC, mdic);
 
         /* Poll the ready bit to see if the MDI read completed */
-        for(i = 0; i < 64; i++) {
+        for (i = 0; i < 64; i++) {
             udelay(50);
             mdic = E1000_READ_REG(hw, MDIC);
-            if(mdic & E1000_MDIC_READY) break;
+            if (mdic & E1000_MDIC_READY) break;
         }
-        if(!(mdic & E1000_MDIC_READY)) {
+        if (!(mdic & E1000_MDIC_READY)) {
             DEBUGOUT("MDI Read did not complete\n");
             return -E1000_ERR_PHY;
         }
-        if(mdic & E1000_MDIC_ERROR) {
+        if (mdic & E1000_MDIC_ERROR) {
             DEBUGOUT("MDI Error\n");
             return -E1000_ERR_PHY;
         }
@@ -3478,7 +3523,7 @@
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                          (uint16_t)reg_addr);
-        if(ret_val) {
+        if (ret_val) {
             e1000_swfw_sync_release(hw, swfw);
             return ret_val;
         }
@@ -3523,12 +3568,12 @@
 
     DEBUGFUNC("e1000_write_phy_reg_ex");
 
-    if(reg_addr > MAX_PHY_REG_ADDRESS) {
+    if (reg_addr > MAX_PHY_REG_ADDRESS) {
         DEBUGOUT1("PHY Address %d is out of range\n", reg_addr);
         return -E1000_ERR_PARAM;
     }
 
-    if(hw->mac_type > e1000_82543) {
+    if (hw->mac_type > e1000_82543) {
         /* Set up Op-code, Phy Address, register address, and data intended
          * for the PHY register in the MDI Control register.  The MAC will take
          * care of interfacing with the PHY to send the desired data.
@@ -3541,12 +3586,12 @@
         E1000_WRITE_REG(hw, MDIC, mdic);
 
         /* Poll the ready bit to see if the MDI read completed */
-        for(i = 0; i < 640; i++) {
+        for (i = 0; i < 641; i++) {
             udelay(5);
             mdic = E1000_READ_REG(hw, MDIC);
-            if(mdic & E1000_MDIC_READY) break;
+            if (mdic & E1000_MDIC_READY) break;
         }
-        if(!(mdic & E1000_MDIC_READY)) {
+        if (!(mdic & E1000_MDIC_READY)) {
             DEBUGOUT("MDI Write did not complete\n");
             return -E1000_ERR_PHY;
         }
@@ -3575,7 +3620,7 @@
     return E1000_SUCCESS;
 }
 
-int32_t
+static int32_t
 e1000_read_kmrn_reg(struct e1000_hw *hw,
                     uint32_t reg_addr,
                     uint16_t *data)
@@ -3608,7 +3653,7 @@
     return E1000_SUCCESS;
 }
 
-int32_t
+static int32_t
 e1000_write_kmrn_reg(struct e1000_hw *hw,
                      uint32_t reg_addr,
                      uint16_t data)
@@ -3658,7 +3703,7 @@
 
     DEBUGOUT("Resetting Phy...\n");
 
-    if(hw->mac_type > e1000_82543) {
+    if (hw->mac_type > e1000_82543) {
         if ((hw->mac_type == e1000_80003es2lan) &&
             (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) {
             swfw = E1000_SWFW_PHY1_SM;
@@ -3706,7 +3751,7 @@
     }
     udelay(150);
 
-    if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+    if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
         /* Configure activity LED after PHY reset */
         led_ctrl = E1000_READ_REG(hw, LEDCTL);
         led_ctrl &= IGP_ACTIVITY_LED_MASK;
@@ -3716,14 +3761,13 @@
 
     /* Wait for FW to finish PHY configuration. */
     ret_val = e1000_get_phy_cfg_done(hw);
+    if (ret_val != E1000_SUCCESS)
+        return ret_val;
     e1000_release_software_semaphore(hw);
 
-        if ((hw->mac_type == e1000_ich8lan) &&
-            (hw->phy_type == e1000_phy_igp_3)) {
-            ret_val = e1000_init_lcd_from_nvm(hw);
-            if (ret_val)
-                return ret_val;
-        }
+    if ((hw->mac_type == e1000_ich8lan) && (hw->phy_type == e1000_phy_igp_3))
+        ret_val = e1000_init_lcd_from_nvm(hw);
+
     return ret_val;
 }
 
@@ -3754,25 +3798,25 @@
     case e1000_82572:
     case e1000_ich8lan:
         ret_val = e1000_phy_hw_reset(hw);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         break;
     default:
         ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data |= MII_CR_RESET;
         ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         udelay(1);
         break;
     }
 
-    if(hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2)
+    if (hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2)
         e1000_phy_init_script(hw);
 
     return E1000_SUCCESS;
@@ -3839,7 +3883,7 @@
 *
 * hw - struct containing variables accessed by shared code
 ******************************************************************************/
-int32_t
+static int32_t
 e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw)
 {
     int32_t ret_val;
@@ -3850,8 +3894,8 @@
     if (hw->kmrn_lock_loss_workaround_disabled)
         return E1000_SUCCESS;
 
-    /* Make sure link is up before proceeding. If not just return.
-     * Attempting this while link is negotiating fouls up link
+    /* Make sure link is up before proceeding.  If not just return.
+     * Attempting this while link is negotiating fouled up link
      * stability */
     ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
     ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
@@ -3928,34 +3972,34 @@
     hw->phy_id = (uint32_t) (phy_id_high << 16);
     udelay(20);
     ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
     hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK;
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82543:
-        if(hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
+        if (hw->phy_id == M88E1000_E_PHY_ID) match = TRUE;
         break;
     case e1000_82544:
-        if(hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
+        if (hw->phy_id == M88E1000_I_PHY_ID) match = TRUE;
         break;
     case e1000_82540:
     case e1000_82545:
     case e1000_82545_rev_3:
     case e1000_82546:
     case e1000_82546_rev_3:
-        if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
+        if (hw->phy_id == M88E1011_I_PHY_ID) match = TRUE;
         break;
     case e1000_82541:
     case e1000_82541_rev_2:
     case e1000_82547:
     case e1000_82547_rev_2:
-        if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
+        if (hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
         break;
     case e1000_82573:
-        if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
+        if (hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
         break;
     case e1000_80003es2lan:
         if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
@@ -3994,14 +4038,14 @@
     do {
         if (hw->phy_type != e1000_phy_gg82563) {
             ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
-            if(ret_val) break;
+            if (ret_val) break;
         }
         ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
-        if(ret_val) break;
+        if (ret_val) break;
         ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
-        if(ret_val) break;
+        if (ret_val) break;
         ret_val = E1000_SUCCESS;
-    } while(0);
+    } while (0);
 
     return ret_val;
 }
@@ -4033,23 +4077,23 @@
 
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >>
                           IGP01E1000_PSSR_MDIX_SHIFT;
 
-    if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
+    if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
        IGP01E1000_PSSR_SPEED_1000MBPS) {
         /* Local/Remote Receiver Information are only valid at 1000 Mbps */
         ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
@@ -4059,19 +4103,19 @@
 
         /* Get cable length */
         ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* Translate to old method */
         average = (max_length + min_length) / 2;
 
-        if(average <= e1000_igp_cable_length_50)
+        if (average <= e1000_igp_cable_length_50)
             phy_info->cable_length = e1000_cable_length_50;
-        else if(average <= e1000_igp_cable_length_80)
+        else if (average <= e1000_igp_cable_length_80)
             phy_info->cable_length = e1000_cable_length_50_80;
-        else if(average <= e1000_igp_cable_length_110)
+        else if (average <= e1000_igp_cable_length_110)
             phy_info->cable_length = e1000_cable_length_80_110;
-        else if(average <= e1000_igp_cable_length_140)
+        else if (average <= e1000_igp_cable_length_140)
             phy_info->cable_length = e1000_cable_length_110_140;
         else
             phy_info->cable_length = e1000_cable_length_140;
@@ -4086,7 +4130,7 @@
 * hw - Struct containing variables accessed by shared code
 * phy_info - PHY information structure
 ******************************************************************************/
-int32_t
+static int32_t
 e1000_phy_ife_get_info(struct e1000_hw *hw,
                        struct e1000_phy_info *phy_info)
 {
@@ -4147,7 +4191,7 @@
     phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_info->extended_10bt_distance =
@@ -4159,12 +4203,12 @@
 
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
@@ -4187,7 +4231,7 @@
         }
 
         ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
@@ -4224,20 +4268,20 @@
     phy_info->local_rx = e1000_1000t_rx_status_undefined;
     phy_info->remote_rx = e1000_1000t_rx_status_undefined;
 
-    if(hw->media_type != e1000_media_type_copper) {
+    if (hw->media_type != e1000_media_type_copper) {
         DEBUGOUT("PHY info is only valid for copper media\n");
         return -E1000_ERR_CONFIG;
     }
 
     ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
-    if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
+    if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
         DEBUGOUT("PHY info is only valid if link is up\n");
         return -E1000_ERR_CONFIG;
     }
@@ -4257,7 +4301,7 @@
 {
     DEBUGFUNC("e1000_validate_mdi_settings");
 
-    if(!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
+    if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
         DEBUGOUT("Invalid MDI setting detected\n");
         hw->mdix = 1;
         return -E1000_ERR_CONFIG;
@@ -4304,7 +4348,7 @@
         eeprom->type = e1000_eeprom_microwire;
         eeprom->opcode_bits = 3;
         eeprom->delay_usec = 50;
-        if(eecd & E1000_EECD_SIZE) {
+        if (eecd & E1000_EECD_SIZE) {
             eeprom->word_size = 256;
             eeprom->address_bits = 8;
         } else {
@@ -4372,7 +4416,7 @@
         }
         eeprom->use_eerd = TRUE;
         eeprom->use_eewr = TRUE;
-        if(e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+        if (e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
             eeprom->type = e1000_eeprom_flash;
             eeprom->word_size = 2048;
 
@@ -4433,17 +4477,17 @@
         /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
          * 32KB (incremented by powers of 2).
          */
-        if(hw->mac_type <= e1000_82547_rev_2) {
+        if (hw->mac_type <= e1000_82547_rev_2) {
             /* Set to default value for initial eeprom read. */
             eeprom->word_size = 64;
             ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
             eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
             /* 256B eeprom size was not supported in earlier hardware, so we
              * bump eeprom_size up one to ensure that "1" (which maps to 256B)
              * is never the result used in the shifting logic below. */
-            if(eeprom_size)
+            if (eeprom_size)
                 eeprom_size++;
         } else {
             eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
@@ -4528,7 +4572,7 @@
          */
         eecd &= ~E1000_EECD_DI;
 
-        if(data & mask)
+        if (data & mask)
             eecd |= E1000_EECD_DI;
 
         E1000_WRITE_REG(hw, EECD, eecd);
@@ -4541,7 +4585,7 @@
 
         mask = mask >> 1;
 
-    } while(mask);
+    } while (mask);
 
     /* We leave the "DI" bit set to "0" when we leave this routine. */
     eecd &= ~E1000_EECD_DI;
@@ -4573,14 +4617,14 @@
     eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
     data = 0;
 
-    for(i = 0; i < count; i++) {
+    for (i = 0; i < count; i++) {
         data = data << 1;
         e1000_raise_ee_clk(hw, &eecd);
 
         eecd = E1000_READ_REG(hw, EECD);
 
         eecd &= ~(E1000_EECD_DI);
-        if(eecd & E1000_EECD_DO)
+        if (eecd & E1000_EECD_DO)
             data |= 1;
 
         e1000_lower_ee_clk(hw, &eecd);
@@ -4611,17 +4655,17 @@
 
     if (hw->mac_type != e1000_82573) {
         /* Request EEPROM Access */
-        if(hw->mac_type > e1000_82544) {
+        if (hw->mac_type > e1000_82544) {
             eecd |= E1000_EECD_REQ;
             E1000_WRITE_REG(hw, EECD, eecd);
             eecd = E1000_READ_REG(hw, EECD);
-            while((!(eecd & E1000_EECD_GNT)) &&
+            while ((!(eecd & E1000_EECD_GNT)) &&
                   (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
                 i++;
                 udelay(5);
                 eecd = E1000_READ_REG(hw, EECD);
             }
-            if(!(eecd & E1000_EECD_GNT)) {
+            if (!(eecd & E1000_EECD_GNT)) {
                 eecd &= ~E1000_EECD_REQ;
                 E1000_WRITE_REG(hw, EECD, eecd);
                 DEBUGOUT("Could not acquire EEPROM grant\n");
@@ -4664,7 +4708,7 @@
 
     eecd = E1000_READ_REG(hw, EECD);
 
-    if(eeprom->type == e1000_eeprom_microwire) {
+    if (eeprom->type == e1000_eeprom_microwire) {
         eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
         E1000_WRITE_REG(hw, EECD, eecd);
         E1000_WRITE_FLUSH(hw);
@@ -4687,7 +4731,7 @@
         E1000_WRITE_REG(hw, EECD, eecd);
         E1000_WRITE_FLUSH(hw);
         udelay(eeprom->delay_usec);
-    } else if(eeprom->type == e1000_eeprom_spi) {
+    } else if (eeprom->type == e1000_eeprom_spi) {
         /* Toggle CS to flush commands */
         eecd |= E1000_EECD_CS;
         E1000_WRITE_REG(hw, EECD, eecd);
@@ -4721,7 +4765,7 @@
         E1000_WRITE_REG(hw, EECD, eecd);
 
         udelay(hw->eeprom.delay_usec);
-    } else if(hw->eeprom.type == e1000_eeprom_microwire) {
+    } else if (hw->eeprom.type == e1000_eeprom_microwire) {
         /* cleanup eeprom */
 
         /* CS on Microwire is active-high */
@@ -4743,7 +4787,7 @@
     }
 
     /* Stop requesting EEPROM access */
-    if(hw->mac_type > e1000_82544) {
+    if (hw->mac_type > e1000_82544) {
         eecd &= ~E1000_EECD_REQ;
         E1000_WRITE_REG(hw, EECD, eecd);
     }
@@ -4781,12 +4825,12 @@
         retry_count += 5;
 
         e1000_standby_eeprom(hw);
-    } while(retry_count < EEPROM_MAX_RETRY_SPI);
+    } while (retry_count < EEPROM_MAX_RETRY_SPI);
 
     /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
      * only 0-5mSec on 5V devices)
      */
-    if(retry_count >= EEPROM_MAX_RETRY_SPI) {
+    if (retry_count >= EEPROM_MAX_RETRY_SPI) {
         DEBUGOUT("SPI EEPROM Status error\n");
         return -E1000_ERR_EEPROM;
     }
@@ -4817,7 +4861,7 @@
     /* A check for invalid values:  offset too large, too many words, and not
      * enough words.
      */
-    if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
+    if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
        (words == 0)) {
         DEBUGOUT("\"words\" parameter out of bounds\n");
         return -E1000_ERR_EEPROM;
@@ -4825,7 +4869,7 @@
 
     /* FLASH reads without acquiring the semaphore are safe */
     if (e1000_is_onboard_nvm_eeprom(hw) == TRUE &&
-    hw->eeprom.use_eerd == FALSE) {
+        hw->eeprom.use_eerd == FALSE) {
         switch (hw->mac_type) {
         case e1000_80003es2lan:
             break;
@@ -4852,7 +4896,7 @@
         uint16_t word_in;
         uint8_t read_opcode = EEPROM_READ_OPCODE_SPI;
 
-        if(e1000_spi_eeprom_ready(hw)) {
+        if (e1000_spi_eeprom_ready(hw)) {
             e1000_release_eeprom(hw);
             return -E1000_ERR_EEPROM;
         }
@@ -4860,7 +4904,7 @@
         e1000_standby_eeprom(hw);
 
         /* Some SPI eeproms use the 8th address bit embedded in the opcode */
-        if((eeprom->address_bits == 8) && (offset >= 128))
+        if ((eeprom->address_bits == 8) && (offset >= 128))
             read_opcode |= EEPROM_A8_OPCODE_SPI;
 
         /* Send the READ command (opcode + addr)  */
@@ -4876,7 +4920,7 @@
             word_in = e1000_shift_in_ee_bits(hw, 16);
             data[i] = (word_in >> 8) | (word_in << 8);
         }
-    } else if(eeprom->type == e1000_eeprom_microwire) {
+    } else if (eeprom->type == e1000_eeprom_microwire) {
         for (i = 0; i < words; i++) {
             /* Send the READ command (opcode + addr)  */
             e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE,
@@ -4921,7 +4965,7 @@
         E1000_WRITE_REG(hw, EERD, eerd);
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
 
-        if(error) {
+        if (error) {
             break;
         }
         data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
@@ -4958,7 +5002,7 @@
                          E1000_EEPROM_RW_REG_START;
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
-        if(error) {
+        if (error) {
             break;
         }
 
@@ -4966,7 +5010,7 @@
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
 
-        if(error) {
+        if (error) {
             break;
         }
     }
@@ -4987,13 +5031,13 @@
     uint32_t i, reg = 0;
     int32_t done = E1000_ERR_EEPROM;
 
-    for(i = 0; i < attempts; i++) {
-        if(eerd == E1000_EEPROM_POLL_READ)
+    for (i = 0; i < attempts; i++) {
+        if (eerd == E1000_EEPROM_POLL_READ)
             reg = E1000_READ_REG(hw, EERD);
         else
             reg = E1000_READ_REG(hw, EEWR);
 
-        if(reg & E1000_EEPROM_RW_REG_DONE) {
+        if (reg & E1000_EEPROM_RW_REG_DONE) {
             done = E1000_SUCCESS;
             break;
         }
@@ -5025,7 +5069,7 @@
         eecd = ((eecd >> 15) & 0x03);
 
         /* If both bits are set, device is Flash type */
-        if(eecd == 0x03) {
+        if (eecd == 0x03) {
             return FALSE;
         }
     }
@@ -5090,7 +5134,7 @@
         checksum += eeprom_data;
     }
 
-    if(checksum == (uint16_t) EEPROM_SUM)
+    if (checksum == (uint16_t) EEPROM_SUM)
         return E1000_SUCCESS;
     else {
         DEBUGOUT("EEPROM Checksum Invalid\n");
@@ -5115,15 +5159,15 @@
 
     DEBUGFUNC("e1000_update_eeprom_checksum");
 
-    for(i = 0; i < EEPROM_CHECKSUM_REG; i++) {
-        if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
+    for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
+        if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
             DEBUGOUT("EEPROM Read Error\n");
             return -E1000_ERR_EEPROM;
         }
         checksum += eeprom_data;
     }
     checksum = (uint16_t) EEPROM_SUM - checksum;
-    if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
+    if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
         DEBUGOUT("EEPROM Write Error\n");
         return -E1000_ERR_EEPROM;
     } else if (hw->eeprom.type == e1000_eeprom_flash) {
@@ -5165,14 +5209,14 @@
     /* A check for invalid values:  offset too large, too many words, and not
      * enough words.
      */
-    if((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
+    if ((offset >= eeprom->word_size) || (words > eeprom->word_size - offset) ||
        (words == 0)) {
         DEBUGOUT("\"words\" parameter out of bounds\n");
         return -E1000_ERR_EEPROM;
     }
 
     /* 82573 writes only through eewr */
-    if(eeprom->use_eewr == TRUE)
+    if (eeprom->use_eewr == TRUE)
         return e1000_write_eeprom_eewr(hw, offset, words, data);
 
     if (eeprom->type == e1000_eeprom_ich8)
@@ -5182,7 +5226,7 @@
     if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
         return -E1000_ERR_EEPROM;
 
-    if(eeprom->type == e1000_eeprom_microwire) {
+    if (eeprom->type == e1000_eeprom_microwire) {
         status = e1000_write_eeprom_microwire(hw, offset, words, data);
     } else {
         status = e1000_write_eeprom_spi(hw, offset, words, data);
@@ -5218,7 +5262,7 @@
     while (widx < words) {
         uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI;
 
-        if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
+        if (e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM;
 
         e1000_standby_eeprom(hw);
 
@@ -5229,7 +5273,7 @@
         e1000_standby_eeprom(hw);
 
         /* Some SPI eeproms use the 8th address bit embedded in the opcode */
-        if((eeprom->address_bits == 8) && (offset >= 128))
+        if ((eeprom->address_bits == 8) && (offset >= 128))
             write_opcode |= EEPROM_A8_OPCODE_SPI;
 
         /* Send the Write command (8-bit opcode + addr) */
@@ -5251,7 +5295,7 @@
              * operation, while the smaller eeproms are capable of an 8-byte
              * PAGE WRITE operation.  Break the inner loop to pass new address
              */
-            if((((offset + widx)*2) % eeprom->page_size) == 0) {
+            if ((((offset + widx)*2) % eeprom->page_size) == 0) {
                 e1000_standby_eeprom(hw);
                 break;
             }
@@ -5317,12 +5361,12 @@
          * signal that the command has been completed by raising the DO signal.
          * If DO does not go high in 10 milliseconds, then error out.
          */
-        for(i = 0; i < 200; i++) {
+        for (i = 0; i < 200; i++) {
             eecd = E1000_READ_REG(hw, EECD);
-            if(eecd & E1000_EECD_DO) break;
+            if (eecd & E1000_EECD_DO) break;
             udelay(50);
         }
-        if(i == 200) {
+        if (i == 200) {
             DEBUGOUT("EEPROM Write did not complete\n");
             return -E1000_ERR_EEPROM;
         }
@@ -5513,40 +5557,6 @@
 }
 
 /******************************************************************************
- * Reads the adapter's part number from the EEPROM
- *
- * hw - Struct containing variables accessed by shared code
- * part_num - Adapter's part number
- *****************************************************************************/
-int32_t
-e1000_read_part_num(struct e1000_hw *hw,
-                    uint32_t *part_num)
-{
-    uint16_t offset = EEPROM_PBA_BYTE_1;
-    uint16_t eeprom_data;
-
-    DEBUGFUNC("e1000_read_part_num");
-
-    /* Get word 0 from EEPROM */
-    if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
-        DEBUGOUT("EEPROM Read Error\n");
-        return -E1000_ERR_EEPROM;
-    }
-    /* Save word 0 in upper half of part_num */
-    *part_num = (uint32_t) (eeprom_data << 16);
-
-    /* Get word 1 from EEPROM */
-    if(e1000_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) {
-        DEBUGOUT("EEPROM Read Error\n");
-        return -E1000_ERR_EEPROM;
-    }
-    /* Save word 1 in lower half of part_num */
-    *part_num |= eeprom_data;
-
-    return E1000_SUCCESS;
-}
-
-/******************************************************************************
  * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
  * second function of dual function devices
  *
@@ -5560,9 +5570,9 @@
 
     DEBUGFUNC("e1000_read_mac_addr");
 
-    for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
+    for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
         offset = i >> 1;
-        if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+        if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
             DEBUGOUT("EEPROM Read Error\n");
             return -E1000_ERR_EEPROM;
         }
@@ -5577,12 +5587,12 @@
     case e1000_82546_rev_3:
     case e1000_82571:
     case e1000_80003es2lan:
-        if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
+        if (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)
             hw->perm_mac_addr[5] ^= 0x01;
         break;
     }
 
-    for(i = 0; i < NODE_ADDRESS_SIZE; i++)
+    for (i = 0; i < NODE_ADDRESS_SIZE; i++)
         hw->mac_addr[i] = hw->perm_mac_addr[i];
     return E1000_SUCCESS;
 }
@@ -5621,7 +5631,7 @@
 
     /* Zero out the other 15 receive addresses. */
     DEBUGOUT("Clearing RAR[1-15]\n");
-    for(i = 1; i < rar_num; i++) {
+    for (i = 1; i < rar_num; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
         E1000_WRITE_FLUSH(hw);
         E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -5643,6 +5653,7 @@
  * for the first 15 multicast addresses, and hashes the rest into the
  * multicast table.
  *****************************************************************************/
+#if 0
 void
 e1000_mc_addr_list_update(struct e1000_hw *hw,
                           uint8_t *mc_addr_list,
@@ -5671,7 +5682,7 @@
     if ((hw->mac_type == e1000_82571) && (hw->laa_is_present == TRUE))
         num_rar_entry -= 1;
 
-    for(i = rar_used_count; i < num_rar_entry; i++) {
+    for (i = rar_used_count; i < num_rar_entry; i++) {
         E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
         E1000_WRITE_FLUSH(hw);
         E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
@@ -5683,13 +5694,13 @@
     num_mta_entry = E1000_NUM_MTA_REGISTERS;
     if (hw->mac_type == e1000_ich8lan)
         num_mta_entry = E1000_NUM_MTA_REGISTERS_ICH8LAN;
-    for(i = 0; i < num_mta_entry; i++) {
+    for (i = 0; i < num_mta_entry; i++) {
         E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
         E1000_WRITE_FLUSH(hw);
     }
 
     /* Add the new addresses */
-    for(i = 0; i < mc_addr_count; i++) {
+    for (i = 0; i < mc_addr_count; i++) {
         DEBUGOUT(" Adding the multicast addresses:\n");
         DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i,
                   mc_addr_list[i * (ETH_LENGTH_OF_ADDRESS + pad)],
@@ -5719,6 +5730,7 @@
     }
     DEBUGOUT("MC Update Complete\n");
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Hashes an address to determine its location in the multicast table
@@ -5820,7 +5832,7 @@
      * in the MTA, save off the previous entry before writing and
      * restore the old value after writing.
      */
-    if((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
+    if ((hw->mac_type == e1000_82544) && ((hash_reg & 0x1) == 1)) {
         temp = E1000_READ_REG_ARRAY(hw, MTA, (hash_reg - 1));
         E1000_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta);
         E1000_WRITE_FLUSH(hw);
@@ -5970,7 +5982,7 @@
 
     DEBUGFUNC("e1000_id_led_init");
 
-    if(hw->mac_type < e1000_82540) {
+    if (hw->mac_type < e1000_82540) {
         /* Nothing to do */
         return E1000_SUCCESS;
     }
@@ -5980,7 +5992,7 @@
     hw->ledctl_mode1 = hw->ledctl_default;
     hw->ledctl_mode2 = hw->ledctl_default;
 
-    if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
+    if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
         DEBUGOUT("EEPROM Read Error\n");
         return -E1000_ERR_EEPROM;
     }
@@ -5997,7 +6009,7 @@
     }
     for (i = 0; i < 4; i++) {
         temp = (eeprom_data >> (i << 2)) & led_mask;
-        switch(temp) {
+        switch (temp) {
         case ID_LED_ON1_DEF2:
         case ID_LED_ON1_ON2:
         case ID_LED_ON1_OFF2:
@@ -6014,7 +6026,7 @@
             /* Do nothing */
             break;
         }
-        switch(temp) {
+        switch (temp) {
         case ID_LED_DEF1_ON2:
         case ID_LED_ON1_ON2:
         case ID_LED_OFF1_ON2:
@@ -6048,7 +6060,7 @@
 
     DEBUGFUNC("e1000_setup_led");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82542_rev2_0:
     case e1000_82542_rev2_1:
     case e1000_82543:
@@ -6062,16 +6074,16 @@
         /* Turn off PHY Smart Power Down (if enabled) */
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
                                      &hw->phy_spd_default);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
                                       (uint16_t)(hw->phy_spd_default &
                                       ~IGP01E1000_GMII_SPD));
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         /* Fall Through */
     default:
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             ledctl = E1000_READ_REG(hw, LEDCTL);
             /* Save current LEDCTL settings */
             hw->ledctl_default = ledctl;
@@ -6082,7 +6094,7 @@
             ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
                        E1000_LEDCTL_LED0_MODE_SHIFT);
             E1000_WRITE_REG(hw, LEDCTL, ledctl);
-        } else if(hw->media_type == e1000_media_type_copper)
+        } else if (hw->media_type == e1000_media_type_copper)
             E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1);
         break;
     }
@@ -6090,6 +6102,7 @@
     return E1000_SUCCESS;
 }
 
+
 /******************************************************************************
  * Used on 82571 and later Si that has LED blink bits.
  * Callers must use their own timer and should have already called
@@ -6140,7 +6153,7 @@
 
     DEBUGFUNC("e1000_cleanup_led");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82542_rev2_0:
     case e1000_82542_rev2_1:
     case e1000_82543:
@@ -6154,7 +6167,7 @@
         /* Turn on PHY Smart Power Down (if previously enabled) */
         ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
                                       hw->phy_spd_default);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         /* Fall Through */
     default:
@@ -6182,7 +6195,7 @@
 
     DEBUGFUNC("e1000_led_on");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82542_rev2_0:
     case e1000_82542_rev2_1:
     case e1000_82543:
@@ -6191,7 +6204,7 @@
         ctrl |= E1000_CTRL_SWDPIO0;
         break;
     case e1000_82544:
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             /* Set SW Defineable Pin 0 to turn on the LED */
             ctrl |= E1000_CTRL_SWDPIN0;
             ctrl |= E1000_CTRL_SWDPIO0;
@@ -6202,7 +6215,7 @@
         }
         break;
     default:
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             /* Clear SW Defineable Pin 0 to turn on the LED */
             ctrl &= ~E1000_CTRL_SWDPIN0;
             ctrl |= E1000_CTRL_SWDPIO0;
@@ -6233,7 +6246,7 @@
 
     DEBUGFUNC("e1000_led_off");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82542_rev2_0:
     case e1000_82542_rev2_1:
     case e1000_82543:
@@ -6242,7 +6255,7 @@
         ctrl |= E1000_CTRL_SWDPIO0;
         break;
     case e1000_82544:
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             /* Clear SW Defineable Pin 0 to turn off the LED */
             ctrl &= ~E1000_CTRL_SWDPIN0;
             ctrl |= E1000_CTRL_SWDPIO0;
@@ -6253,7 +6266,7 @@
         }
         break;
     default:
-        if(hw->media_type == e1000_media_type_fiber) {
+        if (hw->media_type == e1000_media_type_fiber) {
             /* Set SW Defineable Pin 0 to turn off the LED */
             ctrl |= E1000_CTRL_SWDPIN0;
             ctrl |= E1000_CTRL_SWDPIO0;
@@ -6277,7 +6290,7 @@
  *
  * hw - Struct containing variables accessed by shared code
  *****************************************************************************/
-static void
+void
 e1000_clear_hw_cntrs(struct e1000_hw *hw)
 {
     volatile uint32_t temp;
@@ -6340,7 +6353,7 @@
     temp = E1000_READ_REG(hw, MPTC);
     temp = E1000_READ_REG(hw, BPTC);
 
-    if(hw->mac_type < e1000_82543) return;
+    if (hw->mac_type < e1000_82543) return;
 
     temp = E1000_READ_REG(hw, ALGNERRC);
     temp = E1000_READ_REG(hw, RXERRC);
@@ -6349,13 +6362,13 @@
     temp = E1000_READ_REG(hw, TSCTC);
     temp = E1000_READ_REG(hw, TSCTFC);
 
-    if(hw->mac_type <= e1000_82544) return;
+    if (hw->mac_type <= e1000_82544) return;
 
     temp = E1000_READ_REG(hw, MGTPRC);
     temp = E1000_READ_REG(hw, MGTPDC);
     temp = E1000_READ_REG(hw, MGTPTC);
 
-    if(hw->mac_type <= e1000_82547_rev_2) return;
+    if (hw->mac_type <= e1000_82547_rev_2) return;
 
     temp = E1000_READ_REG(hw, IAC);
     temp = E1000_READ_REG(hw, ICRXOC);
@@ -6386,8 +6399,8 @@
 {
     DEBUGFUNC("e1000_reset_adaptive");
 
-    if(hw->adaptive_ifs) {
-        if(!hw->ifs_params_forced) {
+    if (hw->adaptive_ifs) {
+        if (!hw->ifs_params_forced) {
             hw->current_ifs_val = 0;
             hw->ifs_min_val = IFS_MIN;
             hw->ifs_max_val = IFS_MAX;
@@ -6414,12 +6427,12 @@
 {
     DEBUGFUNC("e1000_update_adaptive");
 
-    if(hw->adaptive_ifs) {
-        if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
-            if(hw->tx_packet_delta > MIN_NUM_XMITS) {
+    if (hw->adaptive_ifs) {
+        if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) {
+            if (hw->tx_packet_delta > MIN_NUM_XMITS) {
                 hw->in_ifs_mode = TRUE;
-                if(hw->current_ifs_val < hw->ifs_max_val) {
-                    if(hw->current_ifs_val == 0)
+                if (hw->current_ifs_val < hw->ifs_max_val) {
+                    if (hw->current_ifs_val == 0)
                         hw->current_ifs_val = hw->ifs_min_val;
                     else
                         hw->current_ifs_val += hw->ifs_step_size;
@@ -6427,7 +6440,7 @@
                 }
             }
         } else {
-            if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
+            if (hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
                 hw->current_ifs_val = 0;
                 hw->in_ifs_mode = FALSE;
                 E1000_WRITE_REG(hw, AIT, 0);
@@ -6474,46 +6487,46 @@
      * This could be simplified if all environments supported
      * 64-bit integers.
      */
-    if(carry_bit && ((stats->gorcl & 0x80000000) == 0))
+    if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
         stats->gorch++;
     /* Is this a broadcast or multicast?  Check broadcast first,
      * since the test for a multicast frame will test positive on
      * a broadcast frame.
      */
-    if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
+    if ((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff))
         /* Broadcast packet */
         stats->bprc++;
-    else if(*mac_addr & 0x01)
+    else if (*mac_addr & 0x01)
         /* Multicast packet */
         stats->mprc++;
 
-    if(frame_len == hw->max_frame_size) {
+    if (frame_len == hw->max_frame_size) {
         /* In this case, the hardware has overcounted the number of
          * oversize frames.
          */
-        if(stats->roc > 0)
+        if (stats->roc > 0)
             stats->roc--;
     }
 
     /* Adjust the bin counters when the extra byte put the frame in the
      * wrong bin. Remember that the frame_len was adjusted above.
      */
-    if(frame_len == 64) {
+    if (frame_len == 64) {
         stats->prc64++;
         stats->prc127--;
-    } else if(frame_len == 127) {
+    } else if (frame_len == 127) {
         stats->prc127++;
         stats->prc255--;
-    } else if(frame_len == 255) {
+    } else if (frame_len == 255) {
         stats->prc255++;
         stats->prc511--;
-    } else if(frame_len == 511) {
+    } else if (frame_len == 511) {
         stats->prc511++;
         stats->prc1023--;
-    } else if(frame_len == 1023) {
+    } else if (frame_len == 1023) {
         stats->prc1023++;
         stats->prc1522--;
-    } else if(frame_len == 1522) {
+    } else if (frame_len == 1522) {
         stats->prc1522++;
     }
 }
@@ -6553,10 +6566,10 @@
         hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
                        e1000_bus_type_pcix : e1000_bus_type_pci;
 
-        if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+        if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
             hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
                             e1000_bus_speed_66 : e1000_bus_speed_120;
-        } else if(hw->bus_type == e1000_bus_type_pci) {
+        } else if (hw->bus_type == e1000_bus_type_pci) {
             hw->bus_speed = (status & E1000_STATUS_PCI66) ?
                             e1000_bus_speed_66 : e1000_bus_speed_33;
         } else {
@@ -6587,6 +6600,7 @@
  * hw - Struct containing variables accessed by shared code
  * offset - offset to read from
  *****************************************************************************/
+#if 0
 uint32_t
 e1000_read_reg_io(struct e1000_hw *hw,
                   uint32_t offset)
@@ -6597,6 +6611,7 @@
     e1000_io_write(hw, io_addr, offset);
     return e1000_io_read(hw, io_data);
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Writes a value to one of the devices registers using port I/O (as opposed to
@@ -6649,11 +6664,11 @@
     *min_length = *max_length = 0;
 
     /* Use old method for Phy older than IGP */
-    if(hw->phy_type == e1000_phy_m88) {
+    if (hw->phy_type == e1000_phy_m88) {
 
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                        M88E1000_PSSR_CABLE_LENGTH_SHIFT;
@@ -6712,7 +6727,7 @@
             return -E1000_ERR_PHY;
             break;
         }
-    } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
+    } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */
         uint16_t cur_agc_value;
         uint16_t min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
         uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
@@ -6721,10 +6736,10 @@
                                                           IGP01E1000_PHY_AGC_C,
                                                           IGP01E1000_PHY_AGC_D};
         /* Read the AGC registers for all channels */
-        for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+        for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
 
             ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
@@ -6774,7 +6789,7 @@
             if (ret_val)
                 return ret_val;
 
-	    /* Getting bits 15:9, which represent the combination of course and
+            /* Getting bits 15:9, which represent the combination of course and
              * fine gain values.  The result is a number that can be put into
              * the lookup table to obtain the approximate cable length. */
             cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
@@ -6839,7 +6854,7 @@
         /* return the Polarity bit in the Status register. */
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
         *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
                     M88E1000_PSSR_REV_POLARITY_SHIFT;
@@ -6849,18 +6864,18 @@
         /* Read the Status register to check the speed */
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
          * find the polarity status */
-        if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
+        if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
            IGP01E1000_PSSR_SPEED_1000MBPS) {
 
             /* Read the GIG initialization PCS register (0x00B4) */
             ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
                                          &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             /* Check the polarity bits */
@@ -6909,7 +6924,7 @@
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
@@ -6917,7 +6932,7 @@
                (hw->phy_type == e1000_phy_gg82563)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
@@ -6957,42 +6972,42 @@
 
     DEBUGFUNC("e1000_config_dsp_after_link_change");
 
-    if(hw->phy_type != e1000_phy_igp)
+    if (hw->phy_type != e1000_phy_igp)
         return E1000_SUCCESS;
 
-    if(link_up) {
+    if (link_up) {
         ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
-        if(ret_val) {
+        if (ret_val) {
             DEBUGOUT("Error getting link speed and duplex\n");
             return ret_val;
         }
 
-        if(speed == SPEED_1000) {
+        if (speed == SPEED_1000) {
 
             ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
             if (ret_val)
                 return ret_val;
 
-            if((hw->dsp_config_state == e1000_dsp_config_enabled) &&
+            if ((hw->dsp_config_state == e1000_dsp_config_enabled) &&
                 min_length >= e1000_igp_cable_length_50) {
 
-                for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+                for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
                     ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
                                                  &phy_data);
-                    if(ret_val)
+                    if (ret_val)
                         return ret_val;
 
                     phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
 
                     ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
                                                   phy_data);
-                    if(ret_val)
+                    if (ret_val)
                         return ret_val;
                 }
                 hw->dsp_config_state = e1000_dsp_config_activated;
             }
 
-            if((hw->ffe_config_state == e1000_ffe_config_enabled) &&
+            if ((hw->ffe_config_state == e1000_ffe_config_enabled) &&
                (min_length < e1000_igp_cable_length_50)) {
 
                 uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
@@ -7001,70 +7016,70 @@
                 /* clear previous idle error counts */
                 ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
                                              &phy_data);
-                if(ret_val)
+                if (ret_val)
                     return ret_val;
 
-                for(i = 0; i < ffe_idle_err_timeout; i++) {
+                for (i = 0; i < ffe_idle_err_timeout; i++) {
                     udelay(1000);
                     ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
                                                  &phy_data);
-                    if(ret_val)
+                    if (ret_val)
                         return ret_val;
 
                     idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
-                    if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
+                    if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
                         hw->ffe_config_state = e1000_ffe_config_active;
 
                         ret_val = e1000_write_phy_reg(hw,
                                     IGP01E1000_PHY_DSP_FFE,
                                     IGP01E1000_PHY_DSP_FFE_CM_CP);
-                        if(ret_val)
+                        if (ret_val)
                             return ret_val;
                         break;
                     }
 
-                    if(idle_errs)
+                    if (idle_errs)
                         ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100;
                 }
             }
         }
     } else {
-        if(hw->dsp_config_state == e1000_dsp_config_activated) {
+        if (hw->dsp_config_state == e1000_dsp_config_activated) {
             /* Save off the current value of register 0x2F5B to be restored at
              * the end of the routines. */
             ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             /* Disable the PHY transmitter */
             ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             msec_delay_irq(20);
 
             ret_val = e1000_write_phy_reg(hw, 0x0000,
                                           IGP01E1000_IEEE_FORCE_GIGA);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
-            for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
+            for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
                 ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], &phy_data);
-                if(ret_val)
+                if (ret_val)
                     return ret_val;
 
                 phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
                 phy_data |=  IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
 
                 ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], phy_data);
-                if(ret_val)
+                if (ret_val)
                     return ret_val;
             }
 
             ret_val = e1000_write_phy_reg(hw, 0x0000,
                                           IGP01E1000_IEEE_RESTART_AUTONEG);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             msec_delay_irq(20);
@@ -7072,40 +7087,40 @@
             /* Now enable the transmitter */
             ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             hw->dsp_config_state = e1000_dsp_config_enabled;
         }
 
-        if(hw->ffe_config_state == e1000_ffe_config_active) {
+        if (hw->ffe_config_state == e1000_ffe_config_active) {
             /* Save off the current value of register 0x2F5B to be restored at
              * the end of the routines. */
             ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             /* Disable the PHY transmitter */
             ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             msec_delay_irq(20);
 
             ret_val = e1000_write_phy_reg(hw, 0x0000,
                                           IGP01E1000_IEEE_FORCE_GIGA);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
                                           IGP01E1000_PHY_DSP_FFE_DEFAULT);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             ret_val = e1000_write_phy_reg(hw, 0x0000,
                                           IGP01E1000_IEEE_RESTART_AUTONEG);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             msec_delay_irq(20);
@@ -7113,7 +7128,7 @@
             /* Now enable the transmitter */
             ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
 
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             hw->ffe_config_state = e1000_ffe_config_enabled;
@@ -7138,20 +7153,20 @@
 
     DEBUGFUNC("e1000_set_phy_mode");
 
-    if((hw->mac_type == e1000_82545_rev_3) &&
-       (hw->media_type == e1000_media_type_copper)) {
+    if ((hw->mac_type == e1000_82545_rev_3) &&
+        (hw->media_type == e1000_media_type_copper)) {
         ret_val = e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, &eeprom_data);
-        if(ret_val) {
+        if (ret_val) {
             return ret_val;
         }
 
-        if((eeprom_data != EEPROM_RESERVED_WORD) &&
-           (eeprom_data & EEPROM_PHY_CLASS_A)) {
+        if ((eeprom_data != EEPROM_RESERVED_WORD) &&
+            (eeprom_data & EEPROM_PHY_CLASS_A)) {
             ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
             ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             hw->phy_reset_disable = FALSE;
@@ -7202,16 +7217,16 @@
         phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
     } else {
         ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
-    if(!active) {
-        if(hw->mac_type == e1000_82541_rev_2 ||
-           hw->mac_type == e1000_82547_rev_2) {
+    if (!active) {
+        if (hw->mac_type == e1000_82541_rev_2 ||
+            hw->mac_type == e1000_82547_rev_2) {
             phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         } else {
             if (hw->mac_type == e1000_ich8lan) {
@@ -7233,13 +7248,13 @@
         if (hw->smart_speed == e1000_smart_speed_on) {
             ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                          &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                           phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         } else if (hw->smart_speed == e1000_smart_speed_off) {
             ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
@@ -7250,19 +7265,19 @@
             phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                           phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         }
 
-    } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
-              (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
-              (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
+    } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
+               (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
+               (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
 
-        if(hw->mac_type == e1000_82541_rev_2 ||
+        if (hw->mac_type == e1000_82541_rev_2 ||
             hw->mac_type == e1000_82547_rev_2) {
             phy_data |= IGP01E1000_GMII_FLEX_SPD;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         } else {
             if (hw->mac_type == e1000_ich8lan) {
@@ -7279,12 +7294,12 @@
 
         /* When LPLU is enabled we should disable SmartSpeed */
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
         ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
     }
@@ -7314,14 +7329,14 @@
     uint16_t phy_data;
     DEBUGFUNC("e1000_set_d0_lplu_state");
 
-    if(hw->mac_type <= e1000_82547_rev_2)
+    if (hw->mac_type <= e1000_82547_rev_2)
         return E1000_SUCCESS;
 
     if (hw->mac_type == e1000_ich8lan) {
         phy_ctrl = E1000_READ_REG(hw, PHY_CTRL);
     } else {
         ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
     }
 
@@ -7343,13 +7358,13 @@
         if (hw->smart_speed == e1000_smart_speed_on) {
             ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                          &phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
 
             phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                           phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         } else if (hw->smart_speed == e1000_smart_speed_off) {
             ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
@@ -7360,7 +7375,7 @@
             phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
             ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
                                           phy_data);
-            if(ret_val)
+            if (ret_val)
                 return ret_val;
         }
 
@@ -7379,12 +7394,12 @@
 
         /* When LPLU is enabled we should disable SmartSpeed */
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
         ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
     }
@@ -7405,7 +7420,7 @@
 
     DEBUGFUNC("e1000_set_vco_speed");
 
-    switch(hw->mac_type) {
+    switch (hw->mac_type) {
     case e1000_82545_rev_3:
     case e1000_82546_rev_3:
        break;
@@ -7416,39 +7431,39 @@
     /* Set PHY register 30, page 5, bit 8 to 0 */
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* Set PHY register 30, page 4, bit 11 to 1 */
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     phy_data |= M88E1000_PHY_VCO_REG_BIT11;
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     return E1000_SUCCESS;
@@ -7527,7 +7542,7 @@
 {
     uint8_t *tmp;
     uint8_t *bufptr = buffer;
-    uint32_t data;
+    uint32_t data = 0;
     uint16_t remaining, i, j, prev_bytes;
 
     /* sum = only sum of the data and it is not checksum */
@@ -7607,7 +7622,7 @@
 
     buffer = (uint8_t *) hdr;
     i = length;
-    while(i--)
+    while (i--)
         sum += buffer[i];
 
     hdr->checksum = 0 - sum;
@@ -7630,8 +7645,7 @@
  * returns  - E1000_SUCCESS for success.
  ****************************************************************************/
 static int32_t
-e1000_mng_write_commit(
-    struct e1000_hw * hw)
+e1000_mng_write_commit(struct e1000_hw * hw)
 {
     uint32_t hicr;
 
@@ -7803,31 +7817,31 @@
     /* Disable the transmitter on the PHY */
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* This loop will early-out if the NO link condition has been met. */
-    for(i = PHY_FORCE_TIME; i > 0; i--) {
+    for (i = PHY_FORCE_TIME; i > 0; i--) {
         /* Read the MII Status Register and wait for Link Status bit
          * to be clear.
          */
 
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
+        if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) break;
         msec_delay_irq(100);
     }
 
@@ -7837,40 +7851,40 @@
     /* Now we will re-enable th transmitter on the PHY */
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
     msec_delay_irq(50);
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
     msec_delay_irq(50);
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
     msec_delay_irq(50);
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
-    if(ret_val)
+    if (ret_val)
         return ret_val;
 
     /* This loop will early-out if the link condition has been met. */
-    for(i = PHY_FORCE_TIME; i > 0; i--) {
+    for (i = PHY_FORCE_TIME; i > 0; i--) {
         /* Read the MII Status Register and wait for Link Status bit
          * to be set.
          */
 
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
         ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
-        if(ret_val)
+        if (ret_val)
             return ret_val;
 
-        if(mii_status_reg & MII_SR_LINK_STATUS) break;
+        if (mii_status_reg & MII_SR_LINK_STATUS) break;
         msec_delay_irq(100);
     }
     return E1000_SUCCESS;
@@ -7909,6 +7923,7 @@
  * returns: - none.
  *
  ***************************************************************************/
+#if 0
 void
 e1000_enable_pciex_master(struct e1000_hw *hw)
 {
@@ -7923,6 +7938,7 @@
     ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
     E1000_WRITE_REG(hw, CTRL, ctrl);
 }
+#endif  /*  0  */
 
 /*******************************************************************************
  *
@@ -7947,15 +7963,15 @@
 
     e1000_set_pci_express_master_disable(hw);
 
-    while(timeout) {
-        if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+    while (timeout) {
+        if (!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
             break;
         else
             udelay(100);
         timeout--;
     }
 
-    if(!timeout) {
+    if (!timeout) {
         DEBUGOUT("Master requests are pending.\n");
         return -E1000_ERR_MASTER_REQUESTS_PENDING;
     }
@@ -7996,7 +8012,7 @@
             timeout--;
         }
 
-        if(!timeout) {
+        if (!timeout) {
             DEBUGOUT("Auto read by HW from EEPROM has not completed.\n");
             return -E1000_ERR_RESET;
         }
@@ -8077,7 +8093,7 @@
 
     DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
 
-    if(!hw->eeprom_semaphore_present)
+    if (!hw->eeprom_semaphore_present)
         return E1000_SUCCESS;
 
     if (hw->mac_type == e1000_80003es2lan) {
@@ -8088,20 +8104,20 @@
 
     /* Get the FW semaphore. */
     timeout = hw->eeprom.word_size + 1;
-    while(timeout) {
+    while (timeout) {
         swsm = E1000_READ_REG(hw, SWSM);
         swsm |= E1000_SWSM_SWESMBI;
         E1000_WRITE_REG(hw, SWSM, swsm);
         /* if we managed to set the bit we got the semaphore. */
         swsm = E1000_READ_REG(hw, SWSM);
-        if(swsm & E1000_SWSM_SWESMBI)
+        if (swsm & E1000_SWSM_SWESMBI)
             break;
 
         udelay(50);
         timeout--;
     }
 
-    if(!timeout) {
+    if (!timeout) {
         /* Release semaphores */
         e1000_put_hw_eeprom_semaphore(hw);
         DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n");
@@ -8126,7 +8142,7 @@
 
     DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
 
-    if(!hw->eeprom_semaphore_present)
+    if (!hw->eeprom_semaphore_present)
         return;
 
     swsm = E1000_READ_REG(hw, SWSM);
@@ -8148,7 +8164,7 @@
  *            E1000_SUCCESS at any other case.
  *
  ***************************************************************************/
-int32_t
+static int32_t
 e1000_get_software_semaphore(struct e1000_hw *hw)
 {
     int32_t timeout = hw->eeprom.word_size + 1;
@@ -8159,16 +8175,16 @@
     if (hw->mac_type != e1000_80003es2lan)
         return E1000_SUCCESS;
 
-    while(timeout) {
+    while (timeout) {
         swsm = E1000_READ_REG(hw, SWSM);
         /* If SMBI bit cleared, it is now set and we hold the semaphore */
-        if(!(swsm & E1000_SWSM_SMBI))
+        if (!(swsm & E1000_SWSM_SMBI))
             break;
         msec_delay_irq(1);
         timeout--;
     }
 
-    if(!timeout) {
+    if (!timeout) {
         DEBUGOUT("Driver can't access device - SMBI bit is set.\n");
         return -E1000_ERR_RESET;
     }
@@ -8183,7 +8199,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-void
+static void
 e1000_release_software_semaphore(struct e1000_hw *hw)
 {
     uint32_t swsm;
@@ -8244,7 +8260,7 @@
     case e1000_82573:
     case e1000_80003es2lan:
         fwsm = E1000_READ_REG(hw, FWSM);
-        if((fwsm & E1000_FWSM_MODE_MASK) != 0)
+        if ((fwsm & E1000_FWSM_MODE_MASK) != 0)
             return TRUE;
         break;
     case e1000_ich8lan:
@@ -8265,7 +8281,7 @@
  * returns: E1000_SUCCESS
  *
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop)
 {
     uint32_t gcr_reg = 0;
@@ -8306,7 +8322,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-int32_t
+static int32_t
 e1000_get_software_flag(struct e1000_hw *hw)
 {
     int32_t timeout = PHY_CFG_TIMEOUT;
@@ -8345,7 +8361,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
-void
+static void
 e1000_release_software_flag(struct e1000_hw *hw)
 {
     uint32_t extcnf_ctrl;
@@ -8369,6 +8385,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
+#if 0
 int32_t
 e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw)
 {
@@ -8388,6 +8405,7 @@
 
     return ret_val;
 }
+#endif  /*  0  */
 
 /***************************************************************************
  *
@@ -8397,6 +8415,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  ***************************************************************************/
+#if 0
 int32_t
 e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw)
 {
@@ -8416,6 +8435,7 @@
 
     return ret_val;
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access
@@ -8426,7 +8446,7 @@
  * data - word read from the EEPROM
  * words - number of words to read
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
                        uint16_t *data)
 {
@@ -8482,7 +8502,7 @@
  * words - number of words to write
  * data - words to write to the EEPROM
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words,
                         uint16_t *data)
 {
@@ -8529,7 +8549,7 @@
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-int32_t
+static int32_t
 e1000_ich8_cycle_init(struct e1000_hw *hw)
 {
     union ich8_hws_flash_status hsfsts;
@@ -8596,7 +8616,7 @@
  *
  * hw - The pointer to the hw structure
  ****************************************************************************/
-int32_t
+static int32_t
 e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout)
 {
     union ich8_hws_flash_ctrl hsflctl;
@@ -8631,7 +8651,7 @@
  * size - Size of data to read, 1=byte 2=word
  * data - Pointer to the word to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
                      uint32_t size, uint16_t* data)
 {
@@ -8710,7 +8730,7 @@
  * size - Size of data to read, 1=byte 2=word
  * data - The byte(s) to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size,
                       uint16_t data)
 {
@@ -8785,7 +8805,7 @@
  * index - The index of the byte to read.
  * data - Pointer to a byte to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8808,7 +8828,7 @@
  * index - The index of the byte to write.
  * byte - The byte to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte)
 {
     int32_t error = E1000_SUCCESS;
@@ -8839,7 +8859,7 @@
  * index - The index of the byte to read.
  * data - The byte to write to the NVM.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8857,7 +8877,7 @@
  * index - The starting byte index of the word to read.
  * data - Pointer to a word to store the value read.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data)
 {
     int32_t status = E1000_SUCCESS;
@@ -8872,6 +8892,7 @@
  * index - The starting byte index of the word to read.
  * data - The word to write to the NVM.
  *****************************************************************************/
+#if 0
 int32_t
 e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data)
 {
@@ -8879,6 +8900,7 @@
     status = e1000_write_ich8_data(hw, index, 2, data);
     return status;
 }
+#endif  /*  0  */
 
 /******************************************************************************
  * Erases the bank specified. Each bank is a 4k block. Segments are 0 based.
@@ -8887,7 +8909,7 @@
  * hw - pointer to e1000_hw structure
  * segment - 0 for first segment, 1 for second segment, etc.
  *****************************************************************************/
-int32_t
+static int32_t
 e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment)
 {
     union ich8_hws_flash_status hsfsts;
@@ -8984,6 +9006,7 @@
  * hw: Struct containing variables accessed by shared code
  *
  *****************************************************************************/
+#if 0
 int32_t
 e1000_duplex_reversal(struct e1000_hw *hw)
 {
@@ -9012,8 +9035,9 @@
 
     return ret_val;
 }
+#endif  /*  0  */
 
-int32_t
+static int32_t
 e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw,
                                       uint32_t cnf_base_addr, uint32_t cnf_size)
 {
@@ -9047,7 +9071,7 @@
 }
 
 
-int32_t
+static int32_t
 e1000_init_lcd_from_nvm(struct e1000_hw *hw)
 {
     uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop;
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index f9341e3..a170e96 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -323,13 +323,8 @@
 int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
 int32_t e1000_phy_reset(struct e1000_hw *hw);
 void e1000_phy_powerdown_workaround(struct e1000_hw *hw);
-int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw);
-int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size);
-int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw);
 int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
 int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
-int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data);
-int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
 
 /* EEPROM Functions */
 int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
@@ -341,9 +336,9 @@
 #define E1000_HI_MAX_MNG_DATA_LENGTH    0x6F8   /* Host Interface data length */
 
 #define E1000_MNG_DHCP_COMMAND_TIMEOUT  10      /* Time in ms to process MNG command */
-#define E1000_MNG_DHCP_COOKIE_OFFSET	0x6F0   /* Cookie offset */
-#define E1000_MNG_DHCP_COOKIE_LENGTH	0x10    /* Cookie length */
-#define E1000_MNG_IAMT_MODE		0x3
+#define E1000_MNG_DHCP_COOKIE_OFFSET    0x6F0   /* Cookie offset */
+#define E1000_MNG_DHCP_COOKIE_LENGTH    0x10    /* Cookie length */
+#define E1000_MNG_IAMT_MODE             0x3
 #define E1000_MNG_ICH_IAMT_MODE         0x2
 #define E1000_IAMT_SIGNATURE            0x544D4149 /* Intel(R) Active Management Technology signature */
 
@@ -390,7 +385,7 @@
 #endif
 
 int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
-							uint16_t length);
+                                  uint16_t length);
 boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
 boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
 
@@ -400,13 +395,8 @@
 int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
 int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
 int32_t e1000_read_mac_addr(struct e1000_hw * hw);
-int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
-void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
-void e1000_release_software_flag(struct e1000_hw *hw);
-int32_t e1000_get_software_flag(struct e1000_hw *hw);
 
 /* Filters (multicast, vlan, receive) */
-void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count);
 uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr);
 void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value);
 void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index);
@@ -431,31 +421,9 @@
 void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value);
 /* Port I/O is only supported on 82544 and newer */
-uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port);
-uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset);
 void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
-void e1000_enable_pciex_master(struct e1000_hw *hw);
 int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
-int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
-void e1000_release_software_semaphore(struct e1000_hw *hw);
 int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
-int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop);
-
-int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                             uint8_t *data);
-int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                                     uint8_t byte);
-int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index,
-                              uint8_t byte);
-int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index,
-                             uint16_t *data);
-int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index,
-                             uint32_t size, uint16_t *data);
-int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
-                               uint16_t words, uint16_t *data);
-int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset,
-                                uint16_t words, uint16_t *data);
-int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment);
 
 
 #define E1000_READ_REG_IO(a, reg) \
@@ -502,6 +470,7 @@
 #define E1000_DEV_ID_82571EB_COPPER      0x105E
 #define E1000_DEV_ID_82571EB_FIBER       0x105F
 #define E1000_DEV_ID_82571EB_SERDES      0x1060
+#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4
 #define E1000_DEV_ID_82572EI_COPPER      0x107D
 #define E1000_DEV_ID_82572EI_FIBER       0x107E
 #define E1000_DEV_ID_82572EI_SERDES      0x107F
@@ -555,7 +524,7 @@
 
 
 /* 802.1q VLAN Packet Sizes */
-#define VLAN_TAG_SIZE                     4     /* 802.3ac tag (not DMAed) */
+#define VLAN_TAG_SIZE  4     /* 802.3ac tag (not DMAed) */
 
 /* Ethertype field values */
 #define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
@@ -729,6 +698,7 @@
     E1000_RXDEXT_STATERR_CXE |            \
     E1000_RXDEXT_STATERR_RXE)
 
+
 /* Transmit Descriptor */
 struct e1000_tx_desc {
     uint64_t buffer_addr;       /* Address of the descriptor's data buffer */
@@ -2118,7 +2088,7 @@
 #define E1000_MANC_EN_IP_ADDR_FILTER    0x00400000 /* Enable IP address
                                                     * filtering */
 #define E1000_MANC_EN_XSUM_FILTER   0x00800000 /* Enable checksum filtering */
-#define E1000_MANC_BR_EN            0x01000000 /* Enable broadcast filtering */
+#define E1000_MANC_BR_EN         0x01000000 /* Enable broadcast filtering */
 #define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
 #define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
 #define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
@@ -2204,7 +2174,7 @@
 
 #define E1000_MDALIGN          4096
 
-/* PCI-Ex registers */
+/* PCI-Ex registers*/
 
 /* PCI-Ex Control Register */
 #define E1000_GCR_RXD_NO_SNOOP          0x00000001
@@ -2256,7 +2226,7 @@
 #define EEPROM_EWDS_OPCODE_MICROWIRE  0x10 /* EEPROM erast/write disable */
 
 /* EEPROM Commands - SPI */
-#define EEPROM_MAX_RETRY_SPI    5000 /* Max wait of 5ms, for RDY signal */
+#define EEPROM_MAX_RETRY_SPI        5000 /* Max wait of 5ms, for RDY signal */
 #define EEPROM_READ_OPCODE_SPI      0x03  /* EEPROM read opcode */
 #define EEPROM_WRITE_OPCODE_SPI     0x02  /* EEPROM write opcode */
 #define EEPROM_A8_OPCODE_SPI        0x08  /* opcode bit-3 = address bit-8 */
@@ -3114,10 +3084,10 @@
 
 /* DSP Distance Register (Page 5, Register 26) */
 #define GG82563_DSPD_CABLE_LENGTH               0x0007 /* 0 = <50M;
-							      1 = 50-80M;
-							      2 = 80-110M;
-							      3 = 110-140M;
-							      4 = >140M */
+                                                          1 = 50-80M;
+                                                          2 = 80-110M;
+                                                          3 = 110-140M;
+                                                          4 = >140M */
 
 /* Kumeran Mode Control Register (Page 193, Register 16) */
 #define GG82563_KMCR_PHY_LEDS_EN                    0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index da62db8..dece183 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -36,7 +36,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "7.1.9-k4"DRIVERNAPI
+#define DRV_VERSION "7.2.7-k2"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
 static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
@@ -48,7 +48,6 @@
  *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-	INTEL_E1000_ETHERNET_DEVICE(0x1000),
 	INTEL_E1000_ETHERNET_DEVICE(0x1001),
 	INTEL_E1000_ETHERNET_DEVICE(0x1004),
 	INTEL_E1000_ETHERNET_DEVICE(0x1008),
@@ -99,6 +98,7 @@
 	INTEL_E1000_ETHERNET_DEVICE(0x1098),
 	INTEL_E1000_ETHERNET_DEVICE(0x1099),
 	INTEL_E1000_ETHERNET_DEVICE(0x109A),
+	INTEL_E1000_ETHERNET_DEVICE(0x10A4),
 	INTEL_E1000_ETHERNET_DEVICE(0x10B5),
 	INTEL_E1000_ETHERNET_DEVICE(0x10B9),
 	INTEL_E1000_ETHERNET_DEVICE(0x10BA),
@@ -245,7 +245,7 @@
 
 	printk(KERN_INFO "%s\n", e1000_copyright);
 
-	ret = pci_module_init(&e1000_driver);
+	ret = pci_register_driver(&e1000_driver);
 
 	return ret;
 }
@@ -485,7 +485,7 @@
  *
  **/
 
-static void e1000_power_up_phy(struct e1000_adapter *adapter)
+void e1000_power_up_phy(struct e1000_adapter *adapter)
 {
 	uint16_t mii_reg = 0;
 
@@ -682,9 +682,9 @@
 	unsigned long flash_start, flash_len;
 
 	static int cards_found = 0;
-	static int e1000_ksp3_port_a = 0; /* global ksp3 port a indication */
+	static int global_quad_port_a = 0; /* global ksp3 port a indication */
 	int i, err, pci_using_dac;
-	uint16_t eeprom_data;
+	uint16_t eeprom_data = 0;
 	uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
 	if ((err = pci_enable_device(pdev)))
 		return err;
@@ -696,21 +696,20 @@
 		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) &&
 		    (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
 			E1000_ERR("No usable DMA configuration, aborting\n");
-			return err;
+			goto err_dma;
 		}
 		pci_using_dac = 0;
 	}
 
 	if ((err = pci_request_regions(pdev, e1000_driver_name)))
-		return err;
+		goto err_pci_reg;
 
 	pci_set_master(pdev);
 
+	err = -ENOMEM;
 	netdev = alloc_etherdev(sizeof(struct e1000_adapter));
-	if (!netdev) {
-		err = -ENOMEM;
+	if (!netdev)
 		goto err_alloc_etherdev;
-	}
 
 	SET_MODULE_OWNER(netdev);
 	SET_NETDEV_DEV(netdev, &pdev->dev);
@@ -725,11 +724,10 @@
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
 
+	err = -EIO;
 	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);
-	if (!adapter->hw.hw_addr) {
-		err = -EIO;
+	if (!adapter->hw.hw_addr)
 		goto err_ioremap;
-	}
 
 	for (i = BAR_1; i <= BAR_5; i++) {
 		if (pci_resource_len(pdev, i) == 0)
@@ -774,6 +772,7 @@
 	if ((err = e1000_sw_init(adapter)))
 		goto err_sw_init;
 
+	err = -EIO;
 	/* Flash BAR mapping must happen after e1000_sw_init
 	 * because it depends on mac_type */
 	if ((adapter->hw.mac_type == e1000_ich8lan) &&
@@ -781,24 +780,13 @@
 		flash_start = pci_resource_start(pdev, 1);
 		flash_len = pci_resource_len(pdev, 1);
 		adapter->hw.flash_address = ioremap(flash_start, flash_len);
-		if (!adapter->hw.flash_address) {
-			err = -EIO;
+		if (!adapter->hw.flash_address)
 			goto err_flashmap;
-		}
 	}
 
-	if ((err = e1000_check_phy_reset_block(&adapter->hw)))
+	if (e1000_check_phy_reset_block(&adapter->hw))
 		DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
-	/* if ksp3, indicate if it's port a being setup */
-	if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 &&
-			e1000_ksp3_port_a == 0)
-		adapter->ksp3_port_a = 1;
-	e1000_ksp3_port_a++;
-	/* Reset for multiple KP3 adapters */
-	if (e1000_ksp3_port_a == 4)
-		e1000_ksp3_port_a = 0;
-
 	if (adapter->hw.mac_type >= e1000_82543) {
 		netdev->features = NETIF_F_SG |
 				   NETIF_F_HW_CSUM |
@@ -830,7 +818,7 @@
 
 	if (e1000_init_eeprom_params(&adapter->hw)) {
 		E1000_ERR("EEPROM initialization failed\n");
-		return -EIO;
+		goto err_eeprom;
 	}
 
 	/* before reading the EEPROM, reset the controller to
@@ -842,7 +830,6 @@
 
 	if (e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
 		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
-		err = -EIO;
 		goto err_eeprom;
 	}
 
@@ -855,12 +842,9 @@
 
 	if (!is_valid_ether_addr(netdev->perm_addr)) {
 		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
-		err = -EIO;
 		goto err_eeprom;
 	}
 
-	e1000_read_part_num(&adapter->hw, &(adapter->part_num));
-
 	e1000_get_bus_info(&adapter->hw);
 
 	init_timer(&adapter->tx_fifo_stall_timer);
@@ -921,7 +905,38 @@
 		break;
 	}
 	if (eeprom_data & eeprom_apme_mask)
-		adapter->wol |= E1000_WUFC_MAG;
+		adapter->eeprom_wol |= E1000_WUFC_MAG;
+
+	/* now that we have the eeprom settings, apply the special cases
+	 * where the eeprom may be wrong or the board simply won't support
+	 * wake on lan on a particular port */
+	switch (pdev->device) {
+	case E1000_DEV_ID_82546GB_PCIE:
+		adapter->eeprom_wol = 0;
+		break;
+	case E1000_DEV_ID_82546EB_FIBER:
+	case E1000_DEV_ID_82546GB_FIBER:
+	case E1000_DEV_ID_82571EB_FIBER:
+		/* Wake events only supported on port A for dual fiber
+		 * regardless of eeprom setting */
+		if (E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
+			adapter->eeprom_wol = 0;
+		break;
+	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
+	case E1000_DEV_ID_82571EB_QUAD_COPPER:
+		/* if quad port adapter, disable WoL on all but port A */
+		if (global_quad_port_a != 0)
+			adapter->eeprom_wol = 0;
+		else
+			adapter->quad_port_a = 1;
+		/* Reset for multiple quad port adapters */
+		if (++global_quad_port_a == 4)
+			global_quad_port_a = 0;
+		break;
+	}
+
+	/* initialize the wol settings based on the eeprom settings */
+	adapter->wol = adapter->eeprom_wol;
 
 	/* print bus type/speed/width info */
 	{
@@ -964,16 +979,33 @@
 	return 0;
 
 err_register:
+	e1000_release_hw_control(adapter);
+err_eeprom:
+	if (!e1000_check_phy_reset_block(&adapter->hw))
+		e1000_phy_hw_reset(&adapter->hw);
+
 	if (adapter->hw.flash_address)
 		iounmap(adapter->hw.flash_address);
 err_flashmap:
+#ifdef CONFIG_E1000_NAPI
+	for (i = 0; i < adapter->num_rx_queues; i++)
+		dev_put(&adapter->polling_netdev[i]);
+#endif
+
+	kfree(adapter->tx_ring);
+	kfree(adapter->rx_ring);
+#ifdef CONFIG_E1000_NAPI
+	kfree(adapter->polling_netdev);
+#endif
 err_sw_init:
-err_eeprom:
 	iounmap(adapter->hw.hw_addr);
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_regions(pdev);
+err_pci_reg:
+err_dma:
+	pci_disable_device(pdev);
 	return err;
 }
 
@@ -1208,7 +1240,7 @@
 
 	err = e1000_request_irq(adapter);
 	if (err)
-		goto err_up;
+		goto err_req_irq;
 
 	e1000_power_up_phy(adapter);
 
@@ -1229,6 +1261,9 @@
 	return E1000_SUCCESS;
 
 err_up:
+	e1000_power_down_phy(adapter);
+	e1000_free_irq(adapter);
+err_req_irq:
 	e1000_free_all_rx_resources(adapter);
 err_setup_rx:
 	e1000_free_all_tx_resources(adapter);
@@ -1381,10 +1416,6 @@
  * 				  (Descriptors) for all queues
  * @adapter: board private structure
  *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not).  It is the
- * callers duty to clean those orphaned rings.
- *
  * Return 0 on success, negative on failure
  **/
 
@@ -1398,6 +1429,9 @@
 		if (err) {
 			DPRINTK(PROBE, ERR,
 				"Allocation for Tx Queue %u failed\n", i);
+			for (i-- ; i >= 0; i--)
+				e1000_free_tx_resources(adapter,
+							&adapter->tx_ring[i]);
 			break;
 		}
 	}
@@ -1433,8 +1467,8 @@
 		E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
 		E1000_WRITE_REG(hw, TDT, 0);
 		E1000_WRITE_REG(hw, TDH, 0);
-		adapter->tx_ring[0].tdh = E1000_TDH;
-		adapter->tx_ring[0].tdt = E1000_TDT;
+		adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH);
+		adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT);
 		break;
 	}
 
@@ -1499,8 +1533,6 @@
 	} else if (hw->mac_type == e1000_80003es2lan) {
 		tarc = E1000_READ_REG(hw, TARC0);
 		tarc |= 1;
-		if (hw->media_type == e1000_media_type_internal_serdes)
-			tarc |= (1 << 20);
 		E1000_WRITE_REG(hw, TARC0, tarc);
 		tarc = E1000_READ_REG(hw, TARC1);
 		tarc |= 1;
@@ -1639,10 +1671,6 @@
  * 				  (Descriptors) for all queues
  * @adapter: board private structure
  *
- * If this function returns with an error, then it's possible one or
- * more of the rings is populated (while the rest are not).  It is the
- * callers duty to clean those orphaned rings.
- *
  * Return 0 on success, negative on failure
  **/
 
@@ -1656,6 +1684,9 @@
 		if (err) {
 			DPRINTK(PROBE, ERR,
 				"Allocation for Rx Queue %u failed\n", i);
+			for (i-- ; i >= 0; i--)
+				e1000_free_rx_resources(adapter,
+							&adapter->rx_ring[i]);
 			break;
 		}
 	}
@@ -1840,8 +1871,8 @@
 		E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
 		E1000_WRITE_REG(hw, RDT, 0);
 		E1000_WRITE_REG(hw, RDH, 0);
-		adapter->rx_ring[0].rdh = E1000_RDH;
-		adapter->rx_ring[0].rdt = E1000_RDT;
+		adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH);
+		adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT);
 		break;
 	}
 
@@ -2442,10 +2473,9 @@
 			 * disable receives in the ISR and
 			 * reset device here in the watchdog
 			 */
-			if (adapter->hw.mac_type == e1000_80003es2lan) {
+			if (adapter->hw.mac_type == e1000_80003es2lan)
 				/* reset device */
 				schedule_work(&adapter->reset_task);
-			}
 		}
 
 		e1000_smartspeed(adapter);
@@ -2545,7 +2575,7 @@
 			cmd_length = E1000_TXD_CMD_IP;
 			ipcse = skb->h.raw - skb->data - 1;
 #ifdef NETIF_F_TSO_IPV6
-		} else if (skb->protocol == ntohs(ETH_P_IPV6)) {
+		} else if (skb->protocol == htons(ETH_P_IPV6)) {
 			skb->nh.ipv6h->payload_len = 0;
 			skb->h.th->check =
 				~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
@@ -3127,7 +3157,7 @@
 		break;
 	}
 
-	/* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
 	 * means we reserve 2 more, this pushes us to allocate from the next
 	 * larger slab size
 	 * i.e. RXBUFFER_2048 --> size-4096 slab */
@@ -3680,7 +3710,7 @@
 			E1000_DBG("%s: Receive packet consumed multiple"
 				  " buffers\n", netdev->name);
 			/* recycle */
-			buffer_info-> skb = skb;
+			buffer_info->skb = skb;
 			goto next_desc;
 		}
 
@@ -3708,10 +3738,9 @@
 #define E1000_CB_LENGTH 256
 		if (length < E1000_CB_LENGTH) {
 			struct sk_buff *new_skb =
-			    dev_alloc_skb(length + NET_IP_ALIGN);
+			    netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
 			if (new_skb) {
 				skb_reserve(new_skb, NET_IP_ALIGN);
-				new_skb->dev = netdev;
 				memcpy(new_skb->data - NET_IP_ALIGN,
 				       skb->data - NET_IP_ALIGN,
 				       length + NET_IP_ALIGN);
@@ -3978,13 +4007,13 @@
 	buffer_info = &rx_ring->buffer_info[i];
 
 	while (cleaned_count--) {
-		if (!(skb = buffer_info->skb))
-			skb = dev_alloc_skb(bufsz);
-		else {
+		skb = buffer_info->skb;
+		if (skb) {
 			skb_trim(skb, 0);
 			goto map_skb;
 		}
 
+		skb = netdev_alloc_skb(netdev, bufsz);
 		if (unlikely(!skb)) {
 			/* Better luck next round */
 			adapter->alloc_rx_buff_failed++;
@@ -3997,7 +4026,7 @@
 			DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes "
 					     "at %p\n", bufsz, skb->data);
 			/* Try again, without freeing the previous */
-			skb = dev_alloc_skb(bufsz);
+			skb = netdev_alloc_skb(netdev, bufsz);
 			/* Failed allocation, critical failure */
 			if (!skb) {
 				dev_kfree_skb(oldskb);
@@ -4009,10 +4038,10 @@
 				dev_kfree_skb(skb);
 				dev_kfree_skb(oldskb);
 				break; /* while !buffer_info->skb */
-			} else {
-				/* Use new allocation */
-				dev_kfree_skb(oldskb);
 			}
+
+			/* Use new allocation */
+			dev_kfree_skb(oldskb);
 		}
 		/* Make buffer alignment 2 beyond a 16 byte boundary
 		 * this will result in a 16 byte aligned IP header after
@@ -4020,8 +4049,6 @@
 		 */
 		skb_reserve(skb, NET_IP_ALIGN);
 
-		skb->dev = netdev;
-
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
 map_skb:
@@ -4121,7 +4148,8 @@
 				rx_desc->read.buffer_addr[j+1] = ~0;
 		}
 
-		skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+		skb = netdev_alloc_skb(netdev,
+				       adapter->rx_ps_bsize0 + NET_IP_ALIGN);
 
 		if (unlikely(!skb)) {
 			adapter->alloc_rx_buff_failed++;
@@ -4134,8 +4162,6 @@
 		 */
 		skb_reserve(skb, NET_IP_ALIGN);
 
-		skb->dev = netdev;
-
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_ps_bsize0;
 		buffer_info->dma = pci_map_single(pdev, skb->data,
@@ -4385,11 +4411,13 @@
 	pci_write_config_word(adapter->pdev, reg, *value);
 }
 
+#if 0
 uint32_t
 e1000_io_read(struct e1000_hw *hw, unsigned long port)
 {
 	return inl(port);
 }
+#endif  /*  0  */
 
 void
 e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value)
@@ -4625,7 +4653,7 @@
 		e1000_set_multi(netdev);
 
 		/* turn on all-multi mode if wake on multicast is enabled */
-		if (adapter->wol & E1000_WUFC_MC) {
+		if (wufc & E1000_WUFC_MC) {
 			rctl = E1000_READ_REG(&adapter->hw, RCTL);
 			rctl |= E1000_RCTL_MPE;
 			E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
@@ -4697,11 +4725,14 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	uint32_t manc, ret_val;
+	uint32_t manc, err;
 
 	pci_set_power_state(pdev, PCI_D0);
 	e1000_pci_restore_state(adapter);
-	ret_val = pci_enable_device(pdev);
+	if ((err = pci_enable_device(pdev))) {
+		printk(KERN_ERR "e1000: Cannot enable PCI device from suspend\n");
+		return err;
+	}
 	pci_set_master(pdev);
 
 	pci_enable_wake(pdev, PCI_D3hot, 0);
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 0ef4131..2128427 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -324,7 +324,6 @@
 		DPRINTK(PROBE, NOTICE,
 		       "Warning: no configuration for board #%i\n", bd);
 		DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
-		bd = E1000_MAX_NIC;
 	}
 
 	{ /* Transmit Descriptor Count */
@@ -342,9 +341,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ?
 			E1000_MAX_TXD : E1000_MAX_82544_TXD;
 
-		tx_ring->count = TxDescriptors[bd];
-		e1000_validate_option(&tx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
+		if (num_TxDescriptors > bd) {
+			tx_ring->count = TxDescriptors[bd];
+			e1000_validate_option(&tx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(tx_ring->count,
+						REQ_TX_DESCRIPTOR_MULTIPLE);
+		} else {
+			tx_ring->count = opt.def;
+		}
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			tx_ring[i].count = tx_ring->count;
 	}
@@ -363,9 +367,14 @@
 		opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
 			E1000_MAX_82544_RXD;
 
-		rx_ring->count = RxDescriptors[bd];
-		e1000_validate_option(&rx_ring->count, &opt, adapter);
-		E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
+		if (num_RxDescriptors > bd) {
+			rx_ring->count = RxDescriptors[bd];
+			e1000_validate_option(&rx_ring->count, &opt, adapter);
+			E1000_ROUNDUP(rx_ring->count,
+						REQ_RX_DESCRIPTOR_MULTIPLE);
+		} else {
+			rx_ring->count = opt.def;
+		}
 		for (i = 0; i < adapter->num_rx_queues; i++)
 			rx_ring[i].count = rx_ring->count;
 	}
@@ -377,9 +386,13 @@
 			.def  = OPTION_ENABLED
 		};
 
-		int rx_csum = XsumRX[bd];
-		e1000_validate_option(&rx_csum, &opt, adapter);
-		adapter->rx_csum = rx_csum;
+		if (num_XsumRX > bd) {
+			int rx_csum = XsumRX[bd];
+			e1000_validate_option(&rx_csum, &opt, adapter);
+			adapter->rx_csum = rx_csum;
+		} else {
+			adapter->rx_csum = opt.def;
+		}
 	}
 	{ /* Flow Control */
 
@@ -399,9 +412,13 @@
 					 .p = fc_list }}
 		};
 
-		int fc = FlowControl[bd];
-		e1000_validate_option(&fc, &opt, adapter);
-		adapter->hw.fc = adapter->hw.original_fc = fc;
+		if (num_FlowControl > bd) {
+			int fc = FlowControl[bd];
+			e1000_validate_option(&fc, &opt, adapter);
+			adapter->hw.fc = adapter->hw.original_fc = fc;
+		} else {
+			adapter->hw.fc = adapter->hw.original_fc = opt.def;
+		}
 	}
 	{ /* Transmit Interrupt Delay */
 		struct e1000_option opt = {
@@ -413,8 +430,13 @@
 					 .max = MAX_TXDELAY }}
 		};
 
-		adapter->tx_int_delay = TxIntDelay[bd];
-		e1000_validate_option(&adapter->tx_int_delay, &opt, adapter);
+		if (num_TxIntDelay > bd) {
+			adapter->tx_int_delay = TxIntDelay[bd];
+			e1000_validate_option(&adapter->tx_int_delay, &opt,
+			                      adapter);
+		} else {
+			adapter->tx_int_delay = opt.def;
+		}
 	}
 	{ /* Transmit Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -426,9 +448,13 @@
 					 .max = MAX_TXABSDELAY }}
 		};
 
-		adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
-		                      adapter);
+		if (num_TxAbsIntDelay > bd) {
+			adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
+			                      adapter);
+		} else {
+			adapter->tx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Interrupt Delay */
 		struct e1000_option opt = {
@@ -440,8 +466,13 @@
 					 .max = MAX_RXDELAY }}
 		};
 
-		adapter->rx_int_delay = RxIntDelay[bd];
-		e1000_validate_option(&adapter->rx_int_delay, &opt, adapter);
+		if (num_RxIntDelay > bd) {
+			adapter->rx_int_delay = RxIntDelay[bd];
+			e1000_validate_option(&adapter->rx_int_delay, &opt,
+			                      adapter);
+		} else {
+			adapter->rx_int_delay = opt.def;
+		}
 	}
 	{ /* Receive Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -453,9 +484,13 @@
 					 .max = MAX_RXABSDELAY }}
 		};
 
-		adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
-		                      adapter);
+		if (num_RxAbsIntDelay > bd) {
+			adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
+			e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
+			                      adapter);
+		} else {
+			adapter->rx_abs_int_delay = opt.def;
+		}
 	}
 	{ /* Interrupt Throttling Rate */
 		struct e1000_option opt = {
@@ -467,18 +502,24 @@
 					 .max = MAX_ITR }}
 		};
 
-		adapter->itr = InterruptThrottleRate[bd];
-		switch (adapter->itr) {
-		case 0:
-			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
-			break;
-		case 1:
-			DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
-				opt.name);
-			break;
-		default:
-			e1000_validate_option(&adapter->itr, &opt, adapter);
-			break;
+		if (num_InterruptThrottleRate > bd) {
+			adapter->itr = InterruptThrottleRate[bd];
+			switch (adapter->itr) {
+			case 0:
+				DPRINTK(PROBE, INFO, "%s turned off\n",
+				        opt.name);
+				break;
+			case 1:
+				DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
+				        opt.name);
+				break;
+			default:
+				e1000_validate_option(&adapter->itr, &opt,
+				                      adapter);
+				break;
+			}
+		} else {
+			adapter->itr = opt.def;
 		}
 	}
 	{ /* Smart Power Down */
@@ -489,9 +530,13 @@
 			.def  = OPTION_DISABLED
 		};
 
-		int spd = SmartPowerDownEnable[bd];
-		e1000_validate_option(&spd, &opt, adapter);
-		adapter->smart_power_down = spd;
+		if (num_SmartPowerDownEnable > bd) {
+			int spd = SmartPowerDownEnable[bd];
+			e1000_validate_option(&spd, &opt, adapter);
+			adapter->smart_power_down = spd;
+		} else {
+			adapter->smart_power_down = opt.def;
+		}
 	}
 	{ /* Kumeran Lock Loss Workaround */
 		struct e1000_option opt = {
@@ -501,9 +546,13 @@
 			.def  = OPTION_ENABLED
 		};
 
+		if (num_KumeranLockLoss > bd) {
 			int kmrn_lock_loss = KumeranLockLoss[bd];
 			e1000_validate_option(&kmrn_lock_loss, &opt, adapter);
 			adapter->hw.kmrn_lock_loss_workaround_disabled = !kmrn_lock_loss;
+		} else {
+			adapter->hw.kmrn_lock_loss_workaround_disabled = !opt.def;
+		}
 	}
 
 	switch (adapter->hw.media_type) {
@@ -530,18 +579,17 @@
 e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
-	if ((Speed[bd] != OPTION_UNSET)) {
+	if (num_Speed > bd) {
 		DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 
-	if ((Duplex[bd] != OPTION_UNSET)) {
+	if (num_Duplex > bd) {
 		DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 
-	if ((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
+	if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
 		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
 				 "not valid for fiber adapters, "
 				 "parameter ignored\n");
@@ -560,7 +608,6 @@
 {
 	int speed, dplx, an;
 	int bd = adapter->bd_number;
-	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
 
 	{ /* Speed */
 		struct e1000_opt_list speed_list[] = {{          0, "" },
@@ -577,8 +624,12 @@
 					 .p = speed_list }}
 		};
 
-		speed = Speed[bd];
-		e1000_validate_option(&speed, &opt, adapter);
+		if (num_Speed > bd) {
+			speed = Speed[bd];
+			e1000_validate_option(&speed, &opt, adapter);
+		} else {
+			speed = opt.def;
+		}
 	}
 	{ /* Duplex */
 		struct e1000_opt_list dplx_list[] = {{           0, "" },
@@ -600,11 +651,15 @@
 			        "Speed/Duplex/AutoNeg parameter ignored.\n");
 			return;
 		}
-		dplx = Duplex[bd];
-		e1000_validate_option(&dplx, &opt, adapter);
+		if (num_Duplex > bd) {
+			dplx = Duplex[bd];
+			e1000_validate_option(&dplx, &opt, adapter);
+		} else {
+			dplx = opt.def;
+		}
 	}
 
-	if (AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
+	if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
 		DPRINTK(PROBE, INFO,
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
@@ -653,15 +708,19 @@
 					 .p = an_list }}
 		};
 
-		an = AutoNeg[bd];
-		e1000_validate_option(&an, &opt, adapter);
+		if (num_AutoNeg > bd) {
+			an = AutoNeg[bd];
+			e1000_validate_option(&an, &opt, adapter);
+		} else {
+			an = opt.def;
+		}
 		adapter->hw.autoneg_advertised = an;
 	}
 
 	switch (speed + dplx) {
 	case 0:
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
-		if (Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
+		if ((num_Speed > bd) && (speed != 0 || dplx != 0))
 			DPRINTK(PROBE, INFO,
 			       "Speed and duplex autonegotiation enabled\n");
 		break;
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index e5c5cd2..e4e733a 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -425,8 +425,8 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
-init_module(void)
+
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 20d3143..bf9efa7 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -154,7 +154,7 @@
 #include <asm/dma.h>
 
 #define DRV_NAME "eepro"
-#define DRV_VERSION "0.13b"
+#define DRV_VERSION "0.13c"
 
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
@@ -1333,7 +1333,6 @@
 		mode = inb(ioaddr + REG3);
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
-		printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name);
 	}
 
 	else if (dev->mc_count==0 )
@@ -1807,8 +1806,7 @@
 MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
 MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
 
-int
-init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int i;
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index e445988..a3d515d 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -2385,7 +2385,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init(&eepro100_driver);
+	return pci_register_driver(&eepro100_driver);
 }
 
 static void __exit eepro100_cleanup_module(void)
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 33291bc..0701c1d 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -1698,7 +1698,7 @@
  * are specified, we verify and then use them.  If no parameters are given, we
  * autoprobe for one card only.
  */
-int init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index a67650cc..b885b20 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -26,8 +26,8 @@
 */
 
 #define DRV_NAME        "epic100"
-#define DRV_VERSION     "2.0"
-#define DRV_RELDATE     "June 27, 2006"
+#define DRV_VERSION     "2.1"
+#define DRV_RELDATE     "Sept 11, 2006"
 
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
@@ -1386,7 +1386,6 @@
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		outl(0x002C, ioaddr + RxCtrl);
 		/* Unconditionally log net taps. */
-		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
 	} else if ((dev->mc_count > 0)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* There is apparently a chip bug, so the multicast filter
@@ -1604,7 +1603,7 @@
 		version, version2, version3);
 #endif
 
-	return pci_module_init (&epic_driver);
+	return pci_register_driver(&epic_driver);
 }
 
 
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 6b0ab1e..fd7b32a 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -421,8 +421,7 @@
 MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int
-init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 4bf76f8..ca42efa 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1434,7 +1434,7 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	int this_dev, found = 0;
 	struct net_device *dev;
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index 97d34fe..56f81a2 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -25,8 +25,8 @@
 */
 
 #define DRV_NAME	"fealnx"
-#define DRV_VERSION	"2.51"
-#define DRV_RELDATE	"Nov-17-2001"
+#define DRV_VERSION	"2.52"
+#define DRV_RELDATE	"Sep-11-2006"
 
 static int debug;		/* 1-> print debug message */
 static int max_interrupt_work = 20;
@@ -92,7 +92,7 @@
 #include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
@@ -1800,8 +1800,6 @@
 	u32 rx_mode;
 
 	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
 		rx_mode = CR_W_PROM | CR_W_AB | CR_W_AM;
 	} else if ((dev->mc_count > multicast_filter_limit)
@@ -1984,7 +1982,7 @@
 	printk(version);
 #endif
 
-	return pci_module_init(&fealnx_driver);
+	return pci_register_driver(&fealnx_driver);
 }
 
 static void __exit fealnx_exit(void)
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 9b40300..9eedb27 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -2227,8 +2227,6 @@
 	ep = fep->hwp;
 
 	if (dev->flags&IFF_PROMISC) {
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
 		ep->fec_r_cntrl |= 0x0008;
 	} else {
 
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 11b8f1b..59f9a51 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -109,6 +109,7 @@
  *	0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
  *	0.55: 22 Mar 2006: Add flow control (pause frame).
  *	0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
+ *	0.57: 14 May 2006: Mac address set in probe/remove and order corrections.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -120,7 +121,12 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.56"
+#ifdef CONFIG_FORCEDETH_NAPI
+#define DRIVERNAPI "-NAPI"
+#else
+#define DRIVERNAPI
+#endif
+#define FORCEDETH_VERSION		"0.57"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -262,7 +268,8 @@
 	NvRegRingSizes = 0x108,
 #define NVREG_RINGSZ_TXSHIFT 0
 #define NVREG_RINGSZ_RXSHIFT 16
-	NvRegUnknownTransmitterReg = 0x10c,
+	NvRegTransmitPoll = 0x10c,
+#define NVREG_TRANSMITPOLL_MAC_ADDR_REV	0x00008000
 	NvRegLinkSpeed = 0x110,
 #define NVREG_LINKSPEED_FORCE 0x10000
 #define NVREG_LINKSPEED_10	1000
@@ -381,21 +388,21 @@
 
 /* Big endian: should work, but is untested */
 struct ring_desc {
-	u32 PacketBuffer;
-	u32 FlagLen;
+	__le32 buf;
+	__le32 flaglen;
 };
 
 struct ring_desc_ex {
-	u32 PacketBufferHigh;
-	u32 PacketBufferLow;
-	u32 TxVlan;
-	u32 FlagLen;
+	__le32 bufhigh;
+	__le32 buflow;
+	__le32 txvlan;
+	__le32 flaglen;
 };
 
-typedef union _ring_type {
+union ring_type {
 	struct ring_desc* orig;
 	struct ring_desc_ex* ex;
-} ring_type;
+};
 
 #define FLAG_MASK_V1 0xffff0000
 #define FLAG_MASK_V2 0xffffc000
@@ -536,6 +543,9 @@
 #define PHYID1_OUI_SHFT	6
 #define PHYID2_OUI_MASK	0xfc00
 #define PHYID2_OUI_SHFT	10
+#define PHYID2_MODEL_MASK		0x03f0
+#define PHY_MODEL_MARVELL_E3016		0x220
+#define PHY_MARVELL_E3016_INITMASK	0x0300
 #define PHY_INIT1	0x0f000
 #define PHY_INIT2	0x0e00
 #define PHY_INIT3	0x01000
@@ -653,8 +663,8 @@
 };
 
 struct register_test {
-	u32 reg;
-	u32 mask;
+	__le32 reg;
+	__le32 mask;
 };
 
 static const struct register_test nv_registers_test[] = {
@@ -694,6 +704,7 @@
 	int phyaddr;
 	int wolenabled;
 	unsigned int phy_oui;
+	unsigned int phy_model;
 	u16 gigabit;
 	int intr_test;
 
@@ -707,13 +718,14 @@
 	u32 vlanctl_bits;
 	u32 driver_data;
 	u32 register_size;
+	int rx_csum;
 
 	void __iomem *base;
 
 	/* rx specific fields.
 	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
 	 */
-	ring_type rx_ring;
+	union ring_type rx_ring;
 	unsigned int cur_rx, refill_rx;
 	struct sk_buff **rx_skbuff;
 	dma_addr_t *rx_dma;
@@ -733,7 +745,7 @@
 	/*
 	 * tx specific fields.
 	 */
-	ring_type tx_ring;
+	union ring_type tx_ring;
 	unsigned int next_tx, nic_tx;
 	struct sk_buff **tx_skbuff;
 	dma_addr_t *tx_dma;
@@ -826,13 +838,13 @@
 
 static inline u32 nv_descr_getlength(struct ring_desc *prd, u32 v)
 {
-	return le32_to_cpu(prd->FlagLen)
+	return le32_to_cpu(prd->flaglen)
 		& ((v == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2);
 }
 
 static inline u32 nv_descr_getlength_ex(struct ring_desc_ex *prd, u32 v)
 {
-	return le32_to_cpu(prd->FlagLen) & LEN_MASK_V2;
+	return le32_to_cpu(prd->flaglen) & LEN_MASK_V2;
 }
 
 static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
@@ -885,7 +897,7 @@
 	struct fe_priv *np = get_nvpriv(dev);
 
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-		if(np->rx_ring.orig)
+		if (np->rx_ring.orig)
 			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
 					    np->rx_ring.orig, np->ring_addr);
 	} else {
@@ -1020,14 +1032,13 @@
 	return retval;
 }
 
-static int phy_reset(struct net_device *dev)
+static int phy_reset(struct net_device *dev, u32 bmcr_setup)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u32 miicontrol;
 	unsigned int tries = 0;
 
-	miicontrol = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-	miicontrol |= BMCR_RESET;
+	miicontrol = BMCR_RESET | bmcr_setup;
 	if (mii_rw(dev, np->phyaddr, MII_BMCR, miicontrol)) {
 		return -1;
 	}
@@ -1052,6 +1063,16 @@
 	u8 __iomem *base = get_hwbase(dev);
 	u32 phyinterface, phy_reserved, mii_status, mii_control, mii_control_1000,reg;
 
+	/* phy errata for E3016 phy */
+	if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
+		reg = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ);
+		reg &= ~PHY_MARVELL_E3016_INITMASK;
+		if (mii_rw(dev, np->phyaddr, MII_NCONFIG, reg)) {
+			printk(KERN_INFO "%s: phy write to errata reg failed.\n", pci_name(np->pci_dev));
+			return PHY_ERROR;
+		}
+	}
+
 	/* set advertise register */
 	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
 	reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
@@ -1082,8 +1103,13 @@
 	else
 		np->gigabit = 0;
 
-	/* reset the phy */
-	if (phy_reset(dev)) {
+	mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+	mii_control |= BMCR_ANENABLE;
+
+	/* reset the phy
+	 * (certain phys need bmcr to be setup with reset)
+	 */
+	if (phy_reset(dev, mii_control)) {
 		printk(KERN_INFO "%s: phy reset failed\n", pci_name(np->pci_dev));
 		return PHY_ERROR;
 	}
@@ -1178,7 +1204,7 @@
 			KERN_INFO "nv_stop_tx: TransmitterStatus remained busy");
 
 	udelay(NV_TXSTOP_DELAY2);
-	writel(0, base + NvRegUnknownTransmitterReg);
+	writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
 }
 
 static void nv_txrx_reset(struct net_device *dev)
@@ -1258,14 +1284,14 @@
 		np->rx_dma[nr] = pci_map_single(np->pci_dev, skb->data,
 					skb->end-skb->data, PCI_DMA_FROMDEVICE);
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-			np->rx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->rx_dma[nr]);
+			np->rx_ring.orig[nr].buf = cpu_to_le32(np->rx_dma[nr]);
 			wmb();
-			np->rx_ring.orig[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
+			np->rx_ring.orig[nr].flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX_AVAIL);
 		} else {
-			np->rx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
-			np->rx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF;
+			np->rx_ring.ex[nr].bufhigh = cpu_to_le64(np->rx_dma[nr]) >> 32;
+			np->rx_ring.ex[nr].buflow = cpu_to_le64(np->rx_dma[nr]) & 0x0FFFFFFFF;
 			wmb();
-			np->rx_ring.ex[nr].FlagLen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
+			np->rx_ring.ex[nr].flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
 		}
 		dprintk(KERN_DEBUG "%s: nv_alloc_rx: Packet %d marked as Available\n",
 					dev->name, refill_rx);
@@ -1277,6 +1303,16 @@
 	return 0;
 }
 
+/* If rx bufs are exhausted called after 50ms to attempt to refresh */
+#ifdef CONFIG_FORCEDETH_NAPI
+static void nv_do_rx_refill(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+
+	/* Just reschedule NAPI rx processing */
+	netif_rx_schedule(dev);
+}
+#else
 static void nv_do_rx_refill(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
@@ -1305,6 +1341,7 @@
 		enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
 	}
 }
+#endif
 
 static void nv_init_rx(struct net_device *dev)
 {
@@ -1315,9 +1352,9 @@
 	np->refill_rx = 0;
 	for (i = 0; i < np->rx_ring_size; i++)
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-			np->rx_ring.orig[i].FlagLen = 0;
+			np->rx_ring.orig[i].flaglen = 0;
 	        else
-			np->rx_ring.ex[i].FlagLen = 0;
+			np->rx_ring.ex[i].flaglen = 0;
 }
 
 static void nv_init_tx(struct net_device *dev)
@@ -1328,9 +1365,9 @@
 	np->next_tx = np->nic_tx = 0;
 	for (i = 0; i < np->tx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-			np->tx_ring.orig[i].FlagLen = 0;
+			np->tx_ring.orig[i].flaglen = 0;
 	        else
-			np->tx_ring.ex[i].FlagLen = 0;
+			np->tx_ring.ex[i].flaglen = 0;
 		np->tx_skbuff[i] = NULL;
 		np->tx_dma[i] = 0;
 	}
@@ -1373,9 +1410,9 @@
 
 	for (i = 0; i < np->tx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-			np->tx_ring.orig[i].FlagLen = 0;
+			np->tx_ring.orig[i].flaglen = 0;
 		else
-			np->tx_ring.ex[i].FlagLen = 0;
+			np->tx_ring.ex[i].flaglen = 0;
 		if (nv_release_txskb(dev, i))
 			np->stats.tx_dropped++;
 	}
@@ -1387,9 +1424,9 @@
 	int i;
 	for (i = 0; i < np->rx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-			np->rx_ring.orig[i].FlagLen = 0;
+			np->rx_ring.orig[i].flaglen = 0;
 		else
-			np->rx_ring.ex[i].FlagLen = 0;
+			np->rx_ring.ex[i].flaglen = 0;
 		wmb();
 		if (np->rx_skbuff[i]) {
 			pci_unmap_single(np->pci_dev, np->rx_dma[i],
@@ -1450,17 +1487,17 @@
 		np->tx_dma_len[nr] = bcnt;
 
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-			np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
-			np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+			np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]);
+			np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 		} else {
-			np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
-			np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
-			np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+			np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+			np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+			np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 		}
 		tx_flags = np->tx_flags;
 		offset += bcnt;
 		size -= bcnt;
-	} while(size);
+	} while (size);
 
 	/* setup the fragments */
 	for (i = 0; i < fragments; i++) {
@@ -1477,12 +1514,12 @@
 			np->tx_dma_len[nr] = bcnt;
 
 			if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-				np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
-				np->tx_ring.orig[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+				np->tx_ring.orig[nr].buf = cpu_to_le32(np->tx_dma[nr]);
+				np->tx_ring.orig[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 			} else {
-				np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
-				np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
-				np->tx_ring.ex[nr].FlagLen = cpu_to_le32((bcnt-1) | tx_flags);
+				np->tx_ring.ex[nr].bufhigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
+				np->tx_ring.ex[nr].buflow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
+				np->tx_ring.ex[nr].flaglen = cpu_to_le32((bcnt-1) | tx_flags);
 			}
 			offset += bcnt;
 			size -= bcnt;
@@ -1491,9 +1528,9 @@
 
 	/* set last fragment flag  */
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-		np->tx_ring.orig[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+		np->tx_ring.orig[nr].flaglen |= cpu_to_le32(tx_flags_extra);
 	} else {
-		np->tx_ring.ex[nr].FlagLen |= cpu_to_le32(tx_flags_extra);
+		np->tx_ring.ex[nr].flaglen |= cpu_to_le32(tx_flags_extra);
 	}
 
 	np->tx_skbuff[nr] = skb;
@@ -1512,10 +1549,10 @@
 
 	/* set tx flags */
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-		np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
+		np->tx_ring.orig[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra);
 	} else {
-		np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
-		np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
+		np->tx_ring.ex[start_nr].txvlan = cpu_to_le32(tx_flags_vlan);
+		np->tx_ring.ex[start_nr].flaglen |= cpu_to_le32(tx_flags | tx_flags_extra);
 	}
 
 	dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
@@ -1547,7 +1584,7 @@
 static void nv_tx_done(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	u32 Flags;
+	u32 flags;
 	unsigned int i;
 	struct sk_buff *skb;
 
@@ -1555,22 +1592,22 @@
 		i = np->nic_tx % np->tx_ring_size;
 
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-			Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
+			flags = le32_to_cpu(np->tx_ring.orig[i].flaglen);
 		else
-			Flags = le32_to_cpu(np->tx_ring.ex[i].FlagLen);
+			flags = le32_to_cpu(np->tx_ring.ex[i].flaglen);
 
-		dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, Flags 0x%x.\n",
-					dev->name, np->nic_tx, Flags);
-		if (Flags & NV_TX_VALID)
+		dprintk(KERN_DEBUG "%s: nv_tx_done: looking at packet %d, flags 0x%x.\n",
+					dev->name, np->nic_tx, flags);
+		if (flags & NV_TX_VALID)
 			break;
 		if (np->desc_ver == DESC_VER_1) {
-			if (Flags & NV_TX_LASTPACKET) {
+			if (flags & NV_TX_LASTPACKET) {
 				skb = np->tx_skbuff[i];
-				if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
+				if (flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
 					     NV_TX_UNDERFLOW|NV_TX_ERROR)) {
-					if (Flags & NV_TX_UNDERFLOW)
+					if (flags & NV_TX_UNDERFLOW)
 						np->stats.tx_fifo_errors++;
-					if (Flags & NV_TX_CARRIERLOST)
+					if (flags & NV_TX_CARRIERLOST)
 						np->stats.tx_carrier_errors++;
 					np->stats.tx_errors++;
 				} else {
@@ -1579,13 +1616,13 @@
 				}
 			}
 		} else {
-			if (Flags & NV_TX2_LASTPACKET) {
+			if (flags & NV_TX2_LASTPACKET) {
 				skb = np->tx_skbuff[i];
-				if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
+				if (flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
 					     NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
-					if (Flags & NV_TX2_UNDERFLOW)
+					if (flags & NV_TX2_UNDERFLOW)
 						np->stats.tx_fifo_errors++;
-					if (Flags & NV_TX2_CARRIERLOST)
+					if (flags & NV_TX2_CARRIERLOST)
 						np->stats.tx_carrier_errors++;
 					np->stats.tx_errors++;
 				} else {
@@ -1638,29 +1675,29 @@
 			if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
 				printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
 				       i,
-				       le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
-				       le32_to_cpu(np->tx_ring.orig[i].FlagLen),
-				       le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
-				       le32_to_cpu(np->tx_ring.orig[i+1].FlagLen),
-				       le32_to_cpu(np->tx_ring.orig[i+2].PacketBuffer),
-				       le32_to_cpu(np->tx_ring.orig[i+2].FlagLen),
-				       le32_to_cpu(np->tx_ring.orig[i+3].PacketBuffer),
-				       le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
+				       le32_to_cpu(np->tx_ring.orig[i].buf),
+				       le32_to_cpu(np->tx_ring.orig[i].flaglen),
+				       le32_to_cpu(np->tx_ring.orig[i+1].buf),
+				       le32_to_cpu(np->tx_ring.orig[i+1].flaglen),
+				       le32_to_cpu(np->tx_ring.orig[i+2].buf),
+				       le32_to_cpu(np->tx_ring.orig[i+2].flaglen),
+				       le32_to_cpu(np->tx_ring.orig[i+3].buf),
+				       le32_to_cpu(np->tx_ring.orig[i+3].flaglen));
 			} else {
 				printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
 				       i,
-				       le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
-				       le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
-				       le32_to_cpu(np->tx_ring.ex[i].FlagLen),
-				       le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferHigh),
-				       le32_to_cpu(np->tx_ring.ex[i+1].PacketBufferLow),
-				       le32_to_cpu(np->tx_ring.ex[i+1].FlagLen),
-				       le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferHigh),
-				       le32_to_cpu(np->tx_ring.ex[i+2].PacketBufferLow),
-				       le32_to_cpu(np->tx_ring.ex[i+2].FlagLen),
-				       le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferHigh),
-				       le32_to_cpu(np->tx_ring.ex[i+3].PacketBufferLow),
-				       le32_to_cpu(np->tx_ring.ex[i+3].FlagLen));
+				       le32_to_cpu(np->tx_ring.ex[i].bufhigh),
+				       le32_to_cpu(np->tx_ring.ex[i].buflow),
+				       le32_to_cpu(np->tx_ring.ex[i].flaglen),
+				       le32_to_cpu(np->tx_ring.ex[i+1].bufhigh),
+				       le32_to_cpu(np->tx_ring.ex[i+1].buflow),
+				       le32_to_cpu(np->tx_ring.ex[i+1].flaglen),
+				       le32_to_cpu(np->tx_ring.ex[i+2].bufhigh),
+				       le32_to_cpu(np->tx_ring.ex[i+2].buflow),
+				       le32_to_cpu(np->tx_ring.ex[i+2].flaglen),
+				       le32_to_cpu(np->tx_ring.ex[i+3].bufhigh),
+				       le32_to_cpu(np->tx_ring.ex[i+3].buflow),
+				       le32_to_cpu(np->tx_ring.ex[i+3].flaglen));
 			}
 		}
 	}
@@ -1697,7 +1734,7 @@
 	int protolen;	/* length as stored in the proto field */
 
 	/* 1) calculate len according to header */
-	if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
+	if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == htons(ETH_P_8021Q)) {
 		protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto );
 		hdrlen = VLAN_HLEN;
 	} else {
@@ -1740,13 +1777,14 @@
 	}
 }
 
-static void nv_rx_process(struct net_device *dev)
+static int nv_rx_process(struct net_device *dev, int limit)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	u32 Flags;
+	u32 flags;
 	u32 vlanflags = 0;
+	int count;
 
-	for (;;) {
+ 	for (count = 0; count < limit; ++count) {
 		struct sk_buff *skb;
 		int len;
 		int i;
@@ -1755,18 +1793,18 @@
 
 		i = np->cur_rx % np->rx_ring_size;
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-			Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
+			flags = le32_to_cpu(np->rx_ring.orig[i].flaglen);
 			len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
 		} else {
-			Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen);
+			flags = le32_to_cpu(np->rx_ring.ex[i].flaglen);
 			len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
-			vlanflags = le32_to_cpu(np->rx_ring.ex[i].PacketBufferLow);
+			vlanflags = le32_to_cpu(np->rx_ring.ex[i].buflow);
 		}
 
-		dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
-					dev->name, np->cur_rx, Flags);
+		dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, flags 0x%x.\n",
+					dev->name, np->cur_rx, flags);
 
-		if (Flags & NV_RX_AVAIL)
+		if (flags & NV_RX_AVAIL)
 			break;	/* still owned by hardware, */
 
 		/*
@@ -1780,7 +1818,7 @@
 
 		{
 			int j;
-			dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",Flags);
+			dprintk(KERN_DEBUG "Dumping packet (flags 0x%x).",flags);
 			for (j=0; j<64; j++) {
 				if ((j%16) == 0)
 					dprintk("\n%03x:", j);
@@ -1790,30 +1828,30 @@
 		}
 		/* look at what we actually got: */
 		if (np->desc_ver == DESC_VER_1) {
-			if (!(Flags & NV_RX_DESCRIPTORVALID))
+			if (!(flags & NV_RX_DESCRIPTORVALID))
 				goto next_pkt;
 
-			if (Flags & NV_RX_ERROR) {
-				if (Flags & NV_RX_MISSEDFRAME) {
+			if (flags & NV_RX_ERROR) {
+				if (flags & NV_RX_MISSEDFRAME) {
 					np->stats.rx_missed_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
+				if (flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX_CRCERR) {
+				if (flags & NV_RX_CRCERR) {
 					np->stats.rx_crc_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX_OVERFLOW) {
+				if (flags & NV_RX_OVERFLOW) {
 					np->stats.rx_over_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX_ERROR4) {
+				if (flags & NV_RX_ERROR4) {
 					len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
 					if (len < 0) {
 						np->stats.rx_errors++;
@@ -1821,32 +1859,32 @@
 					}
 				}
 				/* framing errors are soft errors. */
-				if (Flags & NV_RX_FRAMINGERR) {
-					if (Flags & NV_RX_SUBSTRACT1) {
+				if (flags & NV_RX_FRAMINGERR) {
+					if (flags & NV_RX_SUBSTRACT1) {
 						len--;
 					}
 				}
 			}
 		} else {
-			if (!(Flags & NV_RX2_DESCRIPTORVALID))
+			if (!(flags & NV_RX2_DESCRIPTORVALID))
 				goto next_pkt;
 
-			if (Flags & NV_RX2_ERROR) {
-				if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
+			if (flags & NV_RX2_ERROR) {
+				if (flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX2_CRCERR) {
+				if (flags & NV_RX2_CRCERR) {
 					np->stats.rx_crc_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX2_OVERFLOW) {
+				if (flags & NV_RX2_OVERFLOW) {
 					np->stats.rx_over_errors++;
 					np->stats.rx_errors++;
 					goto next_pkt;
 				}
-				if (Flags & NV_RX2_ERROR4) {
+				if (flags & NV_RX2_ERROR4) {
 					len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
 					if (len < 0) {
 						np->stats.rx_errors++;
@@ -1854,17 +1892,17 @@
 					}
 				}
 				/* framing errors are soft errors */
-				if (Flags & NV_RX2_FRAMINGERR) {
-					if (Flags & NV_RX2_SUBSTRACT1) {
+				if (flags & NV_RX2_FRAMINGERR) {
+					if (flags & NV_RX2_SUBSTRACT1) {
 						len--;
 					}
 				}
 			}
-			if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) {
-				Flags &= NV_RX2_CHECKSUMMASK;
-				if (Flags == NV_RX2_CHECKSUMOK1 ||
-				    Flags == NV_RX2_CHECKSUMOK2 ||
-				    Flags == NV_RX2_CHECKSUMOK3) {
+			if (np->rx_csum) {
+				flags &= NV_RX2_CHECKSUMMASK;
+				if (flags == NV_RX2_CHECKSUMOK1 ||
+				    flags == NV_RX2_CHECKSUMOK2 ||
+				    flags == NV_RX2_CHECKSUMOK3) {
 					dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
 					np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
 				} else {
@@ -1880,17 +1918,27 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n",
 					dev->name, np->cur_rx, len, skb->protocol);
-		if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) {
-			vlan_hwaccel_rx(skb, np->vlangrp, vlanflags & NV_RX3_VLAN_TAG_MASK);
-		} else {
+#ifdef CONFIG_FORCEDETH_NAPI
+		if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT))
+			vlan_hwaccel_receive_skb(skb, np->vlangrp,
+						 vlanflags & NV_RX3_VLAN_TAG_MASK);
+		else
+			netif_receive_skb(skb);
+#else
+		if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT))
+			vlan_hwaccel_rx(skb, np->vlangrp,
+					vlanflags & NV_RX3_VLAN_TAG_MASK);
+		else
 			netif_rx(skb);
-		}
+#endif
 		dev->last_rx = jiffies;
 		np->stats.rx_packets++;
 		np->stats.rx_bytes += len;
 next_pkt:
 		np->cur_rx++;
 	}
+
+	return count;
 }
 
 static void set_bufsize(struct net_device *dev)
@@ -1990,7 +2038,7 @@
 	struct fe_priv *np = netdev_priv(dev);
 	struct sockaddr *macaddr = (struct sockaddr*)addr;
 
-	if(!is_valid_ether_addr(macaddr->sa_data))
+	if (!is_valid_ether_addr(macaddr->sa_data))
 		return -EADDRNOTAVAIL;
 
 	/* synchronized against open : rtnl_lock() held by caller */
@@ -2032,7 +2080,6 @@
 	memset(mask, 0, sizeof(mask));
 
 	if (dev->flags & IFF_PROMISC) {
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		pff |= NVREG_PFF_PROMISC;
 	} else {
 		pff |= NVREG_PFF_MYADDR;
@@ -2283,20 +2330,20 @@
 			lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
 
 			switch (adv_pause) {
-			case (ADVERTISE_PAUSE_CAP):
+			case ADVERTISE_PAUSE_CAP:
 				if (lpa_pause & LPA_PAUSE_CAP) {
 					pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
 					if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
 						pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
 				}
 				break;
-			case (ADVERTISE_PAUSE_ASYM):
+			case ADVERTISE_PAUSE_ASYM:
 				if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
 				{
 					pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
 				}
 				break;
-			case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
+			case ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM:
 				if (lpa_pause & LPA_PAUSE_CAP)
 				{
 					pause_flags |=  NV_PAUSEFRAME_RX_ENABLE;
@@ -2376,14 +2423,6 @@
 		nv_tx_done(dev);
 		spin_unlock(&np->lock);
 
-		nv_rx_process(dev);
-		if (nv_alloc_rx(dev)) {
-			spin_lock(&np->lock);
-			if (!np->in_shutdown)
-				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
-			spin_unlock(&np->lock);
-		}
-
 		if (events & NVREG_IRQ_LINK) {
 			spin_lock(&np->lock);
 			nv_link_irq(dev);
@@ -2403,6 +2442,29 @@
 			printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n",
 						dev->name, events);
 		}
+#ifdef CONFIG_FORCEDETH_NAPI
+		if (events & NVREG_IRQ_RX_ALL) {
+			netif_rx_schedule(dev);
+
+			/* Disable furthur receive irq's */
+			spin_lock(&np->lock);
+			np->irqmask &= ~NVREG_IRQ_RX_ALL;
+
+			if (np->msi_flags & NV_MSI_X_ENABLED)
+				writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+			else
+				writel(np->irqmask, base + NvRegIrqMask);
+			spin_unlock(&np->lock);
+		}
+#else
+		nv_rx_process(dev, dev->weight);
+		if (nv_alloc_rx(dev)) {
+			spin_lock(&np->lock);
+			if (!np->in_shutdown)
+				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+			spin_unlock(&np->lock);
+		}
+#endif
 		if (i > max_interrupt_work) {
 			spin_lock(&np->lock);
 			/* disable interrupts on the nic */
@@ -2474,6 +2536,63 @@
 	return IRQ_RETVAL(i);
 }
 
+#ifdef CONFIG_FORCEDETH_NAPI
+static int nv_napi_poll(struct net_device *dev, int *budget)
+{
+	int pkts, limit = min(*budget, dev->quota);
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+
+	pkts = nv_rx_process(dev, limit);
+
+	if (nv_alloc_rx(dev)) {
+		spin_lock_irq(&np->lock);
+		if (!np->in_shutdown)
+			mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+		spin_unlock_irq(&np->lock);
+	}
+
+	if (pkts < limit) {
+		/* all done, no more packets present */
+		netif_rx_complete(dev);
+
+		/* re-enable receive interrupts */
+		spin_lock_irq(&np->lock);
+		np->irqmask |= NVREG_IRQ_RX_ALL;
+		if (np->msi_flags & NV_MSI_X_ENABLED)
+			writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+		else
+			writel(np->irqmask, base + NvRegIrqMask);
+		spin_unlock_irq(&np->lock);
+		return 0;
+	} else {
+		/* used up our quantum, so reschedule */
+		dev->quota -= pkts;
+		*budget -= pkts;
+		return 1;
+	}
+}
+#endif
+
+#ifdef CONFIG_FORCEDETH_NAPI
+static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) data;
+	u8 __iomem *base = get_hwbase(dev);
+	u32 events;
+
+	events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_RX_ALL;
+	writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
+
+	if (events) {
+		netif_rx_schedule(dev);
+		/* disable receive interrupts on the nic */
+		writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
+		pci_push(base);
+	}
+	return IRQ_HANDLED;
+}
+#else
 static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) data;
@@ -2492,7 +2611,7 @@
 		if (!(events & np->irqmask))
 			break;
 
-		nv_rx_process(dev);
+		nv_rx_process(dev, dev->weight);
 		if (nv_alloc_rx(dev)) {
 			spin_lock_irq(&np->lock);
 			if (!np->in_shutdown)
@@ -2514,12 +2633,12 @@
 			spin_unlock_irq(&np->lock);
 			break;
 		}
-
 	}
 	dprintk(KERN_DEBUG "%s: nv_nic_irq_rx completed\n", dev->name);
 
 	return IRQ_RETVAL(i);
 }
+#endif
 
 static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs)
 {
@@ -3057,9 +3176,18 @@
 		if (netif_running(dev))
 			printk(KERN_INFO "%s: link down.\n", dev->name);
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
-
+		if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
+			bmcr |= BMCR_ANENABLE;
+			/* reset the phy in order for settings to stick,
+			 * and cause autoneg to start */
+			if (phy_reset(dev, bmcr)) {
+				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				return -EINVAL;
+			}
+		} else {
+			bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+			mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+		}
 	} else {
 		int adv, bmcr;
 
@@ -3099,17 +3227,19 @@
 			bmcr |= BMCR_FULLDPLX;
 		if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
 			bmcr |= BMCR_SPEED100;
-		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
 		if (np->phy_oui == PHY_OUI_MARVELL) {
-			/* reset the phy */
-			if (phy_reset(dev)) {
+			/* reset the phy in order for forced mode settings to stick */
+			if (phy_reset(dev, bmcr)) {
 				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
 				return -EINVAL;
 			}
-		} else if (netif_running(dev)) {
-			/* Wait a bit and then reconfigure the nic. */
-			udelay(10);
-			nv_linkchange(dev);
+		} else {
+			mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+			if (netif_running(dev)) {
+				/* Wait a bit and then reconfigure the nic. */
+				udelay(10);
+				nv_linkchange(dev);
+			}
 		}
 	}
 
@@ -3166,8 +3296,17 @@
 		}
 
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+		if (np->phy_model == PHY_MODEL_MARVELL_E3016) {
+			bmcr |= BMCR_ANENABLE;
+			/* reset the phy in order for settings to stick*/
+			if (phy_reset(dev, bmcr)) {
+				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				return -EINVAL;
+			}
+		} else {
+			bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+			mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+		}
 
 		if (netif_running(dev)) {
 			nv_start_rx(dev);
@@ -3245,7 +3384,7 @@
 	if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) {
 		/* fall back to old rings */
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-			if(rxtx_ring)
+			if (rxtx_ring)
 				pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
 						    rxtx_ring, ring_addr);
 		} else {
@@ -3418,7 +3557,7 @@
 static u32 nv_get_rx_csum(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
-	return (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) != 0;
+	return (np->rx_csum) != 0;
 }
 
 static int nv_set_rx_csum(struct net_device *dev, u32 data)
@@ -3428,22 +3567,15 @@
 	int retcode = 0;
 
 	if (np->driver_data & DEV_HAS_CHECKSUM) {
-
-		if (((np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && data) ||
-		    (!(np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && !data)) {
-			/* already set or unset */
-			return 0;
-		}
-
 		if (data) {
+			np->rx_csum = 1;
 			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
-		} else if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) {
-			np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
 		} else {
-			printk(KERN_INFO "Can not disable rx checksum if vlan is enabled\n");
-			return -EINVAL;
+			np->rx_csum = 0;
+			/* vlan is dependent on rx checksum offload */
+			if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE))
+				np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
 		}
-
 		if (netif_running(dev)) {
 			spin_lock_irq(&np->lock);
 			writel(np->txrxctl_bits, base + NvRegTxRxControl);
@@ -3481,7 +3613,7 @@
 	struct fe_priv *np = netdev_priv(dev);
 
 	if (np->driver_data & DEV_HAS_STATISTICS)
-		return (sizeof(struct nv_ethtool_stats)/sizeof(u64));
+		return sizeof(struct nv_ethtool_stats)/sizeof(u64);
 	else
 		return 0;
 }
@@ -3619,7 +3751,7 @@
 	struct sk_buff *tx_skb, *rx_skb;
 	dma_addr_t test_dma_addr;
 	u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
-	u32 Flags;
+	u32 flags;
 	int len, i, pkt_len;
 	u8 *pkt_data;
 	u32 filter_flags = 0;
@@ -3663,12 +3795,12 @@
 				       tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE);
 
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-		np->tx_ring.orig[0].PacketBuffer = cpu_to_le32(test_dma_addr);
-		np->tx_ring.orig[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+		np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
+		np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
 	} else {
-		np->tx_ring.ex[0].PacketBufferHigh = cpu_to_le64(test_dma_addr) >> 32;
-		np->tx_ring.ex[0].PacketBufferLow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
-		np->tx_ring.ex[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+		np->tx_ring.ex[0].bufhigh = cpu_to_le64(test_dma_addr) >> 32;
+		np->tx_ring.ex[0].buflow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
+		np->tx_ring.ex[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
 	}
 	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
 	pci_push(get_hwbase(dev));
@@ -3677,21 +3809,21 @@
 
 	/* check for rx of the packet */
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
-		Flags = le32_to_cpu(np->rx_ring.orig[0].FlagLen);
+		flags = le32_to_cpu(np->rx_ring.orig[0].flaglen);
 		len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
 
 	} else {
-		Flags = le32_to_cpu(np->rx_ring.ex[0].FlagLen);
+		flags = le32_to_cpu(np->rx_ring.ex[0].flaglen);
 		len = nv_descr_getlength_ex(&np->rx_ring.ex[0], np->desc_ver);
 	}
 
-	if (Flags & NV_RX_AVAIL) {
+	if (flags & NV_RX_AVAIL) {
 		ret = 0;
 	} else if (np->desc_ver == DESC_VER_1) {
-		if (Flags & NV_RX_ERROR)
+		if (flags & NV_RX_ERROR)
 			ret = 0;
 	} else {
-		if (Flags & NV_RX2_ERROR) {
+		if (flags & NV_RX2_ERROR) {
 			ret = 0;
 		}
 	}
@@ -3753,6 +3885,7 @@
 	if (test->flags & ETH_TEST_FL_OFFLINE) {
 		if (netif_running(dev)) {
 			netif_stop_queue(dev);
+			netif_poll_disable(dev);
 			netif_tx_lock_bh(dev);
 			spin_lock_irq(&np->lock);
 			nv_disable_hw_interrupts(dev, np->irqmask);
@@ -3811,6 +3944,7 @@
 			nv_start_rx(dev);
 			nv_start_tx(dev);
 			netif_start_queue(dev);
+			netif_poll_enable(dev);
 			nv_enable_hw_interrupts(dev, np->irqmask);
 		}
 	}
@@ -3895,10 +4029,9 @@
 
 	dprintk(KERN_DEBUG "nv_open: begin\n");
 
-	/* 1) erase previous misconfiguration */
+	/* erase previous misconfiguration */
 	if (np->driver_data & DEV_HAS_POWER_CNTRL)
 		nv_mac_reset(dev);
-	/* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */
 	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
 	writel(0, base + NvRegMulticastAddrB);
 	writel(0, base + NvRegMulticastMaskA);
@@ -3913,26 +4046,22 @@
 	if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
 		writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
 
-	/* 2) initialize descriptor rings */
+	/* initialize descriptor rings */
 	set_bufsize(dev);
 	oom = nv_init_ring(dev);
 
 	writel(0, base + NvRegLinkSpeed);
-	writel(0, base + NvRegUnknownTransmitterReg);
+	writel(readl(base + NvRegTransmitPoll) & NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
 	nv_txrx_reset(dev);
 	writel(0, base + NvRegUnknownSetupReg6);
 
 	np->in_shutdown = 0;
 
-	/* 3) set mac address */
-	nv_copy_mac_to_hw(dev);
-
-	/* 4) give hw rings */
+	/* give hw rings */
 	setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
 	writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 		base + NvRegRingSizes);
 
-	/* 5) continue setup */
 	writel(np->linkspeed, base + NvRegLinkSpeed);
 	if (np->desc_ver == DESC_VER_1)
 		writel(NVREG_TX_WM_DESC1_DEFAULT, base + NvRegTxWatermark);
@@ -3950,7 +4079,6 @@
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
 	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
 
-	/* 6) continue setup */
 	writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
 	writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
 	writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags);
@@ -4020,6 +4148,8 @@
 	nv_start_rx(dev);
 	nv_start_tx(dev);
 	netif_start_queue(dev);
+	netif_poll_enable(dev);
+
 	if (ret) {
 		netif_carrier_on(dev);
 	} else {
@@ -4049,6 +4179,7 @@
 	spin_lock_irq(&np->lock);
 	np->in_shutdown = 1;
 	spin_unlock_irq(&np->lock);
+	netif_poll_disable(dev);
 	synchronize_irq(dev->irq);
 
 	del_timer_sync(&np->oom_kick);
@@ -4076,12 +4207,6 @@
 	if (np->wolenabled)
 		nv_start_rx(dev);
 
-	/* special op: write back the misordered MAC address - otherwise
-	 * the next nv_probe would see a wrong address.
-	 */
-	writel(np->orig_mac[0], base + NvRegMacAddrA);
-	writel(np->orig_mac[1], base + NvRegMacAddrB);
-
 	/* FIXME: power down nic */
 
 	return 0;
@@ -4094,7 +4219,7 @@
 	unsigned long addr;
 	u8 __iomem *base;
 	int err, i;
-	u32 powerstate;
+	u32 powerstate, txreg;
 
 	dev = alloc_etherdev(sizeof(struct fe_priv));
 	err = -ENOMEM;
@@ -4190,6 +4315,7 @@
 		np->pkt_limit = NV_PKTLIMIT_2;
 
 	if (id->driver_data & DEV_HAS_CHECKSUM) {
+		np->rx_csum = 1;
 		np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
 		dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
 #ifdef NETIF_F_TSO
@@ -4270,6 +4396,10 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = nv_poll_controller;
 #endif
+	dev->weight = 64;
+#ifdef CONFIG_FORCEDETH_NAPI
+	dev->poll = nv_napi_poll;
+#endif
 	SET_ETHTOOL_OPS(dev, &ops);
 	dev->tx_timeout = nv_tx_timeout;
 	dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
@@ -4281,12 +4411,30 @@
 	np->orig_mac[0] = readl(base + NvRegMacAddrA);
 	np->orig_mac[1] = readl(base + NvRegMacAddrB);
 
-	dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;
-	dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;
-	dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
-	dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
-	dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
-	dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+	/* check the workaround bit for correct mac address order */
+	txreg = readl(base + NvRegTransmitPoll);
+	if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) {
+		/* mac address is already in correct order */
+		dev->dev_addr[0] = (np->orig_mac[0] >>  0) & 0xff;
+		dev->dev_addr[1] = (np->orig_mac[0] >>  8) & 0xff;
+		dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff;
+		dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff;
+		dev->dev_addr[4] = (np->orig_mac[1] >>  0) & 0xff;
+		dev->dev_addr[5] = (np->orig_mac[1] >>  8) & 0xff;
+	} else {
+		/* need to reverse mac address to correct order */
+		dev->dev_addr[0] = (np->orig_mac[1] >>  8) & 0xff;
+		dev->dev_addr[1] = (np->orig_mac[1] >>  0) & 0xff;
+		dev->dev_addr[2] = (np->orig_mac[0] >> 24) & 0xff;
+		dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
+		dev->dev_addr[4] = (np->orig_mac[0] >>  8) & 0xff;
+		dev->dev_addr[5] = (np->orig_mac[0] >>  0) & 0xff;
+		/* set permanent address to be correct aswell */
+		np->orig_mac[0] = (dev->dev_addr[0] << 0) + (dev->dev_addr[1] << 8) +
+			(dev->dev_addr[2] << 16) + (dev->dev_addr[3] << 24);
+		np->orig_mac[1] = (dev->dev_addr[4] << 0) + (dev->dev_addr[5] << 8);
+		writel(txreg|NVREG_TRANSMITPOLL_MAC_ADDR_REV, base + NvRegTransmitPoll);
+	}
 	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
 
 	if (!is_valid_ether_addr(dev->perm_addr)) {
@@ -4309,6 +4457,9 @@
 			dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 			dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
+	/* set mac address */
+	nv_copy_mac_to_hw(dev);
+
 	/* disable WOL */
 	writel(0, base + NvRegWakeUpFlags);
 	np->wolenabled = 0;
@@ -4369,6 +4520,7 @@
 		if (id2 < 0 || id2 == 0xffff)
 			continue;
 
+		np->phy_model = id2 & PHYID2_MODEL_MASK;
 		id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT;
 		id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT;
 		dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n",
@@ -4421,9 +4573,17 @@
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
 	struct net_device *dev = pci_get_drvdata(pci_dev);
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
 
 	unregister_netdev(dev);
 
+	/* special op: write back the misordered MAC address - otherwise
+	 * the next nv_probe would see a wrong address.
+	 */
+	writel(np->orig_mac[0], base + NvRegMacAddrA);
+	writel(np->orig_mac[1], base + NvRegMacAddrB);
+
 	/* free all structures */
 	free_rings(dev);
 	iounmap(get_hwbase(dev));
@@ -4540,7 +4700,7 @@
 static int __init init_nic(void)
 {
 	printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION);
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit exit_nic(void)
diff --git a/drivers/net/fs_enet/Makefile b/drivers/net/fs_enet/Makefile
index d6dd3f2..02d4dc1 100644
--- a/drivers/net/fs_enet/Makefile
+++ b/drivers/net/fs_enet/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_FS_ENET) += fs_enet.o
 
-obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o
-obj-$(CONFIG_8260) += mac-fcc.o
+obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o
+obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o
 
-fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o
+fs_enet-objs := fs_enet-main.o
diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
new file mode 100644
index 0000000..e980527
--- /dev/null
+++ b/drivers/net/fs_enet/fec.h
@@ -0,0 +1,42 @@
+#ifndef FS_ENET_FEC_H
+#define FS_ENET_FEC_H
+
+/* CRC polynomium used by the FEC for the multicast group filtering */
+#define FEC_CRC_POLY   0x04C11DB7
+
+#define FEC_MAX_MULTICAST_ADDRS	64
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR	0x80000000U	/* Heartbeat error          */
+#define FEC_ENET_BABR	0x40000000U	/* Babbling receiver        */
+#define FEC_ENET_BABT	0x20000000U	/* Babbling transmitter     */
+#define FEC_ENET_GRA	0x10000000U	/* Graceful stop complete   */
+#define FEC_ENET_TXF	0x08000000U	/* Full frame transmitted   */
+#define FEC_ENET_TXB	0x04000000U	/* A buffer was transmitted */
+#define FEC_ENET_RXF	0x02000000U	/* Full frame received      */
+#define FEC_ENET_RXB	0x01000000U	/* A buffer was received    */
+#define FEC_ENET_MII	0x00800000U	/* MII interrupt            */
+#define FEC_ENET_EBERR	0x00400000U	/* SDMA bus error           */
+
+#define FEC_ECNTRL_PINMUX	0x00000004
+#define FEC_ECNTRL_ETHER_EN	0x00000002
+#define FEC_ECNTRL_RESET	0x00000001
+
+#define FEC_RCNTRL_BC_REJ	0x00000010
+#define FEC_RCNTRL_PROM		0x00000008
+#define FEC_RCNTRL_MII_MODE	0x00000004
+#define FEC_RCNTRL_DRT		0x00000002
+#define FEC_RCNTRL_LOOP		0x00000001
+
+#define FEC_TCNTRL_FDEN		0x00000004
+#define FEC_TCNTRL_HBC		0x00000002
+#define FEC_TCNTRL_GTS		0x00000001
+
+
+
+/*
+ * Delay to wait for FEC reset command to complete (in us)
+ */
+#define FEC_RESET_DELAY		50
+#endif
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index f6abff5..df62506 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -37,6 +37,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
@@ -682,35 +683,6 @@
 	(*fep->ops->post_free_irq)(dev, irq);
 }
 
-/**********************************************************************************/
-
-/* This interrupt occurs when the PHY detects a link change. */
-static irqreturn_t
-fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = dev_id;
-	struct fs_enet_private *fep;
-	const struct fs_platform_info *fpi;
-
-	fep = netdev_priv(dev);
-	fpi = fep->fpi;
-
-	/*
-	 * Acknowledge the interrupt if possible. If we have not
-	 * found the PHY yet we can't process or acknowledge the
-	 * interrupt now. Instead we ignore this interrupt for now,
-	 * which we can do since it is edge triggered. It will be
-	 * acknowledged later by fs_enet_open().
-	 */
-	if (!fep->phy)
-		return IRQ_NONE;
-
-	fs_mii_ack_int(dev);
-	fs_mii_link_status_change_check(dev, 0);
-
-	return IRQ_HANDLED;
-}
-
 static void fs_timeout(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
@@ -722,10 +694,13 @@
 	spin_lock_irqsave(&fep->lock, flags);
 
 	if (dev->flags & IFF_UP) {
+		phy_stop(fep->phydev);
 		(*fep->ops->stop)(dev);
 		(*fep->ops->restart)(dev);
+		phy_start(fep->phydev);
 	}
 
+	phy_start(fep->phydev);
 	wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
 	spin_unlock_irqrestore(&fep->lock, flags);
 
@@ -733,35 +708,112 @@
 		netif_wake_queue(dev);
 }
 
+/*-----------------------------------------------------------------------------
+ *  generic link-change handler - should be sufficient for most cases
+ *-----------------------------------------------------------------------------*/
+static void generic_adjust_link(struct  net_device *dev)
+{
+       struct fs_enet_private *fep = netdev_priv(dev);
+       struct phy_device *phydev = fep->phydev;
+       int new_state = 0;
+
+       if (phydev->link) {
+
+               /* adjust to duplex mode */
+               if (phydev->duplex != fep->oldduplex){
+                       new_state = 1;
+                       fep->oldduplex = phydev->duplex;
+               }
+
+               if (phydev->speed != fep->oldspeed) {
+                       new_state = 1;
+                       fep->oldspeed = phydev->speed;
+               }
+
+               if (!fep->oldlink) {
+                       new_state = 1;
+                       fep->oldlink = 1;
+                       netif_schedule(dev);
+                       netif_carrier_on(dev);
+                       netif_start_queue(dev);
+               }
+
+               if (new_state)
+                       fep->ops->restart(dev);
+
+       } else if (fep->oldlink) {
+               new_state = 1;
+               fep->oldlink = 0;
+               fep->oldspeed = 0;
+               fep->oldduplex = -1;
+               netif_carrier_off(dev);
+               netif_stop_queue(dev);
+       }
+
+       if (new_state && netif_msg_link(fep))
+               phy_print_status(phydev);
+}
+
+
+static void fs_adjust_link(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fep->lock, flags);
+
+	if(fep->ops->adjust_link)
+		fep->ops->adjust_link(dev);
+	else
+		generic_adjust_link(dev);
+
+	spin_unlock_irqrestore(&fep->lock, flags);
+}
+
+static int fs_init_phy(struct net_device *dev)
+{
+	struct fs_enet_private *fep = netdev_priv(dev);
+	struct phy_device *phydev;
+
+	fep->oldlink = 0;
+	fep->oldspeed = 0;
+	fep->oldduplex = -1;
+	if(fep->fpi->bus_id)
+		phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0);
+	else {
+		printk("No phy bus ID specified in BSP code\n");
+		return -EINVAL;
+	}
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
+
+	fep->phydev = phydev;
+
+	return 0;
+}
+
+
 static int fs_enet_open(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
 	int r;
+	int err;
 
 	/* Install our interrupt handler. */
 	r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
 	if (r != 0) {
 		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s Could not allocate FEC IRQ!", dev->name);
+		       ": %s Could not allocate FS_ENET IRQ!", dev->name);
 		return -EINVAL;
 	}
 
-	/* Install our phy interrupt handler */
-	if (fpi->phy_irq != -1) {
+	err = fs_init_phy(dev);
+	if(err)
+		return err;
 
-		r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt);
-		if (r != 0) {
-			printk(KERN_ERR DRV_MODULE_NAME
-			       ": %s Could not allocate PHY IRQ!", dev->name);
-			fs_free_irq(dev, fep->interrupt);
-			return -EINVAL;
-		}
-	}
-
-	fs_mii_startup(dev);
-	netif_carrier_off(dev);
-	fs_mii_link_status_change_check(dev, 1);
+	phy_start(fep->phydev);
 
 	return 0;
 }
@@ -769,20 +821,19 @@
 static int fs_enet_close(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
 	unsigned long flags;
 
 	netif_stop_queue(dev);
 	netif_carrier_off(dev);
-	fs_mii_shutdown(dev);
+	phy_stop(fep->phydev);
 
 	spin_lock_irqsave(&fep->lock, flags);
 	(*fep->ops->stop)(dev);
 	spin_unlock_irqrestore(&fep->lock, flags);
 
 	/* release any irqs */
-	if (fpi->phy_irq != -1)
-		fs_free_irq(dev, fpi->phy_irq);
+	phy_disconnect(fep->phydev);
+	fep->phydev = NULL;
 	fs_free_irq(dev, fep->interrupt);
 
 	return 0;
@@ -830,33 +881,19 @@
 static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&fep->lock, flags);
-	rc = mii_ethtool_gset(&fep->mii_if, cmd);
-	spin_unlock_irqrestore(&fep->lock, flags);
-
-	return rc;
+	return phy_ethtool_gset(fep->phydev, cmd);
 }
 
 static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&fep->lock, flags);
-	rc = mii_ethtool_sset(&fep->mii_if, cmd);
-	spin_unlock_irqrestore(&fep->lock, flags);
-
-	return rc;
+	phy_ethtool_sset(fep->phydev, cmd);
+	return 0;
 }
 
 static int fs_nway_reset(struct net_device *dev)
 {
-	struct fs_enet_private *fep = netdev_priv(dev);
-	return mii_nway_restart(&fep->mii_if);
+	return 0;
 }
 
 static u32 fs_get_msglevel(struct net_device *dev)
@@ -898,7 +935,7 @@
 		return -EINVAL;
 
 	spin_lock_irqsave(&fep->lock, flags);
-	rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL);
+	rc = phy_mii_ioctl(fep->phydev, mii, cmd);
 	spin_unlock_irqrestore(&fep->lock, flags);
 	return rc;
 }
@@ -1030,12 +1067,6 @@
 	}
 	registered = 1;
 
-	err = fs_mii_connect(ndev);
-	if (err != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s fs_mii_connect failed.\n", ndev->name);
-		goto err;
-	}
 
 	return ndev;
 
@@ -1073,8 +1104,6 @@
 
 	fpi = fep->fpi;
 
-	fs_mii_disconnect(ndev);
-
 	unregister_netdev(ndev);
 
 	dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
@@ -1196,17 +1225,39 @@
 	r = setup_immap();
 	if (r != 0)
 		return r;
-	r = driver_register(&fs_enet_fec_driver);
-	if (r != 0)
-		goto err;
 
+#ifdef CONFIG_FS_ENET_HAS_FCC
+	/* let's insert mii stuff */
+	r = fs_enet_mdio_bb_init();
+
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+			"BB PHY init failed.\n");
+		return r;
+	}
 	r = driver_register(&fs_enet_fcc_driver);
 	if (r != 0)
 		goto err;
+#endif
 
+#ifdef CONFIG_FS_ENET_HAS_FEC
+	r =  fs_enet_mdio_fec_init();
+	if (r != 0) {
+		printk(KERN_ERR DRV_MODULE_NAME
+			"FEC PHY init failed.\n");
+		return r;
+	}
+
+	r = driver_register(&fs_enet_fec_driver);
+	if (r != 0)
+		goto err;
+#endif
+
+#ifdef CONFIG_FS_ENET_HAS_SCC
 	r = driver_register(&fs_enet_scc_driver);
 	if (r != 0)
 		goto err;
+#endif
 
 	return 0;
 err:
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
deleted file mode 100644
index b7e6e21..0000000
--- a/drivers/net/fs_enet/fs_enet-mii.c
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A. 
- *  by Pantelis Antoniou <panto@intracom.gr>
- * 
- * 2005 (c) MontaVista Software, Inc. 
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
- * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
- *
- * 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.
- */
-
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "fs_enet.h"
-
-/*************************************************/
-
-/*
- * Generic PHY support.
- * Should work for all PHYs, but link change is detected by polling
- */
-
-static void generic_timer_callback(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	fep->phy_timer_list.expires = jiffies + HZ / 2;
-
-	add_timer(&fep->phy_timer_list);
-
-	fs_mii_link_status_change_check(dev, 0);
-}
-
-static void generic_startup(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	fep->phy_timer_list.expires = jiffies + HZ / 2;	/* every 500ms */
-	fep->phy_timer_list.data = (unsigned long)dev;
-	fep->phy_timer_list.function = generic_timer_callback;
-	add_timer(&fep->phy_timer_list);
-}
-
-static void generic_shutdown(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	del_timer_sync(&fep->phy_timer_list);
-}
-
-/* ------------------------------------------------------------------------- */
-/* The Davicom DM9161 is used on the NETTA board			     */
-
-/* register definitions */
-
-#define MII_DM9161_ANAR		4	/* Aux. Config Register         */
-#define MII_DM9161_ACR		16	/* Aux. Config Register         */
-#define MII_DM9161_ACSR		17	/* Aux. Config/Status Register  */
-#define MII_DM9161_10TCSR	18	/* 10BaseT Config/Status Reg.   */
-#define MII_DM9161_INTR		21	/* Interrupt Register           */
-#define MII_DM9161_RECR		22	/* Receive Error Counter Reg.   */
-#define MII_DM9161_DISCR	23	/* Disconnect Counter Register  */
-
-static void dm9161_startup(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000);
-	/* Start autonegotiation */
-	fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200);
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ*8);
-}
-
-static void dm9161_ack_int(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR);
-}
-
-static void dm9161_shutdown(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00);
-}
-
-/**********************************************************************************/
-
-static const struct phy_info phy_info[] = {
-	{
-		.id = 0x00181b88,
-		.name = "DM9161",
-		.startup = dm9161_startup,
-		.ack_int = dm9161_ack_int,
-		.shutdown = dm9161_shutdown,
-	}, {
-		.id = 0,
-		.name = "GENERIC",
-		.startup = generic_startup,
-		.shutdown = generic_shutdown,
-	},
-};
-
-/**********************************************************************************/
-
-static int phy_id_detect(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
-	struct fs_enet_mii_bus *bus = fep->mii_bus;
-	int i, r, start, end, phytype, physubtype;
-	const struct phy_info *phy;
-	int phy_hwid, phy_id;
-
-	phy_hwid = -1;
-	fep->phy = NULL;
-
-	/* auto-detect? */
-	if (fpi->phy_addr == -1) {
-		start = 1;
-		end = 32;
-	} else {		/* direct */
-		start = fpi->phy_addr;
-		end = start + 1;
-	}
-
-	for (phy_id = start; phy_id < end; phy_id++) {
-		/* skip already used phy addresses on this bus */ 
-		if (bus->usage_map & (1 << phy_id))
-			continue;
-		r = fs_mii_read(dev, phy_id, MII_PHYSID1);
-		if (r == -1 || (phytype = (r & 0xffff)) == 0xffff)
-			continue;
-		r = fs_mii_read(dev, phy_id, MII_PHYSID2);
-		if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff)
-			continue;
-		phy_hwid = (phytype << 16) | physubtype;
-		if (phy_hwid != -1)
-			break;
-	}
-
-	if (phy_hwid == -1) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s No PHY detected! range=0x%02x-0x%02x\n",
-			dev->name, start, end);
-		return -1;
-	}
-
-	for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++)
-		if (phy->id == (phy_hwid >> 4) || phy->id == 0)
-			break;
-
-	if (i >= ARRAY_SIZE(phy_info)) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       ": %s PHY id 0x%08x is not supported!\n",
-		       dev->name, phy_hwid);
-		return -1;
-	}
-
-	fep->phy = phy;
-
-	/* mark this address as used */
-	bus->usage_map |= (1 << phy_id);
-
-	printk(KERN_INFO DRV_MODULE_NAME
-	       ": %s Phy @ 0x%x, type %s (0x%08x)%s\n",
-	       dev->name, phy_id, fep->phy->name, phy_hwid,
-	       fpi->phy_addr == -1 ? " (auto-detected)" : "");
-
-	return phy_id;
-}
-
-void fs_mii_startup(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	if (fep->phy->startup)
-		(*fep->phy->startup) (dev);
-}
-
-void fs_mii_shutdown(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	if (fep->phy->shutdown)
-		(*fep->phy->shutdown) (dev);
-}
-
-void fs_mii_ack_int(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-
-	if (fep->phy->ack_int)
-		(*fep->phy->ack_int) (dev);
-}
-
-#define MII_LINK	0x0001
-#define MII_HALF	0x0002
-#define MII_FULL	0x0004
-#define MII_BASE4	0x0008
-#define MII_10M		0x0010
-#define MII_100M	0x0020
-#define MII_1G		0x0040
-#define MII_10G		0x0080
-
-/* return full mii info at one gulp, with a usable form */
-static unsigned int mii_full_status(struct mii_if_info *mii)
-{
-	unsigned int status;
-	int bmsr, adv, lpa, neg;
-	struct fs_enet_private* fep = netdev_priv(mii->dev);
-	
-	/* first, a dummy read, needed to latch some MII phys */
-	(void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-	bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
-
-	/* no link */
-	if ((bmsr & BMSR_LSTATUS) == 0)
-		return 0;
-
-	status = MII_LINK;
-	
-	/* Lets look what ANEG says if it's supported - otherwize we shall
-	   take the right values from the platform info*/
-	if(!mii->force_media) {
-		/* autoneg not completed; don't bother */
-		if ((bmsr & BMSR_ANEGCOMPLETE) == 0)
-			return 0;
-
-		adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE);
-		lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA);
-
-		neg = lpa & adv;
-	} else {
-		neg = fep->fpi->bus_info->lpa;
-	}
-
-	if (neg & LPA_100FULL)
-		status |= MII_FULL | MII_100M;
-	else if (neg & LPA_100BASE4)
-		status |= MII_FULL | MII_BASE4 | MII_100M;
-	else if (neg & LPA_100HALF)
-		status |= MII_HALF | MII_100M;
-	else if (neg & LPA_10FULL)
-		status |= MII_FULL | MII_10M;
-	else
-		status |= MII_HALF | MII_10M;
-	
-	return status;
-}
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	struct mii_if_info *mii = &fep->mii_if;
-	unsigned int mii_status;
-	int ok_to_print, link, duplex, speed;
-	unsigned long flags;
-
-	ok_to_print = netif_msg_link(fep);
-
-	mii_status = mii_full_status(mii);
-
-	if (!init_media && mii_status == fep->last_mii_status)
-		return;
-
-	fep->last_mii_status = mii_status;
-
-	link = !!(mii_status & MII_LINK);
-	duplex = !!(mii_status & MII_FULL);
-	speed = (mii_status & MII_100M) ? 100 : 10;
-
-	if (link == 0) {
-		netif_carrier_off(mii->dev);
-		netif_stop_queue(dev);
-		if (!init_media) {
-			spin_lock_irqsave(&fep->lock, flags);
-			(*fep->ops->stop)(dev);
-			spin_unlock_irqrestore(&fep->lock, flags);
-		}
-
-		if (ok_to_print)
-			printk(KERN_INFO "%s: link down\n", mii->dev->name);
-
-	} else {
-
-		mii->full_duplex = duplex;
-
-		netif_carrier_on(mii->dev);
-
-		spin_lock_irqsave(&fep->lock, flags);
-		fep->duplex = duplex;
-		fep->speed = speed;
-		(*fep->ops->restart)(dev);
-		spin_unlock_irqrestore(&fep->lock, flags);
-
-		netif_start_queue(dev);
-
-		if (ok_to_print)
-			printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n",
-			       dev->name, speed, duplex ? "full" : "half");
-	}
-}
-
-/**********************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	struct fs_enet_mii_bus *bus = fep->mii_bus;
-
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&bus->mii_lock, flags);
-	ret = (*bus->mii_read)(bus, phy_id, location);
-	spin_unlock_irqrestore(&bus->mii_lock, flags);
-
-	return ret;
-}
-
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	struct fs_enet_mii_bus *bus = fep->mii_bus;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bus->mii_lock, flags);
-	(*bus->mii_write)(bus, phy_id, location, value);
-	spin_unlock_irqrestore(&bus->mii_lock, flags);
-}
-
-/*****************************************************************************/
-
-/* list of all registered mii buses */
-static LIST_HEAD(fs_mii_bus_list);
-
-static struct fs_enet_mii_bus *lookup_bus(int method, int id)
-{
-	struct list_head *ptr;
-	struct fs_enet_mii_bus *bus;
-
-	list_for_each(ptr, &fs_mii_bus_list) {
-		bus = list_entry(ptr, struct fs_enet_mii_bus, list);
-		if (bus->bus_info->method == method &&
-			bus->bus_info->id == id)
-			return bus;
-	}
-	return NULL;
-}
-
-static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi)
-{
-	struct fs_enet_mii_bus *bus;
-	int ret = 0;
-
-	bus = kmalloc(sizeof(*bus), GFP_KERNEL);
-	if (bus == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-	memset(bus, 0, sizeof(*bus));
-	spin_lock_init(&bus->mii_lock);
-	bus->bus_info = bi;
-	bus->refs = 0;
-	bus->usage_map = 0;
-
-	/* perform initialization */
-	switch (bi->method) {
-
-		case fsmii_fixed:
-			ret = fs_mii_fixed_init(bus);
-			if (ret != 0)
-				goto err;
-			break;
-
-		case fsmii_bitbang:
-			ret = fs_mii_bitbang_init(bus);
-			if (ret != 0)
-				goto err;
-			break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
-		case fsmii_fec:
-			ret = fs_mii_fec_init(bus);
-			if (ret != 0)
-				goto err;
-			break;
-#endif
-		default:
-			ret = -EINVAL;
-			goto err;
-	}
-
-	list_add(&bus->list, &fs_mii_bus_list);
-
-	return bus;
-
-err:
-	kfree(bus);
-	return ERR_PTR(ret);
-}
-
-static void destroy_bus(struct fs_enet_mii_bus *bus)
-{
-	/* remove from bus list */
-	list_del(&bus->list);
-
-	/* nothing more needed */
-	kfree(bus);
-}
-
-int fs_mii_connect(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	const struct fs_platform_info *fpi = fep->fpi;
-	struct fs_enet_mii_bus *bus = NULL;
-
-	/* check method validity */
-	switch (fpi->bus_info->method) {
-		case fsmii_fixed:
-		case fsmii_bitbang:
-			break;
-#ifdef CONFIG_FS_ENET_HAS_FEC
-		case fsmii_fec:
-			break;
-#endif
-		default:
-			printk(KERN_ERR DRV_MODULE_NAME
-			       ": %s Unknown MII bus method (%d)!\n",
-			       dev->name, fpi->bus_info->method);
-			return -EINVAL; 
-	}
-
-	bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id);
-
-	/* if not found create new bus */
-	if (bus == NULL) {
-		bus = create_bus(fpi->bus_info);
-		if (IS_ERR(bus)) {
-			printk(KERN_ERR DRV_MODULE_NAME
-			       ": %s MII bus creation failure!\n", dev->name);
-			return PTR_ERR(bus);
-		}
-	}
-
-	bus->refs++;
-
-	fep->mii_bus = bus;
-
-	fep->mii_if.dev = dev;
-	fep->mii_if.phy_id_mask = 0x1f;
-	fep->mii_if.reg_num_mask = 0x1f;
-	fep->mii_if.mdio_read = fs_mii_read;
-	fep->mii_if.mdio_write = fs_mii_write;
-	fep->mii_if.force_media = fpi->bus_info->disable_aneg;
-	fep->mii_if.phy_id = phy_id_detect(dev);
-
-	return 0;
-}
-
-void fs_mii_disconnect(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	struct fs_enet_mii_bus *bus = NULL;
-
-	bus = fep->mii_bus;
-	fep->mii_bus = NULL;
-
-	if (--bus->refs <= 0)
-		destroy_bus(bus);
-}
diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h
index e7ec96c..95022c005 100644
--- a/drivers/net/fs_enet/fs_enet.h
+++ b/drivers/net/fs_enet/fs_enet.h
@@ -5,6 +5,7 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/phy.h>
 
 #include <linux/fs_enet_pd.h>
 
@@ -12,12 +13,30 @@
 
 #ifdef CONFIG_CPM1
 #include <asm/commproc.h>
+
+struct fec_info {
+        fec_t*  fecp;
+	u32     mii_speed;
+};
 #endif
 
 #ifdef CONFIG_CPM2
 #include <asm/cpm2.h>
 #endif
 
+/* This is used to operate with pins.
+  Note that the actual port size may
+    be different; cpm(s) handle it OK  */
+struct bb_info {
+	u8 mdio_dat_msk;
+	u8 mdio_dir_msk;
+	u8 *mdio_dir;
+	u8 *mdio_dat;
+	u8 mdc_msk;
+	u8 *mdc_dat;
+	int delay;
+};
+
 /* hw driver ops */
 struct fs_ops {
 	int (*setup_data)(struct net_device *dev);
@@ -25,6 +44,7 @@
 	void (*free_bd)(struct net_device *dev);
 	void (*cleanup_data)(struct net_device *dev);
 	void (*set_multicast_list)(struct net_device *dev);
+	void (*adjust_link)(struct net_device *dev);
 	void (*restart)(struct net_device *dev);
 	void (*stop)(struct net_device *dev);
 	void (*pre_request_irq)(struct net_device *dev, int irq);
@@ -100,10 +120,6 @@
 	};
 };
 
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus);
-
 struct fs_enet_private {
 	struct device *dev;	/* pointer back to the device (must be initialized first) */
 	spinlock_t lock;	/* during all ops except TX pckt processing */
@@ -130,7 +146,8 @@
 	struct fs_enet_mii_bus *mii_bus;
 	int interrupt;
 
-	int duplex, speed;	/* current settings */
+	struct phy_device *phydev;
+	int oldduplex, oldspeed, oldlink;	/* current settings */
 
 	/* event masks */
 	u32 ev_napi_rx;		/* mask of NAPI rx events */
@@ -168,15 +185,9 @@
 };
 
 /***************************************************************************/
-
-int fs_mii_read(struct net_device *dev, int phy_id, int location);
-void fs_mii_write(struct net_device *dev, int phy_id, int location, int value);
-
-void fs_mii_startup(struct net_device *dev);
-void fs_mii_shutdown(struct net_device *dev);
-void fs_mii_ack_int(struct net_device *dev);
-
-void fs_mii_link_status_change_check(struct net_device *dev, int init_media);
+int fs_enet_mdio_bb_init(void);
+int fs_mii_fixed_init(struct fs_enet_mii_bus *bus);
+int fs_enet_mdio_fec_init(void);
 
 void fs_init_bds(struct net_device *dev);
 void fs_cleanup_bds(struct net_device *dev);
@@ -194,7 +205,6 @@
 void fs_enet_platform_cleanup(void);
 
 /***************************************************************************/
-
 /* buffer descriptor access macros */
 
 /* access macros */
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 64e2098..1ff2597 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -34,6 +34,7 @@
 #include <linux/bitops.h>
 #include <linux/fs.h>
 #include <linux/platform_device.h>
+#include <linux/phy.h>
 
 #include <asm/immap_cpm2.h>
 #include <asm/mpc8260.h>
@@ -122,22 +123,32 @@
 
 	/* Attach the memory for the FCC Parameter RAM */
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram");
-	fep->fcc.ep = (void *)r->start;
-
+	fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1);
 	if (fep->fcc.ep == NULL)
 		return -EINVAL;
 
 	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs");
-	fep->fcc.fccp = (void *)r->start;
-
+	fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1);
 	if (fep->fcc.fccp == NULL)
 		return -EINVAL;
 
-	fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+	if (fep->fpi->fcc_regs_c) {
+
+		fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c;
+	} else {
+		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+				"fcc_regs_c");
+		fep->fcc.fcccp = (void *)ioremap(r->start,
+				r->end - r->start + 1);
+	}
 
 	if (fep->fcc.fcccp == NULL)
 		return -EINVAL;
 
+	fep->fcc.mem = (void *)fep->fpi->mem_offset;
+	if (fep->fcc.mem == NULL)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -155,8 +166,6 @@
 	if ((unsigned int)fep->fcc.idx >= 3)	/* max 3 FCCs */
 		return -EINVAL;
 
-	fep->fcc.mem = (void *)fpi->mem_offset;
-
 	if (do_pd_setup(fep) != 0)
 		return -EINVAL;
 
@@ -394,7 +403,7 @@
 
 	/* adjust to speed (for RMII mode) */
 	if (fpi->use_rmii) {
-		if (fep->speed == 100)
+		if (fep->phydev->speed == 100)
 			C8(fcccp, fcc_gfemr, 0x20);
 		else
 			S8(fcccp, fcc_gfemr, 0x20);
@@ -420,7 +429,7 @@
 		S32(fccp, fcc_fpsmr, FCC_PSMR_RMII);
 
 	/* adjust to duplex mode */
-	if (fep->duplex)
+	if (fep->phydev->duplex)
 		S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
 	else
 		C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
@@ -486,7 +495,10 @@
 
 static void tx_kickstart(struct net_device *dev)
 {
-	/* nothing */
+	struct fs_enet_private *fep = netdev_priv(dev);
+	fcc_t *fccp = fep->fcc.fccp;
+
+	S32(fccp, fcc_ftodr, 0x80);
 }
 
 static u32 get_int_events(struct net_device *dev)
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index e095470..c2c5fd4 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -46,6 +46,7 @@
 #endif
 
 #include "fs_enet.h"
+#include "fec.h"
 
 /*************************************************/
 
@@ -75,50 +76,8 @@
 /* clear bits */
 #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
 
-
-/* CRC polynomium used by the FEC for the multicast group filtering */
-#define FEC_CRC_POLY   0x04C11DB7
-
-#define FEC_MAX_MULTICAST_ADDRS	64
-
-/* Interrupt events/masks.
-*/
-#define FEC_ENET_HBERR	0x80000000U	/* Heartbeat error          */
-#define FEC_ENET_BABR	0x40000000U	/* Babbling receiver        */
-#define FEC_ENET_BABT	0x20000000U	/* Babbling transmitter     */
-#define FEC_ENET_GRA	0x10000000U	/* Graceful stop complete   */
-#define FEC_ENET_TXF	0x08000000U	/* Full frame transmitted   */
-#define FEC_ENET_TXB	0x04000000U	/* A buffer was transmitted */
-#define FEC_ENET_RXF	0x02000000U	/* Full frame received      */
-#define FEC_ENET_RXB	0x01000000U	/* A buffer was received    */
-#define FEC_ENET_MII	0x00800000U	/* MII interrupt            */
-#define FEC_ENET_EBERR	0x00400000U	/* SDMA bus error           */
-
-#define FEC_ECNTRL_PINMUX	0x00000004
-#define FEC_ECNTRL_ETHER_EN	0x00000002
-#define FEC_ECNTRL_RESET	0x00000001
-
-#define FEC_RCNTRL_BC_REJ	0x00000010
-#define FEC_RCNTRL_PROM		0x00000008
-#define FEC_RCNTRL_MII_MODE	0x00000004
-#define FEC_RCNTRL_DRT		0x00000002
-#define FEC_RCNTRL_LOOP		0x00000001
-
-#define FEC_TCNTRL_FDEN		0x00000004
-#define FEC_TCNTRL_HBC		0x00000002
-#define FEC_TCNTRL_GTS		0x00000001
-
-
-/* Make MII read/write commands for the FEC.
-*/
-#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
-#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
-#define mk_mii_end		0
-
-#define FEC_MII_LOOPS	10000
-
 /*
- * Delay to wait for FEC reset command to complete (in us) 
+ * Delay to wait for FEC reset command to complete (in us)
  */
 #define FEC_RESET_DELAY		50
 
@@ -303,13 +262,15 @@
 	int r;
 	u32 addrhi, addrlo;
 
+	struct mii_bus* mii = fep->phydev->bus;
+	struct fec_info* fec_inf = mii->priv;
+
 	r = whack_reset(fep->fec.fecp);
 	if (r != 0)
 		printk(KERN_ERR DRV_MODULE_NAME
 				": %s FEC Reset FAILED!\n", dev->name);
-
 	/*
-	 * Set station address. 
+	 * Set station address.
 	 */
 	addrhi = ((u32) dev->dev_addr[0] << 24) |
 		 ((u32) dev->dev_addr[1] << 16) |
@@ -350,12 +311,12 @@
 	FW(fecp, fun_code, 0x78000000);
 
 	/*
-	 * Set MII speed. 
+	 * Set MII speed.
 	 */
-	FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed);
+	FW(fecp, mii_speed, fec_inf->mii_speed);
 
 	/*
-	 * Clear any outstanding interrupt. 
+	 * Clear any outstanding interrupt.
 	 */
 	FW(fecp, ievent, 0xffc0);
 	FW(fecp, ivec, (fep->interrupt / 2) << 29);
@@ -390,11 +351,12 @@
 	}
 #endif
 
+
 	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 	/*
-	 * adjust to duplex mode 
+	 * adjust to duplex mode
 	 */
-	if (fep->duplex) {
+	if (fep->phydev->duplex) {
 		FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
 		FS(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD enable */
 	} else {
@@ -418,9 +380,11 @@
 static void stop(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
+	const struct fs_platform_info *fpi = fep->fpi;
 	fec_t *fecp = fep->fec.fecp;
-	struct fs_enet_mii_bus *bus = fep->mii_bus;
-	const struct fs_mii_bus_info *bi = bus->bus_info;
+
+	struct fec_info* feci= fep->phydev->bus->priv;
+
 	int i;
 
 	if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
@@ -444,11 +408,11 @@
 	fs_cleanup_bds(dev);
 
 	/* shut down FEC1? that's where the mii bus is */
-	if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) {
+	if (fpi->has_phy) {
 		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 		FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
 		FW(fecp, ievent, FEC_ENET_MII);
-		FW(fecp, mii_speed, bus->fec.mii_speed);
+		FW(fecp, mii_speed, feci->mii_speed);
 	}
 }
 
@@ -583,73 +547,3 @@
 	.free_bd		= free_bd,
 };
 
-/***********************************************************************/
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
-	fec_t *fecp = bus->fec.fecp;
-	int i, ret = -1;
-
-	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-		BUG();
-
-	/* Add PHY address to register command.  */
-	FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location));
-
-	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
-			break;
-
-	if (i < FEC_MII_LOOPS) {
-		FW(fecp, ievent, FEC_ENET_MII);
-		ret = FR(fecp, mii_data) & 0xffff;
-	}
-
-	return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value)
-{
-	fec_t *fecp = bus->fec.fecp;
-	int i;
-
-	/* this must never happen */
-	if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
-		BUG();
-
-	/* Add PHY address to register command.  */
-	FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value));
-
-	for (i = 0; i < FEC_MII_LOOPS; i++)
-		if ((FR(fecp, ievent) & FEC_ENET_MII) != 0)
-			break;
-
-	if (i < FEC_MII_LOOPS)
-		FW(fecp, ievent, FEC_ENET_MII);
-}
-
-int fs_mii_fec_init(struct fs_enet_mii_bus *bus)
-{
-	bd_t *bd = (bd_t *)__res;
-	const struct fs_mii_bus_info *bi = bus->bus_info;
-	fec_t *fecp;
-
-	if (bi->id != 0)
-		return -1;
-
-	bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec;
-	bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2)
-				& 0x3F) << 1;
-
-	fecp = bus->fec.fecp;
-
-	FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
-	FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
-	FW(fecp, ievent, FEC_ENET_MII);
-	FW(fecp, mii_speed, bus->fec.mii_speed);
-
-	bus->mii_read = mii_read;
-	bus->mii_write = mii_write;
-
-	return 0;
-}
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index eaa24fa..95ec587 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -369,7 +369,7 @@
 	W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22);
 
 	/* Set full duplex mode if needed */
-	if (fep->duplex)
+	if (fep->phydev->duplex)
 		S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE);
 
 	S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
@@ -500,6 +500,8 @@
 	scc_cr_cmd(fep, CPM_CR_RESTART_TX);
 }
 
+
+
 /*************************************************************************/
 
 const struct fs_ops fs_scc_ops = {
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 48f9cf8..0b9b8b5 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -33,6 +33,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
+#include <linux/platform_device.h>
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
@@ -40,129 +41,25 @@
 
 #include "fs_enet.h"
 
-#ifdef CONFIG_8xx
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
+static int bitbang_prep_bit(u8 **datp, u8 *mskp,
+		struct fs_mii_bit *mii_bit)
 {
-	immap_t *im = (immap_t *)fs_enet_immap;
-	void *dir, *dat, *ppar;
+	void *dat;
 	int adv;
 	u8 msk;
 
-	switch (port) {
-		case fsiop_porta:
-			dir = &im->im_ioport.iop_padir;
-			dat = &im->im_ioport.iop_padat;
-			ppar = &im->im_ioport.iop_papar;
-			break;
+	dat = (void*) mii_bit->offset;
 
-		case fsiop_portb:
-			dir = &im->im_cpm.cp_pbdir;
-			dat = &im->im_cpm.cp_pbdat;
-			ppar = &im->im_cpm.cp_pbpar;
-			break;
-
-		case fsiop_portc:
-			dir = &im->im_ioport.iop_pcdir;
-			dat = &im->im_ioport.iop_pcdat;
-			ppar = &im->im_ioport.iop_pcpar;
-			break;
-
-		case fsiop_portd:
-			dir = &im->im_ioport.iop_pddir;
-			dat = &im->im_ioport.iop_pddat;
-			ppar = &im->im_ioport.iop_pdpar;
-			break;
-
-		case fsiop_porte:
-			dir = &im->im_cpm.cp_pedir;
-			dat = &im->im_cpm.cp_pedat;
-			ppar = &im->im_cpm.cp_pepar;
-			break;
-
-		default:
-			printk(KERN_ERR DRV_MODULE_NAME
-			       "Illegal port value %d!\n", port);
-			return -EINVAL;
-	}
-
-	adv = bit >> 3;
-	dir = (char *)dir + adv;
+	adv = mii_bit->bit >> 3;
 	dat = (char *)dat + adv;
-	ppar = (char *)ppar + adv;
 
-	msk = 1 << (7 - (bit & 7));
-	if ((in_8(ppar) & msk) != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       "pin %d on port %d is not general purpose!\n", bit, port);
-		return -EINVAL;
-	}
+	msk = 1 << (7 - (mii_bit->bit & 7));
 
-	*dirp = dir;
 	*datp = dat;
 	*mskp = msk;
 
 	return 0;
 }
-#endif
-
-#ifdef CONFIG_8260
-static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit)
-{
-	iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport;
-	void *dir, *dat, *ppar;
-	int adv;
-	u8 msk;
-
-	switch (port) {
-		case fsiop_porta:
-			dir = &io->iop_pdira;
-			dat = &io->iop_pdata;
-			ppar = &io->iop_ppara;
-			break;
-
-		case fsiop_portb:
-			dir = &io->iop_pdirb;
-			dat = &io->iop_pdatb;
-			ppar = &io->iop_pparb;
-			break;
-
-		case fsiop_portc:
-			dir = &io->iop_pdirc;
-			dat = &io->iop_pdatc;
-			ppar = &io->iop_pparc;
-			break;
-
-		case fsiop_portd:
-			dir = &io->iop_pdird;
-			dat = &io->iop_pdatd;
-			ppar = &io->iop_ppard;
-			break;
-
-		default:
-			printk(KERN_ERR DRV_MODULE_NAME
-			       "Illegal port value %d!\n", port);
-			return -EINVAL;
-	}
-
-	adv = bit >> 3;
-	dir = (char *)dir + adv;
-	dat = (char *)dat + adv;
-	ppar = (char *)ppar + adv;
-
-	msk = 1 << (7 - (bit & 7));
-	if ((in_8(ppar) & msk) != 0) {
-		printk(KERN_ERR DRV_MODULE_NAME
-		       "pin %d on port %d is not general purpose!\n", bit, port);
-		return -EINVAL;
-	}
-
-	*dirp = dir;
-	*datp = dat;
-	*mskp = msk;
-
-	return 0;
-}
-#endif
 
 static inline void bb_set(u8 *p, u8 m)
 {
@@ -179,44 +76,44 @@
 	return (in_8(p) & m) != 0;
 }
 
-static inline void mdio_active(struct fs_enet_mii_bus *bus)
+static inline void mdio_active(struct bb_info *bitbang)
 {
-	bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+	bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk);
 }
 
-static inline void mdio_tristate(struct fs_enet_mii_bus *bus)
+static inline void mdio_tristate(struct bb_info *bitbang )
 {
-	bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk);
+	bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk);
 }
 
-static inline int mdio_read(struct fs_enet_mii_bus *bus)
+static inline int mdio_read(struct bb_info *bitbang )
 {
-	return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+	return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk);
 }
 
-static inline void mdio(struct fs_enet_mii_bus *bus, int what)
+static inline void mdio(struct bb_info *bitbang , int what)
 {
 	if (what)
-		bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+		bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk);
 	else
-		bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk);
+		bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk);
 }
 
-static inline void mdc(struct fs_enet_mii_bus *bus, int what)
+static inline void mdc(struct bb_info *bitbang , int what)
 {
 	if (what)
-		bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+		bb_set(bitbang->mdc_dat, bitbang->mdc_msk);
 	else
-		bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk);
+		bb_clr(bitbang->mdc_dat, bitbang->mdc_msk);
 }
 
-static inline void mii_delay(struct fs_enet_mii_bus *bus)
+static inline void mii_delay(struct bb_info *bitbang )
 {
-	udelay(bus->bus_info->i.bitbang.delay);
+	udelay(bitbang->delay);
 }
 
 /* Utility to send the preamble, address, and register (common to read and write). */
-static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg)
+static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg)
 {
 	int j;
 
@@ -228,177 +125,284 @@
 	 * but it is safer and will be much more robust.
 	 */
 
-	mdio_active(bus);
-	mdio(bus, 1);
+	mdio_active(bitbang);
+	mdio(bitbang, 1);
 	for (j = 0; j < 32; j++) {
-		mdc(bus, 0);
-		mii_delay(bus);
-		mdc(bus, 1);
-		mii_delay(bus);
+		mdc(bitbang, 0);
+		mii_delay(bitbang);
+		mdc(bitbang, 1);
+		mii_delay(bitbang);
 	}
 
 	/* send the start bit (01) and the read opcode (10) or write (10) */
-	mdc(bus, 0);
-	mdio(bus, 0);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 0);
-	mdio(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 0);
-	mdio(bus, read);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 0);
-	mdio(bus, !read);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
+	mdc(bitbang, 0);
+	mdio(bitbang, 0);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 0);
+	mdio(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 0);
+	mdio(bitbang, read);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 0);
+	mdio(bitbang, !read);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
 
 	/* send the PHY address */
 	for (j = 0; j < 5; j++) {
-		mdc(bus, 0);
-		mdio(bus, (addr & 0x10) != 0);
-		mii_delay(bus);
-		mdc(bus, 1);
-		mii_delay(bus);
+		mdc(bitbang, 0);
+		mdio(bitbang, (addr & 0x10) != 0);
+		mii_delay(bitbang);
+		mdc(bitbang, 1);
+		mii_delay(bitbang);
 		addr <<= 1;
 	}
 
 	/* send the register address */
 	for (j = 0; j < 5; j++) {
-		mdc(bus, 0);
-		mdio(bus, (reg & 0x10) != 0);
-		mii_delay(bus);
-		mdc(bus, 1);
-		mii_delay(bus);
+		mdc(bitbang, 0);
+		mdio(bitbang, (reg & 0x10) != 0);
+		mii_delay(bitbang);
+		mdc(bitbang, 1);
+		mii_delay(bitbang);
 		reg <<= 1;
 	}
 }
 
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
+static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location)
 {
 	u16 rdreg;
 	int ret, j;
 	u8 addr = phy_id & 0xff;
 	u8 reg = location & 0xff;
+	struct bb_info* bitbang = bus->priv;
 
-	bitbang_pre(bus, 1, addr, reg);
+	bitbang_pre(bitbang, 1, addr, reg);
 
 	/* tri-state our MDIO I/O pin so we can read */
-	mdc(bus, 0);
-	mdio_tristate(bus);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
+	mdc(bitbang, 0);
+	mdio_tristate(bitbang);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
 
 	/* check the turnaround bit: the PHY should be driving it to zero */
-	if (mdio_read(bus) != 0) {
+	if (mdio_read(bitbang) != 0) {
 		/* PHY didn't drive TA low */
 		for (j = 0; j < 32; j++) {
-			mdc(bus, 0);
-			mii_delay(bus);
-			mdc(bus, 1);
-			mii_delay(bus);
+			mdc(bitbang, 0);
+			mii_delay(bitbang);
+			mdc(bitbang, 1);
+			mii_delay(bitbang);
 		}
 		ret = -1;
 		goto out;
 	}
 
-	mdc(bus, 0);
-	mii_delay(bus);
+	mdc(bitbang, 0);
+	mii_delay(bitbang);
 
 	/* read 16 bits of register data, MSB first */
 	rdreg = 0;
 	for (j = 0; j < 16; j++) {
-		mdc(bus, 1);
-		mii_delay(bus);
+		mdc(bitbang, 1);
+		mii_delay(bitbang);
 		rdreg <<= 1;
-		rdreg |= mdio_read(bus);
-		mdc(bus, 0);
-		mii_delay(bus);
+		rdreg |= mdio_read(bitbang);
+		mdc(bitbang, 0);
+		mii_delay(bitbang);
 	}
 
-	mdc(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 0);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 0);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
 
 	ret = rdreg;
 out:
 	return ret;
 }
 
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
+static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val)
 {
 	int j;
+	struct bb_info* bitbang = bus->priv;
+
 	u8 addr = phy_id & 0xff;
 	u8 reg = location & 0xff;
 	u16 value = val & 0xffff;
 
-	bitbang_pre(bus, 0, addr, reg);
+	bitbang_pre(bitbang, 0, addr, reg);
 
 	/* send the turnaround (10) */
-	mdc(bus, 0);
-	mdio(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
-	mdc(bus, 0);
-	mdio(bus, 0);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
+	mdc(bitbang, 0);
+	mdio(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	mdc(bitbang, 0);
+	mdio(bitbang, 0);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
 
 	/* write 16 bits of register data, MSB first */
 	for (j = 0; j < 16; j++) {
-		mdc(bus, 0);
-		mdio(bus, (value & 0x8000) != 0);
-		mii_delay(bus);
-		mdc(bus, 1);
-		mii_delay(bus);
+		mdc(bitbang, 0);
+		mdio(bitbang, (value & 0x8000) != 0);
+		mii_delay(bitbang);
+		mdc(bitbang, 1);
+		mii_delay(bitbang);
 		value <<= 1;
 	}
 
 	/*
 	 * Tri-state the MDIO line.
 	 */
-	mdio_tristate(bus);
-	mdc(bus, 0);
-	mii_delay(bus);
-	mdc(bus, 1);
-	mii_delay(bus);
+	mdio_tristate(bitbang);
+	mdc(bitbang, 0);
+	mii_delay(bitbang);
+	mdc(bitbang, 1);
+	mii_delay(bitbang);
+	return 0;
 }
 
-int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus)
+static int fs_enet_mii_bb_reset(struct mii_bus *bus)
 {
-	const struct fs_mii_bus_info *bi = bus->bus_info;
+	/*nothing here - dunno how to reset it*/
+	return 0;
+}
+
+static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi)
+{
 	int r;
 
-	r = bitbang_prep_bit(&bus->bitbang.mdio_dir,
-			 &bus->bitbang.mdio_dat,
-			 &bus->bitbang.mdio_msk,
-			 bi->i.bitbang.mdio_port,
-			 bi->i.bitbang.mdio_bit);
+	bitbang->delay = fmpi->delay;
+
+	r = bitbang_prep_bit(&bitbang->mdio_dir,
+			 &bitbang->mdio_dir_msk,
+			 &fmpi->mdio_dir);
 	if (r != 0)
 		return r;
 
-	r = bitbang_prep_bit(&bus->bitbang.mdc_dir,
-			 &bus->bitbang.mdc_dat,
-			 &bus->bitbang.mdc_msk,
-			 bi->i.bitbang.mdc_port,
-			 bi->i.bitbang.mdc_bit);
+	r = bitbang_prep_bit(&bitbang->mdio_dat,
+			 &bitbang->mdio_dat_msk,
+			 &fmpi->mdio_dat);
 	if (r != 0)
 		return r;
 
-	bus->mii_read = mii_read;
-	bus->mii_write = mii_write;
+	r = bitbang_prep_bit(&bitbang->mdc_dat,
+			 &bitbang->mdc_msk,
+			 &fmpi->mdc_dat);
+	if (r != 0)
+		return r;
 
 	return 0;
 }
+
+
+static int __devinit fs_enet_mdio_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fs_mii_bb_platform_info *pdata;
+	struct mii_bus *new_bus;
+	struct bb_info *bitbang;
+	int err = 0;
+
+	if (NULL == dev)
+		return -EINVAL;
+
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+	if (NULL == new_bus)
+		return -ENOMEM;
+
+	bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL);
+
+	if (NULL == bitbang)
+		return -ENOMEM;
+
+	new_bus->name = "BB MII Bus",
+	new_bus->read = &fs_enet_mii_bb_read,
+	new_bus->write = &fs_enet_mii_bb_write,
+	new_bus->reset = &fs_enet_mii_bb_reset,
+	new_bus->id = pdev->id;
+
+	new_bus->phy_mask = ~0x9;
+	pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data;
+
+	if (NULL == pdata) {
+		printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
+		return -ENODEV;
+	}
+
+	/*set up workspace*/
+	fs_mii_bitbang_init(bitbang, pdata);
+
+	new_bus->priv = bitbang;
+
+	new_bus->irq = pdata->irq;
+
+	new_bus->dev = dev;
+	dev_set_drvdata(dev, new_bus);
+
+	err = mdiobus_register(new_bus);
+
+	if (0 != err) {
+		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+				new_bus->name);
+		goto bus_register_fail;
+	}
+
+	return 0;
+
+bus_register_fail:
+	kfree(bitbang);
+	kfree(new_bus);
+
+	return err;
+}
+
+
+static int fs_enet_mdio_remove(struct device *dev)
+{
+	struct mii_bus *bus = dev_get_drvdata(dev);
+
+	mdiobus_unregister(bus);
+
+	dev_set_drvdata(dev, NULL);
+
+	iounmap((void *) (&bus->priv));
+	bus->priv = NULL;
+	kfree(bus);
+
+	return 0;
+}
+
+static struct device_driver fs_enet_bb_mdio_driver = {
+	.name = "fsl-bb-mdio",
+	.bus = &platform_bus_type,
+	.probe = fs_enet_mdio_probe,
+	.remove = fs_enet_mdio_remove,
+};
+
+int fs_enet_mdio_bb_init(void)
+{
+	return driver_register(&fs_enet_bb_mdio_driver);
+}
+
+void fs_enet_mdio_bb_exit(void)
+{
+	driver_unregister(&fs_enet_bb_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
new file mode 100644
index 0000000..1328e10
--- /dev/null
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -0,0 +1,243 @@
+/*
+ * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ *  by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (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.
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "fs_enet.h"
+#include "fec.h"
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff))
+#define mk_mii_end		0
+
+#define FEC_MII_LOOPS	10000
+
+static int match_has_phy (struct device *dev, void* data)
+{
+	struct platform_device* pdev = container_of(dev, struct platform_device, dev);
+	struct fs_platform_info* fpi;
+	if(strcmp(pdev->name, (char*)data))
+	{
+	    return 0;
+	}
+
+	fpi = pdev->dev.platform_data;
+	if((fpi)&&(fpi->has_phy))
+		return 1;
+	return 0;
+}
+
+static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi)
+{
+	struct resource *r;
+	fec_t *fecp;
+	char* name = "fsl-cpm-fec";
+
+	/* we need fec in order to be useful */
+	struct platform_device *fec_pdev =
+		container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy),
+				struct platform_device, dev);
+
+	if(fec_pdev == NULL) {
+		printk(KERN_ERR"Unable to find PHY for %s", name);
+		return -ENODEV;
+	}
+
+	r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs");
+
+	fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t));
+	fec->mii_speed = fmpi->mii_speed;
+
+	setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+	setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
+	out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+	out_be32(&fecp->fec_mii_speed, fec->mii_speed);
+
+	return 0;
+}
+
+static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location)
+{
+	struct fec_info* fec = bus->priv;
+	fec_t *fecp = fec->fecp;
+	int i, ret = -1;
+
+	if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS) {
+		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+		ret = in_be32(&fecp->fec_mii_data) & 0xffff;
+	}
+
+	return ret;
+
+}
+
+static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+	struct fec_info* fec = bus->priv;
+	fec_t *fecp = fec->fecp;
+	int i;
+
+	/* this must never happen */
+	if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0)
+		BUG();
+
+	/* Add PHY address to register command.  */
+	out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val));
+
+	for (i = 0; i < FEC_MII_LOOPS; i++)
+		if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0)
+			break;
+
+	if (i < FEC_MII_LOOPS)
+		out_be32(&fecp->fec_ievent, FEC_ENET_MII);
+
+	return 0;
+
+}
+
+static int fs_enet_fec_mii_reset(struct mii_bus *bus)
+{
+	/* nothing here - for now */
+	return 0;
+}
+
+static int __devinit fs_enet_fec_mdio_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct fs_mii_fec_platform_info *pdata;
+	struct mii_bus *new_bus;
+	struct fec_info *fec;
+	int err = 0;
+	if (NULL == dev)
+		return -EINVAL;
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+	if (NULL == new_bus)
+		return -ENOMEM;
+
+	fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
+
+	if (NULL == fec)
+		return -ENOMEM;
+
+	new_bus->name = "FEC MII Bus",
+	new_bus->read = &fs_enet_fec_mii_read,
+	new_bus->write = &fs_enet_fec_mii_write,
+	new_bus->reset = &fs_enet_fec_mii_reset,
+	new_bus->id = pdev->id;
+
+	pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data;
+
+	if (NULL == pdata) {
+		printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id);
+		return -ENODEV;
+	}
+
+	/*set up workspace*/
+
+	fs_mii_fec_init(fec, pdata);
+	new_bus->priv = fec;
+
+	new_bus->irq = pdata->irq;
+
+	new_bus->dev = dev;
+	dev_set_drvdata(dev, new_bus);
+
+	err = mdiobus_register(new_bus);
+
+	if (0 != err) {
+		printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
+				new_bus->name);
+		goto bus_register_fail;
+	}
+
+	return 0;
+
+bus_register_fail:
+	kfree(new_bus);
+
+	return err;
+}
+
+
+static int fs_enet_fec_mdio_remove(struct device *dev)
+{
+	struct mii_bus *bus = dev_get_drvdata(dev);
+
+	mdiobus_unregister(bus);
+
+	dev_set_drvdata(dev, NULL);
+	kfree(bus->priv);
+
+	bus->priv = NULL;
+	kfree(bus);
+
+	return 0;
+}
+
+static struct device_driver fs_enet_fec_mdio_driver = {
+	.name = "fsl-cpm-fec-mdio",
+	.bus = &platform_bus_type,
+	.probe = fs_enet_fec_mdio_probe,
+	.remove = fs_enet_fec_mdio_remove,
+};
+
+int fs_enet_mdio_fec_init(void)
+{
+	return driver_register(&fs_enet_fec_mdio_driver);
+}
+
+void fs_enet_mdio_fec_exit(void)
+{
+	driver_unregister(&fs_enet_fec_mdio_driver);
+}
+
diff --git a/drivers/net/fs_enet/mii-fixed.c b/drivers/net/fs_enet/mii-fixed.c
deleted file mode 100644
index ae4a9c3..0000000
--- a/drivers/net/fs_enet/mii-fixed.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
- *
- * Copyright (c) 2003 Intracom S.A. 
- *  by Pantelis Antoniou <panto@intracom.gr>
- * 
- * 2005 (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.
- */
-
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/mii.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "fs_enet.h"
-
-static const u16 mii_regs[7] = {
-	0x3100,
-	0x786d,
-	0x0fff,
-	0x0fff,
-	0x01e1,
-	0x45e1,
-	0x0003,
-};
-
-static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location)
-{
-	int ret = 0;
-
-	if ((unsigned int)location >= ARRAY_SIZE(mii_regs))
-		return -1;
-
-	if (location != 5)
-		ret = mii_regs[location];
-	else
-		ret = bus->fixed.lpa;
-
-	return ret;
-}
-
-static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val)
-{
-	/* do nothing */
-}
-
-int fs_mii_fixed_init(struct fs_enet_mii_bus *bus)
-{
-	const struct fs_mii_bus_info *bi = bus->bus_info;
-
-	bus->fixed.lpa = 0x45e1;	/* default 100Mb, full duplex */
-
-	/* if speed is fixed at 10Mb, remove 100Mb modes */
-	if (bi->i.fixed.speed == 10)
-		bus->fixed.lpa &= ~LPA_100;
-
-	/* if duplex is half, remove full duplex modes */
-	if (bi->i.fixed.duplex == 0)
-		bus->fixed.lpa &= ~LPA_DUPLEX;
-
-	bus->mii_read = mii_read;
-	bus->mii_write = mii_write;
-
-	return 0;
-}
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index ebbbd6c..5130da0 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1708,9 +1708,6 @@
 	u32 tempval;
 
 	if(dev->flags & IFF_PROMISC) {
-		if (netif_msg_drv(priv))
-			printk(KERN_INFO "%s: Entering promiscuous mode.\n",
-					dev->name);
 		/* Set RCTRL to PROM */
 		tempval = gfar_read(&regs->rctrl);
 		tempval |= RCTRL_PROM;
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 409c6aa..9927bff 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -27,8 +27,8 @@
 */
 
 #define DRV_NAME	"hamachi"
-#define DRV_VERSION	"2.0"
-#define DRV_RELDATE	"June 27, 2006"
+#define DRV_VERSION	"2.1"
+#define DRV_RELDATE	"Sept 11, 2006"
 
 
 /* A few user-configurable values. */
@@ -1851,8 +1851,6 @@
 	void __iomem *ioaddr = hmp->base;
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		writew(0x000F, ioaddr + AddrMode);
 	} else if ((dev->mc_count > 63)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to match, or accept all multicasts. */
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index e7d9bf3..ff5a67d 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -111,7 +111,6 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
-#include <linux/config.h>	/* for CONFIG_PCI */
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 68d8af7..fbda761 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -28,7 +28,7 @@
  */
 
 #define IOC3_NAME	"ioc3-eth"
-#define IOC3_VERSION	"2.6.3-3"
+#define IOC3_VERSION	"2.6.3-4"
 
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -1611,8 +1611,6 @@
 	netif_stop_queue(dev);				/* Lock out others. */
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous.  */
-		/* Unconditionally log net taps.  */
-		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 		ip->emcr |= EMCR_PROMISC;
 		ioc3_w_emcr(ip->emcr);
 		(void) ioc3_r_emcr();
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index 47f6f64..415ba8d 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -45,7 +45,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 0ea65c4..b69776e 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -40,7 +40,6 @@
  ********************************************************************/
 
 #include <linux/module.h>
-#include <linux/config.h> 
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 82b67af..a51604b 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -110,9 +110,6 @@
 #define IXGB_RXBUFFER_8192  8192
 #define IXGB_RXBUFFER_16384 16384
 
-/* How many Tx Descriptors do we need to call netif_wake_queue? */
-#define IXGB_TX_QUEUE_WAKE 16
-
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
 #define IXGB_RX_BUFFER_WRITE	4	/* Must be power of 2 */
 
@@ -173,7 +170,7 @@
 	unsigned long led_status;
 
 	/* TX */
-	struct ixgb_desc_ring tx_ring;
+	struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
 	unsigned long timeo_start;
 	uint32_t tx_cmd_type;
 	uint64_t hw_csum_tx_good;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index cf19b89..ba62108 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -654,11 +654,7 @@
 
 	mod_timer(&adapter->blink_timer, jiffies);
 
-	if (data)
-		schedule_timeout_interruptible(data * HZ);
-	else
-		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
-
+	msleep_interruptible(data * 1000);
 	del_timer_sync(&adapter->blink_timer);
 	ixgb_led_off(&adapter->hw);
 	clear_bit(IXGB_LED_ON, &adapter->led_status);
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index f7fa10e..2b15155 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -236,6 +236,17 @@
 		DEBUGOUT("Identified G6104 optics\n");
 		phy_type = ixgb_phy_type_g6104;
 		break;
+	case IXGB_DEVICE_ID_82597EX_CX4:
+		DEBUGOUT("Identified CX4\n");
+		xpak_vendor = ixgb_identify_xpak_vendor(hw);
+		if (xpak_vendor == ixgb_xpak_vendor_intel) {
+			DEBUGOUT("Identified TXN17201 optics\n");
+			phy_type = ixgb_phy_type_txn17201;
+		} else {
+			DEBUGOUT("Identified G6005 optics\n");
+			phy_type = ixgb_phy_type_g6005;
+		}
+		break;
 	default:
 		DEBUGOUT("Unknown physical layer module\n");
 		phy_type = ixgb_phy_type_unknown;
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
index 40a085f..9fd6118 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -45,6 +45,7 @@
 
 #define IXGB_DEVICE_ID_82597EX_CX4   0x109E
 #define IXGB_SUBDEVICE_ID_A00C  0xA00C
+#define IXGB_SUBDEVICE_ID_A01C  0xA01C
 
 #endif /* #ifndef _IXGB_IDS_H_ */
 /* End of File */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 7bbd447..e36dee1 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -36,7 +36,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION		"1.0.109-k2"DRIVERNAPI
+#define DRV_VERSION		"1.0.112-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
 static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
@@ -118,15 +118,26 @@
 static void ixgb_netpoll(struct net_device *dev);
 #endif
 
-/* Exported from other modules */
+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+	                     enum pci_channel_state state);
+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
+static void ixgb_io_resume (struct pci_dev *pdev);
 
+/* Exported from other modules */
 extern void ixgb_check_options(struct ixgb_adapter *adapter);
 
+static struct pci_error_handlers ixgb_err_handler = {
+	.error_detected = ixgb_io_error_detected,
+	.slot_reset = ixgb_io_slot_reset,
+	.resume = ixgb_io_resume,
+};
+
 static struct pci_driver ixgb_driver = {
 	.name     = ixgb_driver_name,
 	.id_table = ixgb_pci_tbl,
 	.probe    = ixgb_probe,
 	.remove   = __devexit_p(ixgb_remove),
+	.err_handler = &ixgb_err_handler
 };
 
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -140,12 +151,12 @@
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* some defines for controlling descriptor fetches in h/w */
-#define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 */
-#define RXDCTL_PTHRESH_DEFAULT 0		/* chip considers prefech below
-						 * this */
-#define RXDCTL_HTHRESH_DEFAULT 0		/* chip will only prefetch if tail
-						 * is pushed this many descriptors
-						 * from head */
+#define RXDCTL_WTHRESH_DEFAULT 15  /* chip writes back at this many or RXT0 */
+#define RXDCTL_PTHRESH_DEFAULT 0   /* chip considers prefech below
+                                    * this */
+#define RXDCTL_HTHRESH_DEFAULT 0   /* chip will only prefetch if tail
+                                    * is pushed this many descriptors
+                                    * from head */
 
 /**
  * ixgb_init_module - Driver Registration Routine
@@ -162,7 +173,7 @@
 
 	printk(KERN_INFO "%s\n", ixgb_copyright);
 
-	return pci_module_init(&ixgb_driver);
+	return pci_register_driver(&ixgb_driver);
 }
 
 module_init(ixgb_init_module);
@@ -1174,6 +1185,7 @@
 	int err;
 
 	if (likely(skb_is_gso(skb))) {
+		struct ixgb_buffer *buffer_info;
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
@@ -1196,6 +1208,8 @@
 
 		i = adapter->tx_ring.next_to_use;
 		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+		buffer_info = &adapter->tx_ring.buffer_info[i];
+		WARN_ON(buffer_info->dma != 0);
 
 		context_desc->ipcss = ipcss;
 		context_desc->ipcso = ipcso;
@@ -1233,11 +1247,14 @@
 	uint8_t css, cso;
 
 	if(likely(skb->ip_summed == CHECKSUM_HW)) {
+		struct ixgb_buffer *buffer_info;
 		css = skb->h.raw - skb->data;
 		cso = (skb->h.raw + skb->csum) - skb->data;
 
 		i = adapter->tx_ring.next_to_use;
 		context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i);
+		buffer_info = &adapter->tx_ring.buffer_info[i];
+		WARN_ON(buffer_info->dma != 0);
 
 		context_desc->tucss = css;
 		context_desc->tucso = cso;
@@ -1283,6 +1300,7 @@
 		buffer_info = &tx_ring->buffer_info[i];
 		size = min(len, IXGB_MAX_DATA_PER_TXD);
 		buffer_info->length = size;
+		WARN_ON(buffer_info->dma != 0);
 		buffer_info->dma =
 			pci_map_single(adapter->pdev,
 				skb->data + offset,
@@ -1543,6 +1561,11 @@
 ixgb_update_stats(struct ixgb_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
+
+	/* Prevent stats update while adapter is being reset */
+	if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
+		return;
 
 	if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
 	   (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {
@@ -1787,7 +1810,7 @@
 	if (unlikely(netif_queue_stopped(netdev))) {
 		spin_lock(&adapter->tx_lock);
 		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-		    (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE))
+		    (IXGB_DESC_UNUSED(tx_ring) >= DESC_NEEDED))
 			netif_wake_queue(netdev);
 		spin_unlock(&adapter->tx_lock);
 	}
@@ -1948,10 +1971,9 @@
 #define IXGB_CB_LENGTH 256
 		if (length < IXGB_CB_LENGTH) {
 			struct sk_buff *new_skb =
-			    dev_alloc_skb(length + NET_IP_ALIGN);
+			    netdev_alloc_skb(netdev, length + NET_IP_ALIGN);
 			if (new_skb) {
 				skb_reserve(new_skb, NET_IP_ALIGN);
-				new_skb->dev = netdev;
 				memcpy(new_skb->data - NET_IP_ALIGN,
 				       skb->data - NET_IP_ALIGN,
 				       length + NET_IP_ALIGN);
@@ -2031,14 +2053,14 @@
 	/* leave three descriptors unused */
 	while(--cleancount > 2) {
 		/* recycle! its good for you */
-		if (!(skb = buffer_info->skb))
-			skb = dev_alloc_skb(adapter->rx_buffer_len
-			                    + NET_IP_ALIGN);
-		else {
+		skb = buffer_info->skb;
+		if (skb) {
 			skb_trim(skb, 0);
 			goto map_skb;
 		}
 
+		skb = netdev_alloc_skb(netdev, adapter->rx_buffer_len
+			               + NET_IP_ALIGN);
 		if (unlikely(!skb)) {
 			/* Better luck next round */
 			adapter->alloc_rx_buff_failed++;
@@ -2051,8 +2073,6 @@
 		 */
 		skb_reserve(skb, NET_IP_ALIGN);
 
-		skb->dev = netdev;
-
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
 map_skb:
@@ -2190,7 +2210,7 @@
 
 static void ixgb_netpoll(struct net_device *dev)
 {
-	struct ixgb_adapter *adapter = dev->priv;
+	struct ixgb_adapter *adapter = netdev_priv(dev);
 
 	disable_irq(adapter->pdev->irq);
 	ixgb_intr(adapter->pdev->irq, dev, NULL);
@@ -2198,4 +2218,98 @@
 }
 #endif
 
+/**
+ * ixgb_io_error_detected() - called when PCI error is detected
+ * @pdev    pointer to pci device with error
+ * @state   pci channel state after error
+ *
+ * This callback is called by the PCI subsystem whenever
+ * a PCI bus error is detected.
+ */
+static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
+			             enum pci_channel_state state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	if(netif_running(netdev))
+		ixgb_down(adapter, TRUE);
+
+	pci_disable_device(pdev);
+
+	/* Request a slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * ixgb_io_slot_reset - called after the pci bus has been reset.
+ * @pdev    pointer to pci device with error
+ *
+ * This callback is called after the PCI buss has been reset.
+ * Basically, this tries to restart the card from scratch.
+ * This is a shortened version of the device probe/discovery code,
+ * it resembles the first-half of the ixgb_probe() routine.
+ */
+static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	if(pci_enable_device(pdev)) {
+		DPRINTK(PROBE, ERR, "Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	/* Perform card reset only on one instance of the card */
+	if (0 != PCI_FUNC (pdev->devfn))
+		return PCI_ERS_RESULT_RECOVERED;
+
+	pci_set_master(pdev);
+
+	netif_carrier_off(netdev);
+	netif_stop_queue(netdev);
+	ixgb_reset(adapter);
+
+	/* Make sure the EEPROM is good */
+	if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+		DPRINTK(PROBE, ERR, "After reset, the EEPROM checksum is not valid.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+	memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
+
+	if(!is_valid_ether_addr(netdev->perm_addr)) {
+		DPRINTK(PROBE, ERR, "After reset, invalid MAC address.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * ixgb_io_resume - called when its OK to resume normal operations
+ * @pdev    pointer to pci device with error
+ *
+ * The error recovery driver tells us that its OK to resume
+ * normal operation. Implementation resembles the second-half
+ * of the ixgb_probe() routine.
+ */
+static void ixgb_io_resume (struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct ixgb_adapter *adapter = netdev->priv;
+
+	pci_set_master(pdev);
+
+	if(netif_running(netdev)) {
+		if(ixgb_up(adapter)) {
+			printk ("ixgb: can't bring device back up after reset\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+	mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
 /* ixgb_main.c */
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index c1c3452..dc997be 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -42,7 +42,7 @@
 	Vesselin Kostadinov <vesok at yahoo dot com > - 22/4/2004
 */
 
-static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -326,7 +326,7 @@
 MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)");
 MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
@@ -1281,8 +1281,6 @@
 	outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance.	 */
 
 	if (dev->flags&IFF_PROMISC) {
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
 		outw(15, ioaddr+LANCE_ADDR);
 		outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */
 	} else {
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 646e89f..c0ec7f6 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -406,7 +406,7 @@
 MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 07ca948..b19e203 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -177,6 +177,7 @@
 	struct work_struct watchdog_work;
 	struct timer_list watchdog_timer;
 	int watchdog_tx_done;
+	int watchdog_tx_req;
 	int watchdog_resets;
 	int tx_linearized;
 	int pause;
@@ -186,11 +187,14 @@
 	u8 mac_addr[6];		/* eeprom mac address */
 	unsigned long serial_number;
 	int vendor_specific_offset;
+	int fw_multicast_support;
 	u32 devctl;
 	u16 msi_flags;
 	u32 read_dma;
 	u32 write_dma;
 	u32 read_write_dma;
+	u32 link_changes;
+	u32 msg_enable;
 };
 
 static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -256,6 +260,12 @@
 MODULE_PARM_DESC(myri10ge_max_irq_loops,
 		 "Set stuck legacy IRQ detection threshold\n");
 
+#define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINK
+
+static int myri10ge_debug = -1;	/* defaults above */
+module_param(myri10ge_debug, int, 0);
+MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
+
 #define MYRI10GE_FW_OFFSET 1024*1024
 #define MYRI10GE_HIGHPART_TO_U32(X) \
 (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -270,7 +280,7 @@
 	struct mcp_cmd *buf;
 	char buf_bytes[sizeof(*buf) + 8];
 	struct mcp_cmd_response *response = mgp->cmd;
-	char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+	char __iomem *cmd_addr = mgp->sram + MXGEFW_ETH_CMD;
 	u32 dma_low, dma_high, result, value;
 	int sleep_total = 0;
 
@@ -319,6 +329,8 @@
 		if (result == 0) {
 			data->data0 = value;
 			return 0;
+		} else if (result == MXGEFW_CMD_UNKNOWN) {
+			return -ENOSYS;
 		} else {
 			dev_err(&mgp->pdev->dev,
 				"command %d failed, result = %d\n",
@@ -403,7 +415,7 @@
 	buf[4] = htonl(dma_low);	/* dummy addr LSW */
 	buf[5] = htonl(enable);	/* enable? */
 
-	submit = mgp->sram + 0xfc01c0;
+	submit = mgp->sram + MXGEFW_BOOT_DUMMY_RDMA;
 
 	myri10ge_pio_copy(submit, &buf, sizeof(buf));
 	for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
@@ -448,6 +460,7 @@
 	struct mcp_gen_header *hdr;
 	size_t hdr_offset;
 	int status;
+	unsigned i;
 
 	if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
 		dev_err(dev, "Unable to load %s firmware image via hotplug\n",
@@ -479,18 +492,12 @@
 		goto abort_with_fw;
 
 	crc = crc32(~0, fw->data, fw->size);
-	if (mgp->tx.boundary == 2048) {
-		/* Avoid PCI burst on chipset with unaligned completions. */
-		int i;
-		__iomem u32 *ptr = (__iomem u32 *) (mgp->sram +
-						    MYRI10GE_FW_OFFSET);
-		for (i = 0; i < fw->size / 4; i++) {
-			__raw_writel(((u32 *) fw->data)[i], ptr + i);
-			wmb();
-		}
-	} else {
-		myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data,
-				  fw->size);
+	for (i = 0; i < fw->size; i += 256) {
+		myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i,
+				  fw->data + i,
+				  min(256U, (unsigned)(fw->size - i)));
+		mb();
+		readb(mgp->sram);
 	}
 	/* corruption checking is good for parity recovery and buggy chipset */
 	memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
@@ -604,7 +611,7 @@
 	buf[5] = htonl(8);	/* where to copy to */
 	buf[6] = htonl(0);	/* where to jump to */
 
-	submit = mgp->sram + 0xfc0000;
+	submit = mgp->sram + MXGEFW_BOOT_HANDOFF;
 
 	myri10ge_pio_copy(submit, &buf, sizeof(buf));
 	mb();
@@ -620,7 +627,7 @@
 		return -ENXIO;
 	}
 	dev_info(&mgp->pdev->dev, "handoff confirmed\n");
-	myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+	myri10ge_dummy_rdma(mgp, 1);
 
 	return 0;
 }
@@ -768,6 +775,7 @@
 	mgp->rx_small.cnt = 0;
 	mgp->rx_done.idx = 0;
 	mgp->rx_done.cnt = 0;
+	mgp->link_changes = 0;
 	status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
 	myri10ge_change_promisc(mgp, 0, 0);
 	myri10ge_change_pause(mgp, mgp->pause);
@@ -802,12 +810,13 @@
  * pages directly and building a fraglist in the near future.
  */
 
-static inline struct sk_buff *myri10ge_alloc_big(int bytes)
+static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev,
+						 int bytes)
 {
 	struct sk_buff *skb;
 	unsigned long data, roundup;
 
-	skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD);
+	skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD);
 	if (skb == NULL)
 		return NULL;
 
@@ -825,12 +834,13 @@
 
 /* Allocate 2x as much space as required and use whichever portion
  * does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
+static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev,
+							unsigned int bytes)
 {
 	struct sk_buff *skb;
 	unsigned long data, boundary;
 
-	skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1);
+	skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1);
 	if (unlikely(skb == NULL))
 		return NULL;
 
@@ -851,12 +861,13 @@
 
 /* Allocate just enough space, and verify that the allocated
  * space does not cross a 4KB boundary */
-static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev,
+						   int bytes)
 {
 	struct sk_buff *skb;
 	unsigned long roundup, data, end;
 
-	skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD);
+	skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD);
 	if (unlikely(skb == NULL))
 		return NULL;
 
@@ -872,15 +883,17 @@
 		       "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
 		myri10ge_skb_cross_4k = 1;
 		dev_kfree_skb_any(skb);
-		skb = myri10ge_alloc_small_safe(bytes);
+		skb = myri10ge_alloc_small_safe(dev, bytes);
 	}
 	return skb;
 }
 
 static inline int
-myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
-		int idx)
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp,
+		int bytes, int idx)
 {
+	struct net_device *dev = mgp->dev;
+	struct pci_dev *pdev = mgp->pdev;
 	struct sk_buff *skb;
 	dma_addr_t bus;
 	int len, retval = 0;
@@ -888,11 +901,11 @@
 	bytes += VLAN_HLEN;	/* account for 802.1q vlan tag */
 
 	if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
-		skb = myri10ge_alloc_big(bytes);
+		skb = myri10ge_alloc_big(dev, bytes);
 	else if (myri10ge_skb_cross_4k)
-		skb = myri10ge_alloc_small_safe(bytes);
+		skb = myri10ge_alloc_small_safe(dev, bytes);
 	else
-		skb = myri10ge_alloc_small(bytes);
+		skb = myri10ge_alloc_small(dev, bytes);
 
 	if (unlikely(skb == NULL)) {
 		rx->alloc_fail++;
@@ -955,7 +968,7 @@
 	unmap_len = pci_unmap_len(&rx->info[idx], len);
 
 	/* try to replace the received skb */
-	if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+	if (myri10ge_getbuf(rx, mgp, bytes, idx)) {
 		/* drop the frame -- the old skbuf is re-cycled */
 		mgp->stats.rx_dropped += 1;
 		return 0;
@@ -972,7 +985,6 @@
 	skb_put(skb, len);
 
 	skb->protocol = eth_type_trans(skb, mgp->dev);
-	skb->dev = mgp->dev;
 	if (mgp->csum_flag) {
 		if ((skb->protocol == ntohs(ETH_P_IP)) ||
 		    (skb->protocol == ntohs(ETH_P_IPV6))) {
@@ -1085,13 +1097,19 @@
 		if (mgp->link_state != stats->link_up) {
 			mgp->link_state = stats->link_up;
 			if (mgp->link_state) {
-				printk(KERN_INFO "myri10ge: %s: link up\n",
-				       mgp->dev->name);
+				if (netif_msg_link(mgp))
+					printk(KERN_INFO
+					       "myri10ge: %s: link up\n",
+					       mgp->dev->name);
 				netif_carrier_on(mgp->dev);
+				mgp->link_changes++;
 			} else {
-				printk(KERN_INFO "myri10ge: %s: link down\n",
-				       mgp->dev->name);
+				if (netif_msg_link(mgp))
+					printk(KERN_INFO
+					       "myri10ge: %s: link down\n",
+					       mgp->dev->name);
 				netif_carrier_off(mgp->dev);
+				mgp->link_changes++;
 			}
 		}
 		if (mgp->rdma_tags_available !=
@@ -1293,7 +1311,8 @@
 	"serial_number", "tx_pkt_start", "tx_pkt_done",
 	"tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
 	"wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
-	"link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+	"link_changes", "link_up", "dropped_link_overflow",
+	"dropped_link_error_or_filtered", "dropped_multicast_filtered",
 	"dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
 	"dropped_no_big_buffer"
 };
@@ -1345,16 +1364,31 @@
 	data[i++] = (unsigned int)mgp->stop_queue;
 	data[i++] = (unsigned int)mgp->watchdog_resets;
 	data[i++] = (unsigned int)mgp->tx_linearized;
+	data[i++] = (unsigned int)mgp->link_changes;
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
 	data[i++] =
 	    (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+	data[i++] =
+	    (unsigned int)ntohl(mgp->fw_stats->dropped_multicast_filtered);
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
 	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
 }
 
+static void myri10ge_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	mgp->msg_enable = value;
+}
+
+static u32 myri10ge_get_msglevel(struct net_device *netdev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	return mgp->msg_enable;
+}
+
 static struct ethtool_ops myri10ge_ethtool_ops = {
 	.get_settings = myri10ge_get_settings,
 	.get_drvinfo = myri10ge_get_drvinfo,
@@ -1375,7 +1409,9 @@
 #endif
 	.get_strings = myri10ge_get_strings,
 	.get_stats_count = myri10ge_get_stats_count,
-	.get_ethtool_stats = myri10ge_get_ethtool_stats
+	.get_ethtool_stats = myri10ge_get_ethtool_stats,
+	.set_msglevel = myri10ge_set_msglevel,
+	.get_msglevel = myri10ge_get_msglevel
 };
 
 static int myri10ge_allocate_rings(struct net_device *dev)
@@ -1443,7 +1479,7 @@
 	/* Fill the receive rings */
 
 	for (i = 0; i <= mgp->rx_small.mask; i++) {
-		status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+		status = myri10ge_getbuf(&mgp->rx_small, mgp,
 					 mgp->small_bytes, i);
 		if (status) {
 			printk(KERN_ERR
@@ -1455,8 +1491,7 @@
 
 	for (i = 0; i <= mgp->rx_big.mask; i++) {
 		status =
-		    myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
-				    dev->mtu + ETH_HLEN, i);
+		    myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i);
 		if (status) {
 			printk(KERN_ERR
 			       "myri10ge: %s: alloced only %d big bufs\n",
@@ -1652,9 +1687,11 @@
 	}
 
 	if (mgp->mtrr >= 0) {
-		mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
-		mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
-		mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+		mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4;
+		mgp->rx_small.wc_fifo =
+		    (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL;
+		mgp->rx_big.wc_fifo =
+		    (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_BIG;
 	} else {
 		mgp->tx.wc_fifo = NULL;
 		mgp->rx_small.wc_fifo = NULL;
@@ -1690,7 +1727,21 @@
 
 	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
 	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
-	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+	cmd.data2 = sizeof(struct mcp_irq_data);
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
+	if (status == -ENOSYS) {
+		dma_addr_t bus = mgp->fw_stats_bus;
+		bus += offsetof(struct mcp_irq_data, send_done_count);
+		cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus);
+		cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus);
+		status = myri10ge_send_cmd(mgp,
+					   MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,
+					   &cmd, 0);
+		/* Firmware cannot support multicast without STATS_DMA_V2 */
+		mgp->fw_multicast_support = 0;
+	} else {
+		mgp->fw_multicast_support = 1;
+	}
 	if (status) {
 		printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
 		       dev->name);
@@ -1845,7 +1896,8 @@
 	if (cnt > 0) {
 		/* pad it to 64 bytes.  The src is 64 bytes bigger than it
 		 * needs to be so that we don't overrun it */
-		myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+		myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt),
+				  src, 64);
 		mb();
 	}
 }
@@ -2144,9 +2196,81 @@
 
 static void myri10ge_set_multicast_list(struct net_device *dev)
 {
+	struct myri10ge_cmd cmd;
+	struct myri10ge_priv *mgp;
+	struct dev_mc_list *mc_list;
+	int err;
+
+	mgp = netdev_priv(dev);
 	/* can be called from atomic contexts,
 	 * pass 1 to force atomicity in myri10ge_send_cmd() */
-	myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1);
+	myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1);
+
+	/* This firmware is known to not support multicast */
+	if (!mgp->fw_multicast_support)
+		return;
+
+	/* Disable multicast filtering */
+
+	err = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1);
+	if (err != 0) {
+		printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_ENABLE_ALLMULTI,"
+		       " error status: %d\n", dev->name, err);
+		goto abort;
+	}
+
+	if (dev->flags & IFF_ALLMULTI) {
+		/* request to disable multicast filtering, so quit here */
+		return;
+	}
+
+	/* Flush the filters */
+
+	err = myri10ge_send_cmd(mgp, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
+				&cmd, 1);
+	if (err != 0) {
+		printk(KERN_ERR
+		       "myri10ge: %s: Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS"
+		       ", error status: %d\n", dev->name, err);
+		goto abort;
+	}
+
+	/* Walk the multicast list, and add each address */
+	for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) {
+		memcpy(&cmd.data0, &mc_list->dmi_addr, 4);
+		memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2);
+		cmd.data0 = htonl(cmd.data0);
+		cmd.data1 = htonl(cmd.data1);
+		err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP,
+					&cmd, 1);
+
+		if (err != 0) {
+			printk(KERN_ERR "myri10ge: %s: Failed "
+			       "MXGEFW_JOIN_MULTICAST_GROUP, error status:"
+			       "%d\t", dev->name, err);
+			printk(KERN_ERR "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       ((unsigned char *)&mc_list->dmi_addr)[0],
+			       ((unsigned char *)&mc_list->dmi_addr)[1],
+			       ((unsigned char *)&mc_list->dmi_addr)[2],
+			       ((unsigned char *)&mc_list->dmi_addr)[3],
+			       ((unsigned char *)&mc_list->dmi_addr)[4],
+			       ((unsigned char *)&mc_list->dmi_addr)[5]
+			    );
+			goto abort;
+		}
+	}
+	/* Enable multicast filtering */
+	err = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_ALLMULTI, &cmd, 1);
+	if (err != 0) {
+		printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_DISABLE_ALLMULTI,"
+		       "error status: %d\n", dev->name, err);
+		goto abort;
+	}
+
+	return;
+
+abort:
+	return;
 }
 
 static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
@@ -2293,6 +2417,8 @@
  */
 
 #define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE	0x0132
+#define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7
+#define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa
 
 static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
 {
@@ -2302,15 +2428,34 @@
 	mgp->fw_name = myri10ge_fw_unaligned;
 
 	if (myri10ge_force_firmware == 0) {
+		int link_width, exp_cap;
+		u16 lnk;
+
+		exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP);
+		pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk);
+		link_width = (lnk >> 4) & 0x3f;
+
 		myri10ge_enable_ecrc(mgp);
 
-		/* Check to see if the upstream bridge is known to
-		 * provide aligned completions */
-		if (bridge
-		    /* ServerWorks HT2000/HT1000 */
-		    && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
-		    && bridge->device ==
-		    PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) {
+		/* Check to see if Link is less than 8 or if the
+		 * upstream bridge is known to provide aligned
+		 * completions */
+		if (link_width < 8) {
+			dev_info(&mgp->pdev->dev, "PCIE x%d Link\n",
+				 link_width);
+			mgp->tx.boundary = 4096;
+			mgp->fw_name = myri10ge_fw_aligned;
+		} else if (bridge &&
+			   /* ServerWorks HT2000/HT1000 */
+			   ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
+			     && bridge->device ==
+			     PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE)
+			    /* All Intel E5000 PCIE ports */
+			    || (bridge->vendor == PCI_VENDOR_ID_INTEL
+				&& bridge->device >=
+				PCI_DEVICE_ID_INTEL_E5000_PCIE23
+				&& bridge->device <=
+				PCI_DEVICE_ID_INTEL_E5000_PCIE47))) {
 			dev_info(&mgp->pdev->dev,
 				 "Assuming aligned completions (0x%x:0x%x)\n",
 				 bridge->vendor, bridge->device);
@@ -2429,7 +2574,7 @@
 	}
 
 	myri10ge_reset(mgp);
-	myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+	myri10ge_dummy_rdma(mgp, 1);
 
 	/* Save configuration space to be restored if the
 	 * nic resets due to a parity error */
@@ -2547,7 +2692,8 @@
 
 	mgp = (struct myri10ge_priv *)arg;
 	if (mgp->tx.req != mgp->tx.done &&
-	    mgp->tx.done == mgp->watchdog_tx_done)
+	    mgp->tx.done == mgp->watchdog_tx_done &&
+	    mgp->watchdog_tx_req != mgp->watchdog_tx_done)
 		/* nic seems like it might be stuck.. */
 		schedule_work(&mgp->watchdog_work);
 	else
@@ -2556,6 +2702,7 @@
 			  jiffies + myri10ge_watchdog_timeout * HZ);
 
 	mgp->watchdog_tx_done = mgp->tx.done;
+	mgp->watchdog_tx_req = mgp->tx.req;
 }
 
 static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -2583,6 +2730,7 @@
 	mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
 	mgp->pause = myri10ge_flow_control;
 	mgp->intr_coal_delay = myri10ge_intr_coal_delay;
+	mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT);
 	init_waitqueue_head(&mgp->down_wq);
 
 	if (pci_enable_device(pdev)) {
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
index 0a6cae6..9519ae7 100644
--- a/drivers/net/myri10ge/myri10ge_mcp.h
+++ b/drivers/net/myri10ge/myri10ge_mcp.h
@@ -91,7 +91,19 @@
 
 /* Commands */
 
-#define MXGEFW_CMD_OFFSET 0xf80000
+#define	MXGEFW_BOOT_HANDOFF	0xfc0000
+#define	MXGEFW_BOOT_DUMMY_RDMA	0xfc01c0
+
+#define	MXGEFW_ETH_CMD		0xf80000
+#define	MXGEFW_ETH_SEND_4	0x200000
+#define	MXGEFW_ETH_SEND_1	0x240000
+#define	MXGEFW_ETH_SEND_2	0x280000
+#define	MXGEFW_ETH_SEND_3	0x2c0000
+#define	MXGEFW_ETH_RECV_SMALL	0x300000
+#define	MXGEFW_ETH_RECV_BIG	0x340000
+
+#define	MXGEFW_ETH_SEND(n)		(0x200000 + (((n) & 0x03) * 0x40000))
+#define	MXGEFW_ETH_SEND_OFFSET(n)	(MXGEFW_ETH_SEND(n) - MXGEFW_ETH_SEND_4)
 
 enum myri10ge_mcp_cmd_type {
 	MXGEFW_CMD_NONE = 0,
@@ -154,7 +166,7 @@
 	MXGEFW_CMD_SET_MTU,
 	MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,	/* in microseconds */
 	MXGEFW_CMD_SET_STATS_INTERVAL,	/* in microseconds */
-	MXGEFW_CMD_SET_STATS_DMA,
+	MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,	/* replaced by SET_STATS_DMA_V2 */
 
 	MXGEFW_ENABLE_PROMISC,
 	MXGEFW_DISABLE_PROMISC,
@@ -168,7 +180,26 @@
 	 * data2       = RDMA length (MSH), WDMA length (LSH)
 	 * command return data = repetitions (MSH), 0.5-ms ticks (LSH)
 	 */
-	MXGEFW_DMA_TEST
+	MXGEFW_DMA_TEST,
+
+	MXGEFW_ENABLE_ALLMULTI,
+	MXGEFW_DISABLE_ALLMULTI,
+
+	/* returns MXGEFW_CMD_ERROR_MULTICAST
+	 * if there is no room in the cache
+	 * data0,MSH(data1) = multicast group address */
+	MXGEFW_JOIN_MULTICAST_GROUP,
+	/* returns MXGEFW_CMD_ERROR_MULTICAST
+	 * if the address is not in the cache,
+	 * or is equal to FF-FF-FF-FF-FF-FF
+	 * data0,MSH(data1) = multicast group address */
+	MXGEFW_LEAVE_MULTICAST_GROUP,
+	MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
+
+	MXGEFW_CMD_SET_STATS_DMA_V2,
+	/* data0, data1 = bus addr,
+	 * data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
+	 * adding new stuff to mcp_irq_data without changing the ABI */
 };
 
 enum myri10ge_mcp_cmd_status {
@@ -180,11 +211,17 @@
 	MXGEFW_CMD_ERROR_CLOSED,
 	MXGEFW_CMD_ERROR_HASH_ERROR,
 	MXGEFW_CMD_ERROR_BAD_PORT,
-	MXGEFW_CMD_ERROR_RESOURCES
+	MXGEFW_CMD_ERROR_RESOURCES,
+	MXGEFW_CMD_ERROR_MULTICAST
 };
 
-/* 40 Bytes */
+#define MXGEFW_OLD_IRQ_DATA_LEN 40
+
 struct mcp_irq_data {
+	/* add new counters at the beginning */
+	u32 future_use[5];
+	u32 dropped_multicast_filtered;
+	/* 40 Bytes */
 	u32 send_done_count;
 
 	u32 link_up;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index db0475a..2a46777 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -54,8 +54,8 @@
 #include <asm/uaccess.h>
 
 #define DRV_NAME	"natsemi"
-#define DRV_VERSION	"2.0"
-#define DRV_RELDATE	"June 27, 2006"
+#define DRV_VERSION	"2.1"
+#define DRV_RELDATE	"Sept 11, 2006"
 
 #define RX_OFFSET	2
 
@@ -2387,9 +2387,6 @@
 	u32 rx_mode;
 
 	if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-			dev->name);
 		rx_mode = RxFilterEnable | AcceptBroadcast
 			| AcceptAllMulticast | AcceptAllPhys | AcceptMyPhys;
 	} else if ((dev->mc_count > multicast_filter_limit)
@@ -3246,7 +3243,7 @@
 	printk(version);
 #endif
 
-	return pci_module_init (&natsemi_driver);
+	return pci_register_driver(&natsemi_driver);
 }
 
 static void __exit natsemi_exit_mod (void)
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 34bdba9..654b477 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -702,7 +702,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init (&ne2k_driver);
+	return pci_register_driver(&ne2k_driver);
 }
 
 
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index b1311ae..30ed9a5 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -17,7 +17,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index fa854c8..4d52ecf 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -1323,7 +1323,7 @@
 MODULE_PARM_DESC(memstart, "NI5210 memory base address,required");
 MODULE_PARM_DESC(memend, "NI5210 memory end address,required");
 
-int init_module(void)
+int __init init_module(void)
 {
 	if(io <= 0x0 || !memend || !memstart || irq < 2) {
 		printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n");
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index bb42ff2..810cc57 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1253,7 +1253,7 @@
 MODULE_PARM_DESC(io, "ni6510 I/O base address");
 MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
 
-int init_module(void)
+int __init init_module(void)
 {
  	dev_ni65 = ni65_probe(-1);
 	return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 0e76859..0dedd34 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -2178,7 +2178,7 @@
 static int __init ns83820_init(void)
 {
 	printk(KERN_INFO "ns83820.c: National Semiconductor DP83820 10/100/1000 driver.\n");
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit ns83820_exit(void)
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index e0e2939..dea843a 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -98,7 +98,7 @@
 #include <linux/crc32.h>
 #include <asm/io.h>
 
-#define NETDRV_VERSION		"1.0.0"
+#define NETDRV_VERSION		"1.0.1"
 #define MODNAME			"netdrv"
 #define NETDRV_DRIVER_LOAD_MSG	"MyVendor Fast Ethernet driver " NETDRV_VERSION " loaded"
 #define PFX			MODNAME ": "
@@ -1853,9 +1853,6 @@
 
 	/* Note: do not reorder, GCC is clever about common statements. */
 	if (dev->flags & IFF_PROMISC) {
-		/* Unconditionally log net taps. */
-		printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-			dev->name);
 		rx_mode =
 		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 		    AcceptAllPhys;
@@ -1963,7 +1960,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init (&netdrv_pci_driver);
+	return pci_register_driver(&netdrv_pci_driver);
 }
 
 
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 297e9f8..c54f6a7 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -771,6 +771,7 @@
 	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
 	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
 	PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
+	PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), 
 	PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
 	PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
 	PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
@@ -786,8 +787,6 @@
 	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
 	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
 	PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef),
-	/* this is not specific enough */
-	/* PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), */
 	PCMCIA_DEVICE_NULL,
 };
 MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index ea93b8f1..74211af 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -29,7 +29,7 @@
 ======================================================================*/
 
 #define DRV_NAME	"fmvj18x_cs"
-#define DRV_VERSION	"2.8"
+#define DRV_VERSION	"2.9"
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -1193,8 +1193,6 @@
 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
 
     if (dev->flags & IFF_PROMISC) {
-	/* Unconditionally log net taps. */
-	printk("%s: Promiscuous mode enabled.\n", dev->name);
 	memset(mc_filter, 0xff, sizeof(mc_filter));
 	outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
     } else if (dev->mc_count > MC_FILTERBREAK
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 0ecebfc..cc0dcc9 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -654,11 +654,8 @@
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
     if (info->flags & (IS_DL10019|IS_DL10022)) {
-	u_char id = inb(dev->base_addr + 0x1a);
 	dev->do_ioctl = &ei_ioctl;
 	mii_phy_probe(dev);
-	if ((id == 0x30) && !info->pna_phy && (info->eth_phy == 4))
-	    info->eth_phy = 0;
     }
 
     link->dev_node = &info->node;
@@ -821,15 +818,6 @@
     }
 }
 
-static void mdio_reset(kio_addr_t addr, int phy_id)
-{
-    outb_p(0x08, addr);
-    outb_p(0x0c, addr);
-    outb_p(0x08, addr);
-    outb_p(0x0c, addr);
-    outb_p(0x00, addr);
-}
-
 /*======================================================================
 
     EEPROM access routines for DL10019 and DL10022 based cards
@@ -942,7 +930,8 @@
     }
     if (info->flags & IS_DL10022) {
 	if (info->flags & HAS_MII) {
-	    mdio_reset(nic_base + DLINK_GPIO, info->eth_phy);
+	    /* Advertise 100F, 100H, 10F, 10H */
+	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
 	    /* Restart MII autonegotiation */
 	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
 	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index a73d545..3fb369f 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -80,14 +80,14 @@
 #ifdef PCMCIA_DEBUG
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 static const char *version =
-"smc91c92_cs.c 0.09 1996/8/4 Donald Becker, becker@scyld.com.\n";
+"smc91c92_cs.c 1.123 2006/11/09 Donald Becker, becker@scyld.com.\n";
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 #else
 #define DEBUG(n, args...)
 #endif
 
 #define DRV_NAME	"smc91c92_cs"
-#define DRV_VERSION	"1.122"
+#define DRV_VERSION	"1.123"
 
 /*====================================================================*/
 
@@ -1780,7 +1780,6 @@
     u_short rx_cfg_setting;
 
     if (dev->flags & IFF_PROMISC) {
-	printk(KERN_NOTICE "%s: setting Rx mode to promiscuous.\n", dev->name);
 	rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti;
     } else if (dev->flags & IFF_ALLMULTI)
 	rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 9bae77c..4122bb4 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -345,6 +345,7 @@
     void __iomem *dingo_ccr; /* only used for CEM56 cards */
     unsigned last_ptr_value; /* last packets transmitted value */
     const char *manf_str;
+    struct work_struct tx_timeout_task;
 } local_info_t;
 
 /****************
@@ -352,6 +353,7 @@
  */
 static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void do_tx_timeout(struct net_device *dev);
+static void xirc2ps_tx_timeout_task(void *data);
 static struct net_device_stats *do_get_stats(struct net_device *dev);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
@@ -589,6 +591,7 @@
 #ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = do_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+    INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev);
 #endif
 
     return xirc2ps_config(link);
@@ -1341,17 +1344,24 @@
 /*====================================================================*/
 
 static void
-do_tx_timeout(struct net_device *dev)
+xirc2ps_tx_timeout_task(void *data)
 {
-    local_info_t *lp = netdev_priv(dev);
-    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
-    lp->stats.tx_errors++;
+    struct net_device *dev = data;
     /* reset the card */
     do_reset(dev,1);
     dev->trans_start = jiffies;
     netif_wake_queue(dev);
 }
 
+static void
+do_tx_timeout(struct net_device *dev)
+{
+    local_info_t *lp = netdev_priv(dev);
+    lp->stats.tx_errors++;
+    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);
+    schedule_work(&lp->tx_timeout_task);
+}
+
 static int
 do_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 4daafe3..5e26fe8 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -202,6 +202,8 @@
 #define CSR15		15
 #define PCNET32_MC_FILTER	8
 
+#define PCNET32_79C970A	0x2621
+
 /* The PCNET32 Rx and Tx ring descriptors. */
 struct pcnet32_rx_head {
 	u32	base;
@@ -289,6 +291,7 @@
 
 	/* each bit indicates an available PHY */
 	u32			phymask;
+	unsigned short		chip_version;	/* which variant this is */
 };
 
 static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
@@ -724,9 +727,11 @@
 	spin_lock_irqsave(&lp->lock, flags);
 	if (lp->mii) {
 		r = mii_link_ok(&lp->mii_if);
-	} else {
+	} else if (lp->chip_version >= PCNET32_79C970A) {
 		ulong ioaddr = dev->base_addr;	/* card base I/O address */
 		r = (lp->a.read_bcr(ioaddr, 4) != 0xc0);
+	} else {	/* can not detect link on really old chips */
+		r = 1;
 	}
 	spin_unlock_irqrestore(&lp->lock, flags);
 
@@ -1091,6 +1096,10 @@
 	ulong ioaddr = dev->base_addr;
 	int ticks;
 
+	/* really old chips have to be stopped. */
+	if (lp->chip_version < PCNET32_79C970A)
+		return 0;
+
 	/* set SUSPEND (SPND) - CSR5 bit 0 */
 	csr5 = a->read_csr(ioaddr, CSR5);
 	a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND);
@@ -1529,6 +1538,7 @@
 	lp->mii_if.reg_num_mask = 0x1f;
 	lp->dxsuflo = dxsuflo;
 	lp->mii = mii;
+	lp->chip_version = chip_version;
 	lp->msg_enable = pcnet32_debug;
 	if ((cards_found >= MAX_UNITS)
 	    || (options[cards_found] > sizeof(options_mapping)))
@@ -1839,10 +1849,7 @@
 				val |= 2;
 		} else if (lp->options & PCNET32_PORT_ASEL) {
 			/* workaround of xSeries250, turn on for 79C975 only */
-			i = ((lp->a.read_csr(ioaddr, 88) |
-			      (lp->a.
-			       read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff;
-			if (i == 0x2627)
+			if (lp->chip_version == 0x2627)
 				val |= 3;
 		}
 		lp->a.write_bcr(ioaddr, 9, val);
@@ -1986,9 +1993,11 @@
 
 	netif_start_queue(dev);
 
-	/* Print the link status and start the watchdog */
-	pcnet32_check_media(dev, 1);
-	mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+	if (lp->chip_version >= PCNET32_79C970A) {
+		/* Print the link status and start the watchdog */
+		pcnet32_check_media(dev, 1);
+		mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+	}
 
 	i = 0;
 	while (i++ < 100)
@@ -2969,7 +2978,7 @@
 		tx_start = tx_start_pt;
 
 	/* find the PCI devices */
-	if (!pci_module_init(&pcnet32_driver))
+	if (!pci_register_driver(&pcnet32_driver))
 		pcnet32_have_pci = 1;
 
 	/* should we find any remaining VLbus devices ? */
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 2ba6d3a..b79ec0d 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,5 +56,22 @@
 	---help---
 	  Currently supports the LAN83C185 PHY
 
+config FIXED_PHY
+	tristate "Drivers for PHY emulation on fixed speed/link"
+	depends on PHYLIB
+	---help---
+	  Adds the driver to PHY layer to cover the boards that do not have any PHY bound,
+	  but with the ability to manipulate with speed/link in software. The relavant MII
+	  speed/duplex parameters could be effectively handled in user-specified  fuction.
+	  Currently tested with mpc866ads.
+
+config FIXED_MII_10_FDX
+	bool "Emulation for 10M Fdx fixed PHY behavior"
+	depends on FIXED_PHY
+
+config FIXED_MII_100_FDX
+	bool "Emulation for 100M Fdx fixed PHY behavior"
+	depends on FIXED_PHY
+
 endmenu
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index a00e619..320f832 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -10,3 +10,4 @@
 obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
 obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
+obj-$(CONFIG_FIXED_PHY)		+= fixed.o
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
new file mode 100644
index 0000000..341036d
--- /dev/null
+++ b/drivers/net/phy/fixed.c
@@ -0,0 +1,358 @@
+/*
+ * drivers/net/phy/fixed.c
+ *
+ * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode.
+ *
+ * Author: Vitaly Bordug
+ *
+ * Copyright (c) 2006 MontaVista Software, Inc.
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#define MII_REGS_NUM	7
+
+/*
+    The idea is to emulate normal phy behavior by responding with
+    pre-defined values to mii BMCR read, so that read_status hook could
+    take all the needed info.
+*/
+
+struct fixed_phy_status {
+	u8 	link;
+	u16	speed;
+	u8 	duplex;
+};
+
+/*-----------------------------------------------------------------------------
+ *  Private information hoder for mii_bus
+ *-----------------------------------------------------------------------------*/
+struct fixed_info {
+	u16 *regs;
+	u8 regs_num;
+	struct fixed_phy_status phy_status;
+	struct phy_device *phydev; /* pointer to the container */
+	/* link & speed cb */
+	int(*link_update)(struct net_device*, struct fixed_phy_status*);
+
+};
+
+/*-----------------------------------------------------------------------------
+ *  If something weird is required to be done with link/speed,
+ * network driver is able to assign a function to implement this.
+ * May be useful for PHY's that need to be software-driven.
+ *-----------------------------------------------------------------------------*/
+int fixed_mdio_set_link_update(struct phy_device* phydev,
+		int(*link_update)(struct net_device*, struct fixed_phy_status*))
+{
+	struct fixed_info *fixed;
+
+	if(link_update == NULL)
+		return -EINVAL;
+
+	if(phydev) {
+		if(phydev->bus)	{
+			fixed = phydev->bus->priv;
+			fixed->link_update = link_update;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(fixed_mdio_set_link_update);
+
+/*-----------------------------------------------------------------------------
+ *  This is used for updating internal mii regs from the status
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_update_regs(struct fixed_info *fixed)
+{
+	u16 *regs = fixed->regs;
+	u16 bmsr = 0;
+	u16 bmcr = 0;
+
+	if(!regs) {
+		printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	if(fixed->phy_status.link)
+		bmsr |= BMSR_LSTATUS;
+
+	if(fixed->phy_status.duplex) {
+		bmcr |= BMCR_FULLDPLX;
+
+		switch ( fixed->phy_status.speed ) {
+		case 100:
+			bmsr |= BMSR_100FULL;
+			bmcr |= BMCR_SPEED100;
+		break;
+
+		case 10:
+			bmsr |= BMSR_10FULL;
+		break;
+		}
+	} else {
+		switch ( fixed->phy_status.speed ) {
+		case 100:
+			bmsr |= BMSR_100HALF;
+			bmcr |= BMCR_SPEED100;
+		break;
+
+		case 10:
+			bmsr |= BMSR_100HALF;
+		break;
+		}
+	}
+
+	regs[MII_BMCR] =  bmcr;
+	regs[MII_BMSR] =  bmsr | 0x800; /*we are always capable of 10 hdx*/
+
+	return 0;
+}
+
+static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
+{
+	struct fixed_info *fixed = bus->priv;
+
+	/* if user has registered link update callback, use it */
+	if(fixed->phydev)
+		if(fixed->phydev->attached_dev) {
+			if(fixed->link_update) {
+				fixed->link_update(fixed->phydev->attached_dev,
+						&fixed->phy_status);
+				fixed_mdio_update_regs(fixed);
+			}
+	}
+
+	if ((unsigned int)location >= fixed->regs_num)
+		return -1;
+	return fixed->regs[location];
+}
+
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+{
+	/* do nothing for now*/
+	return 0;
+}
+
+static int fixed_mii_reset(struct mii_bus *bus)
+{
+	/*nothing here - no way/need to reset it*/
+	return 0;
+}
+
+static int fixed_config_aneg(struct phy_device *phydev)
+{
+	/* :TODO:03/13/2006 09:45:37 PM::
+	 The full autoneg funcionality can be emulated,
+	 but no need to have anything here for now
+	 */
+	return 0;
+}
+
+/*-----------------------------------------------------------------------------
+ * the manual bind will do the magic - with phy_id_mask == 0
+ * match will never return true...
+ *-----------------------------------------------------------------------------*/
+static struct phy_driver fixed_mdio_driver = {
+	.name		= "Fixed PHY",
+	.features	= PHY_BASIC_FEATURES,
+	.config_aneg	= fixed_config_aneg,
+	.read_status	= genphy_read_status,
+	.driver 	= { .owner = THIS_MODULE,},
+};
+
+/*-----------------------------------------------------------------------------
+ *  This func is used to create all the necessary stuff, bind
+ * the fixed phy driver and register all it on the mdio_bus_type.
+ * speed is either 10 or 100, duplex is boolean.
+ * number is used to create multiple fixed PHYs, so that several devices can
+ * utilize them simultaneously.
+ *-----------------------------------------------------------------------------*/
+static int fixed_mdio_register_device(int number, int speed, int duplex)
+{
+	struct mii_bus *new_bus;
+	struct fixed_info *fixed;
+	struct phy_device *phydev;
+	int err = 0;
+
+	struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+
+	if (NULL == dev)
+		return -ENOMEM;
+
+	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
+
+	if (NULL == new_bus) {
+		kfree(dev);
+		return -ENOMEM;
+	}
+	fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
+
+	if (NULL == fixed) {
+		kfree(dev);
+		kfree(new_bus);
+		return -ENOMEM;
+	}
+
+	fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
+	fixed->regs_num = MII_REGS_NUM;
+	fixed->phy_status.speed = speed;
+	fixed->phy_status.duplex = duplex;
+	fixed->phy_status.link = 1;
+
+	new_bus->name = "Fixed MII Bus",
+	new_bus->read = &fixed_mii_read,
+	new_bus->write = &fixed_mii_write,
+	new_bus->reset = &fixed_mii_reset,
+
+	/*set up workspace*/
+	fixed_mdio_update_regs(fixed);
+	new_bus->priv = fixed;
+
+	new_bus->dev = dev;
+	dev_set_drvdata(dev, new_bus);
+
+	/* create phy_device and register it on the mdio bus */
+	phydev = phy_device_create(new_bus, 0, 0);
+
+	/*
+	 Put the phydev pointer into the fixed pack so that bus read/write code could
+	 be able to access for instance attached netdev. Well it doesn't have to do
+	 so, only in case of utilizing user-specified link-update...
+	 */
+	fixed->phydev = phydev;
+
+	if(NULL == phydev) {
+		err = -ENOMEM;
+		goto device_create_fail;
+	}
+
+	phydev->irq = -1;
+	phydev->dev.bus = &mdio_bus_type;
+
+	if(number)
+		snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+				"fixed_%d@%d:%d", number, speed, duplex);
+	else
+		snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+				"fixed@%d:%d", speed, duplex);
+	phydev->bus = new_bus;
+
+	err = device_register(&phydev->dev);
+	if(err) {
+		printk(KERN_ERR "Phy %s failed to register\n",
+				phydev->dev.bus_id);
+		goto bus_register_fail;
+	}
+
+	/*
+	   the mdio bus has phy_id match... In order not to do it
+	   artificially, we are binding the driver here by hand;
+	   it will be the same for all the fixed phys anyway.
+	 */
+	down_write(&phydev->dev.bus->subsys.rwsem);
+
+	phydev->dev.driver = &fixed_mdio_driver.driver;
+
+	err = phydev->dev.driver->probe(&phydev->dev);
+	if(err < 0) {
+		printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
+		up_write(&phydev->dev.bus->subsys.rwsem);
+		goto probe_fail;
+	}
+
+	device_bind_driver(&phydev->dev);
+	up_write(&phydev->dev.bus->subsys.rwsem);
+
+	return 0;
+
+probe_fail:
+	device_unregister(&phydev->dev);
+bus_register_fail:
+	kfree(phydev);
+device_create_fail:
+	kfree(dev);
+	kfree(new_bus);
+	kfree(fixed);
+
+	return err;
+}
+
+
+MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
+MODULE_AUTHOR("Vitaly Bordug");
+MODULE_LICENSE("GPL");
+
+static int __init fixed_init(void)
+{
+	int ret;
+	int duplex = 0;
+
+	/* register on the bus... Not expected to be matched with anything there... */
+	phy_driver_register(&fixed_mdio_driver);
+
+	/* So let the fun begin...
+	   We will create several mdio devices here, and will bound the upper
+	   driver to them.
+
+	   Then the external software can lookup the phy bus by searching
+	   fixed@speed:duplex, e.g. fixed@100:1, to be connected to the
+	   virtual 100M Fdx phy.
+
+	   In case several virtual PHYs required, the bus_id will be in form
+	   fixed_<num>@<speed>:<duplex>, which make it able even to define
+	   driver-specific link control callback, if for instance PHY is completely
+	   SW-driven.
+
+	*/
+
+#ifdef CONFIG_FIXED_MII_DUPLEX
+	duplex = 1;
+#endif
+
+#ifdef CONFIG_FIXED_MII_100_FDX
+	fixed_mdio_register_device(0, 100, 1);
+#endif
+
+#ifdef CONFIX_FIXED_MII_10_FDX
+	fixed_mdio_register_device(0, 10, 1);
+#endif
+	return 0;
+}
+
+static void __exit fixed_exit(void)
+{
+	phy_driver_unregister(&fixed_mdio_driver);
+	/* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+}
+
+module_init(fixed_init);
+module_exit(fixed_exit);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 1dde390..cf6660c 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -159,6 +159,7 @@
 	.suspend	= mdio_bus_suspend,
 	.resume		= mdio_bus_resume,
 };
+EXPORT_SYMBOL(mdio_bus_type);
 
 int __init mdio_bus_init(void)
 {
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 7d5c223..f5aad77 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -419,9 +419,8 @@
 
 /* phy_stop_machine
  *
- * description: Stops the state machine timer, sets the state to
- *   UP (unless it wasn't up yet), and then frees the interrupt,
- *   if it is in use. This function must be called BEFORE
+ * description: Stops the state machine timer, sets the state to UP
+ *   (unless it wasn't up yet). This function must be called BEFORE
  *   phy_detach.
  */
 void phy_stop_machine(struct phy_device *phydev)
@@ -433,9 +432,6 @@
 		phydev->state = PHY_UP;
 	spin_unlock(&phydev->lock);
 
-	if (phydev->irq != PHY_POLL)
-		phy_stop_interrupts(phydev);
-
 	phydev->adjust_state = NULL;
 }
 
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 1bc1e03..2d1ecfd 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -45,6 +45,35 @@
 extern int mdio_bus_init(void);
 extern void mdio_bus_exit(void);
 
+struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+{
+	struct phy_device *dev;
+	/* We allocate the device, and initialize the
+	 * default values */
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+
+	if (NULL == dev)
+		return (struct phy_device*) PTR_ERR((void*)-ENOMEM);
+
+	dev->speed = 0;
+	dev->duplex = -1;
+	dev->pause = dev->asym_pause = 0;
+	dev->link = 1;
+
+	dev->autoneg = AUTONEG_ENABLE;
+
+	dev->addr = addr;
+	dev->phy_id = phy_id;
+	dev->bus = bus;
+
+	dev->state = PHY_DOWN;
+
+	spin_lock_init(&dev->lock);
+
+	return dev;
+}
+EXPORT_SYMBOL(phy_device_create);
+
 /* get_phy_device
  *
  * description: Reads the ID registers of the PHY at addr on the
@@ -78,27 +107,7 @@
 	if (0xffffffff == phy_id)
 		return NULL;
 
-	/* Otherwise, we allocate the device, and initialize the
-	 * default values */
-	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
-
-	if (NULL == dev)
-		return ERR_PTR(-ENOMEM);
-
-	dev->speed = 0;
-	dev->duplex = -1;
-	dev->pause = dev->asym_pause = 0;
-	dev->link = 1;
-
-	dev->autoneg = AUTONEG_ENABLE;
-
-	dev->addr = addr;
-	dev->phy_id = phy_id;
-	dev->bus = bus;
-
-	dev->state = PHY_DOWN;
-
-	spin_lock_init(&dev->lock);
+	dev = phy_device_create(bus, addr, phy_id);
 
 	return dev;
 }
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 25e31fb..b1d8ed4 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mii.h>
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index ffd215d..792716b 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mii.h>
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 0ec6e9d..c872f7c 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -192,7 +192,7 @@
 	void *ptr[CARDMAP_WIDTH];
 };
 static void *cardmap_get(struct cardmap *map, unsigned int nr);
-static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
+static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
 static unsigned int cardmap_find_first_free(struct cardmap *map);
 static void cardmap_destroy(struct cardmap **map);
 
@@ -1995,10 +1995,9 @@
 {
 	struct channel *pch;
 
-	pch = kmalloc(sizeof(struct channel), GFP_KERNEL);
+	pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
 	if (pch == 0)
 		return -ENOMEM;
-	memset(pch, 0, sizeof(struct channel));
 	pch->ppp = NULL;
 	pch->chan = chan;
 	chan->ppp = pch;
@@ -2408,13 +2407,12 @@
 	int ret = -ENOMEM;
 	int i;
 
-	ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL);
+	ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL);
 	if (!ppp)
 		goto out;
 	dev = alloc_netdev(0, "", ppp_setup);
 	if (!dev)
 		goto out1;
-	memset(ppp, 0, sizeof(struct ppp));
 
 	ppp->mru = PPP_MRU;
 	init_ppp_file(&ppp->file, INTERFACE);
@@ -2454,11 +2452,16 @@
 	}
 
 	atomic_inc(&ppp_unit_count);
-	cardmap_set(&all_ppp_units, unit, ppp);
+	ret = cardmap_set(&all_ppp_units, unit, ppp);
+	if (ret != 0)
+		goto out3;
+
 	mutex_unlock(&all_ppp_mutex);
 	*retp = 0;
 	return ppp;
 
+out3:
+	atomic_dec(&ppp_unit_count);
 out2:
 	mutex_unlock(&all_ppp_mutex);
 	free_netdev(dev);
@@ -2695,7 +2698,7 @@
 	return NULL;
 }
 
-static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
+static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
 {
 	struct cardmap *p;
 	int i;
@@ -2704,8 +2707,9 @@
 	if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
 		do {
 			/* need a new top level */
-			struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
-			memset(np, 0, sizeof(*np));
+			struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
+			if (!np)
+				goto enomem;
 			np->ptr[0] = p;
 			if (p != NULL) {
 				np->shift = p->shift + CARDMAP_ORDER;
@@ -2719,8 +2723,9 @@
 	while (p->shift > 0) {
 		i = (nr >> p->shift) & CARDMAP_MASK;
 		if (p->ptr[i] == NULL) {
-			struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
-			memset(np, 0, sizeof(*np));
+			struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
+			if (!np)
+				goto enomem;
 			np->shift = p->shift - CARDMAP_ORDER;
 			np->parent = p;
 			p->ptr[i] = np;
@@ -2735,6 +2740,9 @@
 		set_bit(i, &p->inuse);
 	else
 		clear_bit(i, &p->inuse);
+	return 0;
+ enomem:
+	return -ENOMEM;
 }
 
 static unsigned int cardmap_find_first_free(struct cardmap *map)
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
new file mode 100644
index 0000000..c729aee
--- /dev/null
+++ b/drivers/net/qla3xxx.c
@@ -0,0 +1,3537 @@
+/*
+ * QLogic QLA3xxx NIC HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla3xxx for copyright and licensing details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/dmapool.h>
+#include <linux/mempool.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include "qla3xxx.h"
+
+#define DRV_NAME  	"qla3xxx"
+#define DRV_STRING 	"QLogic ISP3XXX Network Driver"
+#define DRV_VERSION	"v2.02.00-k36"
+#define PFX		DRV_NAME " "
+
+static const char ql3xxx_driver_name[] = DRV_NAME;
+static const char ql3xxx_driver_version[] = DRV_VERSION;
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic ISP3XXX Network Driver " DRV_VERSION " ");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static const u32 default_msg
+    = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
+    | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
+
+static int debug = -1;		/* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static int msi;
+module_param(msi, int, 0);
+MODULE_PARM_DESC(msi, "Turn on Message Signaled Interrupts.");
+
+static struct pci_device_id ql3xxx_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QL3022_DEVICE_ID)},
+	/* required last entry */
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, ql3xxx_pci_tbl);
+
+/*
+ * Caller must take hw_lock.
+ */
+static int ql_sem_spinlock(struct ql3_adapter *qdev,
+			    u32 sem_mask, u32 sem_bits)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	u32 value;
+	unsigned int seconds = 3;
+
+	do {
+		writel((sem_mask | sem_bits),
+		       &port_regs->CommonRegs.semaphoreReg);
+		value = readl(&port_regs->CommonRegs.semaphoreReg);
+		if ((value & (sem_mask >> 16)) == sem_bits)
+			return 0;
+		ssleep(1);
+	} while(--seconds);
+	return -1;
+}
+
+static void ql_sem_unlock(struct ql3_adapter *qdev, u32 sem_mask)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	writel(sem_mask, &port_regs->CommonRegs.semaphoreReg);
+	readl(&port_regs->CommonRegs.semaphoreReg);
+}
+
+static int ql_sem_lock(struct ql3_adapter *qdev, u32 sem_mask, u32 sem_bits)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	u32 value;
+
+	writel((sem_mask | sem_bits), &port_regs->CommonRegs.semaphoreReg);
+	value = readl(&port_regs->CommonRegs.semaphoreReg);
+	return ((value & (sem_mask >> 16)) == sem_bits);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_wait_for_drvr_lock(struct ql3_adapter *qdev)
+{
+	int i = 0;
+
+	while (1) {
+		if (!ql_sem_lock(qdev,
+				 QL_DRVR_SEM_MASK,
+				 (QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index)
+				  * 2) << 1)) {
+			if (i < 10) {
+				ssleep(1);
+				i++;
+			} else {
+				printk(KERN_ERR PFX "%s: Timed out waiting for "
+				       "driver lock...\n",
+				       qdev->ndev->name);
+				return 0;
+			}
+		} else {
+			printk(KERN_DEBUG PFX
+			       "%s: driver lock acquired.\n",
+			       qdev->ndev->name);
+			return 1;
+		}
+	}
+}
+
+static void ql_set_register_page(struct ql3_adapter *qdev, u32 page)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+	writel(((ISP_CONTROL_NP_MASK << 16) | page),
+			&port_regs->CommonRegs.ispControlStatus);
+	readl(&port_regs->CommonRegs.ispControlStatus);
+	qdev->current_page = page;
+}
+
+static u32 ql_read_common_reg_l(struct ql3_adapter *qdev,
+			      u32 __iomem * reg)
+{
+	u32 value;
+	unsigned long hw_flags;
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	value = readl(reg);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+	return value;
+}
+
+static u32 ql_read_common_reg(struct ql3_adapter *qdev,
+			      u32 __iomem * reg)
+{
+	return readl(reg);
+}
+
+static u32 ql_read_page0_reg_l(struct ql3_adapter *qdev, u32 __iomem *reg)
+{
+	u32 value;
+	unsigned long hw_flags;
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+	if (qdev->current_page != 0)
+		ql_set_register_page(qdev,0);
+	value = readl(reg);
+
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return value;
+}
+
+static u32 ql_read_page0_reg(struct ql3_adapter *qdev, u32 __iomem *reg)
+{
+	if (qdev->current_page != 0)
+		ql_set_register_page(qdev,0);
+	return readl(reg);
+}
+
+static void ql_write_common_reg_l(struct ql3_adapter *qdev,
+				u32 * reg, u32 value)
+{
+	unsigned long hw_flags;
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	writel(value, (u32 *) reg);
+	readl(reg);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return;
+}
+
+static void ql_write_common_reg(struct ql3_adapter *qdev,
+				u32 * reg, u32 value)
+{
+	writel(value, (u32 *) reg);
+	readl(reg);
+	return;
+}
+
+static void ql_write_page0_reg(struct ql3_adapter *qdev,
+			       u32 * reg, u32 value)
+{
+	if (qdev->current_page != 0)
+		ql_set_register_page(qdev,0);
+	writel(value, (u32 *) reg);
+	readl(reg);
+	return;
+}
+
+/*
+ * Caller holds hw_lock. Only called during init.
+ */
+static void ql_write_page1_reg(struct ql3_adapter *qdev,
+			       u32 * reg, u32 value)
+{
+	if (qdev->current_page != 1)
+		ql_set_register_page(qdev,1);
+	writel(value, (u32 *) reg);
+	readl(reg);
+	return;
+}
+
+/*
+ * Caller holds hw_lock. Only called during init.
+ */
+static void ql_write_page2_reg(struct ql3_adapter *qdev,
+			       u32 * reg, u32 value)
+{
+	if (qdev->current_page != 2)
+		ql_set_register_page(qdev,2);
+	writel(value, (u32 *) reg);
+	readl(reg);
+	return;
+}
+
+static void ql_disable_interrupts(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+	ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg,
+			    (ISP_IMR_ENABLE_INT << 16));
+
+}
+
+static void ql_enable_interrupts(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+	ql_write_common_reg_l(qdev, &port_regs->CommonRegs.ispInterruptMaskReg,
+			    ((0xff << 16) | ISP_IMR_ENABLE_INT));
+
+}
+
+static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
+					    struct ql_rcv_buf_cb *lrg_buf_cb)
+{
+	u64 map;
+	lrg_buf_cb->next = NULL;
+
+	if (qdev->lrg_buf_free_tail == NULL) {	/* The list is empty  */
+		qdev->lrg_buf_free_head = qdev->lrg_buf_free_tail = lrg_buf_cb;
+	} else {
+		qdev->lrg_buf_free_tail->next = lrg_buf_cb;
+		qdev->lrg_buf_free_tail = lrg_buf_cb;
+	}
+
+	if (!lrg_buf_cb->skb) {
+		lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+		if (unlikely(!lrg_buf_cb->skb)) {
+			printk(KERN_ERR PFX "%s: failed dev_alloc_skb().\n",
+			       qdev->ndev->name);
+			qdev->lrg_buf_skb_check++;
+		} else {
+			/*
+			 * We save some space to copy the ethhdr from first
+			 * buffer
+			 */
+			skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+			map = pci_map_single(qdev->pdev,
+					     lrg_buf_cb->skb->data,
+					     qdev->lrg_buffer_len -
+					     QL_HEADER_SPACE,
+					     PCI_DMA_FROMDEVICE);
+			lrg_buf_cb->buf_phy_addr_low =
+			    cpu_to_le32(LS_64BITS(map));
+			lrg_buf_cb->buf_phy_addr_high =
+			    cpu_to_le32(MS_64BITS(map));
+			pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+			pci_unmap_len_set(lrg_buf_cb, maplen,
+					  qdev->lrg_buffer_len -
+					  QL_HEADER_SPACE);
+		}
+	}
+
+	qdev->lrg_buf_free_count++;
+}
+
+static struct ql_rcv_buf_cb *ql_get_from_lrg_buf_free_list(struct ql3_adapter
+							   *qdev)
+{
+	struct ql_rcv_buf_cb *lrg_buf_cb;
+
+	if ((lrg_buf_cb = qdev->lrg_buf_free_head) != NULL) {
+		if ((qdev->lrg_buf_free_head = lrg_buf_cb->next) == NULL)
+			qdev->lrg_buf_free_tail = NULL;
+		qdev->lrg_buf_free_count--;
+	}
+
+	return lrg_buf_cb;
+}
+
+static u32 addrBits = EEPROM_NO_ADDR_BITS;
+static u32 dataBits = EEPROM_NO_DATA_BITS;
+
+static void fm93c56a_deselect(struct ql3_adapter *qdev);
+static void eeprom_readword(struct ql3_adapter *qdev, u32 eepromAddr,
+			    unsigned short *value);
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_select(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ((ISP_NVRAM_MASK << 16) | qdev->eeprom_cmd_data));
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
+{
+	int i;
+	u32 mask;
+	u32 dataBit;
+	u32 previousBit;
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	/* Clock in a zero, then do the start bit */
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+			    AUBURN_EEPROM_DO_1);
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ISP_NVRAM_MASK | qdev->
+			    eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+			    AUBURN_EEPROM_CLK_RISE);
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ISP_NVRAM_MASK | qdev->
+			    eeprom_cmd_data | AUBURN_EEPROM_DO_1 |
+			    AUBURN_EEPROM_CLK_FALL);
+
+	mask = 1 << (FM93C56A_CMD_BITS - 1);
+	/* Force the previous data bit to be different */
+	previousBit = 0xffff;
+	for (i = 0; i < FM93C56A_CMD_BITS; i++) {
+		dataBit =
+		    (cmd & mask) ? AUBURN_EEPROM_DO_1 : AUBURN_EEPROM_DO_0;
+		if (previousBit != dataBit) {
+			/*
+			 * If the bit changed, then change the DO state to
+			 * match
+			 */
+			ql_write_common_reg(qdev,
+					    &port_regs->CommonRegs.
+					    serialPortInterfaceReg,
+					    ISP_NVRAM_MASK | qdev->
+					    eeprom_cmd_data | dataBit);
+			previousBit = dataBit;
+		}
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->
+				    eeprom_cmd_data | dataBit |
+				    AUBURN_EEPROM_CLK_RISE);
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->
+				    eeprom_cmd_data | dataBit |
+				    AUBURN_EEPROM_CLK_FALL);
+		cmd = cmd << 1;
+	}
+
+	mask = 1 << (addrBits - 1);
+	/* Force the previous data bit to be different */
+	previousBit = 0xffff;
+	for (i = 0; i < addrBits; i++) {
+		dataBit =
+		    (eepromAddr & mask) ? AUBURN_EEPROM_DO_1 :
+		    AUBURN_EEPROM_DO_0;
+		if (previousBit != dataBit) {
+			/*
+			 * If the bit changed, then change the DO state to
+			 * match
+			 */
+			ql_write_common_reg(qdev,
+					    &port_regs->CommonRegs.
+					    serialPortInterfaceReg,
+					    ISP_NVRAM_MASK | qdev->
+					    eeprom_cmd_data | dataBit);
+			previousBit = dataBit;
+		}
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->
+				    eeprom_cmd_data | dataBit |
+				    AUBURN_EEPROM_CLK_RISE);
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->
+				    eeprom_cmd_data | dataBit |
+				    AUBURN_EEPROM_CLK_FALL);
+		eepromAddr = eepromAddr << 1;
+	}
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_deselect(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void fm93c56a_datain(struct ql3_adapter *qdev, unsigned short *value)
+{
+	int i;
+	u32 data = 0;
+	u32 dataBit;
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	/* Read the data bits */
+	/* The first bit is a dummy.  Clock right over it. */
+	for (i = 0; i < dataBits; i++) {
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+				    AUBURN_EEPROM_CLK_RISE);
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    serialPortInterfaceReg,
+				    ISP_NVRAM_MASK | qdev->eeprom_cmd_data |
+				    AUBURN_EEPROM_CLK_FALL);
+		dataBit =
+		    (ql_read_common_reg
+		     (qdev,
+		      &port_regs->CommonRegs.
+		      serialPortInterfaceReg) & AUBURN_EEPROM_DI_1) ? 1 : 0;
+		data = (data << 1) | dataBit;
+	}
+	*value = (u16) data;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void eeprom_readword(struct ql3_adapter *qdev,
+			    u32 eepromAddr, unsigned short *value)
+{
+	fm93c56a_select(qdev);
+	fm93c56a_cmd(qdev, (int)FM93C56A_READ, eepromAddr);
+	fm93c56a_datain(qdev, value);
+	fm93c56a_deselect(qdev);
+}
+
+static void ql_swap_mac_addr(u8 * macAddress)
+{
+#ifdef __BIG_ENDIAN
+	u8 temp;
+	temp = macAddress[0];
+	macAddress[0] = macAddress[1];
+	macAddress[1] = temp;
+	temp = macAddress[2];
+	macAddress[2] = macAddress[3];
+	macAddress[3] = temp;
+	temp = macAddress[4];
+	macAddress[4] = macAddress[5];
+	macAddress[5] = temp;
+#endif
+}
+
+static int ql_get_nvram_params(struct ql3_adapter *qdev)
+{
+	u16 *pEEPROMData;
+	u16 checksum = 0;
+	u32 index;
+	unsigned long hw_flags;
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+	pEEPROMData = (u16 *) & qdev->nvram_data;
+	qdev->eeprom_cmd_data = 0;
+	if(ql_sem_spinlock(qdev, QL_NVRAM_SEM_MASK,
+			(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 10)) {
+		printk(KERN_ERR PFX"%s: Failed ql_sem_spinlock().\n",
+			__func__);
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+		return -1;
+	}
+
+	for (index = 0; index < EEPROM_SIZE; index++) {
+		eeprom_readword(qdev, index, pEEPROMData);
+		checksum += *pEEPROMData;
+		pEEPROMData++;
+	}
+	ql_sem_unlock(qdev, QL_NVRAM_SEM_MASK);
+
+	if (checksum != 0) {
+		printk(KERN_ERR PFX "%s: checksum should be zero, is %x!!\n",
+		       qdev->ndev->name, checksum);
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+		return -1;
+	}
+
+	/*
+	 * We have a problem with endianness for the MAC addresses
+	 * and the two 8-bit values version, and numPorts.  We
+	 * have to swap them on big endian systems.
+	 */
+	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn0.macAddress);
+	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn1.macAddress);
+	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn2.macAddress);
+	ql_swap_mac_addr(qdev->nvram_data.funcCfg_fn3.macAddress);
+	pEEPROMData = (u16 *) & qdev->nvram_data.version;
+	*pEEPROMData = le16_to_cpu(*pEEPROMData);
+
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return checksum;
+}
+
+static const u32 PHYAddr[2] = {
+	PORT0_PHY_ADDRESS, PORT1_PHY_ADDRESS
+};
+
+static int ql_wait_for_mii_ready(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 temp;
+	int count = 1000;
+
+	while (count) {
+		temp = ql_read_page0_reg(qdev, &port_regs->macMIIStatusReg);
+		if (!(temp & MAC_MII_STATUS_BSY))
+			return 0;
+		udelay(10);
+		count--;
+	}
+	return -1;
+}
+
+static void ql_mii_enable_scan_mode(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 scanControl;
+
+	if (qdev->numPorts > 1) {
+		/* Auto scan will cycle through multiple ports */
+		scanControl = MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC;
+	} else {
+		scanControl = MAC_MII_CONTROL_SC;
+	}
+
+	/*
+	 * Scan register 1 of PHY/PETBI,
+	 * Set up to scan both devices
+	 * The autoscan starts from the first register, completes
+	 * the last one before rolling over to the first
+	 */
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   PHYAddr[0] | MII_SCAN_REGISTER);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   (scanControl) |
+			   ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS) << 16));
+}
+
+static u8 ql_mii_disable_scan_mode(struct ql3_adapter *qdev)
+{
+	u8 ret;
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    				qdev->mem_map_registers;
+
+	/* See if scan mode is enabled before we turn it off */
+	if (ql_read_page0_reg(qdev, &port_regs->macMIIMgmtControlReg) &
+	    (MAC_MII_CONTROL_AS | MAC_MII_CONTROL_SC)) {
+		/* Scan is enabled */
+		ret = 1;
+	} else {
+		/* Scan is disabled */
+		ret = 0;
+	}
+
+	/*
+	 * When disabling scan mode you must first change the MII register
+	 * address
+	 */
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   PHYAddr[0] | MII_SCAN_REGISTER);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   ((MAC_MII_CONTROL_SC | MAC_MII_CONTROL_AS |
+			     MAC_MII_CONTROL_RC) << 16));
+
+	return ret;
+}
+
+static int ql_mii_write_reg_ex(struct ql3_adapter *qdev,
+			       u16 regAddr, u16 value, u32 mac_index)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u8 scanWasEnabled;
+
+	scanWasEnabled = ql_mii_disable_scan_mode(qdev);
+
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   PHYAddr[mac_index] | regAddr);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);
+
+	/* Wait for write to complete 9/10/04 SJP */
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to"
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	if (scanWasEnabled)
+		ql_mii_enable_scan_mode(qdev);
+
+	return 0;
+}
+
+static int ql_mii_read_reg_ex(struct ql3_adapter *qdev, u16 regAddr,
+			      u16 * value, u32 mac_index)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u8 scanWasEnabled;
+	u32 temp;
+
+	scanWasEnabled = ql_mii_disable_scan_mode(qdev);
+
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   PHYAddr[mac_index] | regAddr);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   (MAC_MII_CONTROL_RC << 16));
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);
+
+	/* Wait for the read to complete */
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free after issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);
+	*value = (u16) temp;
+
+	if (scanWasEnabled)
+		ql_mii_enable_scan_mode(qdev);
+
+	return 0;
+}
+
+static int ql_mii_write_reg(struct ql3_adapter *qdev, u16 regAddr, u16 value)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	ql_mii_disable_scan_mode(qdev);
+
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   qdev->PHYAddr | regAddr);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtDataReg, value);
+
+	/* Wait for write to complete. */
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	ql_mii_enable_scan_mode(qdev);
+
+	return 0;
+}
+
+static int ql_mii_read_reg(struct ql3_adapter *qdev, u16 regAddr, u16 *value)
+{
+	u32 temp;
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	ql_mii_disable_scan_mode(qdev);
+
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtAddrReg,
+			   qdev->PHYAddr | regAddr);
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   (MAC_MII_CONTROL_RC << 16));
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   (MAC_MII_CONTROL_RC << 16) | MAC_MII_CONTROL_RC);
+
+	/* Wait for the read to complete */
+	if (ql_wait_for_mii_ready(qdev)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Timed out waiting for management port to "
+			       "get free before issuing command.\n",
+			       qdev->ndev->name);
+		return -1;
+	}
+
+	temp = ql_read_page0_reg(qdev, &port_regs->macMIIMgmtDataReg);
+	*value = (u16) temp;
+
+	ql_mii_enable_scan_mode(qdev);
+
+	return 0;
+}
+
+static void ql_petbi_reset(struct ql3_adapter *qdev)
+{
+	ql_mii_write_reg(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET);
+}
+
+static void ql_petbi_start_neg(struct ql3_adapter *qdev)
+{
+	u16 reg;
+
+	/* Enable Auto-negotiation sense */
+	ql_mii_read_reg(qdev, PETBI_TBI_CTRL, &reg);
+	reg |= PETBI_TBI_AUTO_SENSE;
+	ql_mii_write_reg(qdev, PETBI_TBI_CTRL, reg);
+
+	ql_mii_write_reg(qdev, PETBI_NEG_ADVER,
+			 PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX);
+
+	ql_mii_write_reg(qdev, PETBI_CONTROL_REG,
+			 PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |
+			 PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000);
+
+}
+
+static void ql_petbi_reset_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG, PETBI_CTRL_SOFT_RESET,
+			    mac_index);
+}
+
+static void ql_petbi_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	u16 reg;
+
+	/* Enable Auto-negotiation sense */
+	ql_mii_read_reg_ex(qdev, PETBI_TBI_CTRL, &reg, mac_index);
+	reg |= PETBI_TBI_AUTO_SENSE;
+	ql_mii_write_reg_ex(qdev, PETBI_TBI_CTRL, reg, mac_index);
+
+	ql_mii_write_reg_ex(qdev, PETBI_NEG_ADVER,
+			    PETBI_NEG_PAUSE | PETBI_NEG_DUPLEX, mac_index);
+
+	ql_mii_write_reg_ex(qdev, PETBI_CONTROL_REG,
+			    PETBI_CTRL_AUTO_NEG | PETBI_CTRL_RESTART_NEG |
+			    PETBI_CTRL_FULL_DUPLEX | PETBI_CTRL_SPEED_1000,
+			    mac_index);
+}
+
+static void ql_petbi_init(struct ql3_adapter *qdev)
+{
+	ql_petbi_reset(qdev);
+	ql_petbi_start_neg(qdev);
+}
+
+static void ql_petbi_init_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	ql_petbi_reset_ex(qdev, mac_index);
+	ql_petbi_start_neg_ex(qdev, mac_index);
+}
+
+static int ql_is_petbi_neg_pause(struct ql3_adapter *qdev)
+{
+	u16 reg;
+
+	if (ql_mii_read_reg(qdev, PETBI_NEG_PARTNER, &reg) < 0)
+		return 0;
+
+	return (reg & PETBI_NEG_PAUSE_MASK) == PETBI_NEG_PAUSE;
+}
+
+static int ql_phy_get_speed(struct ql3_adapter *qdev)
+{
+	u16 reg;
+
+	if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)
+		return 0;
+
+	reg = (((reg & 0x18) >> 3) & 3);
+
+	if (reg == 2)
+		return SPEED_1000;
+	else if (reg == 1)
+		return SPEED_100;
+	else if (reg == 0)
+		return SPEED_10;
+	else
+		return -1;
+}
+
+static int ql_is_full_dup(struct ql3_adapter *qdev)
+{
+	u16 reg;
+
+	if (ql_mii_read_reg(qdev, AUX_CONTROL_STATUS, &reg) < 0)
+		return 0;
+
+	return (reg & PHY_AUX_DUPLEX_STAT) != 0;
+}
+
+static int ql_is_phy_neg_pause(struct ql3_adapter *qdev)
+{
+	u16 reg;
+
+	if (ql_mii_read_reg(qdev, PHY_NEG_PARTNER, &reg) < 0)
+		return 0;
+
+	return (reg & PHY_NEG_PAUSE) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_enable(struct ql3_adapter *qdev, u32 enable)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 value;
+
+	if (enable)
+		value = (MAC_CONFIG_REG_PE | (MAC_CONFIG_REG_PE << 16));
+	else
+		value = (MAC_CONFIG_REG_PE << 16);
+
+	if (qdev->mac_index)
+		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+	else
+		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_soft_reset(struct ql3_adapter *qdev, u32 enable)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 value;
+
+	if (enable)
+		value = (MAC_CONFIG_REG_SR | (MAC_CONFIG_REG_SR << 16));
+	else
+		value = (MAC_CONFIG_REG_SR << 16);
+
+	if (qdev->mac_index)
+		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+	else
+		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_gig(struct ql3_adapter *qdev, u32 enable)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 value;
+
+	if (enable)
+		value = (MAC_CONFIG_REG_GM | (MAC_CONFIG_REG_GM << 16));
+	else
+		value = (MAC_CONFIG_REG_GM << 16);
+
+	if (qdev->mac_index)
+		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+	else
+		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_full_dup(struct ql3_adapter *qdev, u32 enable)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 value;
+
+	if (enable)
+		value = (MAC_CONFIG_REG_FD | (MAC_CONFIG_REG_FD << 16));
+	else
+		value = (MAC_CONFIG_REG_FD << 16);
+
+	if (qdev->mac_index)
+		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+	else
+		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_mac_cfg_pause(struct ql3_adapter *qdev, u32 enable)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 value;
+
+	if (enable)
+		value =
+		    ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) |
+		     ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16));
+	else
+		value = ((MAC_CONFIG_REG_TF | MAC_CONFIG_REG_RF) << 16);
+
+	if (qdev->mac_index)
+		ql_write_page0_reg(qdev, &port_regs->mac1ConfigReg, value);
+	else
+		ql_write_page0_reg(qdev, &port_regs->mac0ConfigReg, value);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_is_fiber(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp;
+
+	switch (qdev->mac_index) {
+	case 0:
+		bitToCheck = PORT_STATUS_SM0;
+		break;
+	case 1:
+		bitToCheck = PORT_STATUS_SM1;
+		break;
+	}
+
+	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	return (temp & bitToCheck) != 0;
+}
+
+static int ql_is_auto_cfg(struct ql3_adapter *qdev)
+{
+	u16 reg;
+	ql_mii_read_reg(qdev, 0x00, &reg);
+	return (reg & 0x1000) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_is_auto_neg_complete(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp;
+
+	switch (qdev->mac_index) {
+	case 0:
+		bitToCheck = PORT_STATUS_AC0;
+		break;
+	case 1:
+		bitToCheck = PORT_STATUS_AC1;
+		break;
+	}
+
+	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	if (temp & bitToCheck) {
+		if (netif_msg_link(qdev))
+			printk(KERN_INFO PFX
+			       "%s: Auto-Negotiate complete.\n",
+			       qdev->ndev->name);
+		return 1;
+	} else {
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Auto-Negotiate incomplete.\n",
+			       qdev->ndev->name);
+		return 0;
+	}
+}
+
+/*
+ *  ql_is_neg_pause() returns 1 if pause was negotiated to be on
+ */
+static int ql_is_neg_pause(struct ql3_adapter *qdev)
+{
+	if (ql_is_fiber(qdev))
+		return ql_is_petbi_neg_pause(qdev);
+	else
+		return ql_is_phy_neg_pause(qdev);
+}
+
+static int ql_auto_neg_error(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp;
+
+	switch (qdev->mac_index) {
+	case 0:
+		bitToCheck = PORT_STATUS_AE0;
+		break;
+	case 1:
+		bitToCheck = PORT_STATUS_AE1;
+		break;
+	}
+	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	return (temp & bitToCheck) != 0;
+}
+
+static u32 ql_get_link_speed(struct ql3_adapter *qdev)
+{
+	if (ql_is_fiber(qdev))
+		return SPEED_1000;
+	else
+		return ql_phy_get_speed(qdev);
+}
+
+static int ql_is_link_full_dup(struct ql3_adapter *qdev)
+{
+	if (ql_is_fiber(qdev))
+		return 1;
+	else
+		return ql_is_full_dup(qdev);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_link_down_detect(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp;
+
+	switch (qdev->mac_index) {
+	case 0:
+		bitToCheck = ISP_CONTROL_LINK_DN_0;
+		break;
+	case 1:
+		bitToCheck = ISP_CONTROL_LINK_DN_1;
+		break;
+	}
+
+	temp =
+	    ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus);
+	return (temp & bitToCheck) != 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_link_down_detect_clear(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	switch (qdev->mac_index) {
+	case 0:
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.ispControlStatus,
+				    (ISP_CONTROL_LINK_DN_0) |
+				    (ISP_CONTROL_LINK_DN_0 << 16));
+		break;
+
+	case 1:
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.ispControlStatus,
+				    (ISP_CONTROL_LINK_DN_1) |
+				    (ISP_CONTROL_LINK_DN_1 << 16));
+		break;
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_this_adapter_controls_port(struct ql3_adapter *qdev,
+					 u32 mac_index)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp;
+
+	switch (mac_index) {
+	case 0:
+		bitToCheck = PORT_STATUS_F1_ENABLED;
+		break;
+	case 1:
+		bitToCheck = PORT_STATUS_F3_ENABLED;
+		break;
+	default:
+		break;
+	}
+
+	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	if (temp & bitToCheck) {
+		if (netif_msg_link(qdev))
+			printk(KERN_DEBUG PFX
+			       "%s: is not link master.\n", qdev->ndev->name);
+		return 0;
+	} else {
+		if (netif_msg_link(qdev))
+			printk(KERN_DEBUG PFX
+			       "%s: is link master.\n", qdev->ndev->name);
+		return 1;
+	}
+}
+
+static void ql_phy_reset_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	ql_mii_write_reg_ex(qdev, CONTROL_REG, PHY_CTRL_SOFT_RESET, mac_index);
+}
+
+static void ql_phy_start_neg_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	u16 reg;
+
+	ql_mii_write_reg_ex(qdev, PHY_NEG_ADVER,
+			    PHY_NEG_PAUSE | PHY_NEG_ADV_SPEED | 1, mac_index);
+
+	ql_mii_read_reg_ex(qdev, CONTROL_REG, &reg, mac_index);
+	ql_mii_write_reg_ex(qdev, CONTROL_REG, reg | PHY_CTRL_RESTART_NEG,
+			    mac_index);
+}
+
+static void ql_phy_init_ex(struct ql3_adapter *qdev, u32 mac_index)
+{
+	ql_phy_reset_ex(qdev, mac_index);
+	ql_phy_start_neg_ex(qdev, mac_index);
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static u32 ql_get_link_state(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	u32 bitToCheck = 0;
+	u32 temp, linkState;
+
+	switch (qdev->mac_index) {
+	case 0:
+		bitToCheck = PORT_STATUS_UP0;
+		break;
+	case 1:
+		bitToCheck = PORT_STATUS_UP1;
+		break;
+	}
+	temp = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	if (temp & bitToCheck) {
+		linkState = LS_UP;
+	} else {
+		linkState = LS_DOWN;
+		if (netif_msg_link(qdev))
+			printk(KERN_WARNING PFX
+			       "%s: Link is down.\n", qdev->ndev->name);
+	}
+	return linkState;
+}
+
+static int ql_port_start(struct ql3_adapter *qdev)
+{
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return -1;
+
+	if (ql_is_fiber(qdev)) {
+		ql_petbi_init(qdev);
+	} else {
+		/* Copper port */
+		ql_phy_init_ex(qdev, qdev->mac_index);
+	}
+
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	return 0;
+}
+
+static int ql_finish_auto_neg(struct ql3_adapter *qdev)
+{
+
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return -1;
+
+	if (!ql_auto_neg_error(qdev)) {
+		if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+			/* configure the MAC */
+			if (netif_msg_link(qdev))
+				printk(KERN_DEBUG PFX
+				       "%s: Configuring link.\n",
+				       qdev->ndev->
+				       name);
+			ql_mac_cfg_soft_reset(qdev, 1);
+			ql_mac_cfg_gig(qdev,
+				       (ql_get_link_speed
+					(qdev) ==
+					SPEED_1000));
+			ql_mac_cfg_full_dup(qdev,
+					    ql_is_link_full_dup
+					    (qdev));
+			ql_mac_cfg_pause(qdev,
+					 ql_is_neg_pause
+					 (qdev));
+			ql_mac_cfg_soft_reset(qdev, 0);
+
+			/* enable the MAC */
+			if (netif_msg_link(qdev))
+				printk(KERN_DEBUG PFX
+				       "%s: Enabling mac.\n",
+				       qdev->ndev->
+					       name);
+			ql_mac_enable(qdev, 1);
+		}
+
+		if (netif_msg_link(qdev))
+			printk(KERN_DEBUG PFX
+			       "%s: Change port_link_state LS_DOWN to LS_UP.\n",
+			       qdev->ndev->name);
+		qdev->port_link_state = LS_UP;
+		netif_start_queue(qdev->ndev);
+		netif_carrier_on(qdev->ndev);
+		if (netif_msg_link(qdev))
+			printk(KERN_INFO PFX
+			       "%s: Link is up at %d Mbps, %s duplex.\n",
+			       qdev->ndev->name,
+			       ql_get_link_speed(qdev),
+			       ql_is_link_full_dup(qdev)
+			       ? "full" : "half");
+
+	} else {	/* Remote error detected */
+
+		if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+			if (netif_msg_link(qdev))
+				printk(KERN_DEBUG PFX
+				       "%s: Remote error detected. "
+				       "Calling ql_port_start().\n",
+				       qdev->ndev->
+				       name);
+			/*
+			 * ql_port_start() is shared code and needs
+			 * to lock the PHY on it's own.
+			 */
+			ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+			if(ql_port_start(qdev))	{/* Restart port */
+				return -1;
+			} else
+				return 0;
+		}
+	}
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	return 0;
+}
+
+static void ql_link_state_machine(struct ql3_adapter *qdev)
+{
+	u32 curr_link_state;
+	unsigned long hw_flags;
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+	curr_link_state = ql_get_link_state(qdev);
+
+	if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
+		if (netif_msg_link(qdev))
+			printk(KERN_INFO PFX
+			       "%s: Reset in progress, skip processing link "
+			       "state.\n", qdev->ndev->name);
+		return;
+	}
+
+	switch (qdev->port_link_state) {
+	default:
+		if (test_bit(QL_LINK_MASTER,&qdev->flags)) {
+			ql_port_start(qdev);
+		}
+		qdev->port_link_state = LS_DOWN;
+		/* Fall Through */
+
+	case LS_DOWN:
+		if (netif_msg_link(qdev))
+			printk(KERN_DEBUG PFX
+			       "%s: port_link_state = LS_DOWN.\n",
+			       qdev->ndev->name);
+		if (curr_link_state == LS_UP) {
+			if (netif_msg_link(qdev))
+				printk(KERN_DEBUG PFX
+				       "%s: curr_link_state = LS_UP.\n",
+				       qdev->ndev->name);
+			if (ql_is_auto_neg_complete(qdev))
+				ql_finish_auto_neg(qdev);
+
+			if (qdev->port_link_state == LS_UP)
+				ql_link_down_detect_clear(qdev);
+
+		}
+		break;
+
+	case LS_UP:
+		/*
+		 * See if the link is currently down or went down and came
+		 * back up
+		 */
+		if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) {
+			if (netif_msg_link(qdev))
+				printk(KERN_INFO PFX "%s: Link is down.\n",
+				       qdev->ndev->name);
+			qdev->port_link_state = LS_DOWN;
+		}
+		break;
+	}
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+}
+
+/*
+ * Caller must take hw_lock and QL_PHY_GIO_SEM.
+ */
+static void ql_get_phy_owner(struct ql3_adapter *qdev)
+{
+	if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+		set_bit(QL_LINK_MASTER,&qdev->flags);
+	else
+		clear_bit(QL_LINK_MASTER,&qdev->flags);
+}
+
+/*
+ * Caller must take hw_lock and QL_PHY_GIO_SEM.
+ */
+static void ql_init_scan_mode(struct ql3_adapter *qdev)
+{
+	ql_mii_enable_scan_mode(qdev);
+
+	if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+		if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+			ql_petbi_init_ex(qdev, qdev->mac_index);
+	} else {
+		if (ql_this_adapter_controls_port(qdev, qdev->mac_index))
+			ql_phy_init_ex(qdev, qdev->mac_index);
+	}
+}
+
+/*
+ * MII_Setup needs to be called before taking the PHY out of reset so that the
+ * management interface clock speed can be set properly.  It would be better if
+ * we had a way to disable MDC until after the PHY is out of reset, but we
+ * don't have that capability.
+ */
+static int ql_mii_setup(struct ql3_adapter *qdev)
+{
+	u32 reg;
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+			(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return -1;
+
+	/* Divide 125MHz clock by 28 to meet PHY timing requirements */
+	reg = MAC_MII_CONTROL_CLK_SEL_DIV28;
+
+	ql_write_page0_reg(qdev, &port_regs->macMIIMgmtControlReg,
+			   reg | ((MAC_MII_CONTROL_CLK_SEL_MASK) << 16));
+
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	return 0;
+}
+
+static u32 ql_supported_modes(struct ql3_adapter *qdev)
+{
+	u32 supported;
+
+	if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+		supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE
+		    | SUPPORTED_Autoneg;
+	} else {
+		supported = SUPPORTED_10baseT_Half
+		    | SUPPORTED_10baseT_Full
+		    | SUPPORTED_100baseT_Half
+		    | SUPPORTED_100baseT_Full
+		    | SUPPORTED_1000baseT_Half
+		    | SUPPORTED_1000baseT_Full
+		    | SUPPORTED_Autoneg | SUPPORTED_TP;
+	}
+
+	return supported;
+}
+
+static int ql_get_auto_cfg_status(struct ql3_adapter *qdev)
+{
+	int status;
+	unsigned long hw_flags;
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return 0;
+	status = ql_is_auto_cfg(qdev);
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return status;
+}
+
+static u32 ql_get_speed(struct ql3_adapter *qdev)
+{
+	u32 status;
+	unsigned long hw_flags;
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return 0;
+	status = ql_get_link_speed(qdev);
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return status;
+}
+
+static int ql_get_full_dup(struct ql3_adapter *qdev)
+{
+	int status;
+	unsigned long hw_flags;
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7))
+		return 0;
+	status = ql_is_link_full_dup(qdev);
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	return status;
+}
+
+
+static int ql_get_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->supported = ql_supported_modes(qdev);
+
+	if (test_bit(QL_LINK_OPTICAL,&qdev->flags)) {
+		ecmd->port = PORT_FIBRE;
+	} else {
+		ecmd->port = PORT_TP;
+		ecmd->phy_address = qdev->PHYAddr;
+	}
+	ecmd->advertising = ql_supported_modes(qdev);
+	ecmd->autoneg = ql_get_auto_cfg_status(qdev);
+	ecmd->speed = ql_get_speed(qdev);
+	ecmd->duplex = ql_get_full_dup(qdev);
+	return 0;
+}
+
+static void ql_get_drvinfo(struct net_device *ndev,
+			   struct ethtool_drvinfo *drvinfo)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	strncpy(drvinfo->driver, ql3xxx_driver_name, 32);
+	strncpy(drvinfo->version, ql3xxx_driver_version, 32);
+	strncpy(drvinfo->fw_version, "N/A", 32);
+	strncpy(drvinfo->bus_info, pci_name(qdev->pdev), 32);
+	drvinfo->n_stats = 0;
+	drvinfo->testinfo_len = 0;
+	drvinfo->regdump_len = 0;
+	drvinfo->eedump_len = 0;
+}
+
+static u32 ql_get_msglevel(struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	return qdev->msg_enable;
+}
+
+static void ql_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	qdev->msg_enable = value;
+}
+
+static struct ethtool_ops ql3xxx_ethtool_ops = {
+	.get_settings = ql_get_settings,
+	.get_drvinfo = ql_get_drvinfo,
+	.get_perm_addr = ethtool_op_get_perm_addr,
+	.get_link = ethtool_op_get_link,
+	.get_msglevel = ql_get_msglevel,
+	.set_msglevel = ql_set_msglevel,
+};
+
+static int ql_populate_free_queue(struct ql3_adapter *qdev)
+{
+	struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head;
+	u64 map;
+
+	while (lrg_buf_cb) {
+		if (!lrg_buf_cb->skb) {
+			lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+			if (unlikely(!lrg_buf_cb->skb)) {
+				printk(KERN_DEBUG PFX
+				       "%s: Failed dev_alloc_skb().\n",
+				       qdev->ndev->name);
+				break;
+			} else {
+				/*
+				 * We save some space to copy the ethhdr from
+				 * first buffer
+				 */
+				skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
+				map = pci_map_single(qdev->pdev,
+						     lrg_buf_cb->skb->data,
+						     qdev->lrg_buffer_len -
+						     QL_HEADER_SPACE,
+						     PCI_DMA_FROMDEVICE);
+				lrg_buf_cb->buf_phy_addr_low =
+				    cpu_to_le32(LS_64BITS(map));
+				lrg_buf_cb->buf_phy_addr_high =
+				    cpu_to_le32(MS_64BITS(map));
+				pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+				pci_unmap_len_set(lrg_buf_cb, maplen,
+						  qdev->lrg_buffer_len -
+						  QL_HEADER_SPACE);
+				--qdev->lrg_buf_skb_check;
+				if (!qdev->lrg_buf_skb_check)
+					return 1;
+			}
+		}
+		lrg_buf_cb = lrg_buf_cb->next;
+	}
+	return 0;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
+{
+	struct bufq_addr_element *lrg_buf_q_ele;
+	int i;
+	struct ql_rcv_buf_cb *lrg_buf_cb;
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+	if ((qdev->lrg_buf_free_count >= 8)
+	    && (qdev->lrg_buf_release_cnt >= 16)) {
+
+		if (qdev->lrg_buf_skb_check)
+			if (!ql_populate_free_queue(qdev))
+				return;
+
+		lrg_buf_q_ele = qdev->lrg_buf_next_free;
+
+		while ((qdev->lrg_buf_release_cnt >= 16)
+		       && (qdev->lrg_buf_free_count >= 8)) {
+
+			for (i = 0; i < 8; i++) {
+				lrg_buf_cb =
+				    ql_get_from_lrg_buf_free_list(qdev);
+				lrg_buf_q_ele->addr_high =
+				    lrg_buf_cb->buf_phy_addr_high;
+				lrg_buf_q_ele->addr_low =
+				    lrg_buf_cb->buf_phy_addr_low;
+				lrg_buf_q_ele++;
+
+				qdev->lrg_buf_release_cnt--;
+			}
+
+			qdev->lrg_buf_q_producer_index++;
+
+			if (qdev->lrg_buf_q_producer_index == NUM_LBUFQ_ENTRIES)
+				qdev->lrg_buf_q_producer_index = 0;
+
+			if (qdev->lrg_buf_q_producer_index ==
+			    (NUM_LBUFQ_ENTRIES - 1)) {
+				lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
+			}
+		}
+
+		qdev->lrg_buf_next_free = lrg_buf_q_ele;
+
+		ql_write_common_reg(qdev,
+				    (u32 *) & port_regs->CommonRegs.
+				    rxLargeQProducerIndex,
+				    qdev->lrg_buf_q_producer_index);
+	}
+}
+
+static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
+				   struct ob_mac_iocb_rsp *mac_rsp)
+{
+	struct ql_tx_buf_cb *tx_cb;
+
+	tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
+	pci_unmap_single(qdev->pdev,
+			 pci_unmap_addr(tx_cb, mapaddr),
+			 pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE);
+	dev_kfree_skb_irq(tx_cb->skb);
+	qdev->stats.tx_packets++;
+	qdev->stats.tx_bytes += tx_cb->skb->len;
+	tx_cb->skb = NULL;
+	atomic_inc(&qdev->tx_count);
+}
+
+static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
+				   struct ib_mac_iocb_rsp *ib_mac_rsp_ptr)
+{
+	long int offset;
+	u32 lrg_buf_phy_addr_low = 0;
+	struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
+	struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
+	u32 *curr_ial_ptr;
+	struct sk_buff *skb;
+	u16 length = le16_to_cpu(ib_mac_rsp_ptr->length);
+
+	/*
+	 * Get the inbound address list (small buffer).
+	 */
+	offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
+	if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+		qdev->small_buf_index = 0;
+
+	curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
+	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
+	qdev->small_buf_release_cnt++;
+
+	/* start of first buffer */
+	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+	lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
+	qdev->lrg_buf_release_cnt++;
+	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+		qdev->lrg_buf_index = 0;
+	curr_ial_ptr++;		/* 64-bit pointers require two incs. */
+	curr_ial_ptr++;
+
+	/* start of second buffer */
+	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+	lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+
+	/*
+	 * Second buffer gets sent up the stack.
+	 */
+	qdev->lrg_buf_release_cnt++;
+	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+		qdev->lrg_buf_index = 0;
+	skb = lrg_buf_cb2->skb;
+
+	qdev->stats.rx_packets++;
+	qdev->stats.rx_bytes += length;
+
+	skb_put(skb, length);
+	pci_unmap_single(qdev->pdev,
+			 pci_unmap_addr(lrg_buf_cb2, mapaddr),
+			 pci_unmap_len(lrg_buf_cb2, maplen),
+			 PCI_DMA_FROMDEVICE);
+	prefetch(skb->data);
+	skb->dev = qdev->ndev;
+	skb->ip_summed = CHECKSUM_NONE;
+	skb->protocol = eth_type_trans(skb, qdev->ndev);
+
+	netif_receive_skb(skb);
+	qdev->ndev->last_rx = jiffies;
+	lrg_buf_cb2->skb = NULL;
+
+	ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1);
+	ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2);
+}
+
+static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
+				     struct ib_ip_iocb_rsp *ib_ip_rsp_ptr)
+{
+	long int offset;
+	u32 lrg_buf_phy_addr_low = 0;
+	struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
+	struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
+	u32 *curr_ial_ptr;
+	struct sk_buff *skb1, *skb2;
+	struct net_device *ndev = qdev->ndev;
+	u16 length = le16_to_cpu(ib_ip_rsp_ptr->length);
+	u16 size = 0;
+
+	/*
+	 * Get the inbound address list (small buffer).
+	 */
+
+	offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
+	if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+		qdev->small_buf_index = 0;
+	curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
+	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
+	qdev->small_buf_release_cnt++;
+
+	/* start of first buffer */
+	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+	lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
+
+	qdev->lrg_buf_release_cnt++;
+	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+		qdev->lrg_buf_index = 0;
+	skb1 = lrg_buf_cb1->skb;
+	curr_ial_ptr++;		/* 64-bit pointers require two incs. */
+	curr_ial_ptr++;
+
+	/* start of second buffer */
+	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
+	lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+	skb2 = lrg_buf_cb2->skb;
+	qdev->lrg_buf_release_cnt++;
+	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+		qdev->lrg_buf_index = 0;
+
+	qdev->stats.rx_packets++;
+	qdev->stats.rx_bytes += length;
+
+	/*
+	 * Copy the ethhdr from first buffer to second. This
+	 * is necessary for IP completions.
+	 */
+	if (*((u16 *) skb1->data) != 0xFFFF)
+		size = VLAN_ETH_HLEN;
+	else
+		size = ETH_HLEN;
+
+	skb_put(skb2, length);	/* Just the second buffer length here. */
+	pci_unmap_single(qdev->pdev,
+			 pci_unmap_addr(lrg_buf_cb2, mapaddr),
+			 pci_unmap_len(lrg_buf_cb2, maplen),
+			 PCI_DMA_FROMDEVICE);
+	prefetch(skb2->data);
+
+	memcpy(skb_push(skb2, size), skb1->data + VLAN_ID_LEN, size);
+	skb2->dev = qdev->ndev;
+	skb2->ip_summed = CHECKSUM_NONE;
+	skb2->protocol = eth_type_trans(skb2, qdev->ndev);
+
+	netif_receive_skb(skb2);
+	ndev->last_rx = jiffies;
+	lrg_buf_cb2->skb = NULL;
+
+	ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb1);
+	ql_release_to_lrg_buf_free_list(qdev, lrg_buf_cb2);
+}
+
+static int ql_tx_rx_clean(struct ql3_adapter *qdev,
+			  int *tx_cleaned, int *rx_cleaned, int work_to_do)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	struct net_rsp_iocb *net_rsp;
+	struct net_device *ndev = qdev->ndev;
+	unsigned long hw_flags;
+
+	/* While there are entries in the completion queue. */
+	while ((cpu_to_le32(*(qdev->prsp_producer_index)) !=
+		qdev->rsp_consumer_index) && (*rx_cleaned < work_to_do)) {
+
+		net_rsp = qdev->rsp_current;
+		switch (net_rsp->opcode) {
+
+		case OPCODE_OB_MAC_IOCB_FN0:
+		case OPCODE_OB_MAC_IOCB_FN2:
+			ql_process_mac_tx_intr(qdev, (struct ob_mac_iocb_rsp *)
+					       net_rsp);
+			(*tx_cleaned)++;
+			break;
+
+		case OPCODE_IB_MAC_IOCB:
+			ql_process_mac_rx_intr(qdev, (struct ib_mac_iocb_rsp *)
+					       net_rsp);
+			(*rx_cleaned)++;
+			break;
+
+		case OPCODE_IB_IP_IOCB:
+			ql_process_macip_rx_intr(qdev, (struct ib_ip_iocb_rsp *)
+						 net_rsp);
+			(*rx_cleaned)++;
+			break;
+		default:
+			{
+				u32 *tmp = (u32 *) net_rsp;
+				printk(KERN_ERR PFX
+				       "%s: Hit default case, not "
+				       "handled!\n"
+				       "	dropping the packet, opcode = "
+				       "%x.\n",
+				       ndev->name, net_rsp->opcode);
+				printk(KERN_ERR PFX
+				       "0x%08lx 0x%08lx 0x%08lx 0x%08lx \n",
+				       (unsigned long int)tmp[0],
+				       (unsigned long int)tmp[1],
+				       (unsigned long int)tmp[2],
+				       (unsigned long int)tmp[3]);
+			}
+		}
+
+		qdev->rsp_consumer_index++;
+
+		if (qdev->rsp_consumer_index == NUM_RSP_Q_ENTRIES) {
+			qdev->rsp_consumer_index = 0;
+			qdev->rsp_current = qdev->rsp_q_virt_addr;
+		} else {
+			qdev->rsp_current++;
+		}
+	}
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+	ql_update_lrg_bufq_prod_index(qdev);
+
+	if (qdev->small_buf_release_cnt >= 16) {
+		while (qdev->small_buf_release_cnt >= 16) {
+			qdev->small_buf_q_producer_index++;
+
+			if (qdev->small_buf_q_producer_index ==
+			    NUM_SBUFQ_ENTRIES)
+				qdev->small_buf_q_producer_index = 0;
+			qdev->small_buf_release_cnt -= 8;
+		}
+
+		ql_write_common_reg(qdev,
+				    (u32 *) & port_regs->CommonRegs.
+				    rxSmallQProducerIndex,
+				    qdev->small_buf_q_producer_index);
+	}
+
+	ql_write_common_reg(qdev,
+			    (u32 *) & port_regs->CommonRegs.rspQConsumerIndex,
+			    qdev->rsp_consumer_index);
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+	if (unlikely(netif_queue_stopped(qdev->ndev))) {
+		if (netif_queue_stopped(qdev->ndev) &&
+		    (atomic_read(&qdev->tx_count) > (NUM_REQ_Q_ENTRIES / 4)))
+			netif_wake_queue(qdev->ndev);
+	}
+
+	return *tx_cleaned + *rx_cleaned;
+}
+
+static int ql_poll(struct net_device *ndev, int *budget)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	int work_to_do = min(*budget, ndev->quota);
+	int rx_cleaned = 0, tx_cleaned = 0;
+
+	if (!netif_carrier_ok(ndev))
+		goto quit_polling;
+
+	ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, work_to_do);
+	*budget -= rx_cleaned;
+	ndev->quota -= rx_cleaned;
+
+	if ((!tx_cleaned && !rx_cleaned) || !netif_running(ndev)) {
+quit_polling:
+		netif_rx_complete(ndev);
+		ql_enable_interrupts(qdev);
+		return 0;
+	}
+	return 1;
+}
+
+static irqreturn_t ql3xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	struct net_device *ndev = dev_id;
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	u32 value;
+	int handled = 1;
+	u32 var;
+
+	port_regs = qdev->mem_map_registers;
+
+	value =
+	    ql_read_common_reg_l(qdev, &port_regs->CommonRegs.ispControlStatus);
+
+	if (value & (ISP_CONTROL_FE | ISP_CONTROL_RI)) {
+		spin_lock(&qdev->adapter_lock);
+		netif_stop_queue(qdev->ndev);
+		netif_carrier_off(qdev->ndev);
+		ql_disable_interrupts(qdev);
+		qdev->port_link_state = LS_DOWN;
+		set_bit(QL_RESET_ACTIVE,&qdev->flags) ;
+
+		if (value & ISP_CONTROL_FE) {
+			/*
+			 * Chip Fatal Error.
+			 */
+			var =
+			    ql_read_page0_reg_l(qdev,
+					      &port_regs->PortFatalErrStatus);
+			printk(KERN_WARNING PFX
+			       "%s: Resetting chip. PortFatalErrStatus "
+			       "register = 0x%x\n", ndev->name, var);
+			set_bit(QL_RESET_START,&qdev->flags) ;
+		} else {
+			/*
+			 * Soft Reset Requested.
+			 */
+			set_bit(QL_RESET_PER_SCSI,&qdev->flags) ;
+			printk(KERN_ERR PFX
+			       "%s: Another function issued a reset to the "
+			       "chip. ISR value = %x.\n", ndev->name, value);
+		}
+		queue_work(qdev->workqueue, &qdev->reset_work);
+		spin_unlock(&qdev->adapter_lock);
+	} else if (value & ISP_IMR_DISABLE_CMPL_INT) {
+		ql_disable_interrupts(qdev);
+		if (likely(netif_rx_schedule_prep(ndev)))
+			__netif_rx_schedule(ndev);
+		else
+			ql_enable_interrupts(qdev);
+	} else {
+		return IRQ_NONE;
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	struct ql_tx_buf_cb *tx_cb;
+	struct ob_mac_iocb_req *mac_iocb_ptr;
+	u64 map;
+
+	if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+		return NETDEV_TX_BUSY;
+	}
+	tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
+	mac_iocb_ptr = tx_cb->queue_entry;
+	memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
+	mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
+	mac_iocb_ptr->flags |= qdev->mb_bit_mask;
+	mac_iocb_ptr->transaction_id = qdev->req_producer_index;
+	mac_iocb_ptr->data_len = cpu_to_le16((u16) skb->len);
+	tx_cb->skb = skb;
+	map = pci_map_single(qdev->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
+	mac_iocb_ptr->buf_addr0_low = cpu_to_le32(LS_64BITS(map));
+	mac_iocb_ptr->buf_addr0_high = cpu_to_le32(MS_64BITS(map));
+	mac_iocb_ptr->buf_0_len = cpu_to_le32(skb->len | OB_MAC_IOCB_REQ_E);
+	pci_unmap_addr_set(tx_cb, mapaddr, map);
+	pci_unmap_len_set(tx_cb, maplen, skb->len);
+	atomic_dec(&qdev->tx_count);
+
+	qdev->req_producer_index++;
+	if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
+		qdev->req_producer_index = 0;
+	wmb();
+	ql_write_common_reg_l(qdev,
+			    (u32 *) & port_regs->CommonRegs.reqQProducerIndex,
+			    qdev->req_producer_index);
+
+	ndev->trans_start = jiffies;
+	if (netif_msg_tx_queued(qdev))
+		printk(KERN_DEBUG PFX "%s: tx queued, slot %d, len %d\n",
+		       ndev->name, qdev->req_producer_index, skb->len);
+
+	return NETDEV_TX_OK;
+}
+static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
+{
+	qdev->req_q_size =
+	    (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
+
+	qdev->req_q_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 (size_t) qdev->req_q_size,
+				 &qdev->req_q_phy_addr);
+
+	if ((qdev->req_q_virt_addr == NULL) ||
+	    LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) {
+		printk(KERN_ERR PFX "%s: reqQ failed.\n",
+		       qdev->ndev->name);
+		return -ENOMEM;
+	}
+
+	qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+	qdev->rsp_q_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 (size_t) qdev->rsp_q_size,
+				 &qdev->rsp_q_phy_addr);
+
+	if ((qdev->rsp_q_virt_addr == NULL) ||
+	    LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) {
+		printk(KERN_ERR PFX
+		       "%s: rspQ allocation failed\n",
+		       qdev->ndev->name);
+		pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size,
+				    qdev->req_q_virt_addr,
+				    qdev->req_q_phy_addr);
+		return -ENOMEM;
+	}
+
+	set_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags);
+
+	return 0;
+}
+
+static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev)
+{
+	if (!test_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags)) {
+		printk(KERN_INFO PFX
+		       "%s: Already done.\n", qdev->ndev->name);
+		return;
+	}
+
+	pci_free_consistent(qdev->pdev,
+			    qdev->req_q_size,
+			    qdev->req_q_virt_addr, qdev->req_q_phy_addr);
+
+	qdev->req_q_virt_addr = NULL;
+
+	pci_free_consistent(qdev->pdev,
+			    qdev->rsp_q_size,
+			    qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
+
+	qdev->rsp_q_virt_addr = NULL;
+
+	clear_bit(QL_ALLOC_REQ_RSP_Q_DONE,&qdev->flags);
+}
+
+static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
+{
+	/* Create Large Buffer Queue */
+	qdev->lrg_buf_q_size =
+	    NUM_LBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+	if (qdev->lrg_buf_q_size < PAGE_SIZE)
+		qdev->lrg_buf_q_alloc_size = PAGE_SIZE;
+	else
+		qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2;
+
+	qdev->lrg_buf_q_alloc_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 qdev->lrg_buf_q_alloc_size,
+				 &qdev->lrg_buf_q_alloc_phy_addr);
+
+	if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
+		printk(KERN_ERR PFX
+		       "%s: lBufQ failed\n", qdev->ndev->name);
+		return -ENOMEM;
+	}
+	qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr;
+	qdev->lrg_buf_q_phy_addr = qdev->lrg_buf_q_alloc_phy_addr;
+
+	/* Create Small Buffer Queue */
+	qdev->small_buf_q_size =
+	    NUM_SBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+	if (qdev->small_buf_q_size < PAGE_SIZE)
+		qdev->small_buf_q_alloc_size = PAGE_SIZE;
+	else
+		qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2;
+
+	qdev->small_buf_q_alloc_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 qdev->small_buf_q_alloc_size,
+				 &qdev->small_buf_q_alloc_phy_addr);
+
+	if (qdev->small_buf_q_alloc_virt_addr == NULL) {
+		printk(KERN_ERR PFX
+		       "%s: Small Buffer Queue allocation failed.\n",
+		       qdev->ndev->name);
+		pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size,
+				    qdev->lrg_buf_q_alloc_virt_addr,
+				    qdev->lrg_buf_q_alloc_phy_addr);
+		return -ENOMEM;
+	}
+
+	qdev->small_buf_q_virt_addr = qdev->small_buf_q_alloc_virt_addr;
+	qdev->small_buf_q_phy_addr = qdev->small_buf_q_alloc_phy_addr;
+	set_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags);
+	return 0;
+}
+
+static void ql_free_buffer_queues(struct ql3_adapter *qdev)
+{
+	if (!test_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags)) {
+		printk(KERN_INFO PFX
+		       "%s: Already done.\n", qdev->ndev->name);
+		return;
+	}
+
+	pci_free_consistent(qdev->pdev,
+			    qdev->lrg_buf_q_alloc_size,
+			    qdev->lrg_buf_q_alloc_virt_addr,
+			    qdev->lrg_buf_q_alloc_phy_addr);
+
+	qdev->lrg_buf_q_virt_addr = NULL;
+
+	pci_free_consistent(qdev->pdev,
+			    qdev->small_buf_q_alloc_size,
+			    qdev->small_buf_q_alloc_virt_addr,
+			    qdev->small_buf_q_alloc_phy_addr);
+
+	qdev->small_buf_q_virt_addr = NULL;
+
+	clear_bit(QL_ALLOC_BUFQS_DONE,&qdev->flags);
+}
+
+static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
+{
+	int i;
+	struct bufq_addr_element *small_buf_q_entry;
+
+	/* Currently we allocate on one of memory and use it for smallbuffers */
+	qdev->small_buf_total_size =
+	    (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES *
+	     QL_SMALL_BUFFER_SIZE);
+
+	qdev->small_buf_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 qdev->small_buf_total_size,
+				 &qdev->small_buf_phy_addr);
+
+	if (qdev->small_buf_virt_addr == NULL) {
+		printk(KERN_ERR PFX
+		       "%s: Failed to get small buffer memory.\n",
+		       qdev->ndev->name);
+		return -ENOMEM;
+	}
+
+	qdev->small_buf_phy_addr_low = LS_64BITS(qdev->small_buf_phy_addr);
+	qdev->small_buf_phy_addr_high = MS_64BITS(qdev->small_buf_phy_addr);
+
+	small_buf_q_entry = qdev->small_buf_q_virt_addr;
+
+	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low;
+
+	/* Initialize the small buffer queue. */
+	for (i = 0; i < (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES); i++) {
+		small_buf_q_entry->addr_high =
+		    cpu_to_le32(qdev->small_buf_phy_addr_high);
+		small_buf_q_entry->addr_low =
+		    cpu_to_le32(qdev->small_buf_phy_addr_low +
+				(i * QL_SMALL_BUFFER_SIZE));
+		small_buf_q_entry++;
+	}
+	qdev->small_buf_index = 0;
+	set_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags);
+	return 0;
+}
+
+static void ql_free_small_buffers(struct ql3_adapter *qdev)
+{
+	if (!test_bit(QL_ALLOC_SMALL_BUF_DONE,&qdev->flags)) {
+		printk(KERN_INFO PFX
+		       "%s: Already done.\n", qdev->ndev->name);
+		return;
+	}
+	if (qdev->small_buf_virt_addr != NULL) {
+		pci_free_consistent(qdev->pdev,
+				    qdev->small_buf_total_size,
+				    qdev->small_buf_virt_addr,
+				    qdev->small_buf_phy_addr);
+
+		qdev->small_buf_virt_addr = NULL;
+	}
+}
+
+static void ql_free_large_buffers(struct ql3_adapter *qdev)
+{
+	int i = 0;
+	struct ql_rcv_buf_cb *lrg_buf_cb;
+
+	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+		lrg_buf_cb = &qdev->lrg_buf[i];
+		if (lrg_buf_cb->skb) {
+			dev_kfree_skb(lrg_buf_cb->skb);
+			pci_unmap_single(qdev->pdev,
+					 pci_unmap_addr(lrg_buf_cb, mapaddr),
+					 pci_unmap_len(lrg_buf_cb, maplen),
+					 PCI_DMA_FROMDEVICE);
+			memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+		} else {
+			break;
+		}
+	}
+}
+
+static void ql_init_large_buffers(struct ql3_adapter *qdev)
+{
+	int i;
+	struct ql_rcv_buf_cb *lrg_buf_cb;
+	struct bufq_addr_element *buf_addr_ele = qdev->lrg_buf_q_virt_addr;
+
+	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+		lrg_buf_cb = &qdev->lrg_buf[i];
+		buf_addr_ele->addr_high = lrg_buf_cb->buf_phy_addr_high;
+		buf_addr_ele->addr_low = lrg_buf_cb->buf_phy_addr_low;
+		buf_addr_ele++;
+	}
+	qdev->lrg_buf_index = 0;
+	qdev->lrg_buf_skb_check = 0;
+}
+
+static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
+{
+	int i;
+	struct ql_rcv_buf_cb *lrg_buf_cb;
+	struct sk_buff *skb;
+	u64 map;
+
+	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+		skb = dev_alloc_skb(qdev->lrg_buffer_len);
+		if (unlikely(!skb)) {
+			/* Better luck next round */
+			printk(KERN_ERR PFX
+			       "%s: large buff alloc failed, "
+			       "for %d bytes at index %d.\n",
+			       qdev->ndev->name,
+			       qdev->lrg_buffer_len * 2, i);
+			ql_free_large_buffers(qdev);
+			return -ENOMEM;
+		} else {
+
+			lrg_buf_cb = &qdev->lrg_buf[i];
+			memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+			lrg_buf_cb->index = i;
+			lrg_buf_cb->skb = skb;
+			/*
+			 * We save some space to copy the ethhdr from first
+			 * buffer
+			 */
+			skb_reserve(skb, QL_HEADER_SPACE);
+			map = pci_map_single(qdev->pdev,
+					     skb->data,
+					     qdev->lrg_buffer_len -
+					     QL_HEADER_SPACE,
+					     PCI_DMA_FROMDEVICE);
+			pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
+			pci_unmap_len_set(lrg_buf_cb, maplen,
+					  qdev->lrg_buffer_len -
+					  QL_HEADER_SPACE);
+			lrg_buf_cb->buf_phy_addr_low =
+			    cpu_to_le32(LS_64BITS(map));
+			lrg_buf_cb->buf_phy_addr_high =
+			    cpu_to_le32(MS_64BITS(map));
+		}
+	}
+	return 0;
+}
+
+static void ql_create_send_free_list(struct ql3_adapter *qdev)
+{
+	struct ql_tx_buf_cb *tx_cb;
+	int i;
+	struct ob_mac_iocb_req *req_q_curr =
+					qdev->req_q_virt_addr;
+
+	/* Create free list of transmit buffers */
+	for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) {
+		tx_cb = &qdev->tx_buf[i];
+		tx_cb->skb = NULL;
+		tx_cb->queue_entry = req_q_curr;
+		req_q_curr++;
+	}
+}
+
+static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
+{
+	if (qdev->ndev->mtu == NORMAL_MTU_SIZE)
+		qdev->lrg_buffer_len = NORMAL_MTU_SIZE;
+	else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) {
+		qdev->lrg_buffer_len = JUMBO_MTU_SIZE;
+	} else {
+		printk(KERN_ERR PFX
+		       "%s: Invalid mtu size.  Only 1500 and 9000 are accepted.\n",
+		       qdev->ndev->name);
+		return -ENOMEM;
+	}
+	qdev->lrg_buffer_len += VLAN_ETH_HLEN + VLAN_ID_LEN + QL_HEADER_SPACE;
+	qdev->max_frame_size =
+	    (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE;
+
+	/*
+	 * First allocate a page of shared memory and use it for shadow
+	 * locations of Network Request Queue Consumer Address Register and
+	 * Network Completion Queue Producer Index Register
+	 */
+	qdev->shadow_reg_virt_addr =
+	    pci_alloc_consistent(qdev->pdev,
+				 PAGE_SIZE, &qdev->shadow_reg_phy_addr);
+
+	if (qdev->shadow_reg_virt_addr != NULL) {
+		qdev->preq_consumer_index = (u16 *) qdev->shadow_reg_virt_addr;
+		qdev->req_consumer_index_phy_addr_high =
+		    MS_64BITS(qdev->shadow_reg_phy_addr);
+		qdev->req_consumer_index_phy_addr_low =
+		    LS_64BITS(qdev->shadow_reg_phy_addr);
+
+		qdev->prsp_producer_index =
+		    (u32 *) (((u8 *) qdev->preq_consumer_index) + 8);
+		qdev->rsp_producer_index_phy_addr_high =
+		    qdev->req_consumer_index_phy_addr_high;
+		qdev->rsp_producer_index_phy_addr_low =
+		    qdev->req_consumer_index_phy_addr_low + 8;
+	} else {
+		printk(KERN_ERR PFX
+		       "%s: shadowReg Alloc failed.\n", qdev->ndev->name);
+		return -ENOMEM;
+	}
+
+	if (ql_alloc_net_req_rsp_queues(qdev) != 0) {
+		printk(KERN_ERR PFX
+		       "%s: ql_alloc_net_req_rsp_queues failed.\n",
+		       qdev->ndev->name);
+		goto err_req_rsp;
+	}
+
+	if (ql_alloc_buffer_queues(qdev) != 0) {
+		printk(KERN_ERR PFX
+		       "%s: ql_alloc_buffer_queues failed.\n",
+		       qdev->ndev->name);
+		goto err_buffer_queues;
+	}
+
+	if (ql_alloc_small_buffers(qdev) != 0) {
+		printk(KERN_ERR PFX
+		       "%s: ql_alloc_small_buffers failed\n", qdev->ndev->name);
+		goto err_small_buffers;
+	}
+
+	if (ql_alloc_large_buffers(qdev) != 0) {
+		printk(KERN_ERR PFX
+		       "%s: ql_alloc_large_buffers failed\n", qdev->ndev->name);
+		goto err_small_buffers;
+	}
+
+	/* Initialize the large buffer queue. */
+	ql_init_large_buffers(qdev);
+	ql_create_send_free_list(qdev);
+
+	qdev->rsp_current = qdev->rsp_q_virt_addr;
+
+	return 0;
+
+err_small_buffers:
+	ql_free_buffer_queues(qdev);
+err_buffer_queues:
+	ql_free_net_req_rsp_queues(qdev);
+err_req_rsp:
+	pci_free_consistent(qdev->pdev,
+			    PAGE_SIZE,
+			    qdev->shadow_reg_virt_addr,
+			    qdev->shadow_reg_phy_addr);
+
+	return -ENOMEM;
+}
+
+static void ql_free_mem_resources(struct ql3_adapter *qdev)
+{
+	ql_free_large_buffers(qdev);
+	ql_free_small_buffers(qdev);
+	ql_free_buffer_queues(qdev);
+	ql_free_net_req_rsp_queues(qdev);
+	if (qdev->shadow_reg_virt_addr != NULL) {
+		pci_free_consistent(qdev->pdev,
+				    PAGE_SIZE,
+				    qdev->shadow_reg_virt_addr,
+				    qdev->shadow_reg_phy_addr);
+		qdev->shadow_reg_virt_addr = NULL;
+	}
+}
+
+static int ql_init_misc_registers(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_local_ram_registers *local_ram =
+	    (struct ql3xxx_local_ram_registers *)qdev->mem_map_registers;
+
+	if(ql_sem_spinlock(qdev, QL_DDR_RAM_SEM_MASK,
+			(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 4))
+		return -1;
+
+	ql_write_page2_reg(qdev,
+			   &local_ram->bufletSize, qdev->nvram_data.bufletSize);
+
+	ql_write_page2_reg(qdev,
+			   &local_ram->maxBufletCount,
+			   qdev->nvram_data.bufletCount);
+
+	ql_write_page2_reg(qdev,
+			   &local_ram->freeBufletThresholdLow,
+			   (qdev->nvram_data.tcpWindowThreshold25 << 16) |
+			   (qdev->nvram_data.tcpWindowThreshold0));
+
+	ql_write_page2_reg(qdev,
+			   &local_ram->freeBufletThresholdHigh,
+			   qdev->nvram_data.tcpWindowThreshold50);
+
+	ql_write_page2_reg(qdev,
+			   &local_ram->ipHashTableBase,
+			   (qdev->nvram_data.ipHashTableBaseHi << 16) |
+			   qdev->nvram_data.ipHashTableBaseLo);
+	ql_write_page2_reg(qdev,
+			   &local_ram->ipHashTableCount,
+			   qdev->nvram_data.ipHashTableSize);
+	ql_write_page2_reg(qdev,
+			   &local_ram->tcpHashTableBase,
+			   (qdev->nvram_data.tcpHashTableBaseHi << 16) |
+			   qdev->nvram_data.tcpHashTableBaseLo);
+	ql_write_page2_reg(qdev,
+			   &local_ram->tcpHashTableCount,
+			   qdev->nvram_data.tcpHashTableSize);
+	ql_write_page2_reg(qdev,
+			   &local_ram->ncbBase,
+			   (qdev->nvram_data.ncbTableBaseHi << 16) |
+			   qdev->nvram_data.ncbTableBaseLo);
+	ql_write_page2_reg(qdev,
+			   &local_ram->maxNcbCount,
+			   qdev->nvram_data.ncbTableSize);
+	ql_write_page2_reg(qdev,
+			   &local_ram->drbBase,
+			   (qdev->nvram_data.drbTableBaseHi << 16) |
+			   qdev->nvram_data.drbTableBaseLo);
+	ql_write_page2_reg(qdev,
+			   &local_ram->maxDrbCount,
+			   qdev->nvram_data.drbTableSize);
+	ql_sem_unlock(qdev, QL_DDR_RAM_SEM_MASK);
+	return 0;
+}
+
+static int ql_adapter_initialize(struct ql3_adapter *qdev)
+{
+	u32 value;
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	struct ql3xxx_host_memory_registers __iomem *hmem_regs =
+	    (struct ql3xxx_host_memory_registers *)port_regs;
+	u32 delay = 10;
+	int status = 0;
+
+	if(ql_mii_setup(qdev))
+		return -1;
+
+	/* Bring out PHY out of reset */
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    (ISP_SERIAL_PORT_IF_WE |
+			     (ISP_SERIAL_PORT_IF_WE << 16)));
+
+	qdev->port_link_state = LS_DOWN;
+	netif_carrier_off(qdev->ndev);
+
+	/* V2 chip fix for ARS-39168. */
+	ql_write_common_reg(qdev, &port_regs->CommonRegs.serialPortInterfaceReg,
+			    (ISP_SERIAL_PORT_IF_SDE |
+			     (ISP_SERIAL_PORT_IF_SDE << 16)));
+
+	/* Request Queue Registers */
+	*((u32 *) (qdev->preq_consumer_index)) = 0;
+	atomic_set(&qdev->tx_count,NUM_REQ_Q_ENTRIES);
+	qdev->req_producer_index = 0;
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->reqConsumerIndexAddrHigh,
+			   qdev->req_consumer_index_phy_addr_high);
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->reqConsumerIndexAddrLow,
+			   qdev->req_consumer_index_phy_addr_low);
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->reqBaseAddrHigh,
+			   MS_64BITS(qdev->req_q_phy_addr));
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->reqBaseAddrLow,
+			   LS_64BITS(qdev->req_q_phy_addr));
+	ql_write_page1_reg(qdev, &hmem_regs->reqLength, NUM_REQ_Q_ENTRIES);
+
+	/* Response Queue Registers */
+	*((u16 *) (qdev->prsp_producer_index)) = 0;
+	qdev->rsp_consumer_index = 0;
+	qdev->rsp_current = qdev->rsp_q_virt_addr;
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rspProducerIndexAddrHigh,
+			   qdev->rsp_producer_index_phy_addr_high);
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rspProducerIndexAddrLow,
+			   qdev->rsp_producer_index_phy_addr_low);
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rspBaseAddrHigh,
+			   MS_64BITS(qdev->rsp_q_phy_addr));
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rspBaseAddrLow,
+			   LS_64BITS(qdev->rsp_q_phy_addr));
+
+	ql_write_page1_reg(qdev, &hmem_regs->rspLength, NUM_RSP_Q_ENTRIES);
+
+	/* Large Buffer Queue */
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxLargeQBaseAddrHigh,
+			   MS_64BITS(qdev->lrg_buf_q_phy_addr));
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxLargeQBaseAddrLow,
+			   LS_64BITS(qdev->lrg_buf_q_phy_addr));
+
+	ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, NUM_LBUFQ_ENTRIES);
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxLargeBufferLength,
+			   qdev->lrg_buffer_len);
+
+	/* Small Buffer Queue */
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxSmallQBaseAddrHigh,
+			   MS_64BITS(qdev->small_buf_q_phy_addr));
+
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxSmallQBaseAddrLow,
+			   LS_64BITS(qdev->small_buf_q_phy_addr));
+
+	ql_write_page1_reg(qdev, &hmem_regs->rxSmallQLength, NUM_SBUFQ_ENTRIES);
+	ql_write_page1_reg(qdev,
+			   &hmem_regs->rxSmallBufferLength,
+			   QL_SMALL_BUFFER_SIZE);
+
+	qdev->small_buf_q_producer_index = NUM_SBUFQ_ENTRIES - 1;
+	qdev->small_buf_release_cnt = 8;
+	qdev->lrg_buf_q_producer_index = NUM_LBUFQ_ENTRIES - 1;
+	qdev->lrg_buf_release_cnt = 8;
+	qdev->lrg_buf_next_free =
+	    (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
+	qdev->small_buf_index = 0;
+	qdev->lrg_buf_index = 0;
+	qdev->lrg_buf_free_count = 0;
+	qdev->lrg_buf_free_head = NULL;
+	qdev->lrg_buf_free_tail = NULL;
+
+	ql_write_common_reg(qdev,
+			    (u32 *) & port_regs->CommonRegs.
+			    rxSmallQProducerIndex,
+			    qdev->small_buf_q_producer_index);
+	ql_write_common_reg(qdev,
+			    (u32 *) & port_regs->CommonRegs.
+			    rxLargeQProducerIndex,
+			    qdev->lrg_buf_q_producer_index);
+
+	/*
+	 * Find out if the chip has already been initialized.  If it has, then
+	 * we skip some of the initialization.
+	 */
+	clear_bit(QL_LINK_MASTER, &qdev->flags);
+	value = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	if ((value & PORT_STATUS_IC) == 0) {
+
+		/* Chip has not been configured yet, so let it rip. */
+		if(ql_init_misc_registers(qdev)) {
+			status = -1;
+			goto out;
+		}
+
+		if (qdev->mac_index)
+			ql_write_page0_reg(qdev,
+					   &port_regs->mac1MaxFrameLengthReg,
+					   qdev->max_frame_size);
+		else
+			ql_write_page0_reg(qdev,
+					   &port_regs->mac0MaxFrameLengthReg,
+					   qdev->max_frame_size);
+
+		value = qdev->nvram_data.tcpMaxWindowSize;
+		ql_write_page0_reg(qdev, &port_regs->tcpMaxWindow, value);
+
+		value = (0xFFFF << 16) | qdev->nvram_data.extHwConfig;
+
+		if(ql_sem_spinlock(qdev, QL_FLASH_SEM_MASK,
+				(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index)
+				 * 2) << 13)) {
+			status = -1;
+			goto out;
+		}
+		ql_write_page0_reg(qdev, &port_regs->ExternalHWConfig, value);
+		ql_write_page0_reg(qdev, &port_regs->InternalChipConfig,
+				   (((INTERNAL_CHIP_SD | INTERNAL_CHIP_WE) <<
+				     16) | (INTERNAL_CHIP_SD |
+					    INTERNAL_CHIP_WE)));
+		ql_sem_unlock(qdev, QL_FLASH_SEM_MASK);
+	}
+
+
+	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
+			(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
+			 2) << 7)) {
+		status = -1;
+		goto out;
+	}
+
+	ql_init_scan_mode(qdev);
+	ql_get_phy_owner(qdev);
+
+	/* Load the MAC Configuration */
+
+	/* Program lower 32 bits of the MAC address */
+	ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+			   (MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16));
+	ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+			   ((qdev->ndev->dev_addr[2] << 24)
+			    | (qdev->ndev->dev_addr[3] << 16)
+			    | (qdev->ndev->dev_addr[4] << 8)
+			    | qdev->ndev->dev_addr[5]));
+
+	/* Program top 16 bits of the MAC address */
+	ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+			   ((MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16) | 1));
+	ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+			   ((qdev->ndev->dev_addr[0] << 8)
+			    | qdev->ndev->dev_addr[1]));
+
+	/* Enable Primary MAC */
+	ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+			   ((MAC_ADDR_INDIRECT_PTR_REG_PE << 16) |
+			    MAC_ADDR_INDIRECT_PTR_REG_PE));
+
+	/* Clear Primary and Secondary IP addresses */
+	ql_write_page0_reg(qdev, &port_regs->ipAddrIndexReg,
+			   ((IP_ADDR_INDEX_REG_MASK << 16) |
+			    (qdev->mac_index << 2)));
+	ql_write_page0_reg(qdev, &port_regs->ipAddrDataReg, 0);
+
+	ql_write_page0_reg(qdev, &port_regs->ipAddrIndexReg,
+			   ((IP_ADDR_INDEX_REG_MASK << 16) |
+			    ((qdev->mac_index << 2) + 1)));
+	ql_write_page0_reg(qdev, &port_regs->ipAddrDataReg, 0);
+
+	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
+
+	/* Indicate Configuration Complete */
+	ql_write_page0_reg(qdev,
+			   &port_regs->portControl,
+			   ((PORT_CONTROL_CC << 16) | PORT_CONTROL_CC));
+
+	do {
+		value = ql_read_page0_reg(qdev, &port_regs->portStatus);
+		if (value & PORT_STATUS_IC)
+			break;
+		msleep(500);
+	} while (--delay);
+
+	if (delay == 0) {
+		printk(KERN_ERR PFX
+		       "%s: Hw Initialization timeout.\n", qdev->ndev->name);
+		status = -1;
+		goto out;
+	}
+
+	/* Enable Ethernet Function */
+	value =
+	    (PORT_CONTROL_EF | PORT_CONTROL_ET | PORT_CONTROL_EI |
+	     PORT_CONTROL_HH);
+	ql_write_page0_reg(qdev, &port_regs->portControl,
+			   ((value << 16) | value));
+
+out:
+	return status;
+}
+
+/*
+ * Caller holds hw_lock.
+ */
+static int ql_adapter_reset(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	int status = 0;
+	u16 value;
+	int max_wait_time;
+
+	set_bit(QL_RESET_ACTIVE, &qdev->flags);
+	clear_bit(QL_RESET_DONE, &qdev->flags);
+
+	/*
+	 * Issue soft reset to chip.
+	 */
+	printk(KERN_DEBUG PFX
+	       "%s: Issue soft reset to chip.\n",
+	       qdev->ndev->name);
+	ql_write_common_reg(qdev,
+			    (u32 *) & port_regs->CommonRegs.ispControlStatus,
+			    ((ISP_CONTROL_SR << 16) | ISP_CONTROL_SR));
+
+	/* Wait 3 seconds for reset to complete. */
+	printk(KERN_DEBUG PFX
+	       "%s: Wait 10 milliseconds for reset to complete.\n",
+	       qdev->ndev->name);
+
+	/* Wait until the firmware tells us the Soft Reset is done */
+	max_wait_time = 5;
+	do {
+		value =
+		    ql_read_common_reg(qdev,
+				       &port_regs->CommonRegs.ispControlStatus);
+		if ((value & ISP_CONTROL_SR) == 0)
+			break;
+
+		ssleep(1);
+	} while ((--max_wait_time));
+
+	/*
+	 * Also, make sure that the Network Reset Interrupt bit has been
+	 * cleared after the soft reset has taken place.
+	 */
+	value =
+	    ql_read_common_reg(qdev, &port_regs->CommonRegs.ispControlStatus);
+	if (value & ISP_CONTROL_RI) {
+		printk(KERN_DEBUG PFX
+		       "ql_adapter_reset: clearing RI after reset.\n");
+		ql_write_common_reg(qdev,
+				    (u32 *) & port_regs->CommonRegs.
+				    ispControlStatus,
+				    ((ISP_CONTROL_RI << 16) | ISP_CONTROL_RI));
+	}
+
+	if (max_wait_time == 0) {
+		/* Issue Force Soft Reset */
+		ql_write_common_reg(qdev,
+				    (u32 *) & port_regs->CommonRegs.
+				    ispControlStatus,
+				    ((ISP_CONTROL_FSR << 16) |
+				     ISP_CONTROL_FSR));
+		/*
+		 * Wait until the firmware tells us the Force Soft Reset is
+		 * done
+		 */
+		max_wait_time = 5;
+		do {
+			value =
+			    ql_read_common_reg(qdev,
+					       &port_regs->CommonRegs.
+					       ispControlStatus);
+			if ((value & ISP_CONTROL_FSR) == 0) {
+				break;
+			}
+			ssleep(1);
+		} while ((--max_wait_time));
+	}
+	if (max_wait_time == 0)
+		status = 1;
+
+	clear_bit(QL_RESET_ACTIVE, &qdev->flags);
+	set_bit(QL_RESET_DONE, &qdev->flags);
+	return status;
+}
+
+static void ql_set_mac_info(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	u32 value, port_status;
+	u8 func_number;
+
+	/* Get the function number */
+	value =
+	    ql_read_common_reg_l(qdev, &port_regs->CommonRegs.ispControlStatus);
+	func_number = (u8) ((value >> 4) & OPCODE_FUNC_ID_MASK);
+	port_status = ql_read_page0_reg(qdev, &port_regs->portStatus);
+	switch (value & ISP_CONTROL_FN_MASK) {
+	case ISP_CONTROL_FN0_NET:
+		qdev->mac_index = 0;
+		qdev->mac_ob_opcode = OUTBOUND_MAC_IOCB | func_number;
+		qdev->tcp_ob_opcode = OUTBOUND_TCP_IOCB | func_number;
+		qdev->update_ob_opcode = UPDATE_NCB_IOCB | func_number;
+		qdev->mb_bit_mask = FN0_MA_BITS_MASK;
+		qdev->PHYAddr = PORT0_PHY_ADDRESS;
+		if (port_status & PORT_STATUS_SM0)
+			set_bit(QL_LINK_OPTICAL,&qdev->flags);
+		else
+			clear_bit(QL_LINK_OPTICAL,&qdev->flags);
+		break;
+
+	case ISP_CONTROL_FN1_NET:
+		qdev->mac_index = 1;
+		qdev->mac_ob_opcode = OUTBOUND_MAC_IOCB | func_number;
+		qdev->tcp_ob_opcode = OUTBOUND_TCP_IOCB | func_number;
+		qdev->update_ob_opcode = UPDATE_NCB_IOCB | func_number;
+		qdev->mb_bit_mask = FN1_MA_BITS_MASK;
+		qdev->PHYAddr = PORT1_PHY_ADDRESS;
+		if (port_status & PORT_STATUS_SM1)
+			set_bit(QL_LINK_OPTICAL,&qdev->flags);
+		else
+			clear_bit(QL_LINK_OPTICAL,&qdev->flags);
+		break;
+
+	case ISP_CONTROL_FN0_SCSI:
+	case ISP_CONTROL_FN1_SCSI:
+	default:
+		printk(KERN_DEBUG PFX
+		       "%s: Invalid function number, ispControlStatus = 0x%x\n",
+		       qdev->ndev->name,value);
+		break;
+	}
+	qdev->numPorts = qdev->nvram_data.numPorts;
+}
+
+static void ql_display_dev_info(struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct pci_dev *pdev = qdev->pdev;
+
+	printk(KERN_INFO PFX
+	       "\n%s Adapter %d RevisionID %d found on PCI slot %d.\n",
+	       DRV_NAME, qdev->index, qdev->chip_rev_id, qdev->pci_slot);
+	printk(KERN_INFO PFX
+	       "%s Interface.\n",
+	       test_bit(QL_LINK_OPTICAL,&qdev->flags) ? "OPTICAL" : "COPPER");
+
+	/*
+	 * Print PCI bus width/type.
+	 */
+	printk(KERN_INFO PFX
+	       "Bus interface is %s %s.\n",
+	       ((qdev->pci_width == 64) ? "64-bit" : "32-bit"),
+	       ((qdev->pci_x) ? "PCI-X" : "PCI"));
+
+	printk(KERN_INFO PFX
+	       "mem  IO base address adjusted = 0x%p\n",
+	       qdev->mem_map_registers);
+	printk(KERN_INFO PFX "Interrupt number = %d\n", pdev->irq);
+
+	if (netif_msg_probe(qdev))
+		printk(KERN_INFO PFX
+		       "%s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       ndev->name, ndev->dev_addr[0], ndev->dev_addr[1],
+		       ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
+		       ndev->dev_addr[5]);
+}
+
+static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset)
+{
+	struct net_device *ndev = qdev->ndev;
+	int retval = 0;
+
+	netif_stop_queue(ndev);
+	netif_carrier_off(ndev);
+
+	clear_bit(QL_ADAPTER_UP,&qdev->flags);
+	clear_bit(QL_LINK_MASTER,&qdev->flags);
+
+	ql_disable_interrupts(qdev);
+
+	free_irq(qdev->pdev->irq, ndev);
+
+	if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
+		printk(KERN_INFO PFX
+		       "%s: calling pci_disable_msi().\n", qdev->ndev->name);
+		clear_bit(QL_MSI_ENABLED,&qdev->flags);
+		pci_disable_msi(qdev->pdev);
+	}
+
+	del_timer_sync(&qdev->adapter_timer);
+
+	netif_poll_disable(ndev);
+
+	if (do_reset) {
+		int soft_reset;
+		unsigned long hw_flags;
+
+		spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+		if (ql_wait_for_drvr_lock(qdev)) {
+			if ((soft_reset = ql_adapter_reset(qdev))) {
+				printk(KERN_ERR PFX
+				       "%s: ql_adapter_reset(%d) FAILED!\n",
+				       ndev->name, qdev->index);
+			}
+			printk(KERN_ERR PFX
+				"%s: Releaseing driver lock via chip reset.\n",ndev->name);
+		} else {
+			printk(KERN_ERR PFX
+			       "%s: Could not acquire driver lock to do "
+			       "reset!\n", ndev->name);
+			retval = -1;
+		}
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+	}
+	ql_free_mem_resources(qdev);
+	return retval;
+}
+
+static int ql_adapter_up(struct ql3_adapter *qdev)
+{
+	struct net_device *ndev = qdev->ndev;
+	int err;
+	unsigned long irq_flags = SA_SAMPLE_RANDOM | SA_SHIRQ;
+	unsigned long hw_flags;
+
+	if (ql_alloc_mem_resources(qdev)) {
+		printk(KERN_ERR PFX
+		       "%s Unable to  allocate buffers.\n", ndev->name);
+		return -ENOMEM;
+	}
+
+	if (qdev->msi) {
+		if (pci_enable_msi(qdev->pdev)) {
+			printk(KERN_ERR PFX
+			       "%s: User requested MSI, but MSI failed to "
+			       "initialize.  Continuing without MSI.\n",
+			       qdev->ndev->name);
+			qdev->msi = 0;
+		} else {
+			printk(KERN_INFO PFX "%s: MSI Enabled...\n", qdev->ndev->name);
+			set_bit(QL_MSI_ENABLED,&qdev->flags);
+			irq_flags &= ~SA_SHIRQ;
+		}
+	}
+
+	if ((err = request_irq(qdev->pdev->irq,
+			       ql3xxx_isr,
+			       irq_flags, ndev->name, ndev))) {
+		printk(KERN_ERR PFX
+		       "%s: Failed to reserve interrupt %d already in use.\n",
+		       ndev->name, qdev->pdev->irq);
+		goto err_irq;
+	}
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+
+	if ((err = ql_wait_for_drvr_lock(qdev))) {
+		if ((err = ql_adapter_initialize(qdev))) {
+			printk(KERN_ERR PFX
+			       "%s: Unable to initialize adapter.\n",
+			       ndev->name);
+			goto err_init;
+		}
+		printk(KERN_ERR PFX
+				"%s: Releaseing driver lock.\n",ndev->name);
+		ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
+	} else {
+		printk(KERN_ERR PFX
+		       "%s: Could not aquire driver lock.\n",
+		       ndev->name);
+		goto err_lock;
+	}
+
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+	set_bit(QL_ADAPTER_UP,&qdev->flags);
+
+	mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+
+	netif_poll_enable(ndev);
+	ql_enable_interrupts(qdev);
+	return 0;
+
+err_init:
+	ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
+err_lock:
+	free_irq(qdev->pdev->irq, ndev);
+err_irq:
+	if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
+		printk(KERN_INFO PFX
+		       "%s: calling pci_disable_msi().\n",
+		       qdev->ndev->name);
+		clear_bit(QL_MSI_ENABLED,&qdev->flags);
+		pci_disable_msi(qdev->pdev);
+	}
+	return err;
+}
+
+static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset)
+{
+	if( ql_adapter_down(qdev,reset) || ql_adapter_up(qdev)) {
+		printk(KERN_ERR PFX
+				"%s: Driver up/down cycle failed, "
+				"closing device\n",qdev->ndev->name);
+		dev_close(qdev->ndev);
+		return -1;
+	}
+	return 0;
+}
+
+static int ql3xxx_close(struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+
+	/*
+	 * Wait for device to recover from a reset.
+	 * (Rarely happens, but possible.)
+	 */
+	while (!test_bit(QL_ADAPTER_UP,&qdev->flags))
+		msleep(50);
+
+	ql_adapter_down(qdev,QL_DO_RESET);
+	return 0;
+}
+
+static int ql3xxx_open(struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	return (ql_adapter_up(qdev));
+}
+
+static struct net_device_stats *ql3xxx_get_stats(struct net_device *dev)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)dev->priv;
+	return &qdev->stats;
+}
+
+static int ql3xxx_change_mtu(struct net_device *ndev, int new_mtu)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	printk(KERN_ERR PFX "%s:  new mtu size = %d.\n", ndev->name, new_mtu);
+	if (new_mtu != NORMAL_MTU_SIZE && new_mtu != JUMBO_MTU_SIZE) {
+		printk(KERN_ERR PFX
+		       "%s: mtu size of %d is not valid.  Use exactly %d or "
+		       "%d.\n", ndev->name, new_mtu, NORMAL_MTU_SIZE,
+		       JUMBO_MTU_SIZE);
+		return -EINVAL;
+	}
+
+	if (!netif_running(ndev)) {
+		ndev->mtu = new_mtu;
+		return 0;
+	}
+
+	ndev->mtu = new_mtu;
+	return ql_cycle_adapter(qdev,QL_DO_RESET);
+}
+
+static void ql3xxx_set_multicast_list(struct net_device *ndev)
+{
+	/*
+	 * We are manually parsing the list in the net_device structure.
+	 */
+	return;
+}
+
+static int ql3xxx_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3xxx_port_registers __iomem *port_regs =
+	    		qdev->mem_map_registers;
+	struct sockaddr *addr = p;
+	unsigned long hw_flags;
+
+	if (netif_running(ndev))
+		return -EBUSY;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
+
+	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	/* Program lower 32 bits of the MAC address */
+	ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+			   (MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16));
+	ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+			   ((ndev->dev_addr[2] << 24) | (ndev->
+							 dev_addr[3] << 16) |
+			    (ndev->dev_addr[4] << 8) | ndev->dev_addr[5]));
+
+	/* Program top 16 bits of the MAC address */
+	ql_write_page0_reg(qdev, &port_regs->macAddrIndirectPtrReg,
+			   ((MAC_ADDR_INDIRECT_PTR_REG_RP_MASK << 16) | 1));
+	ql_write_page0_reg(qdev, &port_regs->macAddrDataReg,
+			   ((ndev->dev_addr[0] << 8) | ndev->dev_addr[1]));
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+	return 0;
+}
+
+static void ql3xxx_tx_timeout(struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+
+	printk(KERN_ERR PFX "%s: Resetting...\n", ndev->name);
+	/*
+	 * Stop the queues, we've got a problem.
+	 */
+	netif_stop_queue(ndev);
+
+	/*
+	 * Wake up the worker to process this event.
+	 */
+	queue_work(qdev->workqueue, &qdev->tx_timeout_work);
+}
+
+static void ql_reset_work(struct ql3_adapter *qdev)
+{
+	struct net_device *ndev = qdev->ndev;
+	u32 value;
+	struct ql_tx_buf_cb *tx_cb;
+	int max_wait_time, i;
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	unsigned long hw_flags;
+
+	if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START),&qdev->flags)) {
+		clear_bit(QL_LINK_MASTER,&qdev->flags);
+
+		/*
+		 * Loop through the active list and return the skb.
+		 */
+		for (i = 0; i < NUM_REQ_Q_ENTRIES; i++) {
+			tx_cb = &qdev->tx_buf[i];
+			if (tx_cb->skb) {
+
+				printk(KERN_DEBUG PFX
+				       "%s: Freeing lost SKB.\n",
+				       qdev->ndev->name);
+				pci_unmap_single(qdev->pdev,
+					pci_unmap_addr(tx_cb, mapaddr),
+					pci_unmap_len(tx_cb, maplen), PCI_DMA_TODEVICE);
+				dev_kfree_skb(tx_cb->skb);
+				tx_cb->skb = NULL;
+			}
+		}
+
+		printk(KERN_ERR PFX
+		       "%s: Clearing NRI after reset.\n", qdev->ndev->name);
+		spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.
+				    ispControlStatus,
+				    ((ISP_CONTROL_RI << 16) | ISP_CONTROL_RI));
+		/*
+		 * Wait the for Soft Reset to Complete.
+		 */
+		max_wait_time = 10;
+		do {
+			value = ql_read_common_reg(qdev,
+						   &port_regs->CommonRegs.
+
+						   ispControlStatus);
+			if ((value & ISP_CONTROL_SR) == 0) {
+				printk(KERN_DEBUG PFX
+				       "%s: reset completed.\n",
+				       qdev->ndev->name);
+				break;
+			}
+
+			if (value & ISP_CONTROL_RI) {
+				printk(KERN_DEBUG PFX
+				       "%s: clearing NRI after reset.\n",
+				       qdev->ndev->name);
+				ql_write_common_reg(qdev,
+						    (u32 *) &
+						    port_regs->
+						    CommonRegs.
+						    ispControlStatus,
+						    ((ISP_CONTROL_RI <<
+						      16) | ISP_CONTROL_RI));
+			}
+
+			ssleep(1);
+		} while (--max_wait_time);
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+		if (value & ISP_CONTROL_SR) {
+
+			/*
+			 * Set the reset flags and clear the board again.
+			 * Nothing else to do...
+			 */
+			printk(KERN_ERR PFX
+			       "%s: Timed out waiting for reset to "
+			       "complete.\n", ndev->name);
+			printk(KERN_ERR PFX
+			       "%s: Do a reset.\n", ndev->name);
+			clear_bit(QL_RESET_PER_SCSI,&qdev->flags);
+			clear_bit(QL_RESET_START,&qdev->flags);
+			ql_cycle_adapter(qdev,QL_DO_RESET);
+			return;
+		}
+
+		clear_bit(QL_RESET_ACTIVE,&qdev->flags);
+		clear_bit(QL_RESET_PER_SCSI,&qdev->flags);
+		clear_bit(QL_RESET_START,&qdev->flags);
+		ql_cycle_adapter(qdev,QL_NO_RESET);
+	}
+}
+
+static void ql_tx_timeout_work(struct ql3_adapter *qdev)
+{
+	ql_cycle_adapter(qdev,QL_DO_RESET);
+}
+
+static void ql_get_board_info(struct ql3_adapter *qdev)
+{
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	u32 value;
+
+	value = ql_read_page0_reg_l(qdev, &port_regs->portStatus);
+
+	qdev->chip_rev_id = ((value & PORT_STATUS_REV_ID_MASK) >> 12);
+	if (value & PORT_STATUS_64)
+		qdev->pci_width = 64;
+	else
+		qdev->pci_width = 32;
+	if (value & PORT_STATUS_X)
+		qdev->pci_x = 1;
+	else
+		qdev->pci_x = 0;
+	qdev->pci_slot = (u8) PCI_SLOT(qdev->pdev->devfn);
+}
+
+static void ql3xxx_timer(unsigned long ptr)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;
+
+	if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
+		printk(KERN_DEBUG PFX
+		       "%s: Reset in progress.\n",
+		       qdev->ndev->name);
+		goto end;
+	}
+
+	ql_link_state_machine(qdev);
+
+	/* Restart timer on 2 second interval. */
+end:
+	mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
+}
+
+static int __devinit ql3xxx_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *pci_entry)
+{
+	struct net_device *ndev = NULL;
+	struct ql3_adapter *qdev = NULL;
+	static int cards_found = 0;
+	int pci_using_dac, err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+		       pci_name(pdev));
+		goto err_out_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		pci_using_dac = 1;
+		err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+	} else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+		pci_using_dac = 0;
+		err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+	}
+
+	if (err) {
+		printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+		       pci_name(pdev));
+		goto err_out_free_regions;
+	}
+
+	ndev = alloc_etherdev(sizeof(struct ql3_adapter));
+	if (!ndev)
+		goto err_out_free_regions;
+
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	ndev->features = NETIF_F_LLTX;
+	if (pci_using_dac)
+		ndev->features |= NETIF_F_HIGHDMA;
+
+	pci_set_drvdata(pdev, ndev);
+
+	qdev = netdev_priv(ndev);
+	qdev->index = cards_found;
+	qdev->ndev = ndev;
+	qdev->pdev = pdev;
+	qdev->port_link_state = LS_DOWN;
+	if (msi)
+		qdev->msi = 1;
+
+	qdev->msg_enable = netif_msg_init(debug, default_msg);
+
+	qdev->mem_map_registers =
+	    ioremap_nocache(pci_resource_start(pdev, 1),
+			    pci_resource_len(qdev->pdev, 1));
+	if (!qdev->mem_map_registers) {
+		printk(KERN_ERR PFX "%s: cannot map device registers\n",
+		       pci_name(pdev));
+		goto err_out_free_ndev;
+	}
+
+	spin_lock_init(&qdev->adapter_lock);
+	spin_lock_init(&qdev->hw_lock);
+
+	/* Set driver entry points */
+	ndev->open = ql3xxx_open;
+	ndev->hard_start_xmit = ql3xxx_send;
+	ndev->stop = ql3xxx_close;
+	ndev->get_stats = ql3xxx_get_stats;
+	ndev->change_mtu = ql3xxx_change_mtu;
+	ndev->set_multicast_list = ql3xxx_set_multicast_list;
+	SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
+	ndev->set_mac_address = ql3xxx_set_mac_address;
+	ndev->tx_timeout = ql3xxx_tx_timeout;
+	ndev->watchdog_timeo = 5 * HZ;
+
+	ndev->poll = &ql_poll;
+	ndev->weight = 64;
+
+	ndev->irq = pdev->irq;
+
+	/* make sure the EEPROM is good */
+	if (ql_get_nvram_params(qdev)) {
+		printk(KERN_ALERT PFX
+		       "ql3xxx_probe: Adapter #%d, Invalid NVRAM parameters.\n",
+		       qdev->index);
+		goto err_out_iounmap;
+	}
+
+	ql_set_mac_info(qdev);
+
+	/* Validate and set parameters */
+	if (qdev->mac_index) {
+		memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn2.macAddress,
+		       ETH_ALEN);
+	} else {
+		memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn0.macAddress,
+		       ETH_ALEN);
+	}
+	memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
+
+	ndev->tx_queue_len = NUM_REQ_Q_ENTRIES;
+
+	/* Turn off support for multicasting */
+	ndev->flags &= ~IFF_MULTICAST;
+
+	/* Record PCI bus information. */
+	ql_get_board_info(qdev);
+
+	/*
+	 * Set the Maximum Memory Read Byte Count value. We do this to handle
+	 * jumbo frames.
+	 */
+	if (qdev->pci_x) {
+		pci_write_config_word(pdev, (int)0x4e, (u16) 0x0036);
+	}
+
+	err = register_netdev(ndev);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cannot register net device\n",
+		       pci_name(pdev));
+		goto err_out_iounmap;
+	}
+
+	/* we're going to reset, so assume we have no link for now */
+
+	netif_carrier_off(ndev);
+	netif_stop_queue(ndev);
+
+	qdev->workqueue = create_singlethread_workqueue(ndev->name);
+	INIT_WORK(&qdev->reset_work, (void (*)(void *))ql_reset_work, qdev);
+	INIT_WORK(&qdev->tx_timeout_work,
+		  (void (*)(void *))ql_tx_timeout_work, qdev);
+
+	init_timer(&qdev->adapter_timer);
+	qdev->adapter_timer.function = ql3xxx_timer;
+	qdev->adapter_timer.expires = jiffies + HZ * 2;	/* two second delay */
+	qdev->adapter_timer.data = (unsigned long)qdev;
+
+	if(!cards_found) {
+		printk(KERN_ALERT PFX "%s\n", DRV_STRING);
+		printk(KERN_ALERT PFX "Driver name: %s, Version: %s.\n",
+	    	   DRV_NAME, DRV_VERSION);
+	}
+	ql_display_dev_info(ndev);
+
+	cards_found++;
+	return 0;
+
+err_out_iounmap:
+	iounmap(qdev->mem_map_registers);
+err_out_free_ndev:
+	free_netdev(ndev);
+err_out_free_regions:
+	pci_release_regions(pdev);
+err_out_disable_pdev:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+err_out:
+	return err;
+}
+
+static void __devexit ql3xxx_remove(struct pci_dev *pdev)
+{
+	struct net_device *ndev = pci_get_drvdata(pdev);
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+
+	unregister_netdev(ndev);
+	qdev = netdev_priv(ndev);
+
+	ql_disable_interrupts(qdev);
+
+	if (qdev->workqueue) {
+		cancel_delayed_work(&qdev->reset_work);
+		cancel_delayed_work(&qdev->tx_timeout_work);
+		destroy_workqueue(qdev->workqueue);
+		qdev->workqueue = NULL;
+	}
+
+	iounmap((void *)qdev->mmap_virt_base);
+	pci_release_regions(pdev);
+	pci_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+}
+
+static struct pci_driver ql3xxx_driver = {
+
+	.name = DRV_NAME,
+	.id_table = ql3xxx_pci_tbl,
+	.probe = ql3xxx_probe,
+	.remove = __devexit_p(ql3xxx_remove),
+};
+
+static int __init ql3xxx_init_module(void)
+{
+	return pci_register_driver(&ql3xxx_driver);
+}
+
+static void __exit ql3xxx_exit(void)
+{
+	pci_unregister_driver(&ql3xxx_driver);
+}
+
+module_init(ql3xxx_init_module);
+module_exit(ql3xxx_exit);
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
new file mode 100644
index 0000000..9492cee
--- /dev/null
+++ b/drivers/net/qla3xxx.h
@@ -0,0 +1,1194 @@
+/*
+ * QLogic QLA3xxx NIC HBA Driver
+ * Copyright (c)  2003-2006 QLogic Corporation
+ *
+ * See LICENSE.qla3xxx for copyright and licensing details.
+ */
+#ifndef _QLA3XXX_H_
+#define _QLA3XXX_H_
+
+/*
+ * IOCB Definitions...
+ */
+#pragma pack(1)
+
+#define OPCODE_OB_MAC_IOCB_FN0          0x01
+#define OPCODE_OB_MAC_IOCB_FN2          0x21
+#define OPCODE_OB_TCP_IOCB_FN0          0x03
+#define OPCODE_OB_TCP_IOCB_FN2          0x23
+#define OPCODE_UPDATE_NCB_IOCB_FN0      0x00
+#define OPCODE_UPDATE_NCB_IOCB_FN2      0x20
+
+#define OPCODE_UPDATE_NCB_IOCB      0xF0
+#define OPCODE_IB_MAC_IOCB          0xF9
+#define OPCODE_IB_IP_IOCB           0xFA
+#define OPCODE_IB_TCP_IOCB          0xFB
+#define OPCODE_DUMP_PROTO_IOCB      0xFE
+#define OPCODE_BUFFER_ALERT_IOCB    0xFB
+
+#define OPCODE_FUNC_ID_MASK                 0x30
+#define OUTBOUND_MAC_IOCB                   0x01	/* plus function bits */
+#define OUTBOUND_TCP_IOCB                   0x03	/* plus function bits */
+#define UPDATE_NCB_IOCB                     0x00	/* plus function bits */
+
+#define FN0_MA_BITS_MASK    0x00
+#define FN1_MA_BITS_MASK    0x80
+
+struct ob_mac_iocb_req {
+	u8 opcode;
+	u8 flags;
+#define OB_MAC_IOCB_REQ_MA  0xC0
+#define OB_MAC_IOCB_REQ_F   0x20
+#define OB_MAC_IOCB_REQ_X   0x10
+#define OB_MAC_IOCB_REQ_D   0x02
+#define OB_MAC_IOCB_REQ_I   0x01
+	__le16 reserved0;
+
+	__le32 transaction_id;
+	__le16 data_len;
+	__le16 reserved1;
+	__le32 reserved2;
+	__le32 reserved3;
+	__le32 buf_addr0_low;
+	__le32 buf_addr0_high;
+	__le32 buf_0_len;
+	__le32 buf_addr1_low;
+	__le32 buf_addr1_high;
+	__le32 buf_1_len;
+	__le32 buf_addr2_low;
+	__le32 buf_addr2_high;
+	__le32 buf_2_len;
+	__le32 reserved4;
+	__le32 reserved5;
+};
+/*
+ * The following constants define control bits for buffer
+ * length fields for all IOCB's.
+ */
+#define OB_MAC_IOCB_REQ_E   0x80000000	/* Last valid buffer in list. */
+#define OB_MAC_IOCB_REQ_C   0x40000000	/* points to an OAL. (continuation) */
+#define OB_MAC_IOCB_REQ_L   0x20000000	/* Auburn local address pointer. */
+#define OB_MAC_IOCB_REQ_R   0x10000000	/* 32-bit address pointer. */
+
+struct ob_mac_iocb_rsp {
+	u8 opcode;
+	u8 flags;
+#define OB_MAC_IOCB_RSP_P   0x08
+#define OB_MAC_IOCB_RSP_S   0x02
+#define OB_MAC_IOCB_RSP_I   0x01
+
+	__le16 reserved0;
+	__le32 transaction_id;
+	__le32 reserved1;
+	__le32 reserved2;
+};
+
+struct ib_mac_iocb_rsp {
+	u8 opcode;
+	u8 flags;
+#define IB_MAC_IOCB_RSP_S   0x80
+#define IB_MAC_IOCB_RSP_H1  0x40
+#define IB_MAC_IOCB_RSP_H0  0x20
+#define IB_MAC_IOCB_RSP_B   0x10
+#define IB_MAC_IOCB_RSP_M   0x08
+#define IB_MAC_IOCB_RSP_MA  0x07
+
+	__le16 length;
+	__le32 reserved;
+	__le32 ial_low;
+	__le32 ial_high;
+
+};
+
+struct ob_ip_iocb_req {
+	u8 opcode;
+	__le16 flags;
+#define OB_IP_IOCB_REQ_O        0x100
+#define OB_IP_IOCB_REQ_H        0x008
+#define OB_IP_IOCB_REQ_U        0x004
+#define OB_IP_IOCB_REQ_D        0x002
+#define OB_IP_IOCB_REQ_I        0x001
+
+	u8 reserved0;
+
+	__le32 transaction_id;
+	__le16 data_len;
+	__le16 reserved1;
+	__le32 hncb_ptr_low;
+	__le32 hncb_ptr_high;
+	__le32 buf_addr0_low;
+	__le32 buf_addr0_high;
+	__le32 buf_0_len;
+	__le32 buf_addr1_low;
+	__le32 buf_addr1_high;
+	__le32 buf_1_len;
+	__le32 buf_addr2_low;
+	__le32 buf_addr2_high;
+	__le32 buf_2_len;
+	__le32 reserved2;
+	__le32 reserved3;
+};
+
+/* defines for BufferLength fields above */
+#define OB_IP_IOCB_REQ_E    0x80000000
+#define OB_IP_IOCB_REQ_C    0x40000000
+#define OB_IP_IOCB_REQ_L    0x20000000
+#define OB_IP_IOCB_REQ_R    0x10000000
+
+struct ob_ip_iocb_rsp {
+	u8 opcode;
+	u8 flags;
+#define OB_MAC_IOCB_RSP_E       0x08
+#define OB_MAC_IOCB_RSP_L       0x04
+#define OB_MAC_IOCB_RSP_S       0x02
+#define OB_MAC_IOCB_RSP_I       0x01
+
+	__le16 reserved0;
+	__le32 transaction_id;
+	__le32 reserved1;
+	__le32 reserved2;
+};
+
+struct ob_tcp_iocb_req {
+	u8 opcode;
+
+	u8 flags0;
+#define OB_TCP_IOCB_REQ_P       0x80
+#define OB_TCP_IOCB_REQ_CI      0x20
+#define OB_TCP_IOCB_REQ_H       0x10
+#define OB_TCP_IOCB_REQ_LN      0x08
+#define OB_TCP_IOCB_REQ_K       0x04
+#define OB_TCP_IOCB_REQ_D       0x02
+#define OB_TCP_IOCB_REQ_I       0x01
+
+	u8 flags1;
+#define OB_TCP_IOCB_REQ_OSM     0x40
+#define OB_TCP_IOCB_REQ_URG     0x20
+#define OB_TCP_IOCB_REQ_ACK     0x10
+#define OB_TCP_IOCB_REQ_PSH     0x08
+#define OB_TCP_IOCB_REQ_RST     0x04
+#define OB_TCP_IOCB_REQ_SYN     0x02
+#define OB_TCP_IOCB_REQ_FIN     0x01
+
+	u8 options_len;
+#define OB_TCP_IOCB_REQ_OMASK   0xF0
+#define OB_TCP_IOCB_REQ_SHIFT   4
+
+	__le32 transaction_id;
+	__le32 data_len;
+	__le32 hncb_ptr_low;
+	__le32 hncb_ptr_high;
+	__le32 buf_addr0_low;
+	__le32 buf_addr0_high;
+	__le32 buf_0_len;
+	__le32 buf_addr1_low;
+	__le32 buf_addr1_high;
+	__le32 buf_1_len;
+	__le32 buf_addr2_low;
+	__le32 buf_addr2_high;
+	__le32 buf_2_len;
+	__le32 time_stamp;
+	__le32 reserved1;
+};
+
+struct ob_tcp_iocb_rsp {
+	u8 opcode;
+
+	u8 flags0;
+#define OB_TCP_IOCB_RSP_C       0x20
+#define OB_TCP_IOCB_RSP_H       0x10
+#define OB_TCP_IOCB_RSP_LN      0x08
+#define OB_TCP_IOCB_RSP_K       0x04
+#define OB_TCP_IOCB_RSP_D       0x02
+#define OB_TCP_IOCB_RSP_I       0x01
+
+	u8 flags1;
+#define OB_TCP_IOCB_RSP_E       0x10
+#define OB_TCP_IOCB_RSP_W       0x08
+#define OB_TCP_IOCB_RSP_P       0x04
+#define OB_TCP_IOCB_RSP_T       0x02
+#define OB_TCP_IOCB_RSP_F       0x01
+
+	u8 state;
+#define OB_TCP_IOCB_RSP_SMASK   0xF0
+#define OB_TCP_IOCB_RSP_SHIFT   4
+
+	__le32 transaction_id;
+	__le32 local_ncb_ptr;
+	__le32 reserved0;
+};
+
+struct ib_ip_iocb_rsp {
+	u8 opcode;
+	u8 flags;
+#define IB_IP_IOCB_RSP_S        0x80
+#define IB_IP_IOCB_RSP_H1       0x40
+#define IB_IP_IOCB_RSP_H0       0x20
+#define IB_IP_IOCB_RSP_B        0x10
+#define IB_IP_IOCB_RSP_M        0x08
+#define IB_IP_IOCB_RSP_MA       0x07
+
+	__le16 length;
+	__le16 checksum;
+	__le16 reserved;
+#define IB_IP_IOCB_RSP_R        0x01
+	__le32 ial_low;
+	__le32 ial_high;
+};
+
+struct ib_tcp_iocb_rsp {
+	u8 opcode;
+	u8 flags;
+#define IB_TCP_IOCB_RSP_P       0x80
+#define IB_TCP_IOCB_RSP_T       0x40
+#define IB_TCP_IOCB_RSP_D       0x20
+#define IB_TCP_IOCB_RSP_N       0x10
+#define IB_TCP_IOCB_RSP_IP      0x03
+#define IB_TCP_FLAG_MASK        0xf0
+#define IB_TCP_FLAG_IOCB_SYN    0x00
+
+#define TCP_IB_RSP_FLAGS(x) (x->flags & ~IB_TCP_FLAG_MASK)
+
+	__le16 length;
+	__le32 hncb_ref_num;
+	__le32 ial_low;
+	__le32 ial_high;
+};
+
+struct net_rsp_iocb {
+	u8 opcode;
+	u8 flags;
+	__le16 reserved0;
+	__le32 reserved[3];
+};
+#pragma pack()
+
+/*
+ * Register Definitions...
+ */
+#define PORT0_PHY_ADDRESS   0x1e00
+#define PORT1_PHY_ADDRESS   0x1f00
+
+#define ETHERNET_CRC_SIZE   4
+
+#define MII_SCAN_REGISTER 0x00000001
+
+/* 32-bit ispControlStatus */
+enum {
+	ISP_CONTROL_NP_MASK = 0x0003,
+	ISP_CONTROL_NP_PCSR = 0x0000,
+	ISP_CONTROL_NP_HMCR = 0x0001,
+	ISP_CONTROL_NP_LRAMCR = 0x0002,
+	ISP_CONTROL_NP_PSR = 0x0003,
+	ISP_CONTROL_RI = 0x0008,
+	ISP_CONTROL_CI = 0x0010,
+	ISP_CONTROL_PI = 0x0020,
+	ISP_CONTROL_IN = 0x0040,
+	ISP_CONTROL_BE = 0x0080,
+	ISP_CONTROL_FN_MASK = 0x0700,
+	ISP_CONTROL_FN0_NET = 0x0400,
+	ISP_CONTROL_FN0_SCSI = 0x0500,
+	ISP_CONTROL_FN1_NET = 0x0600,
+	ISP_CONTROL_FN1_SCSI = 0x0700,
+	ISP_CONTROL_LINK_DN_0 = 0x0800,
+	ISP_CONTROL_LINK_DN_1 = 0x1000,
+	ISP_CONTROL_FSR = 0x2000,
+	ISP_CONTROL_FE = 0x4000,
+	ISP_CONTROL_SR = 0x8000,
+};
+
+/* 32-bit ispInterruptMaskReg */
+enum {
+	ISP_IMR_ENABLE_INT = 0x0004,
+	ISP_IMR_DISABLE_RESET_INT = 0x0008,
+	ISP_IMR_DISABLE_CMPL_INT = 0x0010,
+	ISP_IMR_DISABLE_PROC_INT = 0x0020,
+};
+
+/* 32-bit serialPortInterfaceReg */
+enum {
+	ISP_SERIAL_PORT_IF_CLK = 0x0001,
+	ISP_SERIAL_PORT_IF_CS = 0x0002,
+	ISP_SERIAL_PORT_IF_D0 = 0x0004,
+	ISP_SERIAL_PORT_IF_DI = 0x0008,
+	ISP_NVRAM_MASK = (0x000F << 16),
+	ISP_SERIAL_PORT_IF_WE = 0x0010,
+	ISP_SERIAL_PORT_IF_NVR_MASK = 0x001F,
+	ISP_SERIAL_PORT_IF_SCI = 0x0400,
+	ISP_SERIAL_PORT_IF_SC0 = 0x0800,
+	ISP_SERIAL_PORT_IF_SCE = 0x1000,
+	ISP_SERIAL_PORT_IF_SDI = 0x2000,
+	ISP_SERIAL_PORT_IF_SDO = 0x4000,
+	ISP_SERIAL_PORT_IF_SDE = 0x8000,
+	ISP_SERIAL_PORT_IF_I2C_MASK = 0xFC00,
+};
+
+/* semaphoreReg */
+enum {
+	QL_RESOURCE_MASK_BASE_CODE = 0x7,
+	QL_RESOURCE_BITS_BASE_CODE = 0x4,
+	QL_DRVR_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 1),
+	QL_DDR_RAM_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 4),
+	QL_PHY_GIO_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 7),
+	QL_NVRAM_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 10),
+	QL_FLASH_SEM_BITS = (QL_RESOURCE_BITS_BASE_CODE << 13),
+	QL_DRVR_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (1 + 16)),
+	QL_DDR_RAM_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (4 + 16)),
+	QL_PHY_GIO_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (7 + 16)),
+	QL_NVRAM_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (10 + 16)),
+	QL_FLASH_SEM_MASK = (QL_RESOURCE_MASK_BASE_CODE << (13 + 16)),
+};
+
+ /*
+  * QL3XXX memory-mapped registers
+  * QL3XXX has 4 "pages" of registers, each page occupying
+  * 256 bytes.  Each page has a "common" area at the start and then
+  * page-specific registers after that.
+  */
+struct ql3xxx_common_registers {
+	u32 MB0;		/* Offset 0x00 */
+	u32 MB1;		/* Offset 0x04 */
+	u32 MB2;		/* Offset 0x08 */
+	u32 MB3;		/* Offset 0x0c */
+	u32 MB4;		/* Offset 0x10 */
+	u32 MB5;		/* Offset 0x14 */
+	u32 MB6;		/* Offset 0x18 */
+	u32 MB7;		/* Offset 0x1c */
+	u32 flashBiosAddr;
+	u32 flashBiosData;
+	u32 ispControlStatus;
+	u32 ispInterruptMaskReg;
+	u32 serialPortInterfaceReg;
+	u32 semaphoreReg;
+	u32 reqQProducerIndex;
+	u32 rspQConsumerIndex;
+
+	u32 rxLargeQProducerIndex;
+	u32 rxSmallQProducerIndex;
+	u32 arcMadiCommand;
+	u32 arcMadiData;
+};
+
+enum {
+	EXT_HW_CONFIG_SP_MASK = 0x0006,
+	EXT_HW_CONFIG_SP_NONE = 0x0000,
+	EXT_HW_CONFIG_SP_BYTE_PARITY = 0x0002,
+	EXT_HW_CONFIG_SP_ECC = 0x0004,
+	EXT_HW_CONFIG_SP_ECCx = 0x0006,
+	EXT_HW_CONFIG_SIZE_MASK = 0x0060,
+	EXT_HW_CONFIG_SIZE_128M = 0x0000,
+	EXT_HW_CONFIG_SIZE_256M = 0x0020,
+	EXT_HW_CONFIG_SIZE_512M = 0x0040,
+	EXT_HW_CONFIG_SIZE_INVALID = 0x0060,
+	EXT_HW_CONFIG_PD = 0x0080,
+	EXT_HW_CONFIG_FW = 0x0200,
+	EXT_HW_CONFIG_US = 0x0400,
+	EXT_HW_CONFIG_DCS_MASK = 0x1800,
+	EXT_HW_CONFIG_DCS_9MA = 0x0000,
+	EXT_HW_CONFIG_DCS_15MA = 0x0800,
+	EXT_HW_CONFIG_DCS_18MA = 0x1000,
+	EXT_HW_CONFIG_DCS_24MA = 0x1800,
+	EXT_HW_CONFIG_DDS_MASK = 0x6000,
+	EXT_HW_CONFIG_DDS_9MA = 0x0000,
+	EXT_HW_CONFIG_DDS_15MA = 0x2000,
+	EXT_HW_CONFIG_DDS_18MA = 0x4000,
+	EXT_HW_CONFIG_DDS_24MA = 0x6000,
+};
+
+/* InternalChipConfig */
+enum {
+	INTERNAL_CHIP_DM = 0x0001,
+	INTERNAL_CHIP_SD = 0x0002,
+	INTERNAL_CHIP_RAP_MASK = 0x000C,
+	INTERNAL_CHIP_RAP_RR = 0x0000,
+	INTERNAL_CHIP_RAP_NRM = 0x0004,
+	INTERNAL_CHIP_RAP_ERM = 0x0008,
+	INTERNAL_CHIP_RAP_ERMx = 0x000C,
+	INTERNAL_CHIP_WE = 0x0010,
+	INTERNAL_CHIP_EF = 0x0020,
+	INTERNAL_CHIP_FR = 0x0040,
+	INTERNAL_CHIP_FW = 0x0080,
+	INTERNAL_CHIP_FI = 0x0100,
+	INTERNAL_CHIP_FT = 0x0200,
+};
+
+/* portControl */
+enum {
+	PORT_CONTROL_DS = 0x0001,
+	PORT_CONTROL_HH = 0x0002,
+	PORT_CONTROL_EI = 0x0004,
+	PORT_CONTROL_ET = 0x0008,
+	PORT_CONTROL_EF = 0x0010,
+	PORT_CONTROL_DRM = 0x0020,
+	PORT_CONTROL_RLB = 0x0040,
+	PORT_CONTROL_RCB = 0x0080,
+	PORT_CONTROL_MAC = 0x0100,
+	PORT_CONTROL_IPV = 0x0200,
+	PORT_CONTROL_IFP = 0x0400,
+	PORT_CONTROL_ITP = 0x0800,
+	PORT_CONTROL_FI = 0x1000,
+	PORT_CONTROL_DFP = 0x2000,
+	PORT_CONTROL_OI = 0x4000,
+	PORT_CONTROL_CC = 0x8000,
+};
+
+/* portStatus */
+enum {
+	PORT_STATUS_SM0 = 0x0001,
+	PORT_STATUS_SM1 = 0x0002,
+	PORT_STATUS_X = 0x0008,
+	PORT_STATUS_DL = 0x0080,
+	PORT_STATUS_IC = 0x0200,
+	PORT_STATUS_MRC = 0x0400,
+	PORT_STATUS_NL = 0x0800,
+	PORT_STATUS_REV_ID_MASK = 0x7000,
+	PORT_STATUS_REV_ID_1 = 0x1000,
+	PORT_STATUS_REV_ID_2 = 0x2000,
+	PORT_STATUS_REV_ID_3 = 0x3000,
+	PORT_STATUS_64 = 0x8000,
+	PORT_STATUS_UP0 = 0x10000,
+	PORT_STATUS_AC0 = 0x20000,
+	PORT_STATUS_AE0 = 0x40000,
+	PORT_STATUS_UP1 = 0x100000,
+	PORT_STATUS_AC1 = 0x200000,
+	PORT_STATUS_AE1 = 0x400000,
+	PORT_STATUS_F0_ENABLED = 0x1000000,
+	PORT_STATUS_F1_ENABLED = 0x2000000,
+	PORT_STATUS_F2_ENABLED = 0x4000000,
+	PORT_STATUS_F3_ENABLED = 0x8000000,
+};
+
+/* macMIIMgmtControlReg */
+enum {
+	MAC_ADDR_INDIRECT_PTR_REG_RP_MASK = 0x0003,
+	MAC_ADDR_INDIRECT_PTR_REG_RP_PRI_LWR = 0x0000,
+	MAC_ADDR_INDIRECT_PTR_REG_RP_PRI_UPR = 0x0001,
+	MAC_ADDR_INDIRECT_PTR_REG_RP_SEC_LWR = 0x0002,
+	MAC_ADDR_INDIRECT_PTR_REG_RP_SEC_UPR = 0x0003,
+	MAC_ADDR_INDIRECT_PTR_REG_PR = 0x0008,
+	MAC_ADDR_INDIRECT_PTR_REG_SS = 0x0010,
+	MAC_ADDR_INDIRECT_PTR_REG_SE = 0x0020,
+	MAC_ADDR_INDIRECT_PTR_REG_SP = 0x0040,
+	MAC_ADDR_INDIRECT_PTR_REG_PE = 0x0080,
+};
+
+/* macMIIMgmtControlReg */
+enum {
+	MAC_MII_CONTROL_RC = 0x0001,
+	MAC_MII_CONTROL_SC = 0x0002,
+	MAC_MII_CONTROL_AS = 0x0004,
+	MAC_MII_CONTROL_NP = 0x0008,
+	MAC_MII_CONTROL_CLK_SEL_MASK = 0x0070,
+	MAC_MII_CONTROL_CLK_SEL_DIV2 = 0x0000,
+	MAC_MII_CONTROL_CLK_SEL_DIV4 = 0x0010,
+	MAC_MII_CONTROL_CLK_SEL_DIV6 = 0x0020,
+	MAC_MII_CONTROL_CLK_SEL_DIV8 = 0x0030,
+	MAC_MII_CONTROL_CLK_SEL_DIV10 = 0x0040,
+	MAC_MII_CONTROL_CLK_SEL_DIV14 = 0x0050,
+	MAC_MII_CONTROL_CLK_SEL_DIV20 = 0x0060,
+	MAC_MII_CONTROL_CLK_SEL_DIV28 = 0x0070,
+	MAC_MII_CONTROL_RM = 0x8000,
+};
+
+/* macMIIStatusReg */
+enum {
+	MAC_MII_STATUS_BSY = 0x0001,
+	MAC_MII_STATUS_SC = 0x0002,
+	MAC_MII_STATUS_NV = 0x0004,
+};
+
+enum {
+	MAC_CONFIG_REG_PE = 0x0001,
+	MAC_CONFIG_REG_TF = 0x0002,
+	MAC_CONFIG_REG_RF = 0x0004,
+	MAC_CONFIG_REG_FD = 0x0008,
+	MAC_CONFIG_REG_GM = 0x0010,
+	MAC_CONFIG_REG_LB = 0x0020,
+	MAC_CONFIG_REG_SR = 0x8000,
+};
+
+enum {
+	MAC_HALF_DUPLEX_REG_ED = 0x10000,
+	MAC_HALF_DUPLEX_REG_NB = 0x20000,
+	MAC_HALF_DUPLEX_REG_BNB = 0x40000,
+	MAC_HALF_DUPLEX_REG_ALT = 0x80000,
+};
+
+enum {
+	IP_ADDR_INDEX_REG_MASK = 0x000f,
+	IP_ADDR_INDEX_REG_FUNC_0_PRI = 0x0000,
+	IP_ADDR_INDEX_REG_FUNC_0_SEC = 0x0001,
+	IP_ADDR_INDEX_REG_FUNC_1_PRI = 0x0002,
+	IP_ADDR_INDEX_REG_FUNC_1_SEC = 0x0003,
+	IP_ADDR_INDEX_REG_FUNC_2_PRI = 0x0004,
+	IP_ADDR_INDEX_REG_FUNC_2_SEC = 0x0005,
+	IP_ADDR_INDEX_REG_FUNC_3_PRI = 0x0006,
+	IP_ADDR_INDEX_REG_FUNC_3_SEC = 0x0007,
+};
+
+enum {
+	PROBE_MUX_ADDR_REG_MUX_SEL_MASK = 0x003f,
+	PROBE_MUX_ADDR_REG_SYSCLK = 0x0000,
+	PROBE_MUX_ADDR_REG_PCICLK = 0x0040,
+	PROBE_MUX_ADDR_REG_NRXCLK = 0x0080,
+	PROBE_MUX_ADDR_REG_CPUCLK = 0x00C0,
+	PROBE_MUX_ADDR_REG_MODULE_SEL_MASK = 0x3f00,
+	PROBE_MUX_ADDR_REG_UP = 0x4000,
+	PROBE_MUX_ADDR_REG_RE = 0x8000,
+};
+
+enum {
+	STATISTICS_INDEX_REG_MASK = 0x01ff,
+	STATISTICS_INDEX_REG_MAC0_TX_FRAME = 0x0000,
+	STATISTICS_INDEX_REG_MAC0_TX_BYTES = 0x0001,
+	STATISTICS_INDEX_REG_MAC0_TX_STAT1 = 0x0002,
+	STATISTICS_INDEX_REG_MAC0_TX_STAT2 = 0x0003,
+	STATISTICS_INDEX_REG_MAC0_TX_STAT3 = 0x0004,
+	STATISTICS_INDEX_REG_MAC0_TX_STAT4 = 0x0005,
+	STATISTICS_INDEX_REG_MAC0_TX_STAT5 = 0x0006,
+	STATISTICS_INDEX_REG_MAC0_RX_FRAME = 0x0007,
+	STATISTICS_INDEX_REG_MAC0_RX_BYTES = 0x0008,
+	STATISTICS_INDEX_REG_MAC0_RX_STAT1 = 0x0009,
+	STATISTICS_INDEX_REG_MAC0_RX_STAT2 = 0x000a,
+	STATISTICS_INDEX_REG_MAC0_RX_STAT3 = 0x000b,
+	STATISTICS_INDEX_REG_MAC0_RX_ERR_CRC = 0x000c,
+	STATISTICS_INDEX_REG_MAC0_RX_ERR_ENC = 0x000d,
+	STATISTICS_INDEX_REG_MAC0_RX_ERR_LEN = 0x000e,
+	STATISTICS_INDEX_REG_MAC0_RX_STAT4 = 0x000f,
+	STATISTICS_INDEX_REG_MAC1_TX_FRAME = 0x0010,
+	STATISTICS_INDEX_REG_MAC1_TX_BYTES = 0x0011,
+	STATISTICS_INDEX_REG_MAC1_TX_STAT1 = 0x0012,
+	STATISTICS_INDEX_REG_MAC1_TX_STAT2 = 0x0013,
+	STATISTICS_INDEX_REG_MAC1_TX_STAT3 = 0x0014,
+	STATISTICS_INDEX_REG_MAC1_TX_STAT4 = 0x0015,
+	STATISTICS_INDEX_REG_MAC1_TX_STAT5 = 0x0016,
+	STATISTICS_INDEX_REG_MAC1_RX_FRAME = 0x0017,
+	STATISTICS_INDEX_REG_MAC1_RX_BYTES = 0x0018,
+	STATISTICS_INDEX_REG_MAC1_RX_STAT1 = 0x0019,
+	STATISTICS_INDEX_REG_MAC1_RX_STAT2 = 0x001a,
+	STATISTICS_INDEX_REG_MAC1_RX_STAT3 = 0x001b,
+	STATISTICS_INDEX_REG_MAC1_RX_ERR_CRC = 0x001c,
+	STATISTICS_INDEX_REG_MAC1_RX_ERR_ENC = 0x001d,
+	STATISTICS_INDEX_REG_MAC1_RX_ERR_LEN = 0x001e,
+	STATISTICS_INDEX_REG_MAC1_RX_STAT4 = 0x001f,
+	STATISTICS_INDEX_REG_IP_TX_PKTS = 0x0020,
+	STATISTICS_INDEX_REG_IP_TX_BYTES = 0x0021,
+	STATISTICS_INDEX_REG_IP_TX_FRAG = 0x0022,
+	STATISTICS_INDEX_REG_IP_RX_PKTS = 0x0023,
+	STATISTICS_INDEX_REG_IP_RX_BYTES = 0x0024,
+	STATISTICS_INDEX_REG_IP_RX_FRAG = 0x0025,
+	STATISTICS_INDEX_REG_IP_DGRM_REASSEMBLY = 0x0026,
+	STATISTICS_INDEX_REG_IP_V6_RX_PKTS = 0x0027,
+	STATISTICS_INDEX_REG_IP_RX_PKTERR = 0x0028,
+	STATISTICS_INDEX_REG_IP_REASSEMBLY_ERR = 0x0029,
+	STATISTICS_INDEX_REG_TCP_TX_SEG = 0x0030,
+	STATISTICS_INDEX_REG_TCP_TX_BYTES = 0x0031,
+	STATISTICS_INDEX_REG_TCP_RX_SEG = 0x0032,
+	STATISTICS_INDEX_REG_TCP_RX_BYTES = 0x0033,
+	STATISTICS_INDEX_REG_TCP_TIMER_EXP = 0x0034,
+	STATISTICS_INDEX_REG_TCP_RX_ACK = 0x0035,
+	STATISTICS_INDEX_REG_TCP_TX_ACK = 0x0036,
+	STATISTICS_INDEX_REG_TCP_RX_ERR = 0x0037,
+	STATISTICS_INDEX_REG_TCP_RX_WIN_PROBE = 0x0038,
+	STATISTICS_INDEX_REG_TCP_ECC_ERR_CORR = 0x003f,
+};
+
+enum {
+	PORT_FATAL_ERROR_STATUS_OFB_RE_MAC0 = 0x00000001,
+	PORT_FATAL_ERROR_STATUS_OFB_RE_MAC1 = 0x00000002,
+	PORT_FATAL_ERROR_STATUS_OFB_WE = 0x00000004,
+	PORT_FATAL_ERROR_STATUS_IFB_RE = 0x00000008,
+	PORT_FATAL_ERROR_STATUS_IFB_WE_MAC0 = 0x00000010,
+	PORT_FATAL_ERROR_STATUS_IFB_WE_MAC1 = 0x00000020,
+	PORT_FATAL_ERROR_STATUS_ODE_RE = 0x00000040,
+	PORT_FATAL_ERROR_STATUS_ODE_WE = 0x00000080,
+	PORT_FATAL_ERROR_STATUS_IDE_RE = 0x00000100,
+	PORT_FATAL_ERROR_STATUS_IDE_WE = 0x00000200,
+	PORT_FATAL_ERROR_STATUS_SDE_RE = 0x00000400,
+	PORT_FATAL_ERROR_STATUS_SDE_WE = 0x00000800,
+	PORT_FATAL_ERROR_STATUS_BLE = 0x00001000,
+	PORT_FATAL_ERROR_STATUS_SPE = 0x00002000,
+	PORT_FATAL_ERROR_STATUS_EP0 = 0x00004000,
+	PORT_FATAL_ERROR_STATUS_EP1 = 0x00008000,
+	PORT_FATAL_ERROR_STATUS_ICE = 0x00010000,
+	PORT_FATAL_ERROR_STATUS_ILE = 0x00020000,
+	PORT_FATAL_ERROR_STATUS_OPE = 0x00040000,
+	PORT_FATAL_ERROR_STATUS_TA = 0x00080000,
+	PORT_FATAL_ERROR_STATUS_MA = 0x00100000,
+	PORT_FATAL_ERROR_STATUS_SCE = 0x00200000,
+	PORT_FATAL_ERROR_STATUS_RPE = 0x00400000,
+	PORT_FATAL_ERROR_STATUS_MPE = 0x00800000,
+	PORT_FATAL_ERROR_STATUS_OCE = 0x01000000,
+};
+
+/*
+ *  port control and status page - page 0
+ */
+
+struct ql3xxx_port_registers {
+	struct ql3xxx_common_registers CommonRegs;
+
+	u32 ExternalHWConfig;
+	u32 InternalChipConfig;
+	u32 portControl;
+	u32 portStatus;
+	u32 macAddrIndirectPtrReg;
+	u32 macAddrDataReg;
+	u32 macMIIMgmtControlReg;
+	u32 macMIIMgmtAddrReg;
+	u32 macMIIMgmtDataReg;
+	u32 macMIIStatusReg;
+	u32 mac0ConfigReg;
+	u32 mac0IpgIfgReg;
+	u32 mac0HalfDuplexReg;
+	u32 mac0MaxFrameLengthReg;
+	u32 mac0PauseThresholdReg;
+	u32 mac1ConfigReg;
+	u32 mac1IpgIfgReg;
+	u32 mac1HalfDuplexReg;
+	u32 mac1MaxFrameLengthReg;
+	u32 mac1PauseThresholdReg;
+	u32 ipAddrIndexReg;
+	u32 ipAddrDataReg;
+	u32 ipReassemblyTimeout;
+	u32 tcpMaxWindow;
+	u32 currentTcpTimestamp[2];
+	u32 internalRamRWAddrReg;
+	u32 internalRamWDataReg;
+	u32 reclaimedBufferAddrRegLow;
+	u32 reclaimedBufferAddrRegHigh;
+	u32 reserved[2];
+	u32 fpgaRevID;
+	u32 localRamAddr;
+	u32 localRamDataAutoIncr;
+	u32 localRamDataNonIncr;
+	u32 gpOutput;
+	u32 gpInput;
+	u32 probeMuxAddr;
+	u32 probeMuxData;
+	u32 statisticsIndexReg;
+	u32 statisticsReadDataRegAutoIncr;
+	u32 statisticsReadDataRegNoIncr;
+	u32 PortFatalErrStatus;
+};
+
+/*
+ * port host memory config page - page 1
+ */
+struct ql3xxx_host_memory_registers {
+	struct ql3xxx_common_registers CommonRegs;
+
+	u32 reserved[12];
+
+	/* Network Request Queue */
+	u32 reqConsumerIndex;
+	u32 reqConsumerIndexAddrLow;
+	u32 reqConsumerIndexAddrHigh;
+	u32 reqBaseAddrLow;
+	u32 reqBaseAddrHigh;
+	u32 reqLength;
+
+	/* Network Completion Queue */
+	u32 rspProducerIndex;
+	u32 rspProducerIndexAddrLow;
+	u32 rspProducerIndexAddrHigh;
+	u32 rspBaseAddrLow;
+	u32 rspBaseAddrHigh;
+	u32 rspLength;
+
+	/* RX Large Buffer Queue */
+	u32 rxLargeQConsumerIndex;
+	u32 rxLargeQBaseAddrLow;
+	u32 rxLargeQBaseAddrHigh;
+	u32 rxLargeQLength;
+	u32 rxLargeBufferLength;
+
+	/* RX Small Buffer Queue */
+	u32 rxSmallQConsumerIndex;
+	u32 rxSmallQBaseAddrLow;
+	u32 rxSmallQBaseAddrHigh;
+	u32 rxSmallQLength;
+	u32 rxSmallBufferLength;
+
+};
+
+/*
+ *  port local RAM page - page 2
+ */
+struct ql3xxx_local_ram_registers {
+	struct ql3xxx_common_registers CommonRegs;
+	u32 bufletSize;
+	u32 maxBufletCount;
+	u32 currentBufletCount;
+	u32 reserved;
+	u32 freeBufletThresholdLow;
+	u32 freeBufletThresholdHigh;
+	u32 ipHashTableBase;
+	u32 ipHashTableCount;
+	u32 tcpHashTableBase;
+	u32 tcpHashTableCount;
+	u32 ncbBase;
+	u32 maxNcbCount;
+	u32 currentNcbCount;
+	u32 drbBase;
+	u32 maxDrbCount;
+	u32 currentDrbCount;
+};
+
+/*
+ * definitions for Semaphore bits in Semaphore/Serial NVRAM interface register
+ */
+
+#define LS_64BITS(x)    (u32)(0xffffffff & ((u64)x))
+#define MS_64BITS(x)    (u32)(0xffffffff & (((u64)x)>>16>>16) )
+
+/*
+ * I/O register
+ */
+
+enum {
+	CONTROL_REG = 0,
+	STATUS_REG = 1,
+	PHY_STAT_LINK_UP = 0x0004,
+	PHY_CTRL_LOOPBACK = 0x4000,
+
+	PETBI_CONTROL_REG = 0x00,
+	PETBI_CTRL_SOFT_RESET = 0x8000,
+	PETBI_CTRL_AUTO_NEG = 0x1000,
+	PETBI_CTRL_RESTART_NEG = 0x0200,
+	PETBI_CTRL_FULL_DUPLEX = 0x0100,
+	PETBI_CTRL_SPEED_1000 = 0x0040,
+
+	PETBI_STATUS_REG = 0x01,
+	PETBI_STAT_NEG_DONE = 0x0020,
+	PETBI_STAT_LINK_UP = 0x0004,
+
+	PETBI_NEG_ADVER = 0x04,
+	PETBI_NEG_PAUSE = 0x0080,
+	PETBI_NEG_PAUSE_MASK = 0x0180,
+	PETBI_NEG_DUPLEX = 0x0020,
+	PETBI_NEG_DUPLEX_MASK = 0x0060,
+
+	PETBI_NEG_PARTNER = 0x05,
+	PETBI_NEG_ERROR_MASK = 0x3000,
+
+	PETBI_EXPANSION_REG = 0x06,
+	PETBI_EXP_PAGE_RX = 0x0002,
+
+	PETBI_TBI_CTRL = 0x11,
+	PETBI_TBI_RESET = 0x8000,
+	PETBI_TBI_AUTO_SENSE = 0x0100,
+	PETBI_TBI_SERDES_MODE = 0x0010,
+	PETBI_TBI_SERDES_WRAP = 0x0002,
+
+	AUX_CONTROL_STATUS = 0x1c,
+	PHY_AUX_NEG_DONE = 0x8000,
+	PHY_NEG_PARTNER = 5,
+	PHY_AUX_DUPLEX_STAT = 0x0020,
+	PHY_AUX_SPEED_STAT = 0x0018,
+	PHY_AUX_NO_HW_STRAP = 0x0004,
+	PHY_AUX_RESET_STICK = 0x0002,
+	PHY_NEG_PAUSE = 0x0400,
+	PHY_CTRL_SOFT_RESET = 0x8000,
+	PHY_NEG_ADVER = 4,
+	PHY_NEG_ADV_SPEED = 0x01e0,
+	PHY_CTRL_RESTART_NEG = 0x0200,
+};
+enum {
+/* AM29LV Flash definitions	*/
+	FM93C56A_START = 0x1,
+/* Commands */
+	FM93C56A_READ = 0x2,
+	FM93C56A_WEN = 0x0,
+	FM93C56A_WRITE = 0x1,
+	FM93C56A_WRITE_ALL = 0x0,
+	FM93C56A_WDS = 0x0,
+	FM93C56A_ERASE = 0x3,
+	FM93C56A_ERASE_ALL = 0x0,
+/* Command Extentions */
+	FM93C56A_WEN_EXT = 0x3,
+	FM93C56A_WRITE_ALL_EXT = 0x1,
+	FM93C56A_WDS_EXT = 0x0,
+	FM93C56A_ERASE_ALL_EXT = 0x2,
+/* Special Bits */
+	FM93C56A_READ_DUMMY_BITS = 1,
+	FM93C56A_READY = 0,
+	FM93C56A_BUSY = 1,
+	FM93C56A_CMD_BITS = 2,
+/* AM29LV Flash definitions	*/
+	FM93C56A_SIZE_8 = 0x100,
+	FM93C56A_SIZE_16 = 0x80,
+	FM93C66A_SIZE_8 = 0x200,
+	FM93C66A_SIZE_16 = 0x100,
+	FM93C86A_SIZE_16 = 0x400,
+/* Address Bits */
+	FM93C56A_NO_ADDR_BITS_16 = 8,
+	FM93C56A_NO_ADDR_BITS_8 = 9,
+	FM93C86A_NO_ADDR_BITS_16 = 10,
+/* Data Bits */
+	FM93C56A_DATA_BITS_16 = 16,
+	FM93C56A_DATA_BITS_8 = 8,
+};
+enum {
+/* Auburn Bits */
+	    AUBURN_EEPROM_DI = 0x8,
+	AUBURN_EEPROM_DI_0 = 0x0,
+	AUBURN_EEPROM_DI_1 = 0x8,
+	AUBURN_EEPROM_DO = 0x4,
+	AUBURN_EEPROM_DO_0 = 0x0,
+	AUBURN_EEPROM_DO_1 = 0x4,
+	AUBURN_EEPROM_CS = 0x2,
+	AUBURN_EEPROM_CS_0 = 0x0,
+	AUBURN_EEPROM_CS_1 = 0x2,
+	AUBURN_EEPROM_CLK_RISE = 0x1,
+	AUBURN_EEPROM_CLK_FALL = 0x0,
+};
+enum {EEPROM_SIZE = FM93C86A_SIZE_16,
+	EEPROM_NO_ADDR_BITS = FM93C86A_NO_ADDR_BITS_16,
+	EEPROM_NO_DATA_BITS = FM93C56A_DATA_BITS_16,
+};
+
+/*
+ *  MAC Config data structure
+ */
+    struct eeprom_port_cfg {
+	u16 etherMtu_mac;
+	u16 pauseThreshold_mac;
+	u16 resumeThreshold_mac;
+	u16 portConfiguration;
+#define PORT_CONFIG_AUTO_NEG_ENABLED        0x8000
+#define PORT_CONFIG_SYM_PAUSE_ENABLED       0x4000
+#define PORT_CONFIG_FULL_DUPLEX_ENABLED     0x2000
+#define PORT_CONFIG_HALF_DUPLEX_ENABLED     0x1000
+#define PORT_CONFIG_1000MB_SPEED            0x0400
+#define PORT_CONFIG_100MB_SPEED             0x0200
+#define PORT_CONFIG_10MB_SPEED              0x0100
+#define PORT_CONFIG_LINK_SPEED_MASK         0x0F00
+	u16 reserved[12];
+
+};
+
+/*
+ * BIOS data structure
+ */
+struct eeprom_bios_cfg {
+	u16 SpinDlyEn:1, disBios:1, EnMemMap:1, EnSelectBoot:1, Reserved:12;
+
+	u8 bootID0:7, boodID0Valid:1;
+	u8 bootLun0[8];
+
+	u8 bootID1:7, boodID1Valid:1;
+	u8 bootLun1[8];
+
+	u16 MaxLunsTrgt;
+	u8 reserved[10];
+};
+
+/*
+ *  Function Specific Data structure
+ */
+struct eeprom_function_cfg {
+	u8 reserved[30];
+	u8 macAddress[6];
+	u8 macAddressSecondary[6];
+
+	u16 subsysVendorId;
+	u16 subsysDeviceId;
+};
+
+/*
+ *  EEPROM format
+ */
+struct eeprom_data {
+	u8 asicId[4];
+	u8 version;
+	u8 numPorts;
+	u16 boardId;
+
+#define EEPROM_BOARDID_STR_SIZE   16
+#define EEPROM_SERIAL_NUM_SIZE    16
+
+	u8 boardIdStr[16];
+	u8 serialNumber[16];
+	u16 extHwConfig;
+	struct eeprom_port_cfg macCfg_port0;
+	struct eeprom_port_cfg macCfg_port1;
+	u16 bufletSize;
+	u16 bufletCount;
+	u16 tcpWindowThreshold50;
+	u16 tcpWindowThreshold25;
+	u16 tcpWindowThreshold0;
+	u16 ipHashTableBaseHi;
+	u16 ipHashTableBaseLo;
+	u16 ipHashTableSize;
+	u16 tcpHashTableBaseHi;
+	u16 tcpHashTableBaseLo;
+	u16 tcpHashTableSize;
+	u16 ncbTableBaseHi;
+	u16 ncbTableBaseLo;
+	u16 ncbTableSize;
+	u16 drbTableBaseHi;
+	u16 drbTableBaseLo;
+	u16 drbTableSize;
+	u16 reserved_142[4];
+	u16 ipReassemblyTimeout;
+	u16 tcpMaxWindowSize;
+	u16 ipSecurity;
+#define IPSEC_CONFIG_PRESENT 0x0001
+	u8 reserved_156[294];
+	u16 qDebug[8];
+	struct eeprom_function_cfg funcCfg_fn0;
+	u16 reserved_510;
+	u8 oemSpace[432];
+	struct eeprom_bios_cfg biosCfg_fn1;
+	struct eeprom_function_cfg funcCfg_fn1;
+	u16 reserved_1022;
+	u8 reserved_1024[464];
+	struct eeprom_function_cfg funcCfg_fn2;
+	u16 reserved_1534;
+	u8 reserved_1536[432];
+	struct eeprom_bios_cfg biosCfg_fn3;
+	struct eeprom_function_cfg funcCfg_fn3;
+	u16 checksum;
+};
+
+/*
+ * General definitions...
+ */
+
+/*
+ * Below are a number compiler switches for controlling driver behavior.
+ * Some are not supported under certain conditions and are notated as such.
+ */
+
+#define QL3XXX_VENDOR_ID    0x1077
+#define QL3022_DEVICE_ID    0x3022
+
+/* MTU & Frame Size stuff */
+#define NORMAL_MTU_SIZE 		ETH_DATA_LEN
+#define JUMBO_MTU_SIZE 			9000
+#define VLAN_ID_LEN			    2
+
+/* Request Queue Related Definitions */
+#define NUM_REQ_Q_ENTRIES   256	/* so that 64 * 64  = 4096 (1 page) */
+
+/* Response Queue Related Definitions */
+#define NUM_RSP_Q_ENTRIES   256	/* so that 256 * 16  = 4096 (1 page) */
+
+/* Transmit and Receive Buffers */
+#define NUM_LBUFQ_ENTRIES   	128
+#define NUM_SBUFQ_ENTRIES   	64
+#define QL_SMALL_BUFFER_SIZE    32
+#define QL_ADDR_ELE_PER_BUFQ_ENTRY \
+(sizeof(struct lrg_buf_q_entry) / sizeof(struct bufq_addr_element))
+    /* Each send has at least control block.  This is how many we keep. */
+#define NUM_SMALL_BUFFERS     	NUM_SBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+#define NUM_LARGE_BUFFERS     	NUM_LBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+#define QL_HEADER_SPACE 32	/* make header space at top of skb. */
+/*
+ * Large & Small Buffers for Receives
+ */
+struct lrg_buf_q_entry {
+
+	u32 addr0_lower;
+#define IAL_LAST_ENTRY 0x00000001
+#define IAL_CONT_ENTRY 0x00000002
+#define IAL_FLAG_MASK  0x00000003
+	u32 addr0_upper;
+	u32 addr1_lower;
+	u32 addr1_upper;
+	u32 addr2_lower;
+	u32 addr2_upper;
+	u32 addr3_lower;
+	u32 addr3_upper;
+	u32 addr4_lower;
+	u32 addr4_upper;
+	u32 addr5_lower;
+	u32 addr5_upper;
+	u32 addr6_lower;
+	u32 addr6_upper;
+	u32 addr7_lower;
+	u32 addr7_upper;
+
+};
+
+struct bufq_addr_element {
+	u32 addr_low;
+	u32 addr_high;
+};
+
+#define QL_NO_RESET			0
+#define QL_DO_RESET			1
+
+enum link_state_t {
+	LS_UNKNOWN = 0,
+	LS_DOWN,
+	LS_DEGRADE,
+	LS_RECOVER,
+	LS_UP,
+};
+
+struct ql_rcv_buf_cb {
+	struct ql_rcv_buf_cb *next;
+	struct sk_buff *skb;
+	 DECLARE_PCI_UNMAP_ADDR(mapaddr);
+	 DECLARE_PCI_UNMAP_LEN(maplen);
+	__le32 buf_phy_addr_low;
+	__le32 buf_phy_addr_high;
+	int index;
+};
+
+struct ql_tx_buf_cb {
+	struct sk_buff *skb;
+	struct ob_mac_iocb_req *queue_entry ;
+	 DECLARE_PCI_UNMAP_ADDR(mapaddr);
+	 DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+/* definitions for type field */
+#define QL_BUF_TYPE_MACIOCB 0x01
+#define QL_BUF_TYPE_IPIOCB  0x02
+#define QL_BUF_TYPE_TCPIOCB 0x03
+
+/* qdev->flags definitions. */
+enum { QL_RESET_DONE = 1,	/* Reset finished. */
+	QL_RESET_ACTIVE = 2,	/* Waiting for reset to finish. */
+	QL_RESET_START = 3,	/* Please reset the chip. */
+	QL_RESET_PER_SCSI = 4,	/* SCSI driver requests reset. */
+	QL_TX_TIMEOUT = 5,	/* Timeout in progress. */
+	QL_LINK_MASTER = 6,	/* This driver controls the link. */
+	QL_ADAPTER_UP = 7,	/* Adapter has been brought up. */
+	QL_THREAD_UP = 8,	/* This flag is available. */
+	QL_LINK_UP = 9,	/* Link Status. */
+	QL_ALLOC_REQ_RSP_Q_DONE = 10,
+	QL_ALLOC_BUFQS_DONE = 11,
+	QL_ALLOC_SMALL_BUF_DONE = 12,
+	QL_LINK_OPTICAL = 13,
+	QL_MSI_ENABLED = 14,
+};
+
+/*
+ * ql3_adapter - The main Adapter structure definition.
+ * This structure has all fields relevant to the hardware.
+ */
+
+struct ql3_adapter {
+	u32 reserved_00;
+	unsigned long flags;
+
+	/* PCI Configuration information for this device */
+	struct pci_dev *pdev;
+	struct net_device *ndev;	/* Parent NET device */
+
+	/* Hardware information */
+	u8 chip_rev_id;
+	u8 pci_slot;
+	u8 pci_width;
+	u8 pci_x;
+	u32 msi;
+	int index;
+	struct timer_list adapter_timer;	/* timer used for various functions */
+
+	spinlock_t adapter_lock;
+	spinlock_t hw_lock;
+
+	/* PCI Bus Relative Register Addresses */
+	u8 *mmap_virt_base;	/* stores return value from ioremap() */
+	struct ql3xxx_port_registers __iomem *mem_map_registers;
+	u32 current_page;	/* tracks current register page */
+
+	u32 msg_enable;
+	u8 reserved_01[2];
+	u8 reserved_02[2];
+
+	/* Page for Shadow Registers */
+	void *shadow_reg_virt_addr;
+	dma_addr_t shadow_reg_phy_addr;
+
+	/* Net Request Queue */
+	u32 req_q_size;
+	u32 reserved_03;
+	struct ob_mac_iocb_req *req_q_virt_addr;
+	dma_addr_t req_q_phy_addr;
+	u16 req_producer_index;
+	u16 reserved_04;
+	u16 *preq_consumer_index;
+	u32 req_consumer_index_phy_addr_high;
+	u32 req_consumer_index_phy_addr_low;
+	atomic_t tx_count;
+	struct ql_tx_buf_cb tx_buf[NUM_REQ_Q_ENTRIES];
+
+	/* Net Response Queue */
+	u32 rsp_q_size;
+	u32 eeprom_cmd_data;
+	struct net_rsp_iocb *rsp_q_virt_addr;
+	dma_addr_t rsp_q_phy_addr;
+	struct net_rsp_iocb *rsp_current;
+	u16 rsp_consumer_index;
+	u16 reserved_06;
+	u32 *prsp_producer_index;
+	u32 rsp_producer_index_phy_addr_high;
+	u32 rsp_producer_index_phy_addr_low;
+
+	/* Large Buffer Queue */
+	u32 lrg_buf_q_alloc_size;
+	u32 lrg_buf_q_size;
+	void *lrg_buf_q_alloc_virt_addr;
+	void *lrg_buf_q_virt_addr;
+	dma_addr_t lrg_buf_q_alloc_phy_addr;
+	dma_addr_t lrg_buf_q_phy_addr;
+	u32 lrg_buf_q_producer_index;
+	u32 lrg_buf_release_cnt;
+	struct bufq_addr_element *lrg_buf_next_free;
+
+	/* Large (Receive) Buffers */
+	struct ql_rcv_buf_cb lrg_buf[NUM_LARGE_BUFFERS];
+	struct ql_rcv_buf_cb *lrg_buf_free_head;
+	struct ql_rcv_buf_cb *lrg_buf_free_tail;
+	u32 lrg_buf_free_count;
+	u32 lrg_buffer_len;
+	u32 lrg_buf_index;
+	u32 lrg_buf_skb_check;
+
+	/* Small Buffer Queue */
+	u32 small_buf_q_alloc_size;
+	u32 small_buf_q_size;
+	u32 small_buf_q_producer_index;
+	void *small_buf_q_alloc_virt_addr;
+	void *small_buf_q_virt_addr;
+	dma_addr_t small_buf_q_alloc_phy_addr;
+	dma_addr_t small_buf_q_phy_addr;
+	u32 small_buf_index;
+
+	/* Small (Receive) Buffers */
+	void *small_buf_virt_addr;
+	dma_addr_t small_buf_phy_addr;
+	u32 small_buf_phy_addr_low;
+	u32 small_buf_phy_addr_high;
+	u32 small_buf_release_cnt;
+	u32 small_buf_total_size;
+
+	/* ISR related, saves status for DPC. */
+	u32 control_status;
+
+	struct eeprom_data nvram_data;
+	struct timer_list ioctl_timer;
+	u32 port_link_state;
+	u32 last_rsp_offset;
+
+	/* 4022 specific */
+	u32 mac_index;		/* Driver's MAC number can be 0 or 1 for first and second networking functions respectively */
+	u32 PHYAddr;		/* Address of PHY 0x1e00 Port 0 and 0x1f00 Port 1 */
+	u32 mac_ob_opcode;	/* Opcode to use on mac transmission */
+	u32 tcp_ob_opcode;	/* Opcode to use on tcp transmission */
+	u32 update_ob_opcode;	/* Opcode to use for updating NCB */
+	u32 mb_bit_mask;	/* MA Bits mask to use on transmission */
+	u32 numPorts;
+	struct net_device_stats stats;
+	struct workqueue_struct *workqueue;
+	struct work_struct reset_work;
+	struct work_struct tx_timeout_work;
+	u32 max_frame_size;
+};
+
+#endif				/* _QLA3XXX_H_ */
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 805562b..ebb948b 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -2913,7 +2913,7 @@
 static int __init
 rtl8169_init_module(void)
 {
-	return pci_module_init(&rtl8169_pci_driver);
+	return pci_register_driver(&rtl8169_pci_driver);
 }
 
 static void __exit
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index c3ed734..31bcdad 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1736,7 +1736,7 @@
 
 static int __init rr_init_module(void)
 {
-	return pci_module_init(&rr_driver);
+	return pci_register_driver(&rr_driver);
 }
 
 static void __exit rr_cleanup_module(void)
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e1fe3a0..c16f915 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -71,12 +71,13 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/div64.h>
+#include <asm/irq.h>
 
 /* local include */
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.14.2"
+#define DRV_VERSION "2.0.15.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -370,38 +371,50 @@
 	END_SIGN
 };
 
+MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+
 /* Module Loadable parameters. */
-static unsigned int tx_fifo_num = 1;
+S2IO_PARM_INT(tx_fifo_num, 1);
+S2IO_PARM_INT(rx_ring_num, 1);
+
+
+S2IO_PARM_INT(rx_ring_mode, 1);
+S2IO_PARM_INT(use_continuous_tx_intrs, 1);
+S2IO_PARM_INT(rmac_pause_time, 0x100);
+S2IO_PARM_INT(mc_pause_threshold_q0q3, 187);
+S2IO_PARM_INT(mc_pause_threshold_q4q7, 187);
+S2IO_PARM_INT(shared_splits, 0);
+S2IO_PARM_INT(tmac_util_period, 5);
+S2IO_PARM_INT(rmac_util_period, 5);
+S2IO_PARM_INT(bimodal, 0);
+S2IO_PARM_INT(l3l4hdr_size, 128);
+/* Frequency of Rx desc syncs expressed as power of 2 */
+S2IO_PARM_INT(rxsync_frequency, 3);
+/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
+S2IO_PARM_INT(intr_type, 0);
+/* Large receive offload feature */
+S2IO_PARM_INT(lro, 0);
+/* Max pkts to be aggregated by LRO at one time. If not specified,
+ * aggregation happens until we hit max IP pkt size(64K)
+ */
+S2IO_PARM_INT(lro_max_pkts, 0xFFFF);
+#ifndef CONFIG_S2IO_NAPI
+S2IO_PARM_INT(indicate_max_pkts, 0);
+#endif
+
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
     {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
-static unsigned int rx_ring_num = 1;
 static unsigned int rx_ring_sz[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
 static unsigned int rts_frm_len[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
-static unsigned int rx_ring_mode = 1;
-static unsigned int use_continuous_tx_intrs = 1;
-static unsigned int rmac_pause_time = 0x100;
-static unsigned int mc_pause_threshold_q0q3 = 187;
-static unsigned int mc_pause_threshold_q4q7 = 187;
-static unsigned int shared_splits;
-static unsigned int tmac_util_period = 5;
-static unsigned int rmac_util_period = 5;
-static unsigned int bimodal = 0;
-static unsigned int l3l4hdr_size = 128;
-#ifndef CONFIG_S2IO_NAPI
-static unsigned int indicate_max_pkts;
-#endif
-/* Frequency of Rx desc syncs expressed as power of 2 */
-static unsigned int rxsync_frequency = 3;
-/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
-static unsigned int intr_type = 0;
-/* Large receive offload feature */
-static unsigned int lro = 0;
-/* Max pkts to be aggregated by LRO at one time. If not specified,
- * aggregation happens until we hit max IP pkt size(64K)
- */
-static unsigned int lro_max_pkts = 0xFFFF;
+
+module_param_array(tx_fifo_len, uint, NULL, 0);
+module_param_array(rx_ring_sz, uint, NULL, 0);
+module_param_array(rts_frm_len, uint, NULL, 0);
 
 /*
  * S2IO device table.
@@ -464,10 +477,9 @@
 		size += config->tx_cfg[i].fifo_len;
 	}
 	if (size > MAX_AVAILABLE_TXDS) {
-		DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ",
-			  __FUNCTION__);
+		DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, ");
 		DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);
-		return FAILURE;
+		return -EINVAL;
 	}
 
 	lst_size = (sizeof(TxD_t) * config->max_txds);
@@ -547,6 +559,7 @@
 	nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL);
 	if (!nic->ufo_in_band_v)
 		return -ENOMEM;
+	memset(nic->ufo_in_band_v, 0, size);
 
 	/* Allocation and initialization of RXDs in Rings */
 	size = 0;
@@ -1213,7 +1226,7 @@
 		break;
 	}
 
-	/* Enable Tx FIFO partition 0. */
+	/* Enable all configured Tx FIFO partitions */
 	val64 = readq(&bar0->tx_fifo_partition_0);
 	val64 |= (TX_FIFO_PARTITION_EN);
 	writeq(val64, &bar0->tx_fifo_partition_0);
@@ -1650,7 +1663,7 @@
 			writeq(temp64, &bar0->general_int_mask);
 			/*
 			 * If Hercules adapter enable GPIO otherwise
-			 * disabled all PCIX, Flash, MDIO, IIC and GPIO
+			 * disable all PCIX, Flash, MDIO, IIC and GPIO
 			 * interrupts for now.
 			 * TODO
 			 */
@@ -2119,7 +2132,7 @@
 				       frag->size, PCI_DMA_TODEVICE);
 		}
 	}
-	txdlp->Host_Control = 0;
+	memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds));
 	return(skb);
 }
 
@@ -2371,9 +2384,14 @@
 			skb->data = (void *) (unsigned long)tmp;
 			skb->tail = (void *) (unsigned long)tmp;
 
-			((RxD3_t*)rxdp)->Buffer0_ptr =
-			    pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
+			if (!(((RxD3_t*)rxdp)->Buffer0_ptr))
+				((RxD3_t*)rxdp)->Buffer0_ptr =
+				   pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN,
 					   PCI_DMA_FROMDEVICE);
+			else
+				pci_dma_sync_single_for_device(nic->pdev,
+				    (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr,
+				    BUF0_LEN, PCI_DMA_FROMDEVICE);
 			rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
 			if (nic->rxd_mode == RXD_MODE_3B) {
 				/* Two buffer mode */
@@ -2386,10 +2404,13 @@
 				(nic->pdev, skb->data, dev->mtu + 4,
 						PCI_DMA_FROMDEVICE);
 
-				/* Buffer-1 will be dummy buffer not used */
-				((RxD3_t*)rxdp)->Buffer1_ptr =
-				pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN,
-					PCI_DMA_FROMDEVICE);
+				/* Buffer-1 will be dummy buffer. Not used */
+				if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) {
+					((RxD3_t*)rxdp)->Buffer1_ptr =
+						pci_map_single(nic->pdev, 
+						ba->ba_1, BUF1_LEN,
+						PCI_DMA_FROMDEVICE);
+				}
 				rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
 				rxdp->Control_2 |= SET_BUFFER2_SIZE_3
 								(dev->mtu + 4);
@@ -2614,23 +2635,23 @@
 }
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
 /**
- * s2io_netpoll - Rx interrupt service handler for netpoll support
+ * s2io_netpoll - netpoll event handler entry point
  * @dev : pointer to the device structure.
  * Description:
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
+ * 	This function will be called by upper layer to check for events on the
+ * interface in situations where interrupts are disabled. It is used for
+ * specific in-kernel networking tasks, such as remote consoles and kernel
+ * debugging over the network (example netdump in RedHat).
  */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
 static void s2io_netpoll(struct net_device *dev)
 {
 	nic_t *nic = dev->priv;
 	mac_info_t *mac_control;
 	struct config_param *config;
 	XENA_dev_config_t __iomem *bar0 = nic->bar0;
-	u64 val64;
+	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
 	int i;
 
 	disable_irq(dev->irq);
@@ -2639,9 +2660,17 @@
 	mac_control = &nic->mac_control;
 	config = &nic->config;
 
-	val64 = readq(&bar0->rx_traffic_int);
 	writeq(val64, &bar0->rx_traffic_int);
+	writeq(val64, &bar0->tx_traffic_int);
 
+	/* we need to free up the transmitted skbufs or else netpoll will 
+	 * run out of skbs and will fail and eventually netpoll application such
+	 * as netdump will fail.
+	 */
+	for (i = 0; i < config->tx_fifo_num; i++)
+		tx_intr_handler(&mac_control->fifos[i]);
+
+	/* check for received packet and indicate up to network */
 	for (i = 0; i < config->rx_ring_num; i++)
 		rx_intr_handler(&mac_control->rings[i]);
 
@@ -2708,7 +2737,7 @@
 		/* If your are next to put index then it's FIFO full condition */
 		if ((get_block == put_block) &&
 		    (get_info.offset + 1) == put_info.offset) {
-			DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name);
+			DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name);
 			break;
 		}
 		skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control);
@@ -2728,18 +2757,15 @@
 				 HEADER_SNAP_SIZE,
 				 PCI_DMA_FROMDEVICE);
 		} else if (nic->rxd_mode == RXD_MODE_3B) {
-			pci_unmap_single(nic->pdev, (dma_addr_t)
+			pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
 				 ((RxD3_t*)rxdp)->Buffer0_ptr,
 				 BUF0_LEN, PCI_DMA_FROMDEVICE);
 			pci_unmap_single(nic->pdev, (dma_addr_t)
-				 ((RxD3_t*)rxdp)->Buffer1_ptr,
-				 BUF1_LEN, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(nic->pdev, (dma_addr_t)
 				 ((RxD3_t*)rxdp)->Buffer2_ptr,
 				 dev->mtu + 4,
 				 PCI_DMA_FROMDEVICE);
 		} else {
-			pci_unmap_single(nic->pdev, (dma_addr_t)
+			pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t)
 					 ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN,
 					 PCI_DMA_FROMDEVICE);
 			pci_unmap_single(nic->pdev, (dma_addr_t)
@@ -3327,7 +3353,7 @@
 
 	/* Clear certain PCI/PCI-X fields after reset */
 	if (sp->device_type == XFRAME_II_DEVICE) {
-		/* Clear parity err detect bit */
+		/* Clear "detected parity error" bit */
 		pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000);
 
 		/* Clearing PCIX Ecc status register */
@@ -3528,7 +3554,7 @@
 	u64 val64;
 	int i;
 
-	for (i=0; i< nic->avail_msix_vectors; i++) {
+	for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
 		writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
 		writeq(nic->msix_info[i].data, &bar0->xmsi_data);
 		val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
@@ -3547,7 +3573,7 @@
 	int i;
 
 	/* Store and display */
-	for (i=0; i< nic->avail_msix_vectors; i++) {
+	for (i=0; i < MAX_REQUESTED_MSI_X; i++) {
 		val64 = (BIT(15) | vBIT(i, 26, 6));
 		writeq(val64, &bar0->xmsi_access);
 		if (wait_for_msix_trans(nic, i)) {
@@ -3808,13 +3834,11 @@
 	TxD_t *txdp;
 	TxFIFO_element_t __iomem *tx_fifo;
 	unsigned long flags;
-#ifdef NETIF_F_TSO
-	int mss;
-#endif
 	u16 vlan_tag = 0;
 	int vlan_priority = 0;
 	mac_info_t *mac_control;
 	struct config_param *config;
+	int offload_type;
 
 	mac_control = &sp->mac_control;
 	config = &sp->config;
@@ -3862,13 +3886,11 @@
 		return 0;
 	}
 
-	txdp->Control_1 = 0;
-	txdp->Control_2 = 0;
+	offload_type = s2io_offload_type(skb);
 #ifdef NETIF_F_TSO
-	mss = skb_shinfo(skb)->gso_size;
-	if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+	if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
 		txdp->Control_1 |= TXD_TCP_LSO_EN;
-		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
+		txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb));
 	}
 #endif
 	if (skb->ip_summed == CHECKSUM_HW) {
@@ -3886,10 +3908,10 @@
 	}
 
 	frg_len = skb->len - skb->data_len;
-	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) {
+	if (offload_type == SKB_GSO_UDP) {
 		int ufo_size;
 
-		ufo_size = skb_shinfo(skb)->gso_size;
+		ufo_size = s2io_udp_mss(skb);
 		ufo_size &= ~7;
 		txdp->Control_1 |= TXD_UFO_EN;
 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
@@ -3906,16 +3928,13 @@
 					sp->ufo_in_band_v,
 					sizeof(u64), PCI_DMA_TODEVICE);
 		txdp++;
-		txdp->Control_1 = 0;
-		txdp->Control_2 = 0;
 	}
 
 	txdp->Buffer_Pointer = pci_map_single
 	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE);
 	txdp->Host_Control = (unsigned long) skb;
 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
-
-	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
+	if (offload_type == SKB_GSO_UDP)
 		txdp->Control_1 |= TXD_UFO_EN;
 
 	frg_cnt = skb_shinfo(skb)->nr_frags;
@@ -3930,12 +3949,12 @@
 		    (sp->pdev, frag->page, frag->page_offset,
 		     frag->size, PCI_DMA_TODEVICE);
 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
-		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
+		if (offload_type == SKB_GSO_UDP)
 			txdp->Control_1 |= TXD_UFO_EN;
 	}
 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
-	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
+	if (offload_type == SKB_GSO_UDP)
 		frg_cnt++; /* as Txd0 was used for inband header */
 
 	tx_fifo = mac_control->tx_FIFO_start[queue];
@@ -3944,13 +3963,9 @@
 
 	val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |
 		 TX_FIFO_LAST_LIST);
+	if (offload_type)
+		val64 |= TX_FIFO_SPECIAL_FUNC;
 
-#ifdef NETIF_F_TSO
-	if (mss)
-		val64 |= TX_FIFO_SPECIAL_FUNC;
-#endif
-	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP)
-		val64 |= TX_FIFO_SPECIAL_FUNC;
 	writeq(val64, &tx_fifo->List_Control);
 
 	mmiowb();
@@ -3984,13 +3999,41 @@
 	mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
 }
 
+static int s2io_chk_rx_buffers(nic_t *sp, int rng_n)
+{
+	int rxb_size, level;
+
+	if (!sp->lro) {
+		rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
+		level = rx_buffer_level(sp, rxb_size, rng_n);
+
+		if ((level == PANIC) && (!TASKLET_IN_USE)) {
+			int ret;
+			DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
+			DBG_PRINT(INTR_DBG, "PANIC levels\n");
+			if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
+				DBG_PRINT(ERR_DBG, "Out of memory in %s",
+					  __FUNCTION__);
+				clear_bit(0, (&sp->tasklet_status));
+				return -1;
+			}
+			clear_bit(0, (&sp->tasklet_status));
+		} else if (level == LOW)
+			tasklet_schedule(&sp->task);
+
+	} else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
+			DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name);
+			DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
+	}
+	return 0;
+}
+
 static irqreturn_t
 s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	nic_t *sp = dev->priv;
 	int i;
-	int ret;
 	mac_info_t *mac_control;
 	struct config_param *config;
 
@@ -4012,35 +4055,8 @@
 	 * reallocate the buffers from the interrupt handler itself,
 	 * else schedule a tasklet to reallocate the buffers.
 	 */
-	for (i = 0; i < config->rx_ring_num; i++) {
-		if (!sp->lro) {
-			int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
-			int level = rx_buffer_level(sp, rxb_size, i);
-
-			if ((level == PANIC) && (!TASKLET_IN_USE)) {
-				DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", 
-							dev->name);
-				DBG_PRINT(INTR_DBG, "PANIC levels\n");
-				if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
-					DBG_PRINT(ERR_DBG, "%s:Out of memory",
-						  dev->name);
-					DBG_PRINT(ERR_DBG, " in ISR!!\n");
-					clear_bit(0, (&sp->tasklet_status));
-					atomic_dec(&sp->isr_cnt);
-					return IRQ_HANDLED;
-				}
-				clear_bit(0, (&sp->tasklet_status));
-			} else if (level == LOW) {
-				tasklet_schedule(&sp->task);
-			}
-		}
-		else if (fill_rx_buffers(sp, i) == -ENOMEM) {
-				DBG_PRINT(ERR_DBG, "%s:Out of memory",
-							dev->name);
-				DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
-				break;
-		}
-	}
+	for (i = 0; i < config->rx_ring_num; i++)
+		s2io_chk_rx_buffers(sp, i);
 
 	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
@@ -4051,39 +4067,13 @@
 {
 	ring_info_t *ring = (ring_info_t *)dev_id;
 	nic_t *sp = ring->nic;
-	struct net_device *dev = (struct net_device *) dev_id;
-	int rxb_size, level, rng_n;
 
 	atomic_inc(&sp->isr_cnt);
+
 	rx_intr_handler(ring);
-
-	rng_n = ring->ring_no;
-	if (!sp->lro) {
-		rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
-		level = rx_buffer_level(sp, rxb_size, rng_n);
-
-		if ((level == PANIC) && (!TASKLET_IN_USE)) {
-			int ret;
-			DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
-			DBG_PRINT(INTR_DBG, "PANIC levels\n");
-			if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
-				DBG_PRINT(ERR_DBG, "Out of memory in %s",
-					  __FUNCTION__);
-				clear_bit(0, (&sp->tasklet_status));
-				return IRQ_HANDLED;
-			}
-			clear_bit(0, (&sp->tasklet_status));
-		} else if (level == LOW) {
-			tasklet_schedule(&sp->task);
-		}
-	}
-	else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) {
-			DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
-			DBG_PRINT(ERR_DBG, " in Rx Intr!!\n");
-	}
+	s2io_chk_rx_buffers(sp, ring->ring_no);
 
 	atomic_dec(&sp->isr_cnt);
-
 	return IRQ_HANDLED;
 }
 
@@ -4248,37 +4238,8 @@
 	 * else schedule a tasklet to reallocate the buffers.
 	 */
 #ifndef CONFIG_S2IO_NAPI
-	for (i = 0; i < config->rx_ring_num; i++) {
-		if (!sp->lro) {
-			int ret;
-			int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
-			int level = rx_buffer_level(sp, rxb_size, i);
-
-			if ((level == PANIC) && (!TASKLET_IN_USE)) {
-				DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", 
-							dev->name);
-				DBG_PRINT(INTR_DBG, "PANIC levels\n");
-				if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
-					DBG_PRINT(ERR_DBG, "%s:Out of memory",
-						  dev->name);
-					DBG_PRINT(ERR_DBG, " in ISR!!\n");
-					clear_bit(0, (&sp->tasklet_status));
-					atomic_dec(&sp->isr_cnt);
-					writeq(org_mask, &bar0->general_int_mask);
-					return IRQ_HANDLED;
-				}
-				clear_bit(0, (&sp->tasklet_status));
-			} else if (level == LOW) {
-				tasklet_schedule(&sp->task);
-			}
-		}
-		else if (fill_rx_buffers(sp, i) == -ENOMEM) {
-				DBG_PRINT(ERR_DBG, "%s:Out of memory",
-							dev->name);
-				DBG_PRINT(ERR_DBG, " in Rx intr!!\n");
-				break;
-		}
-	}
+	for (i = 0; i < config->rx_ring_num; i++)
+		s2io_chk_rx_buffers(sp, i);
 #endif
 	writeq(org_mask, &bar0->general_int_mask);
 	atomic_dec(&sp->isr_cnt);
@@ -4308,6 +4269,8 @@
 			if (cnt == 5)
 				break; /* Updt failed */
 		} while(1);
+	} else {
+		memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t));
 	}
 }
 
@@ -4942,7 +4905,8 @@
 }
 static void s2io_vpd_read(nic_t *nic)
 {
-	u8 vpd_data[256],data;
+	u8 *vpd_data;
+	u8 data;
 	int i=0, cnt, fail = 0;
 	int vpd_addr = 0x80;
 
@@ -4955,6 +4919,10 @@
 		vpd_addr = 0x50;
 	}
 
+	vpd_data = kmalloc(256, GFP_KERNEL);
+	if (!vpd_data)
+		return;
+
 	for (i = 0; i < 256; i +=4 ) {
 		pci_write_config_byte(nic->pdev, (vpd_addr + 2), i);
 		pci_read_config_byte(nic->pdev,  (vpd_addr + 2), &data);
@@ -4977,6 +4945,7 @@
 		memset(nic->product_name, 0, vpd_data[1]);
 		memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
 	}
+	kfree(vpd_data);
 }
 
 /**
@@ -5295,7 +5264,7 @@
 	else
 		*data = 0;
 
-	return 0;
+	return *data;
 }
 
 /**
@@ -5753,6 +5722,19 @@
 	return 0;
 }
 
+static u32 s2io_ethtool_op_get_tso(struct net_device *dev)
+{
+	return (dev->features & NETIF_F_TSO) != 0;
+}
+static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data)
+{
+	if (data)
+		dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
+	else
+		dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+	return 0;
+}
 
 static struct ethtool_ops netdev_ethtool_ops = {
 	.get_settings = s2io_ethtool_gset,
@@ -5773,8 +5755,8 @@
 	.get_sg = ethtool_op_get_sg,
 	.set_sg = ethtool_op_set_sg,
 #ifdef NETIF_F_TSO
-	.get_tso = ethtool_op_get_tso,
-	.set_tso = ethtool_op_set_tso,
+	.get_tso = s2io_ethtool_op_get_tso,
+	.set_tso = s2io_ethtool_op_set_tso,
 #endif
 	.get_ufo = ethtool_op_get_ufo,
 	.set_ufo = ethtool_op_set_ufo,
@@ -6337,7 +6319,7 @@
 	s2io_set_multicast(dev);
 
 	if (sp->lro) {
-		/* Initialize max aggregatable pkts based on MTU */
+		/* Initialize max aggregatable pkts per session based on MTU */
 		sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu;
 		/* Check if we can use(if specified) user provided value */
 		if (lro_max_pkts < sp->lro_max_aggr_per_sess)
@@ -6438,7 +6420,7 @@
  *   @cksum : FCS checksum of the frame.
  *   @ring_no : the ring from which this RxD was extracted.
  *   Description:
- *   This function is called by the Tx interrupt serivce routine to perform
+ *   This function is called by the Rx interrupt serivce routine to perform
  *   some OS related operations on the SKB before passing it to the upper
  *   layers. It mainly checks if the checksum is OK, if so adds it to the
  *   SKBs cksum variable, increments the Rx packet count and passes the SKB
@@ -6698,33 +6680,6 @@
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
 }
 
-MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
-
-module_param(tx_fifo_num, int, 0);
-module_param(rx_ring_num, int, 0);
-module_param(rx_ring_mode, int, 0);
-module_param_array(tx_fifo_len, uint, NULL, 0);
-module_param_array(rx_ring_sz, uint, NULL, 0);
-module_param_array(rts_frm_len, uint, NULL, 0);
-module_param(use_continuous_tx_intrs, int, 1);
-module_param(rmac_pause_time, int, 0);
-module_param(mc_pause_threshold_q0q3, int, 0);
-module_param(mc_pause_threshold_q4q7, int, 0);
-module_param(shared_splits, int, 0);
-module_param(tmac_util_period, int, 0);
-module_param(rmac_util_period, int, 0);
-module_param(bimodal, bool, 0);
-module_param(l3l4hdr_size, int , 0);
-#ifndef CONFIG_S2IO_NAPI
-module_param(indicate_max_pkts, int, 0);
-#endif
-module_param(rxsync_frequency, int, 0);
-module_param(intr_type, int, 0);
-module_param(lro, int, 0);
-module_param(lro_max_pkts, int, 0);
-
 static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
 {
 	if ( tx_fifo_num > 8) {
@@ -6832,8 +6787,8 @@
 	}
 	if (dev_intr_type != MSI_X) {
 		if (pci_request_regions(pdev, s2io_driver_name)) {
-			DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
-			    pci_disable_device(pdev);
+			DBG_PRINT(ERR_DBG, "Request Regions failed\n");
+			pci_disable_device(pdev);
 			return -ENODEV;
 		}
 	}
@@ -6957,7 +6912,7 @@
 	/*  initialize the shared memory used by the NIC and the host */
 	if (init_shared_mem(sp)) {
 		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n",
-			  __FUNCTION__);
+			  dev->name);
 		ret = -ENOMEM;
 		goto mem_alloc_failed;
 	}
@@ -7094,6 +7049,9 @@
 	dev->addr_len = ETH_ALEN;
 	memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
 
+	/* reset Nic and bring it to known state */
+	s2io_reset(sp);
+
 	/*
 	 * Initialize the tasklet status and link state flags
 	 * and the card state parameter
@@ -7131,11 +7089,11 @@
 		goto register_failed;
 	}
 	s2io_vpd_read(sp);
-	DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name);
-	DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n",
-				get_xena_rev_id(sp->pdev),
-				s2io_driver_version);
 	DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n");
+	DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name,
+		  sp->product_name, get_xena_rev_id(sp->pdev));
+	DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
+		  s2io_driver_version);
 	DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
 			  "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
 			  sp->def_mac_addr[0].mac_addr[0],
@@ -7275,7 +7233,7 @@
 
 int __init s2io_starter(void)
 {
-	return pci_module_init(&s2io_driver);
+	return pci_register_driver(&s2io_driver);
 }
 
 /**
@@ -7436,8 +7394,13 @@
 	if (ip->ihl != 5) /* IP has options */
 		return -1;
 
+	/* If we see CE codepoint in IP header, packet is not mergeable */
+	if (INET_ECN_is_ce(ipv4_get_dsfield(ip)))
+		return -1;
+
+	/* If we see ECE or CWR flags in TCP header, packet is not mergeable */
 	if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin ||
-								!tcp->ack) {
+				    tcp->ece || tcp->cwr || !tcp->ack) {
 		/*
 		 * Currently recognize only the ack control word and
 		 * any other control field being set would result in
@@ -7591,18 +7554,16 @@
 static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb,
 			   u32 tcp_len)
 {
-	struct sk_buff *tmp, *first = lro->parent;
+	struct sk_buff *first = lro->parent;
 
 	first->len += tcp_len;
 	first->data_len = lro->frags_len;
 	skb_pull(skb, (skb->len - tcp_len));
-	if ((tmp = skb_shinfo(first)->frag_list)) {
-		while (tmp->next)
-			tmp = tmp->next;
-		tmp->next = skb;
-	}
+	if (skb_shinfo(first)->frag_list)
+		lro->last_frag->next = skb;
 	else
 		skb_shinfo(first)->frag_list = skb;
+	lro->last_frag = skb;
 	sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
 	return;
 }
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 217097b..5ed49c3 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -719,6 +719,7 @@
 /* Data structure to represent a LRO session */
 typedef struct lro {
 	struct sk_buff	*parent;
+	struct sk_buff  *last_frag;
 	u8		*l2h;
 	struct iphdr	*iph;
 	struct tcphdr	*tcph;
@@ -1011,4 +1012,13 @@
 static void queue_rx_frame(struct sk_buff *skb);
 static void update_L3L4_header(nic_t *sp, lro_t *lro);
 static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len);
+
+#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
+#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
+#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
+
+#define S2IO_PARM_INT(X, def_val) \
+	static unsigned int X = def_val;\
+		module_param(X , uint, 0);
+
 #endif				/* _S2IO_H */
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index b2acedb..c479b07 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -1131,7 +1131,7 @@
 
 static int __init saa9730_init(void)
 {
-	return pci_module_init(&saa9730_driver);
+	return pci_register_driver(&saa9730_driver);
 }
 
 static void __exit saa9730_cleanup(void)
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 9ab1618..e4c8896 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2708,7 +2708,6 @@
 static void sbmac_set_rx_mode(struct net_device *dev)
 {
 	unsigned long flags;
-	int msg_flag = 0;
 	struct sbmac_softc *sc = netdev_priv(dev);
 
 	spin_lock_irqsave(&sc->sbm_lock, flags);
@@ -2718,22 +2717,14 @@
 		 */
 
 		if (dev->flags & IFF_PROMISC) {
-			/* Unconditionally log net taps. */
-			msg_flag = 1;
 			sbmac_promiscuous_mode(sc,1);
 		}
 		else {
-			msg_flag = 2;
 			sbmac_promiscuous_mode(sc,0);
 		}
 	}
 	spin_unlock_irqrestore(&sc->sbm_lock, flags);
 
-	if (msg_flag) {
-		printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
-		       dev->name,(msg_flag==1)?"en":"dis");
-	}
-
 	/*
 	 * Program the multicasts.  Do this every time.
 	 */
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index efd0f23..01392bc 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -742,7 +742,7 @@
 MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address");
 MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number");
 
-int init_module(void)
+int __init init_module(void)
 {
 	dev_seeq = seeq8005_probe(-1);
 	if (IS_ERR(dev_seeq))
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index df0cbeb..7c1982a 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -821,9 +821,6 @@
 	u16 rx_mode;
 
 	if (dev->flags & IFF_PROMISC) {
-		/* Unconditionally log net taps. */
-		net_drv(tp, KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-			dev->name);
 		rx_mode =
 			AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 			AcceptAllPhys;
@@ -1871,7 +1868,7 @@
 
 static int __init sis190_init_module(void)
 {
-	return pci_module_init(&sis190_pci_driver);
+	return pci_register_driver(&sis190_pci_driver);
 }
 
 static void __exit sis190_cleanup_module(void)
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 29ee7ff..6af5028 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -134,6 +134,7 @@
 	{ "AMD 79C901 10BASE-T PHY",  		0x0000, 0x6B70, LAN },
 	{ "AMD 79C901 HomePNA PHY",		0x0000, 0x6B90, HOME},
 	{ "ICS LAN PHY",			0x0015, 0xF440, LAN },
+	{ "ICS LAN PHY",			0x0143, 0xBC70, LAN },
 	{ "NS 83851 PHY",			0x2000, 0x5C20, MIX },
 	{ "NS 83847 PHY",                       0x2000, 0x5C30, MIX },
 	{ "Realtek RTL8201 PHY",		0x0000, 0x8200, LAN },
@@ -2495,7 +2496,7 @@
 	printk(version);
 #endif
 
-	return pci_module_init(&sis900_pci_driver);
+	return pci_register_driver(&sis900_pci_driver);
 }
 
 static void __exit sis900_cleanup_module(void)
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index ee62845..49e76c7 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -5133,7 +5133,7 @@
 
 static int __init skge_init(void)
 {
-	return pci_module_init(&skge_driver);
+	return pci_register_driver(&skge_driver);
 }
 
 static void __exit skge_exit(void)
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index b5714a60..8e4d184 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -2280,7 +2280,7 @@
 
 static int __init skfd_init(void)
 {
-	return pci_module_init(&skfddi_pci_driver);
+	return pci_register_driver(&skfddi_pci_driver);
 }
 
 static void __exit skfd_exit(void)
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 82200bf..fba8b74 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -43,7 +43,7 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.6"
+#define DRV_VERSION		"1.8"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
@@ -91,7 +91,7 @@
 static int skge_up(struct net_device *dev);
 static int skge_down(struct net_device *dev);
 static void skge_phy_reset(struct skge_port *skge);
-static void skge_tx_clean(struct skge_port *skge);
+static void skge_tx_clean(struct net_device *dev);
 static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
 static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
 static void genesis_get_stats(struct skge_port *skge, u64 *data);
@@ -105,6 +105,7 @@
 static const int rxqaddr[] = { Q_R1, Q_R2 };
 static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
 static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
 
 static int skge_get_regs_len(struct net_device *dev)
 {
@@ -516,10 +517,7 @@
 /* Chip internal frequency for clock calculations */
 static inline u32 hwkhz(const struct skge_hw *hw)
 {
-	if (hw->chip_id == CHIP_ID_GENESIS)
-		return 53215; /* or:  53.125 MHz */
-	else
-		return 78215; /* or:  78.125 MHz */
+	return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125;
 }
 
 /* Chip HZ to microseconds */
@@ -821,8 +819,9 @@
 /* Allocate buffers for receive ring
  * For receive:  to_clean is next received frame.
  */
-static int skge_rx_fill(struct skge_port *skge)
+static int skge_rx_fill(struct net_device *dev)
 {
+	struct skge_port *skge = netdev_priv(dev);
 	struct skge_ring *ring = &skge->rx_ring;
 	struct skge_element *e;
 
@@ -830,7 +829,8 @@
 	do {
 		struct sk_buff *skb;
 
-		skb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_KERNEL);
+		skb = __netdev_alloc_skb(dev, skge->rx_buf_size + NET_IP_ALIGN,
+					 GFP_KERNEL);
 		if (!skb)
 			return -ENOMEM;
 
@@ -2181,7 +2181,7 @@
 	if (err)
 		goto free_pci_mem;
 
-	err = skge_rx_fill(skge);
+	err = skge_rx_fill(dev);
 	if (err)
 		goto free_rx_ring;
 
@@ -2214,6 +2214,7 @@
 	skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
 	skge_led(skge, LED_MODE_ON);
 
+	netif_poll_enable(dev);
 	return 0;
 
  free_rx_ring:
@@ -2282,7 +2283,8 @@
 
 	skge_led(skge, LED_MODE_OFF);
 
-	skge_tx_clean(skge);
+	netif_poll_disable(dev);
+	skge_tx_clean(dev);
 	skge_rx_clean(skge);
 
 	kfree(skge->rx_ring.start);
@@ -2307,25 +2309,12 @@
 	int i;
 	u32 control, len;
 	u64 map;
-	unsigned long flags;
 
 	if (skb_padto(skb, ETH_ZLEN))
 		return NETDEV_TX_OK;
 
-	if (!spin_trylock_irqsave(&skge->tx_lock, flags))
-		/* Collision - tell upper layer to requeue */
-		return NETDEV_TX_LOCKED;
-
-	if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) {
-		if (!netif_queue_stopped(dev)) {
-			netif_stop_queue(dev);
-
-			printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
-			       dev->name);
-		}
-		spin_unlock_irqrestore(&skge->tx_lock, flags);
+	if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1))
 		return NETDEV_TX_BUSY;
-	}
 
 	e = skge->tx_ring.to_use;
 	td = e->desc;
@@ -2400,8 +2389,6 @@
 		netif_stop_queue(dev);
 	}
 
-	spin_unlock_irqrestore(&skge->tx_lock, flags);
-
 	dev->trans_start = jiffies;
 
 	return NETDEV_TX_OK;
@@ -2431,18 +2418,18 @@
 			printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
 			       skge->netdev->name, e - skge->tx_ring.start);
 
-		dev_kfree_skb_any(e->skb);
+		dev_kfree_skb(e->skb);
 	}
 	e->skb = NULL;
 }
 
 /* Free all buffers in transmit ring */
-static void skge_tx_clean(struct skge_port *skge)
+static void skge_tx_clean(struct net_device *dev)
 {
+	struct skge_port *skge = netdev_priv(dev);
 	struct skge_element *e;
-	unsigned long flags;
 
-	spin_lock_irqsave(&skge->tx_lock, flags);
+	netif_tx_lock_bh(dev);
 	for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
 		struct skge_tx_desc *td = e->desc;
 		skge_tx_free(skge, e, td->control);
@@ -2450,8 +2437,8 @@
 	}
 
 	skge->tx_ring.to_clean = e;
-	netif_wake_queue(skge->netdev);
-	spin_unlock_irqrestore(&skge->tx_lock, flags);
+	netif_wake_queue(dev);
+	netif_tx_unlock_bh(dev);
 }
 
 static void skge_tx_timeout(struct net_device *dev)
@@ -2462,7 +2449,7 @@
 		printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name);
 
 	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP);
-	skge_tx_clean(skge);
+	skge_tx_clean(dev);
 }
 
 static int skge_change_mtu(struct net_device *dev, int new_mtu)
@@ -2585,16 +2572,17 @@
 /* Get receive buffer from descriptor.
  * Handles copy of small buffers and reallocation failures
  */
-static inline struct sk_buff *skge_rx_get(struct skge_port *skge,
-					  struct skge_element *e,
-					  u32 control, u32 status, u16 csum)
+static struct sk_buff *skge_rx_get(struct net_device *dev,
+				   struct skge_element *e,
+				   u32 control, u32 status, u16 csum)
 {
+	struct skge_port *skge = netdev_priv(dev);
 	struct sk_buff *skb;
 	u16 len = control & BMU_BBC;
 
 	if (unlikely(netif_msg_rx_status(skge)))
 		printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
-		       skge->netdev->name, e - skge->rx_ring.start,
+		       dev->name, e - skge->rx_ring.start,
 		       status, len);
 
 	if (len > skge->rx_buf_size)
@@ -2610,7 +2598,7 @@
 		goto error;
 
 	if (len < RX_COPY_THRESHOLD) {
-		skb = alloc_skb(len + 2, GFP_ATOMIC);
+		skb = netdev_alloc_skb(dev, len + 2);
 		if (!skb)
 			goto resubmit;
 
@@ -2625,7 +2613,7 @@
 		skge_rx_reuse(e, skge->rx_buf_size);
 	} else {
 		struct sk_buff *nskb;
-		nskb = alloc_skb(skge->rx_buf_size + NET_IP_ALIGN, GFP_ATOMIC);
+		nskb = netdev_alloc_skb(dev, skge->rx_buf_size + NET_IP_ALIGN);
 		if (!nskb)
 			goto resubmit;
 
@@ -2640,20 +2628,19 @@
 	}
 
 	skb_put(skb, len);
-	skb->dev = skge->netdev;
 	if (skge->rx_csum) {
 		skb->csum = csum;
 		skb->ip_summed = CHECKSUM_HW;
 	}
 
-	skb->protocol = eth_type_trans(skb, skge->netdev);
+	skb->protocol = eth_type_trans(skb, dev);
 
 	return skb;
 error:
 
 	if (netif_msg_rx_err(skge))
 		printk(KERN_DEBUG PFX "%s: rx err, slot %td control 0x%x status 0x%x\n",
-		       skge->netdev->name, e - skge->rx_ring.start,
+		       dev->name, e - skge->rx_ring.start,
 		       control, status);
 
 	if (skge->hw->chip_id == CHIP_ID_GENESIS) {
@@ -2678,15 +2665,15 @@
 }
 
 /* Free all buffers in Tx ring which are no longer owned by device */
-static void skge_txirq(struct net_device *dev)
+static void skge_tx_done(struct net_device *dev)
 {
 	struct skge_port *skge = netdev_priv(dev);
 	struct skge_ring *ring = &skge->tx_ring;
 	struct skge_element *e;
 
-	rmb();
+	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
 
-	spin_lock(&skge->tx_lock);
+	netif_tx_lock(dev);
 	for (e = ring->to_clean; e != ring->to_use; e = e->next) {
 		struct skge_tx_desc *td = e->desc;
 
@@ -2697,11 +2684,10 @@
 	}
 	skge->tx_ring.to_clean = e;
 
-	if (netif_queue_stopped(skge->netdev)
-	    && skge_avail(&skge->tx_ring) > TX_LOW_WATER)
-		netif_wake_queue(skge->netdev);
+	if (skge_avail(&skge->tx_ring) > TX_LOW_WATER)
+		netif_wake_queue(dev);
 
-	spin_unlock(&skge->tx_lock);
+	netif_tx_unlock(dev);
 }
 
 static int skge_poll(struct net_device *dev, int *budget)
@@ -2713,6 +2699,10 @@
 	int to_do = min(dev->quota, *budget);
 	int work_done = 0;
 
+	skge_tx_done(dev);
+
+	skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
 	for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
 		struct skge_rx_desc *rd = e->desc;
 		struct sk_buff *skb;
@@ -2723,7 +2713,7 @@
 		if (control & BMU_OWN)
 			break;
 
-		skb = skge_rx_get(skge, e, control, rd->status, rd->csum2);
+		skb = skge_rx_get(dev, e, control, rd->status, rd->csum2);
 		if (likely(skb)) {
 			dev->last_rx = jiffies;
 			netif_receive_skb(skb);
@@ -2743,12 +2733,11 @@
 	if (work_done >=  to_do)
 		return 1; /* not done */
 
-	netif_rx_complete(dev);
-
 	spin_lock_irq(&hw->hw_lock);
-	hw->intr_mask |= rxirqmask[skge->port];
+	__netif_rx_complete(dev);
+	hw->intr_mask |= irqmask[skge->port];
   	skge_write32(hw, B0_IMSK, hw->intr_mask);
-	mmiowb();
+	skge_read32(hw, B0_IMSK);
 	spin_unlock_irq(&hw->hw_lock);
 
 	return 0;
@@ -2882,6 +2871,7 @@
 	spin_lock_irq(&hw->hw_lock);
 	hw->intr_mask |= IS_EXT_REG;
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	skge_read32(hw, B0_IMSK);
 	spin_unlock_irq(&hw->hw_lock);
 }
 
@@ -2889,27 +2879,23 @@
 {
 	struct skge_hw *hw = dev_id;
 	u32 status;
-
-	/* Reading this register masks IRQ */
-	status = skge_read32(hw, B0_SP_ISRC);
-	if (status == 0)
-		return IRQ_NONE;
+	int handled = 0;
 
 	spin_lock(&hw->hw_lock);
+	/* Reading this register masks IRQ */
+	status = skge_read32(hw, B0_SP_ISRC);
+	if (status == 0 || status == ~0)
+		goto out;
+
+	handled = 1;
 	status &= hw->intr_mask;
 	if (status & IS_EXT_REG) {
 		hw->intr_mask &= ~IS_EXT_REG;
 		schedule_work(&hw->phy_work);
 	}
 
-	if (status & IS_XA1_F) {
-		skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F);
-		skge_txirq(hw->dev[0]);
-	}
-
-	if (status & IS_R1_F) {
-		skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
-		hw->intr_mask &= ~IS_R1_F;
+	if (status & (IS_XA1_F|IS_R1_F)) {
+		hw->intr_mask &= ~(IS_XA1_F|IS_R1_F);
 		netif_rx_schedule(hw->dev[0]);
 	}
 
@@ -2928,14 +2914,8 @@
 		skge_mac_intr(hw, 0);
 
 	if (hw->dev[1]) {
-		if (status & IS_XA2_F) {
-			skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F);
-			skge_txirq(hw->dev[1]);
-		}
-
-		if (status & IS_R2_F) {
-			skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
-			hw->intr_mask &= ~IS_R2_F;
+		if (status & (IS_XA2_F|IS_R2_F)) {
+			hw->intr_mask &= ~(IS_XA2_F|IS_R2_F);
 			netif_rx_schedule(hw->dev[1]);
 		}
 
@@ -2956,9 +2936,11 @@
 		skge_error_irq(hw);
 
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	skge_read32(hw, B0_IMSK);
+out:
 	spin_unlock(&hw->hw_lock);
 
-	return IRQ_HANDLED;
+	return IRQ_RETVAL(handled);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3107,7 +3089,6 @@
 	else
 		hw->ram_size = t8 * 4096;
 
-	spin_lock_init(&hw->hw_lock);
 	hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
 	if (hw->ports > 1)
 		hw->intr_mask |= IS_PORT_2;
@@ -3223,7 +3204,7 @@
 	dev->poll_controller = skge_netpoll;
 #endif
 	dev->irq = hw->pdev->irq;
-	dev->features = NETIF_F_LLTX;
+
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
 
@@ -3245,8 +3226,6 @@
 
 	skge->port = port;
 
-	spin_lock_init(&skge->tx_lock);
-
 	if (hw->chip_id != CHIP_ID_GENESIS) {
 		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 		skge->rx_csum = 1;
@@ -3333,6 +3312,7 @@
 	hw->pdev = pdev;
 	mutex_init(&hw->phy_mutex);
 	INIT_WORK(&hw->phy_work, skge_extirq, hw);
+	spin_lock_init(&hw->hw_lock);
 
 	hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
 	if (!hw->regs) {
@@ -3341,23 +3321,16 @@
 		goto err_out_free_hw;
 	}
 
-	err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, DRV_NAME, hw);
-	if (err) {
-		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
-		       pci_name(pdev), pdev->irq);
-		goto err_out_iounmap;
-	}
-	pci_set_drvdata(pdev, hw);
-
 	err = skge_reset(hw);
 	if (err)
-		goto err_out_free_irq;
+		goto err_out_iounmap;
 
 	printk(KERN_INFO PFX DRV_VERSION " addr 0x%llx irq %d chip %s rev %d\n",
 	       (unsigned long long)pci_resource_start(pdev, 0), pdev->irq,
 	       skge_board_name(hw), hw->chip_rev);
 
-	if ((dev = skge_devinit(hw, 0, using_dac)) == NULL)
+	dev = skge_devinit(hw, 0, using_dac);
+	if (!dev)
 		goto err_out_led_off;
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
@@ -3367,7 +3340,6 @@
 		goto err_out_free_netdev;
 	}
 
-
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "%s: cannot register net device\n",
@@ -3375,6 +3347,12 @@
 		goto err_out_free_netdev;
 	}
 
+	err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, dev->name, hw);
+	if (err) {
+		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+		       dev->name, pdev->irq);
+		goto err_out_unregister;
+	}
 	skge_show_addr(dev);
 
 	if (hw->ports > 1 && (dev1 = skge_devinit(hw, 1, using_dac))) {
@@ -3387,15 +3365,16 @@
 			free_netdev(dev1);
 		}
 	}
+	pci_set_drvdata(pdev, hw);
 
 	return 0;
 
+err_out_unregister:
+	unregister_netdev(dev);
 err_out_free_netdev:
 	free_netdev(dev);
 err_out_led_off:
 	skge_write16(hw, B0_LED, LED_STAT_OFF);
-err_out_free_irq:
-	free_irq(pdev->irq, hw);
 err_out_iounmap:
 	iounmap(hw->regs);
 err_out_free_hw:
@@ -3425,6 +3404,7 @@
 	spin_lock_irq(&hw->hw_lock);
 	hw->intr_mask = 0;
 	skge_write32(hw, B0_IMSK, 0);
+	skge_read32(hw, B0_IMSK);
 	spin_unlock_irq(&hw->hw_lock);
 
 	skge_write16(hw, B0_LED, LED_STAT_OFF);
@@ -3450,26 +3430,25 @@
 	struct skge_hw *hw  = pci_get_drvdata(pdev);
 	int i, wol = 0;
 
-	for (i = 0; i < 2; i++) {
+	pci_save_state(pdev);
+	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];
 
-		if (dev) {
+		if (netif_running(dev)) {
 			struct skge_port *skge = netdev_priv(dev);
-			if (netif_running(dev)) {
-				netif_carrier_off(dev);
-				if (skge->wol)
-					netif_stop_queue(dev);
-				else
-					skge_down(dev);
-			}
-			netif_device_detach(dev);
+
+			netif_carrier_off(dev);
+			if (skge->wol)
+				netif_stop_queue(dev);
+			else
+				skge_down(dev);
 			wol |= skge->wol;
 		}
+		netif_device_detach(dev);
 	}
 
-	pci_save_state(pdev);
+	skge_write32(hw, B0_IMSK, 0);
 	pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
-	pci_disable_device(pdev);
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
@@ -3478,23 +3457,33 @@
 static int skge_resume(struct pci_dev *pdev)
 {
 	struct skge_hw *hw  = pci_get_drvdata(pdev);
-	int i;
+	int i, err;
 
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	pci_enable_wake(pdev, PCI_D0, 0);
 
-	skge_reset(hw);
+	err = skge_reset(hw);
+	if (err)
+		goto out;
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < hw->ports; i++) {
 		struct net_device *dev = hw->dev[i];
-		if (dev) {
-			netif_device_attach(dev);
-			if (netif_running(dev) && skge_up(dev))
+
+		netif_device_attach(dev);
+		if (netif_running(dev)) {
+			err = skge_up(dev);
+
+			if (err) {
+				printk(KERN_ERR PFX "%s: could not up: %d\n",
+				       dev->name, err);
 				dev_close(dev);
+				goto out;
+			}
 		}
 	}
-	return 0;
+out:
+	return err;
 }
 #endif
 
@@ -3511,7 +3500,7 @@
 
 static int __init skge_init_module(void)
 {
-	return pci_module_init(&skge_driver);
+	return pci_register_driver(&skge_driver);
 }
 
 static void __exit skge_cleanup_module(void)
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 593387b..79e0927 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2417,7 +2417,6 @@
 	struct net_device    *netdev;
 	int		     port;
 
-	spinlock_t	     tx_lock;
 	struct skge_ring     tx_ring;
 	struct skge_ring     rx_ring;
 
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index de91609..7ce0663 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME		"sky2"
-#define DRV_VERSION		"1.5"
+#define DRV_VERSION		"1.7"
 #define PFX			DRV_NAME " "
 
 /*
@@ -106,6 +106,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) },	/* DGE-560T */
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, 	/* DGE-550SX */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) },
@@ -117,10 +118,17 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4350) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) },
 	{ 0 }
 };
 
@@ -190,7 +198,6 @@
 static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
 {
 	u16 power_control;
-	u32 reg1;
 	int vaux;
 
 	pr_debug("sky2_set_power_state %d\n", state);
@@ -223,18 +230,9 @@
 		else
 			sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 
-		/* Turn off phy power saving */
-		reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-		reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
-
-		/* looks like this XL is back asswards .. */
-		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) {
-			reg1 |= PCI_Y2_PHY1_COMA;
-			if (hw->ports > 1)
-				reg1 |= PCI_Y2_PHY2_COMA;
-		}
-
 		if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
+			u32 reg1;
+
 			sky2_pci_write32(hw, PCI_DEV_REG3, 0);
 			reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
 			reg1 &= P_ASPM_CONTROL_MSK;
@@ -242,22 +240,10 @@
 			sky2_pci_write32(hw, PCI_DEV_REG5, 0);
 		}
 
-		sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-		udelay(100);
-
 		break;
 
 	case PCI_D3hot:
 	case PCI_D3cold:
-		/* Turn on phy power saving */
-		reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
-			reg1 &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
-		else
-			reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
-		sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-		udelay(100);
-
 		if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
 			sky2_write8(hw, B2_Y2_CLK_GATE, 0);
 		else
@@ -281,7 +267,7 @@
 	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 }
 
-static void sky2_phy_reset(struct sky2_hw *hw, unsigned port)
+static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
 {
 	u16 reg;
 
@@ -529,6 +515,29 @@
 		gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
 }
 
+static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
+{
+	u32 reg1;
+	static const u32 phy_power[]
+		= { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
+
+	/* looks like this XL is back asswards .. */
+	if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
+		onoff = !onoff;
+
+	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+
+	if (onoff)
+		/* Turn off phy power saving */
+		reg1 &= ~phy_power[port];
+	else
+		reg1 |= phy_power[port];
+
+	sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+	sky2_pci_read32(hw, PCI_DEV_REG1);
+	udelay(100);
+}
+
 /* Force a renegotiation */
 static void sky2_phy_reinit(struct sky2_port *sky2)
 {
@@ -761,9 +770,10 @@
 /* Update chip's next pointer */
 static inline void sky2_put_idx(struct sky2_hw *hw, unsigned q, u16 idx)
 {
+	q = Y2_QADDR(q, PREF_UNIT_PUT_IDX);
 	wmb();
-	sky2_write16(hw, Y2_QADDR(q, PREF_UNIT_PUT_IDX), idx);
-	mmiowb();
+	sky2_write16(hw, q, idx);
+	sky2_read16(hw, q);
 }
 
 
@@ -950,14 +960,16 @@
 /*
  * It appears the hardware has a bug in the FIFO logic that
  * cause it to hang if the FIFO gets overrun and the receive buffer
- * is not aligned. ALso alloc_skb() won't align properly if slab
- * debugging is enabled.
+ * is not 64 byte aligned. The buffer returned from netdev_alloc_skb is
+ * aligned except if slab debugging is enabled.
  */
-static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask)
+static inline struct sk_buff *sky2_alloc_skb(struct net_device *dev,
+					     unsigned int length,
+					     gfp_t gfp_mask)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask);
+	skb = __netdev_alloc_skb(dev, length + RX_SKB_ALIGN, gfp_mask);
 	if (likely(skb)) {
 		unsigned long p	= (unsigned long) skb->data;
 		skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p);
@@ -993,7 +1005,8 @@
 	for (i = 0; i < sky2->rx_pending; i++) {
 		struct ring_info *re = sky2->rx_ring + i;
 
-		re->skb = sky2_alloc_skb(sky2->rx_bufsize, GFP_KERNEL);
+		re->skb = sky2_alloc_skb(sky2->netdev, sky2->rx_bufsize,
+					 GFP_KERNEL);
 		if (!re->skb)
 			goto nomem;
 
@@ -1081,6 +1094,8 @@
 	if (!sky2->rx_ring)
 		goto err_out;
 
+	sky2_phy_power(hw, port, 1);
+
 	sky2_mac_init(hw, port);
 
 	/* Determine available ram buffer space (in 4K blocks).
@@ -1185,7 +1200,6 @@
 	struct sky2_tx_le *le = NULL;
 	struct tx_ring_info *re;
 	unsigned i, len;
-	int avail;
 	dma_addr_t mapping;
 	u32 addr64;
 	u16 mss;
@@ -1235,25 +1249,18 @@
 	/* Check for TCP Segmentation Offload */
 	mss = skb_shinfo(skb)->gso_size;
 	if (mss != 0) {
-		/* just drop the packet if non-linear expansion fails */
-		if (skb_header_cloned(skb) &&
-		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-			dev_kfree_skb(skb);
-			goto out_unlock;
-		}
-
 		mss += ((skb->h.th->doff - 5) * 4);	/* TCP options */
 		mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
 		mss += ETH_HLEN;
-	}
 
-	if (mss != sky2->tx_last_mss) {
-		le = get_tx_le(sky2);
-		le->tx.tso.size = cpu_to_le16(mss);
-		le->tx.tso.rsvd = 0;
-		le->opcode = OP_LRGLEN | HW_OWNER;
-		le->ctrl = 0;
-		sky2->tx_last_mss = mss;
+		if (mss != sky2->tx_last_mss) {
+			le = get_tx_le(sky2);
+			le->tx.tso.size = cpu_to_le16(mss);
+			le->tx.tso.rsvd = 0;
+			le->opcode = OP_LRGLEN | HW_OWNER;
+			le->ctrl = 0;
+			sky2->tx_last_mss = mss;
+		}
 	}
 
 	ctrl = 0;
@@ -1281,12 +1288,17 @@
 		if (skb->nh.iph->protocol == IPPROTO_UDP)
 			ctrl |= UDPTCP;
 
-		le = get_tx_le(sky2);
-		le->tx.csum.start = cpu_to_le16(hdr);
-		le->tx.csum.offset = cpu_to_le16(offset);
-		le->length = 0;	/* initial checksum value */
-		le->ctrl = 1;	/* one packet */
-		le->opcode = OP_TCPLISW | HW_OWNER;
+		if (hdr != sky2->tx_csum_start || offset != sky2->tx_csum_offset) {
+			sky2->tx_csum_start = hdr;
+			sky2->tx_csum_offset = offset;
+
+			le = get_tx_le(sky2);
+			le->tx.csum.start = cpu_to_le16(hdr);
+			le->tx.csum.offset = cpu_to_le16(offset);
+			le->length = 0;	/* initial checksum value */
+			le->ctrl = 1;	/* one packet */
+			le->opcode = OP_TCPLISW | HW_OWNER;
+		}
 	}
 
 	le = get_tx_le(sky2);
@@ -1321,23 +1333,18 @@
 		le->opcode = OP_BUFFER | HW_OWNER;
 
 		fre = sky2->tx_ring
-		    + RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE);
+			+ RING_NEXT((re - sky2->tx_ring) + i, TX_RING_SIZE);
 		pci_unmap_addr_set(fre, mapaddr, mapping);
 	}
 
 	re->idx = sky2->tx_prod;
 	le->ctrl |= EOP;
 
-	avail = tx_avail(sky2);
-	if (mss != 0 || avail < TX_MIN_PENDING) {
- 		le->ctrl |= FRC_STAT;
-		if (avail <= MAX_SKB_TX_LE)
-			netif_stop_queue(dev);
-	}
+	if (tx_avail(sky2) <= MAX_SKB_TX_LE)
+		netif_stop_queue(dev);
 
 	sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod);
 
-out_unlock:
 	spin_unlock(&sky2->tx_lock);
 
 	dev->trans_start = jiffies;
@@ -1422,7 +1429,7 @@
 	/* Stop more packets from being queued */
 	netif_stop_queue(dev);
 
-	sky2_phy_reset(hw, port);
+	sky2_gmac_reset(hw, port);
 
 	/* Stop transmitter */
 	sky2_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), BMU_STOP);
@@ -1470,6 +1477,8 @@
 	imask &= ~portirq_msk[port];
 	sky2_write32(hw, B0_IMSK, imask);
 
+	sky2_phy_power(hw, port, 0);
+
 	/* turn off LED's */
 	sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
 
@@ -1833,15 +1842,16 @@
  * For small packets or errors, just reuse existing skb.
  * For larger packets, get new buffer.
  */
-static struct sk_buff *sky2_receive(struct sky2_port *sky2,
+static struct sk_buff *sky2_receive(struct net_device *dev,
 				    u16 length, u32 status)
 {
+ 	struct sky2_port *sky2 = netdev_priv(dev);
 	struct ring_info *re = sky2->rx_ring + sky2->rx_next;
 	struct sk_buff *skb = NULL;
 
 	if (unlikely(netif_msg_rx_status(sky2)))
 		printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
-		       sky2->netdev->name, sky2->rx_next, status, length);
+		       dev->name, sky2->rx_next, status, length);
 
 	sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
 	prefetch(sky2->rx_ring + sky2->rx_next);
@@ -1852,11 +1862,11 @@
 	if (!(status & GMR_FS_RX_OK))
 		goto resubmit;
 
-	if (length > sky2->netdev->mtu + ETH_HLEN)
+	if (length > dev->mtu + ETH_HLEN)
 		goto oversize;
 
 	if (length < copybreak) {
-		skb = alloc_skb(length + 2, GFP_ATOMIC);
+		skb = netdev_alloc_skb(dev, length + 2);
 		if (!skb)
 			goto resubmit;
 
@@ -1871,7 +1881,7 @@
 	} else {
 		struct sk_buff *nskb;
 
-		nskb = sky2_alloc_skb(sky2->rx_bufsize, GFP_ATOMIC);
+		nskb = sky2_alloc_skb(dev, sky2->rx_bufsize, GFP_ATOMIC);
 		if (!nskb)
 			goto resubmit;
 
@@ -1901,7 +1911,7 @@
 
 	if (netif_msg_rx_err(sky2) && net_ratelimit())
 		printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n",
-		       sky2->netdev->name, status, length);
+		       dev->name, status, length);
 
 	if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE))
 		sky2->net_stats.rx_length_errors++;
@@ -1927,12 +1937,6 @@
 	}
 }
 
-/* Is status ring empty or is there more to do? */
-static inline int sky2_more_work(const struct sky2_hw *hw)
-{
-	return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX));
-}
-
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
@@ -1961,11 +1965,10 @@
 
 		switch (le->opcode & ~HW_OWNER) {
 		case OP_RXSTAT:
-			skb = sky2_receive(sky2, length, status);
+			skb = sky2_receive(dev, length, status);
 			if (!skb)
 				break;
 
-			skb->dev = dev;
 			skb->protocol = eth_type_trans(skb, dev);
 			dev->last_rx = jiffies;
 
@@ -2023,6 +2026,9 @@
 		}
 	}
 
+	/* Fully processed status ring so clear irq */
+	sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
 exit_loop:
 	if (buf_write[0]) {
 		sky2 = netdev_priv(hw->dev[0]);
@@ -2232,19 +2238,16 @@
 		sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
 
 	work_done = sky2_status_intr(hw, work_limit);
-	*budget -= work_done;
-	dev0->quota -= work_done;
+	if (work_done < work_limit) {
+		netif_rx_complete(dev0);
 
-	if (status & Y2_IS_STAT_BMU)
-		sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
-
-	if (sky2_more_work(hw))
+		sky2_read32(hw, B0_Y2_SP_LISR);
+		return 0;
+	} else {
+		*budget -= work_done;
+		dev0->quota -= work_done;
 		return 1;
-
-	netif_rx_complete(dev0);
-
-	sky2_read32(hw, B0_Y2_SP_LISR);
-	return 0;
+	}
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2410,7 +2413,7 @@
 	sky2_write32(hw, B0_HWE_IMSK, Y2_HWE_ALL_MASK);
 
 	for (i = 0; i < hw->ports; i++)
-		sky2_phy_reset(hw, i);
+		sky2_gmac_reset(hw, i);
 
 	memset(hw->st_le, 0, STATUS_LE_BYTES);
 	hw->st_idx = 0;
@@ -3201,6 +3204,8 @@
 	struct pci_dev *pdev = hw->pdev;
 	int err;
 
+	init_waitqueue_head (&hw->msi_wait);
+
 	sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
 
 	err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw);
@@ -3210,10 +3215,8 @@
 		return err;
 	}
 
-	init_waitqueue_head (&hw->msi_wait);
-
 	sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
-	wmb();
+	sky2_read8(hw, B0_CTST);
 
 	wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10);
 
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 2db8d19..fa8af9f 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -1748,7 +1748,6 @@
 	INIT_SUM= 1<<3,
 	LOCK_SUM= 1<<4,
 	INS_VLAN= 1<<5,
-	FRC_STAT= 1<<6,
 	EOP	= 1<<7,
 };
 
@@ -1844,6 +1843,8 @@
 	u32		     tx_addr64;
 	u16		     tx_pending;
 	u16		     tx_last_mss;
+	u16		     tx_csum_start;
+	u16		     tx_csum_offset;
 
 	struct ring_info     *rx_ring ____cacheline_aligned_in_smp;
 	struct sky2_rx_le    *rx_le;
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index 3a1b713..9a540e2 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -94,27 +94,23 @@
 	register struct cstate *ts;
 	struct slcompress *comp;
 
-	comp = (struct slcompress *)kmalloc(sizeof(struct slcompress),
-					    GFP_KERNEL);
+	comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
 	if (! comp)
 		goto out_fail;
-	memset(comp, 0, sizeof(struct slcompress));
 
 	if ( rslots > 0  &&  rslots < 256 ) {
 		size_t rsize = rslots * sizeof(struct cstate);
-		comp->rstate = (struct cstate *) kmalloc(rsize, GFP_KERNEL);
+		comp->rstate = kzalloc(rsize, GFP_KERNEL);
 		if (! comp->rstate)
 			goto out_free;
-		memset(comp->rstate, 0, rsize);
 		comp->rslot_limit = rslots - 1;
 	}
 
 	if ( tslots > 0  &&  tslots < 256 ) {
 		size_t tsize = tslots * sizeof(struct cstate);
-		comp->tstate = (struct cstate *) kmalloc(tsize, GFP_KERNEL);
+		comp->tstate = kzalloc(tsize, GFP_KERNEL);
 		if (! comp->tstate)
 			goto out_free2;
-		memset(comp->tstate, 0, tsize);
 		comp->tslot_limit = tslots - 1;
 	}
 
@@ -141,9 +137,9 @@
 	return comp;
 
 out_free2:
-	kfree((unsigned char *)comp->rstate);
+	kfree(comp->rstate);
 out_free:
-	kfree((unsigned char *)comp);
+	kfree(comp);
 out_fail:
 	return NULL;
 }
@@ -700,20 +696,6 @@
 EXPORT_SYMBOL(slhc_uncompress);
 EXPORT_SYMBOL(slhc_toss);
 
-#ifdef MODULE
-
-int init_module(void)
-{
-	printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California\n");
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	return;
-}
-
-#endif /* MODULE */
 #else /* CONFIG_INET */
 
 
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index d37bd86..4438fe8 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -55,8 +55,6 @@
 			 )
 #endif
 
-
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -1092,6 +1090,7 @@
 	/* Spurious interrupt check */
 	if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
 		(INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
+		spin_unlock_irqrestore(&lp->lock, flags);
 		return IRQ_NONE;
 	}
 
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 3d8dcb6..cf62373 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -321,12 +321,12 @@
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
 	/* Disable all interrupts, block TX tasklet */
-	spin_lock(&lp->lock);
+	spin_lock_irq(&lp->lock);
 	SMC_SELECT_BANK(2);
 	SMC_SET_INT_MASK(0);
 	pending_skb = lp->pending_tx_skb;
 	lp->pending_tx_skb = NULL;
-	spin_unlock(&lp->lock);
+	spin_unlock_irq(&lp->lock);
 
 	/* free any pending tx skb */
 	if (pending_skb) {
@@ -448,12 +448,12 @@
 	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
 
 	/* no more interrupts for me */
-	spin_lock(&lp->lock);
+	spin_lock_irq(&lp->lock);
 	SMC_SELECT_BANK(2);
 	SMC_SET_INT_MASK(0);
 	pending_skb = lp->pending_tx_skb;
 	lp->pending_tx_skb = NULL;
-	spin_unlock(&lp->lock);
+	spin_unlock_irq(&lp->lock);
 	if (pending_skb)
 		dev_kfree_skb(pending_skb);
 
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 4ec4b4d..7aa7fba 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -136,14 +136,9 @@
 #define SMC_CAN_USE_32BIT	0
 #define SMC_IO_SHIFT		0
 #define SMC_NOWAIT		1
-#define SMC_USE_PXA_DMA		1
 
-#define SMC_inb(a, r)		readb((a) + (r))
 #define SMC_inw(a, r)		readw((a) + (r))
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
 #define SMC_outw(v, a, r)	writew(v, (a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
 #define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
 
@@ -189,16 +184,10 @@
 #define SMC_IO_SHIFT		0
 #define SMC_NOWAIT		1
 
-#define SMC_inb(a, r)		readb((a) + (r))
-#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
 #define SMC_inw(a, r)		readw((a) + (r))
 #define SMC_outw(v, a, r)	writew(v, (a) + (r))
 #define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
-#define SMC_inl(a, r)		readl((a) + (r))
-#define SMC_outl(v, a, r)	writel(v, (a) + (r))
-#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
 
 #include <asm/mach-types.h>
 #include <asm/arch/cpu.h>
@@ -372,6 +361,24 @@
 
 #define SMC_IRQ_FLAGS		(0)
 
+#elif	defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT	1
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	1
+#define SMC_NOWAIT		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS		(0)
+
 #else
 
 #define SMC_CAN_USE_8BIT	1
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 647f62e..8890721 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1611,13 +1611,12 @@
 	int result;
 
 	result = -ENOMEM;
-	if (spider_net_init_chain(card, &card->tx_chain,
-			card->descr,
-			PCI_DMA_TODEVICE, tx_descriptors))
+	if (spider_net_init_chain(card, &card->tx_chain, card->descr,
+			PCI_DMA_TODEVICE, card->tx_desc))
 		goto alloc_tx_failed;
 	if (spider_net_init_chain(card, &card->rx_chain,
-			card->descr + tx_descriptors,
-			PCI_DMA_FROMDEVICE, rx_descriptors))
+			card->descr + card->rx_desc,
+			PCI_DMA_FROMDEVICE, card->rx_desc))
 		goto alloc_rx_failed;
 
 	/* allocate rx skbs */
@@ -2005,6 +2004,9 @@
 
 	card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
 
+	card->tx_desc = tx_descriptors;
+	card->rx_desc = rx_descriptors;
+
 	spider_net_setup_netdev_ops(netdev);
 
 	netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index f6dcf18..30407cd 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -440,6 +440,9 @@
 	/* for ethtool */
 	int msg_enable;
 
+	int rx_desc;
+	int tx_desc;
+
 	struct spider_net_descr descr[0];
 };
 
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index a5bb0b76..0220922 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -130,6 +130,18 @@
         return 0;
 }
 
+static void
+spider_net_ethtool_get_ringparam(struct net_device *netdev,
+				 struct ethtool_ringparam *ering)
+{
+	struct spider_net_card *card = netdev->priv;
+
+	ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
+	ering->tx_pending = card->tx_desc;
+	ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX;
+	ering->rx_pending = card->rx_desc;
+}
+
 struct ethtool_ops spider_net_ethtool_ops = {
 	.get_settings		= spider_net_ethtool_get_settings,
 	.get_drvinfo		= spider_net_ethtool_get_drvinfo,
@@ -141,5 +153,6 @@
 	.set_rx_csum		= spider_net_ethtool_set_rx_csum,
 	.get_tx_csum		= spider_net_ethtool_get_tx_csum,
 	.set_tx_csum		= spider_net_ethtool_set_tx_csum,
+	.get_ringparam          = spider_net_ethtool_get_ringparam,
 };
 
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index c0a62b0..8e1f6206 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -2053,7 +2053,7 @@
 		return -ENODEV;
 	}
 
-	return pci_module_init (&starfire_driver);
+	return pci_register_driver(&starfire_driver);
 }
 
 
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 2dcadb1..0d76e22 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -914,7 +914,7 @@
 
 	if (dev->flags & IFF_PROMISC) {
 		/* Log any net taps. */
-		DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name ));
+		DPRINTK( 3, ( "%s: Promiscuous mode enabled.\n", dev->name ));
 		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
 	} else {
 		short multicast_table[4];
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index ac17377..a3a7a35 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -17,12 +17,14 @@
 	Support and updates available at
 	http://www.scyld.com/network/sundance.html
 	[link no longer provides useful info -jgarzik]
+	Archives of the mailing list are still available at
+	http://www.beowulf.org/pipermail/netdrivers/
 
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.1"
-#define DRV_RELDATE	"27-Jun-2006"
+#define DRV_VERSION	"1.2"
+#define DRV_RELDATE	"11-Sep-2006"
 
 
 /* The user-configurable values.
@@ -107,7 +109,7 @@
 #endif
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/sundance.html\n";
 
@@ -646,7 +648,7 @@
 	/* Reset the chip to erase previous misconfiguration. */
 	if (netif_msg_hw(np))
 		printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
-	iowrite16(0x00ff, ioaddr + ASICCtrl + 2);
+	sundance_reset(dev, 0x00ff << 16);
 	if (netif_msg_hw(np))
 		printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
 
@@ -1075,13 +1077,8 @@
 	
 	/* Reset tx logic, TxListPtr will be cleaned */
 	iowrite16 (TxDisable, ioaddr + MACCtrl1);
-	iowrite16 (TxReset | DMAReset | FIFOReset | NetworkReset,
-			ioaddr + ASICCtrl + 2);
-	for (i=50; i > 0; i--) {
-		if ((ioread16(ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
-			break;
-		mdelay(1);
-	}
+	sundance_reset(dev, (NetworkReset|FIFOReset|DMAReset|TxReset) << 16);
+
 	/* free all tx skbuff */
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		skb = np->tx_skbuff[i];
@@ -1467,8 +1464,6 @@
 	int i;
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
 		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptAll | AcceptMyPhys;
 	} else if ((dev->mc_count > multicast_filter_limit)
@@ -1736,7 +1731,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init(&sundance_driver);
+	return pci_register_driver(&sundance_driver);
 }
 
 static void __exit sundance_exit(void)
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index b70bbd7..1a441a8 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -3194,7 +3194,7 @@
 
 static int __init gem_init(void)
 {
-	return pci_module_init(&gem_driver);
+	return pci_register_driver(&gem_driver);
 }
 
 static void __exit gem_cleanup(void)
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 1ef9fd3..ec04136 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1537,7 +1537,7 @@
 {
 	if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||
 	    (idprom->id_machtype == (SM_SUN4|SM_4_470))) {
-		memset(&sun4_sdev, 0, sizeof(sdev));
+		memset(&sun4_sdev, 0, sizeof(struct sbus_dev));
 		sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
 		sun4_sdev.irqs[0] = 6;
 		return sparc_lance_probe_one(&sun4_sdev, NULL, NULL);
@@ -1547,16 +1547,16 @@
 
 static int __exit sunlance_sun4_remove(void)
 {
-	struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev);
+	struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev);
 	struct net_device *net_dev = lp->dev;
 
 	unregister_netdevice(net_dev);
 
-	lance_free_hwresources(root_lance_dev);
+	lance_free_hwresources(lp);
 
 	free_netdev(net_dev);
 
-	dev_set_drvdata(&sun4_sdev->dev, NULL);
+	dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL);
 
 	return 0;
 }
@@ -1566,20 +1566,21 @@
 static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match)
 {
 	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
-	struct device_node *dp = dev->node;
 	int err;
 
-	if (!strcmp(dp->name, "le")) {
+	if (sdev->parent) {
+		struct of_device *parent = &sdev->parent->ofdev;
+
+		if (!strcmp(parent->node->name, "ledma")) {
+			struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev));
+
+			err = sparc_lance_probe_one(sdev, ledma, NULL);
+		} else if (!strcmp(parent->node->name, "lebuffer")) {
+			err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev));
+		} else
+			err = sparc_lance_probe_one(sdev, NULL, NULL);
+	} else
 		err = sparc_lance_probe_one(sdev, NULL, NULL);
-	} else if (!strcmp(dp->name, "ledma")) {
-		struct sbus_dma *ledma = find_ledma(sdev);
-
-		err = sparc_lance_probe_one(sdev->child, ledma, NULL);
-	} else {
-		BUG_ON(strcmp(dp->name, "lebuffer"));
-
-		err = sparc_lance_probe_one(sdev->child, NULL, sdev);
-	}
 
 	return err;
 }
@@ -1604,12 +1605,6 @@
 	{
 		.name = "le",
 	},
-	{
-		.name = "ledma",
-	},
-	{
-		.name = "lebuffer",
-	},
 	{},
 };
 
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 8b53ded..39460fa 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -1725,7 +1725,7 @@
 
 static int __init tc35815_init_module(void)
 {
-	return pci_module_init(&tc35815_driver);
+	return pci_register_driver(&tc35815_driver);
 }
 
 static void __exit tc35815_cleanup_module(void)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 1b8138f..d6e2a68 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.63"
-#define DRV_MODULE_RELDATE	"July 25, 2006"
+#define DRV_MODULE_VERSION	"3.65"
+#define DRV_MODULE_RELDATE	"August 07, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -123,9 +123,6 @@
 			           TG3_RX_RCB_RING_SIZE(tp))
 #define TG3_TX_RING_BYTES	(sizeof(struct tg3_tx_buffer_desc) * \
 				 TG3_TX_RING_SIZE)
-#define TX_BUFFS_AVAIL(TP)						\
-	((TP)->tx_pending -						\
-	 (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1)))
 #define NEXT_TX(N)		(((N) + 1) & (TG3_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ		(1536 + tp->rx_offset + 64)
@@ -2987,6 +2984,13 @@
 	spin_unlock(&tp->lock);
 }
 
+static inline u32 tg3_tx_avail(struct tg3 *tp)
+{
+	smp_mb();
+	return (tp->tx_pending -
+		((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1)));
+}
+
 /* Tigon3 never reports partial packet sends.  So we do not
  * need special logic to handle SKBs that have not had all
  * of their frags sent yet, like SunGEM does.
@@ -3038,12 +3042,20 @@
 
 	tp->tx_cons = sw_idx;
 
-	if (unlikely(netif_queue_stopped(tp->dev))) {
-		spin_lock(&tp->tx_lock);
+	/* Need to make the tx_cons update visible to tg3_start_xmit()
+	 * before checking for netif_queue_stopped().  Without the
+	 * memory barrier, there is a small possibility that tg3_start_xmit()
+	 * will miss it and cause the queue to be stopped forever.
+	 */
+	smp_mb();
+
+	if (unlikely(netif_queue_stopped(tp->dev) &&
+		     (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) {
+		netif_tx_lock(tp->dev);
 		if (netif_queue_stopped(tp->dev) &&
-		    (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+		    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))
 			netif_wake_queue(tp->dev);
-		spin_unlock(&tp->tx_lock);
+		netif_tx_unlock(tp->dev);
 	}
 }
 
@@ -3097,11 +3109,10 @@
 	 * Callers depend upon this behavior and assume that
 	 * we leave everything unchanged if we fail.
 	 */
-	skb = dev_alloc_skb(skb_size);
+	skb = netdev_alloc_skb(tp->dev, skb_size);
 	if (skb == NULL)
 		return -ENOMEM;
 
-	skb->dev = tp->dev;
 	skb_reserve(skb, tp->rx_offset);
 
 	mapping = pci_map_single(tp->pdev, skb->data,
@@ -3270,11 +3281,10 @@
 			tg3_recycle_rx(tp, opaque_key,
 				       desc_idx, *post_ptr);
 
-			copy_skb = dev_alloc_skb(len + 2);
+			copy_skb = netdev_alloc_skb(tp->dev, len + 2);
 			if (copy_skb == NULL)
 				goto drop_it_no_recycle;
 
-			copy_skb->dev = tp->dev;
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
 			pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
@@ -3797,7 +3807,7 @@
 	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+	if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_queue_stopped(dev)) {
 			netif_stop_queue(dev);
 
@@ -3893,12 +3903,10 @@
 	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
-		spin_lock(&tp->tx_lock);
+	if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
 		netif_stop_queue(dev);
-		if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
 			netif_wake_queue(tp->dev);
-		spin_unlock(&tp->tx_lock);
 	}
 
 out_unlock:
@@ -3920,7 +3928,7 @@
 	struct sk_buff *segs, *nskb;
 
 	/* Estimate the number of fragments in the worst case */
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
+	if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
 		netif_stop_queue(tp->dev);
 		return NETDEV_TX_BUSY;
 	}
@@ -3960,7 +3968,7 @@
 	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+	if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_queue_stopped(dev)) {
 			netif_stop_queue(dev);
 
@@ -4110,12 +4118,10 @@
 	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
-		spin_lock(&tp->tx_lock);
+	if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
 		netif_stop_queue(dev);
-		if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+		if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)
 			netif_wake_queue(tp->dev);
-		spin_unlock(&tp->tx_lock);
 	}
 
 out_unlock:
@@ -8618,7 +8624,7 @@
 	err = -EIO;
 
 	tx_len = 1514;
-	skb = dev_alloc_skb(tx_len);
+	skb = netdev_alloc_skb(tp->dev, tx_len);
 	if (!skb)
 		return -ENOMEM;
 
@@ -11474,7 +11480,6 @@
 	tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA;
 #endif
 	spin_lock_init(&tp->lock);
-	spin_lock_init(&tp->tx_lock);
 	spin_lock_init(&tp->indirect_lock);
 	INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
 
@@ -11814,7 +11819,7 @@
 
 static int __init tg3_init(void)
 {
-	return pci_module_init(&tg3_driver);
+	return pci_register_driver(&tg3_driver);
 }
 
 static void __exit tg3_cleanup(void)
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index ba2c987..3ecf356 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2079,9 +2079,9 @@
 	 * lock: Held during reset, PHY access, timer, and when
 	 *       updating tg3_flags and tg3_flags2.
 	 *
-	 * tx_lock: Held during tg3_start_xmit and tg3_tx only
-	 *          when calling netif_[start|stop]_queue.
-	 *          tg3_start_xmit is protected by netif_tx_lock.
+	 * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds
+	 *                netif_tx_lock when it needs to call
+	 *                netif_wake_queue.
 	 *
 	 * Both of these locks are to be held with BH safety.
 	 *
@@ -2118,8 +2118,6 @@
 	u32				tx_cons;
 	u32				tx_pending;
 
-	spinlock_t			tx_lock;
-
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tx_ring_info		*tx_buffers;
 	dma_addr_t			tx_desc_mapping;
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index 465921e..412390b 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -1815,7 +1815,7 @@
 
 static int __init xl_pci_init (void)
 {
-	return pci_module_init (&xl_3c359_driver);
+	return pci_register_driver(&xl_3c359_driver);
 }
 
 
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 9f49156..4470025 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -140,7 +140,7 @@
 
 /* version and credits */
 #ifndef PCMCIA
-static char version[] __initdata =
+static char version[] __devinitdata =
     "\nibmtr.c: v1.3.57   8/ 7/94 Peter De Schrijver and Mark Swanson\n"
     "         v2.1.125 10/20/98 Paul Norton    <pnorton@ieee.org>\n"
     "         v2.2.0   12/30/98 Joel Sloan     <jjs@c-me.com>\n"
@@ -216,7 +216,7 @@
 static int __devinitdata turbo_searched = 0;
 
 #ifndef PCMCIA
-static __u32 ibmtr_mem_base __initdata = 0xd0000;
+static __u32 ibmtr_mem_base __devinitdata = 0xd0000;
 #endif
 
 static void __devinit PrtChanID(char *pcid, short stride)
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 28d968f..0d66700 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -1998,7 +1998,7 @@
 };
 
 static int __init streamer_init_module(void) {
-  return pci_module_init(&streamer_pci_driver);
+  return pci_register_driver(&streamer_pci_driver);
 }
 
 static void __exit streamer_cleanup_module(void) {
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index cd2e025..85a7f79 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -5666,7 +5666,7 @@
 module_param_array(irq, int, NULL, 0);
 module_param(ringspeed, int, 0);
 
-static struct net_device *setup_card(int n)
+static struct net_device * __init setup_card(int n)
 {
 	struct net_device *dev = alloc_trdev(sizeof(struct net_local));
 	int err;
@@ -5696,9 +5696,8 @@
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
-			
 
-int init_module(void)
+int __init init_module(void)
 {
         int i, found = 0;
 	struct net_device *dev;
diff --git a/drivers/net/tulip/21142.c b/drivers/net/tulip/21142.c
index 683f14b..fa3a2bb 100644
--- a/drivers/net/tulip/21142.c
+++ b/drivers/net/tulip/21142.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/21142.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
@@ -26,9 +26,9 @@
 
 /* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
    of available transceivers.  */
-void t21142_timer(unsigned long data)
+void t21142_media_task(void *data)
 {
-	struct net_device *dev = (struct net_device *)data;
+	struct net_device *dev = data;
 	struct tulip_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->base_addr;
 	int csr12 = ioread32(ioaddr + CSR12);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index d05c5aa..17a2eba 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -2138,17 +2138,21 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct de_private *de = dev->priv;
+	int retval = 0;
 
 	rtnl_lock();
 	if (netif_device_present(dev))
 		goto out;
-	if (netif_running(dev)) {
-		pci_enable_device(pdev);
-		de_init_hw(de);
-		netif_device_attach(dev);
-	} else {
-		netif_device_attach(dev);
+	if (!netif_running(dev))
+		goto out_attach;
+	if ((retval = pci_enable_device(pdev))) {
+		printk (KERN_ERR "%s: pci_enable_device failed in resume\n",
+			dev->name);
+		goto out;
 	}
+	de_init_hw(de);
+out_attach:
+	netif_device_attach(dev);
 out:
 	rtnl_unlock();
 	return 0;
@@ -2172,7 +2176,7 @@
 #ifdef MODULE
 	printk("%s", version);
 #endif
-	return pci_module_init (&de_driver);
+	return pci_register_driver(&de_driver);
 }
 
 static void __exit de_exit (void)
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 75ff14a..e661d0a9 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -5754,7 +5754,7 @@
 	int err = 0;
 
 #ifdef CONFIG_PCI
-	err = pci_module_init (&de4x5_pci_driver);
+	err = pci_register_driver(&de4x5_pci_driver);
 #endif
 #ifdef CONFIG_EISA
 	err |= eisa_driver_register (&de4x5_eisa_driver);
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 4e5b0f2..66dade5 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -2039,7 +2039,7 @@
 	if (HPNA_NoiseFloor > 15)
 		HPNA_NoiseFloor = 0;
 
-	rc = pci_module_init(&dmfe_driver);
+	rc = pci_register_driver(&dmfe_driver);
 	if (rc < 0)
 		return rc;
 
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index 5ffbd5b..206918b 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/eeprom.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 99ccf2e..7f8f5d4 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/interrupt.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index e9bc2a9..20bd52b 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/media.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
diff --git a/drivers/net/tulip/pnic.c b/drivers/net/tulip/pnic.c
index ca7e532..85a521e 100644
--- a/drivers/net/tulip/pnic.c
+++ b/drivers/net/tulip/pnic.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/pnic.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c
index ab98502..c31be0e 100644
--- a/drivers/net/tulip/pnic2.c
+++ b/drivers/net/tulip/pnic2.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/pnic2.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
         Modified to hep support PNIC_II by Kevin B. Hendricks
diff --git a/drivers/net/tulip/timer.c b/drivers/net/tulip/timer.c
index e058a9f..066e5d6 100644
--- a/drivers/net/tulip/timer.c
+++ b/drivers/net/tulip/timer.c
@@ -1,7 +1,7 @@
 /*
 	drivers/net/tulip/timer.c
 
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
@@ -18,13 +18,14 @@
 #include "tulip.h"
 
 
-void tulip_timer(unsigned long data)
+void tulip_media_task(void *data)
 {
-	struct net_device *dev = (struct net_device *)data;
+	struct net_device *dev = data;
 	struct tulip_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->base_addr;
 	u32 csr12 = ioread32(ioaddr + CSR12);
 	int next_tick = 2*HZ;
+	unsigned long flags;
 
 	if (tulip_debug > 2) {
 		printk(KERN_DEBUG "%s: Media selection tick, %s, status %8.8x mode"
@@ -126,6 +127,15 @@
 	}
 	break;
 	}
+
+
+	spin_lock_irqsave(&tp->lock, flags);
+	if (tp->timeout_recovery) {
+		tulip_tx_timeout_complete(tp, ioaddr);
+		tp->timeout_recovery = 0;
+	}
+	spin_unlock_irqrestore(&tp->lock, flags);
+
 	/* mod_timer synchronizes us with potential add_timer calls
 	 * from interrupts.
 	 */
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 3bcfbf3..25668dd 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -30,11 +30,10 @@
 /* undefine, or define to various debugging levels (>4 == obscene levels) */
 #define TULIP_DEBUG 1
 
-/* undefine USE_IO_OPS for MMIO, define for PIO */
 #ifdef CONFIG_TULIP_MMIO
-# undef USE_IO_OPS
+#define TULIP_BAR	1	/* CBMA */
 #else
-# define USE_IO_OPS 1
+#define TULIP_BAR	0	/* CBIO */
 #endif
 
 
@@ -44,7 +43,8 @@
 	int io_size;
 	int valid_intrs;	/* CSR7 interrupt enable settings */
 	int flags;
-	void (*media_timer) (unsigned long data);
+	void (*media_timer) (unsigned long);
+	void (*media_task) (void *);
 };
 
 
@@ -142,6 +142,7 @@
 	RxNoBuf = 0x80,
 	RxIntr = 0x40,
 	TxFIFOUnderflow = 0x20,
+	RxErrIntr = 0x10,
 	TxJabber = 0x08,
 	TxNoBuf = 0x04,
 	TxDied = 0x02,
@@ -192,9 +193,14 @@
 
 
 enum desc_status_bits {
-	DescOwned = 0x80000000,
-	RxDescFatalErr = 0x8000,
-	RxWholePkt = 0x0300,
+	DescOwned    = 0x80000000,
+	DescWholePkt = 0x60000000,
+	DescEndPkt   = 0x40000000,
+	DescStartPkt = 0x20000000,
+	DescEndRing  = 0x02000000,
+	DescUseLink  = 0x01000000,
+	RxDescFatalErr = 0x008000,
+	RxWholePkt   = 0x00000300,
 };
 
 
@@ -366,6 +372,7 @@
 	unsigned int medialock:1;	/* Don't sense media type. */
 	unsigned int mediasense:1;	/* Media sensing in progress. */
 	unsigned int nway:1, nwayset:1;		/* 21143 internal NWay. */
+	unsigned int timeout_recovery:1;
 	unsigned int csr0;	/* CSR0 setting. */
 	unsigned int csr6;	/* Current CSR6 control settings. */
 	unsigned char eeprom[EEPROM_SIZE];	/* Serial EEPROM contents. */
@@ -384,6 +391,7 @@
 	void __iomem *base_addr;
 	int csr12_shadow;
 	int pad0;		/* Used for 8-byte alignment */
+	struct work_struct media_work;
 };
 
 
@@ -398,7 +406,7 @@
 
 /* 21142.c */
 extern u16 t21142_csr14[];
-void t21142_timer(unsigned long data);
+void t21142_media_task(void *data);
 void t21142_start_nway(struct net_device *dev);
 void t21142_lnk_change(struct net_device *dev, int csr5);
 
@@ -436,7 +444,7 @@
 void pnic_timer(unsigned long data);
 
 /* timer.c */
-void tulip_timer(unsigned long data);
+void tulip_media_task(void *data);
 void mxic_timer(unsigned long data);
 void comet_timer(unsigned long data);
 
@@ -485,4 +493,14 @@
 	tulip_start_rxtx(tp);
 }
 
+static inline void tulip_tx_timeout_complete(struct tulip_private *tp, void __iomem *ioaddr)
+{
+	/* Stop and restart the chip's Tx processes. */
+	tulip_restart_rxtx(tp);
+	/* Trigger an immediate transmit demand. */
+	iowrite32(0, ioaddr + CSR1);
+
+	tp->stats.tx_errors++;
+}
+
 #endif /* __NET_TULIP_H__ */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 7351831..2034baf 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1,7 +1,7 @@
 /* tulip_core.c: A DEC 21x4x-family ethernet driver for Linux. */
 
 /*
-	Maintained by Jeff Garzik <jgarzik@pobox.com>
+	Maintained by Valerie Henson <val_henson@linux.intel.com>
 	Copyright 2000,2001  The Linux Kernel Team
 	Written/copyright 1994-2001 by Donald Becker.
 
@@ -17,9 +17,9 @@
 
 #define DRV_NAME	"tulip"
 #ifdef CONFIG_TULIP_NAPI
-#define DRV_VERSION    "1.1.13-NAPI" /* Keep at least for test */
+#define DRV_VERSION    "1.1.14-NAPI" /* Keep at least for test */
 #else
-#define DRV_VERSION	"1.1.13"
+#define DRV_VERSION	"1.1.14"
 #endif
 #define DRV_RELDATE	"May 11, 2002"
 
@@ -130,7 +130,14 @@
 int tulip_debug = 1;
 #endif
 
+static void tulip_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct tulip_private *tp = netdev_priv(dev);
 
+	if (netif_running(dev))
+		schedule_work(&tp->media_work);
+}
 
 /*
  * This table use during operation for capabilities and media timer.
@@ -144,59 +151,60 @@
 
   /* DC21140 */
   { "Digital DS21140 Tulip", 128, 0x0001ebef,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer,
+	tulip_media_task },
 
   /* DC21142, DC21143 */
-  { "Digital DS21143 Tulip", 128, 0x0801fbff,
+  { "Digital DS21142/43 Tulip", 128, 0x0801fbff,
 	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY
-	| HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer },
+	| HAS_INTR_MITIGATION | HAS_PCI_MWI, tulip_timer, t21142_media_task },
 
   /* LC82C168 */
   { "Lite-On 82c168 PNIC", 256, 0x0001fbef,
-	HAS_MII | HAS_PNICNWAY, pnic_timer },
+	HAS_MII | HAS_PNICNWAY, pnic_timer, },
 
   /* MX98713 */
   { "Macronix 98713 PMAC", 128, 0x0001ebef,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
 
   /* MX98715 */
   { "Macronix 98715 PMAC", 256, 0x0001ebef,
-	HAS_MEDIA_TABLE, mxic_timer },
+	HAS_MEDIA_TABLE, mxic_timer, },
 
   /* MX98725 */
   { "Macronix 98725 PMAC", 256, 0x0001ebef,
-	HAS_MEDIA_TABLE, mxic_timer },
+	HAS_MEDIA_TABLE, mxic_timer, },
 
   /* AX88140 */
   { "ASIX AX88140", 128, 0x0001fbff,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
-	| IS_ASIX, tulip_timer },
+	| IS_ASIX, tulip_timer, tulip_media_task },
 
   /* PNIC2 */
   { "Lite-On PNIC-II", 256, 0x0801fbff,
-	HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer },
+	HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, pnic2_timer, },
 
   /* COMET */
   { "ADMtek Comet", 256, 0x0001abef,
-	HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer },
+	HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer, },
 
   /* COMPEX9881 */
   { "Compex 9881 PMAC", 128, 0x0001ebef,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer, },
 
   /* I21145 */
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
 	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI
-	| HAS_NWAY | HAS_PCI_MWI, t21142_timer },
+	| HAS_NWAY | HAS_PCI_MWI, tulip_timer, tulip_media_task },
 
   /* DM910X */
   { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
-	tulip_timer },
+	tulip_timer, tulip_media_task },
 
   /* RS7112 */
   { "Conexant LANfinity", 256, 0x0001ebef,
-	HAS_MII | HAS_ACPI, tulip_timer },
+	HAS_MII | HAS_ACPI, tulip_timer, tulip_media_task },
 
 };
 
@@ -295,12 +303,14 @@
 
 	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
 	iowrite32(0x00000001, ioaddr + CSR0);
+	pci_read_config_dword(tp->pdev, PCI_COMMAND, &i);  /* flush write */
 	udelay(100);
 
 	/* Deassert reset.
 	   Wait the specified 50 PCI cycles after a reset by initializing
 	   Tx and Rx queues and the address filter list. */
 	iowrite32(tp->csr0, ioaddr + CSR0);
+	pci_read_config_dword(tp->pdev, PCI_COMMAND, &i);  /* flush write */
 	udelay(100);
 
 	if (tulip_debug > 1)
@@ -522,20 +532,9 @@
 			   "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
 			   dev->name, ioread32(ioaddr + CSR5), ioread32(ioaddr + CSR12),
 			   ioread32(ioaddr + CSR13), ioread32(ioaddr + CSR14), ioread32(ioaddr + CSR15));
-		if ( ! tp->medialock  &&  tp->mtable) {
-			do
-				--tp->cur_index;
-			while (tp->cur_index >= 0
-				   && (tulip_media_cap[tp->mtable->mleaf[tp->cur_index].media]
-					   & MediaIsFD));
-			if (--tp->cur_index < 0) {
-				/* We start again, but should instead look for default. */
-				tp->cur_index = tp->mtable->leafcount - 1;
-			}
-			tulip_select_media(dev, 0);
-			printk(KERN_WARNING "%s: transmit timed out, switching to %s "
-				   "media.\n", dev->name, medianame[dev->if_port]);
-		}
+		tp->timeout_recovery = 1;
+		schedule_work(&tp->media_work);
+		goto out_unlock;
 	} else if (tp->chip_id == PNIC2) {
 		printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, "
 		       "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n",
@@ -575,14 +574,9 @@
 	}
 #endif
 
-	/* Stop and restart the chip's Tx processes . */
+	tulip_tx_timeout_complete(tp, ioaddr);
 
-	tulip_restart_rxtx(tp);
-	/* Trigger an immediate transmit demand. */
-	iowrite32(0, ioaddr + CSR1);
-
-	tp->stats.tx_errors++;
-
+out_unlock:
 	spin_unlock_irqrestore (&tp->lock, flags);
 	dev->trans_start = jiffies;
 	netif_wake_queue (dev);
@@ -732,6 +726,8 @@
 	void __iomem *ioaddr = tp->base_addr;
 	unsigned long flags;
 
+	flush_scheduled_work();
+
 	del_timer_sync (&tp->timer);
 #ifdef CONFIG_TULIP_NAPI
 	del_timer_sync (&tp->oom_timer);
@@ -1023,8 +1019,6 @@
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		tp->csr6 |= AcceptAllMulticast | AcceptAllPhys;
 		csr6 |= AcceptAllMulticast | AcceptAllPhys;
-		/* Unconditionally log net taps. */
-		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 	} else if ((dev->mc_count > 1000)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to filter well -- accept all multicasts. */
 		tp->csr6 |= AcceptAllMulticast;
@@ -1361,11 +1355,8 @@
 	if (pci_request_regions (pdev, "tulip"))
 		goto err_out_free_netdev;
 
-#ifndef USE_IO_OPS
-	ioaddr =  pci_iomap(pdev, 1, tulip_tbl[chip_idx].io_size);
-#else
-	ioaddr =  pci_iomap(pdev, 0, tulip_tbl[chip_idx].io_size);
-#endif
+	ioaddr =  pci_iomap(pdev, TULIP_BAR, tulip_tbl[chip_idx].io_size);
+
 	if (!ioaddr)
 		goto err_out_free_res;
 
@@ -1398,6 +1389,8 @@
 	tp->timer.data = (unsigned long)dev;
 	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
 
+	INIT_WORK(&tp->media_work, tulip_tbl[tp->chip_id].media_task, dev);
+
 	dev->base_addr = (unsigned long)ioaddr;
 
 #ifdef CONFIG_TULIP_MWI
@@ -1644,8 +1637,14 @@
 	if (register_netdev(dev))
 		goto err_out_free_ring;
 
-	printk(KERN_INFO "%s: %s rev %d at %p,",
-	       dev->name, chip_name, chip_rev, ioaddr);
+	printk(KERN_INFO "%s: %s rev %d at "
+#ifdef CONFIG_TULIP_MMIO
+		"MMIO"
+#else
+		"Port"
+#endif
+		" %#llx,", dev->name, chip_name, chip_rev,
+		(unsigned long long) pci_resource_start(pdev, TULIP_BAR));
 	pci_set_drvdata(pdev, dev);
 
 	if (eeprom_missing)
@@ -1768,7 +1767,10 @@
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 
-	pci_enable_device(pdev);
+	if ((retval = pci_enable_device(pdev))) {
+		printk (KERN_ERR "tulip: pci_enable_device failed in resume\n");
+		return retval;
+	}
 
 	if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) {
 		printk (KERN_ERR "tulip: request_irq failed in resume\n");
@@ -1849,7 +1851,7 @@
 	tulip_max_interrupt_work = max_interrupt_work;
 
 	/* probe for and init boards */
-	return pci_module_init (&tulip_driver);
+	return pci_register_driver(&tulip_driver);
 }
 
 
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index fd64b2b..c4c720e 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -1702,7 +1702,6 @@
 
 static int __init uli526x_init_module(void)
 {
-	int rc;
 
 	printk(version);
 	printed_version = 1;
@@ -1714,22 +1713,19 @@
 	if (cr6set)
 		uli526x_cr6_user_set = cr6set;
 
- 	switch(mode) {
+ 	switch (mode) {
    	case ULI526X_10MHF:
 	case ULI526X_100MHF:
 	case ULI526X_10MFD:
 	case ULI526X_100MFD:
 		uli526x_media_mode = mode;
 		break;
-	default:uli526x_media_mode = ULI526X_AUTO;
+	default:
+		uli526x_media_mode = ULI526X_AUTO;
 		break;
 	}
 
-	rc = pci_module_init(&uli526x_driver);
-	if (rc < 0)
-		return rc;
-
-	return 0;
+	return pci_register_driver(&uli526x_driver);
 }
 
 
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 7f41481..0e5344f 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -45,8 +45,8 @@
 */
 
 #define DRV_NAME	"winbond-840"
-#define DRV_VERSION	"1.01-d"
-#define DRV_RELDATE	"Nov-17-2001"
+#define DRV_VERSION	"1.01-e"
+#define DRV_RELDATE	"Sep-11-2006"
 
 
 /* Automatically extracted configuration info:
@@ -90,10 +90,8 @@
    Making the Tx ring too large decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
 #define TX_QUEUE_LEN_RESTART	5
-#define RX_RING_SIZE	32
 
 #define TX_BUFLIMIT	(1024-128)
 
@@ -137,8 +135,10 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+#include "tulip.h"
+
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE "  Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/drivers.html\n";
 
@@ -242,8 +242,8 @@
 };
 
 /* This driver was written to use PCI memory space, however some x86 systems
-   work only with I/O space accesses.  Pass -DUSE_IO_OPS to use PCI I/O space
-   accesses instead of memory space. */
+   work only with I/O space accesses. See CONFIG_TULIP_MMIO in .config
+*/
 
 /* Offsets to the Command and Status Registers, "CSRs".
    While similar to the Tulip, these registers are longword aligned.
@@ -261,21 +261,11 @@
 	CurTxDescAddr=0x4C, CurTxBufAddr=0x50,
 };
 
-/* Bits in the interrupt status/enable registers. */
-/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
-enum intr_status_bits {
-	NormalIntr=0x10000, AbnormalIntr=0x8000,
-	IntrPCIErr=0x2000, TimerInt=0x800,
-	IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
-	TxFIFOUnderflow=0x20, RxErrIntr=0x10,
-	TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01,
-};
-
 /* Bits in the NetworkConfig register. */
 enum rx_mode_bits {
-	AcceptErr=0x80, AcceptRunt=0x40,
-	AcceptBroadcast=0x20, AcceptMulticast=0x10,
-	AcceptAllPhys=0x08, AcceptMyPhys=0x02,
+	AcceptErr=0x80,
+	RxAcceptBroadcast=0x20, AcceptMulticast=0x10,
+	RxAcceptAllPhys=0x08, AcceptMyPhys=0x02,
 };
 
 enum mii_reg_bits {
@@ -297,13 +287,6 @@
 	u32 buffer1, buffer2;
 };
 
-/* Bits in network_desc.status */
-enum desc_status_bits {
-	DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
-	DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
-	DescIntr=0x80000000,
-};
-
 #define MII_CNT		1 /* winbond only supports one MII */
 struct netdev_private {
 	struct w840_rx_desc *rx_ring;
@@ -371,7 +354,6 @@
 	int irq;
 	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
 	void __iomem *ioaddr;
-	int bar = 1;
 
 	i = pci_enable_device(pdev);
 	if (i) return i;
@@ -393,10 +375,8 @@
 
 	if (pci_request_regions(pdev, DRV_NAME))
 		goto err_out_netdev;
-#ifdef USE_IO_OPS
-	bar = 0;
-#endif
-	ioaddr = pci_iomap(pdev, bar, netdev_res_size);
+
+	ioaddr = pci_iomap(pdev, TULIP_BAR, netdev_res_size);
 	if (!ioaddr)
 		goto err_out_free_res;
 
@@ -838,7 +818,7 @@
 					np->rx_buf_sz,PCI_DMA_FROMDEVICE);
 
 		np->rx_ring[i].buffer1 = np->rx_addr[i];
-		np->rx_ring[i].status = DescOwn;
+		np->rx_ring[i].status = DescOwned;
 	}
 
 	np->cur_rx = 0;
@@ -923,7 +903,7 @@
 	}
 #elif defined(__powerpc__) || defined(__i386__) || defined(__alpha__) || defined(__ia64__) || defined(__x86_64__)
 	i |= 0xE000;
-#elif defined(__sparc__)
+#elif defined(__sparc__) || defined (CONFIG_PARISC)
 	i |= 0x4800;
 #else
 #warning Processor architecture undefined
@@ -1043,11 +1023,11 @@
 
 	/* Now acquire the irq spinlock.
 	 * The difficult race is the the ordering between
-	 * increasing np->cur_tx and setting DescOwn:
+	 * increasing np->cur_tx and setting DescOwned:
 	 * - if np->cur_tx is increased first the interrupt
 	 *   handler could consider the packet as transmitted
-	 *   since DescOwn is cleared.
-	 * - If DescOwn is set first the NIC could report the
+	 *   since DescOwned is cleared.
+	 * - If DescOwned is set first the NIC could report the
 	 *   packet as sent, but the interrupt handler would ignore it
 	 *   since the np->cur_tx was not yet increased.
 	 */
@@ -1055,7 +1035,7 @@
 	np->cur_tx++;
 
 	wmb(); /* flush length, buffer1, buffer2 */
-	np->tx_ring[entry].status = DescOwn;
+	np->tx_ring[entry].status = DescOwned;
 	wmb(); /* flush status and kick the hardware */
 	iowrite32(0, np->base_addr + TxStartDemand);
 	np->tx_q_bytes += skb->len;
@@ -1155,12 +1135,12 @@
 
 		handled = 1;
 
-		if (intr_status & (IntrRxDone | RxNoBuf))
+		if (intr_status & (RxIntr | RxNoBuf))
 			netdev_rx(dev);
 		if (intr_status & RxNoBuf)
 			iowrite32(0, ioaddr + RxStartDemand);
 
-		if (intr_status & (TxIdle | IntrTxDone) &&
+		if (intr_status & (TxNoBuf | TxIntr) &&
 			np->cur_tx != np->dirty_tx) {
 			spin_lock(&np->lock);
 			netdev_tx_done(dev);
@@ -1168,8 +1148,8 @@
 		}
 
 		/* Abnormal error summary/uncommon events handlers. */
-		if (intr_status & (AbnormalIntr | TxFIFOUnderflow | IntrPCIErr |
-						   TimerInt | IntrTxStopped))
+		if (intr_status & (AbnormalIntr | TxFIFOUnderflow | SytemError |
+						   TimerInt | TxDied))
 			netdev_error(dev, intr_status);
 
 		if (--work_limit < 0) {
@@ -1305,7 +1285,7 @@
 			np->rx_ring[entry].buffer1 = np->rx_addr[entry];
 		}
 		wmb();
-		np->rx_ring[entry].status = DescOwn;
+		np->rx_ring[entry].status = DescOwned;
 	}
 
 	return 0;
@@ -1342,7 +1322,7 @@
 			   dev->name, new);
 		update_csr6(dev, new);
 	}
-	if (intr_status & IntrRxDied) {		/* Missed a Rx frame. */
+	if (intr_status & RxDied) {		/* Missed a Rx frame. */
 		np->stats.rx_errors++;
 	}
 	if (intr_status & TimerInt) {
@@ -1378,16 +1358,14 @@
 	u32 rx_mode;
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
-		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptAllPhys
+		rx_mode = RxAcceptBroadcast | AcceptMulticast | RxAcceptAllPhys
 			| AcceptMyPhys;
 	} else if ((dev->mc_count > multicast_filter_limit)
 			   ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to match, or accept all multicasts. */
 		memset(mc_filter, 0xff, sizeof(mc_filter));
-		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+		rx_mode = RxAcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	} else {
 		struct dev_mc_list *mclist;
 		int i;
@@ -1398,7 +1376,7 @@
 			filterbit &= 0x3f;
 			mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
 		}
-		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+		rx_mode = RxAcceptBroadcast | AcceptMulticast | AcceptMyPhys;
 	}
 	iowrite32(mc_filter[0], ioaddr + MulticastFilter0);
 	iowrite32(mc_filter[1], ioaddr + MulticastFilter1);
@@ -1646,14 +1624,18 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct netdev_private *np = netdev_priv(dev);
+	int retval = 0;
 
 	rtnl_lock();
 	if (netif_device_present(dev))
 		goto out; /* device not suspended */
 	if (netif_running(dev)) {
-		pci_enable_device(pdev);
-	/*	pci_power_on(pdev); */
-
+		if ((retval = pci_enable_device(pdev))) {
+			printk (KERN_ERR
+				"%s: pci_enable_device failed in resume\n",
+				dev->name);
+			goto out;
+		}
 		spin_lock_irq(&np->lock);
 		iowrite32(1, np->base_addr+PCIBusCfg);
 		ioread32(np->base_addr+PCIBusCfg);
@@ -1671,7 +1653,7 @@
 	}
 out:
 	rtnl_unlock();
-	return 0;
+	return retval;
 }
 #endif
 
@@ -1689,7 +1671,7 @@
 static int __init w840_init(void)
 {
 	printk(version);
-	return pci_module_init(&w840_driver);
+	return pci_register_driver(&w840_driver);
 }
 
 static void __exit w840_exit(void)
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index f874e4f..cf43390 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -1264,8 +1264,7 @@
 
 static int __init xircom_init(void)
 {
-	pci_register_driver(&xircom_ops);
-	return 0;
+	return pci_register_driver(&xircom_ops);
 }
 
 static void __exit xircom_exit(void)
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index 17ca7dc..d797b7b 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -1707,7 +1707,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init(&xircom_driver);
+	return pci_register_driver(&xircom_driver);
 }
 
 
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 4103c37..1084180 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -100,8 +100,8 @@
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.5.7"
-#define DRV_MODULE_RELDATE	"05/01/07"
+#define DRV_MODULE_VERSION 	"1.5.8"
+#define DRV_MODULE_RELDATE	"06/11/09"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -937,8 +937,6 @@
 
 	filter = TYPHOON_RX_FILTER_DIRECTED | TYPHOON_RX_FILTER_BROADCAST;
 	if(dev->flags & IFF_PROMISC) {
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-		       dev->name);
 		filter |= TYPHOON_RX_FILTER_PROMISCOUS;
 	} else if((dev->mc_count > multicast_filter_limit) ||
 		  (dev->flags & IFF_ALLMULTI)) {
@@ -2660,7 +2658,7 @@
 static int __init
 typhoon_init(void)
 {
-	return pci_module_init(&typhoon_driver);
+	return pci_register_driver(&typhoon_driver);
 }
 
 static void __exit
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
new file mode 100644
index 0000000..4e188f4
--- /dev/null
+++ b/drivers/net/ucc_geth.c
@@ -0,0 +1,4276 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * QE UCC Gigabit Ethernet Driver
+ *
+ * Changelog:
+ * Jul 6, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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/errno.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/mii.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+
+#undef DEBUG
+
+#define DRV_DESC "QE UCC Gigabit Ethernet Controller version:Sept 11, 2006"
+#define DRV_NAME "ucc_geth"
+
+#define ugeth_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugeth_dbg(format, arg...)            \
+        ugeth_printk(KERN_DEBUG , format , ## arg)
+#define ugeth_err(format, arg...)            \
+        ugeth_printk(KERN_ERR , format , ## arg)
+#define ugeth_info(format, arg...)           \
+        ugeth_printk(KERN_INFO , format , ## arg)
+#define ugeth_warn(format, arg...)           \
+        ugeth_printk(KERN_WARNING , format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugeth_vdbg ugeth_dbg
+#else
+#define ugeth_vdbg(fmt, args...) do { } while (0)
+#endif				/* UGETH_VERBOSE_DEBUG */
+
+static DEFINE_SPINLOCK(ugeth_lock);
+
+static ucc_geth_info_t ugeth_primary_info = {
+	.uf_info = {
+		    .bd_mem_part = MEM_PART_SYSTEM,
+		    .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
+		    .max_rx_buf_length = 1536,
+/* FIXME: should be changed in run time for 1G and 100M */
+#ifdef CONFIG_UGETH_HAS_GIGA
+		    .urfs = UCC_GETH_URFS_GIGA_INIT,
+		    .urfet = UCC_GETH_URFET_GIGA_INIT,
+		    .urfset = UCC_GETH_URFSET_GIGA_INIT,
+		    .utfs = UCC_GETH_UTFS_GIGA_INIT,
+		    .utfet = UCC_GETH_UTFET_GIGA_INIT,
+		    .utftt = UCC_GETH_UTFTT_GIGA_INIT,
+#else
+		    .urfs = UCC_GETH_URFS_INIT,
+		    .urfet = UCC_GETH_URFET_INIT,
+		    .urfset = UCC_GETH_URFSET_INIT,
+		    .utfs = UCC_GETH_UTFS_INIT,
+		    .utfet = UCC_GETH_UTFET_INIT,
+		    .utftt = UCC_GETH_UTFTT_INIT,
+#endif
+		    .ufpt = 256,
+		    .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
+		    .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
+		    .tenc = UCC_FAST_TX_ENCODING_NRZ,
+		    .renc = UCC_FAST_RX_ENCODING_NRZ,
+		    .tcrc = UCC_FAST_16_BIT_CRC,
+		    .synl = UCC_FAST_SYNC_LEN_NOT_USED,
+		    },
+	.numQueuesTx = 1,
+	.numQueuesRx = 1,
+	.extendedFilteringChainPointer = ((uint32_t) NULL),
+	.typeorlen = 3072 /*1536 */ ,
+	.nonBackToBackIfgPart1 = 0x40,
+	.nonBackToBackIfgPart2 = 0x60,
+	.miminumInterFrameGapEnforcement = 0x50,
+	.backToBackInterFrameGap = 0x60,
+	.mblinterval = 128,
+	.nortsrbytetime = 5,
+	.fracsiz = 1,
+	.strictpriorityq = 0xff,
+	.altBebTruncation = 0xa,
+	.excessDefer = 1,
+	.maxRetransmission = 0xf,
+	.collisionWindow = 0x37,
+	.receiveFlowControl = 1,
+	.maxGroupAddrInHash = 4,
+	.maxIndAddrInHash = 4,
+	.prel = 7,
+	.maxFrameLength = 1518,
+	.minFrameLength = 64,
+	.maxD1Length = 1520,
+	.maxD2Length = 1520,
+	.vlantype = 0x8100,
+	.ecamptr = ((uint32_t) NULL),
+	.eventRegMask = UCCE_OTHER,
+	.pausePeriod = 0xf000,
+	.interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
+	.bdRingLenTx = {
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN,
+			TX_BD_RING_LEN},
+
+	.bdRingLenRx = {
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN,
+			RX_BD_RING_LEN},
+
+	.numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
+	.largestexternallookupkeysize =
+	    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
+	.statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE,
+	.vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
+	.vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
+	.rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
+	.aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
+	.padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
+	.numThreadsTx = UCC_GETH_NUM_OF_THREADS_4,
+	.numThreadsRx = UCC_GETH_NUM_OF_THREADS_4,
+	.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+	.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
+};
+
+static ucc_geth_info_t ugeth_info[8];
+
+#ifdef DEBUG
+static void mem_disp(u8 *addr, int size)
+{
+	u8 *i;
+	int size16Aling = (size >> 4) << 4;
+	int size4Aling = (size >> 2) << 2;
+	int notAlign = 0;
+	if (size % 16)
+		notAlign = 1;
+
+	for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
+		printk("0x%08x: %08x %08x %08x %08x\r\n",
+		       (u32) i,
+		       *((u32 *) (i)),
+		       *((u32 *) (i + 4)),
+		       *((u32 *) (i + 8)), *((u32 *) (i + 12)));
+	if (notAlign == 1)
+		printk("0x%08x: ", (u32) i);
+	for (; (u32) i < (u32) addr + size4Aling; i += 4)
+		printk("%08x ", *((u32 *) (i)));
+	for (; (u32) i < (u32) addr + size; i++)
+		printk("%02x", *((u8 *) (i)));
+	if (notAlign == 1)
+		printk("\r\n");
+}
+#endif /* DEBUG */
+
+#ifdef CONFIG_UGETH_FILTERING
+static void enqueue(struct list_head *node, struct list_head *lh)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(ugeth_lock, flags);
+	list_add_tail(node, lh);
+	spin_unlock_irqrestore(ugeth_lock, flags);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static struct list_head *dequeue(struct list_head *lh)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(ugeth_lock, flags);
+	if (!list_empty(lh)) {
+		struct list_head *node = lh->next;
+		list_del(node);
+		spin_unlock_irqrestore(ugeth_lock, flags);
+		return node;
+	} else {
+		spin_unlock_irqrestore(ugeth_lock, flags);
+		return NULL;
+	}
+}
+
+static int get_interface_details(enet_interface_e enet_interface,
+				 enet_speed_e *speed,
+				 int *r10m,
+				 int *rmm,
+				 int *rpm,
+				 int *tbi, int *limited_to_full_duplex)
+{
+	/* Analyze enet_interface according to Interface Mode
+	Configuration table */
+	switch (enet_interface) {
+	case ENET_10_MII:
+		*speed = ENET_SPEED_10BT;
+		break;
+	case ENET_10_RMII:
+		*speed = ENET_SPEED_10BT;
+		*r10m = 1;
+		*rmm = 1;
+		break;
+	case ENET_10_RGMII:
+		*speed = ENET_SPEED_10BT;
+		*rpm = 1;
+		*r10m = 1;
+		*limited_to_full_duplex = 1;
+		break;
+	case ENET_100_MII:
+		*speed = ENET_SPEED_100BT;
+		break;
+	case ENET_100_RMII:
+		*speed = ENET_SPEED_100BT;
+		*rmm = 1;
+		break;
+	case ENET_100_RGMII:
+		*speed = ENET_SPEED_100BT;
+		*rpm = 1;
+		*limited_to_full_duplex = 1;
+		break;
+	case ENET_1000_GMII:
+		*speed = ENET_SPEED_1000BT;
+		*limited_to_full_duplex = 1;
+		break;
+	case ENET_1000_RGMII:
+		*speed = ENET_SPEED_1000BT;
+		*rpm = 1;
+		*limited_to_full_duplex = 1;
+		break;
+	case ENET_1000_TBI:
+		*speed = ENET_SPEED_1000BT;
+		*tbi = 1;
+		*limited_to_full_duplex = 1;
+		break;
+	case ENET_1000_RTBI:
+		*speed = ENET_SPEED_1000BT;
+		*rpm = 1;
+		*tbi = 1;
+		*limited_to_full_duplex = 1;
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	return 0;
+}
+
+static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd)
+{
+	struct sk_buff *skb = NULL;
+
+	skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
+				  UCC_GETH_RX_DATA_BUF_ALIGNMENT);
+
+	if (skb == NULL)
+		return NULL;
+
+	/* We need the data buffer to be aligned properly.  We will reserve
+	 * as many bytes as needed to align the data properly
+	 */
+	skb_reserve(skb,
+		    UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+		    (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
+					      1)));
+
+	skb->dev = ugeth->dev;
+
+	BD_BUFFER_SET(bd,
+		      dma_map_single(NULL,
+				     skb->data,
+				     ugeth->ug_info->uf_info.max_rx_buf_length +
+				     UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+				     DMA_FROM_DEVICE));
+
+	BD_STATUS_AND_LENGTH_SET(bd,
+				 (R_E | R_I |
+				  (BD_STATUS_AND_LENGTH(bd) & R_W)));
+
+	return skb;
+}
+
+static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ)
+{
+	u8 *bd;
+	u32 bd_status;
+	struct sk_buff *skb;
+	int i;
+
+	bd = ugeth->p_rx_bd_ring[rxQ];
+	i = 0;
+
+	do {
+		bd_status = BD_STATUS_AND_LENGTH(bd);
+		skb = get_new_skb(ugeth, bd);
+
+		if (!skb)	/* If can not allocate data buffer,
+				abort. Cleanup will be elsewhere */
+			return -ENOMEM;
+
+		ugeth->rx_skbuff[rxQ][i] = skb;
+
+		/* advance the BD pointer */
+		bd += UCC_GETH_SIZE_OF_BD;
+		i++;
+	} while (!(bd_status & R_W));
+
+	return 0;
+}
+
+static int fill_init_enet_entries(ucc_geth_private_t *ugeth,
+				  volatile u32 *p_start,
+				  u8 num_entries,
+				  u32 thread_size,
+				  u32 thread_alignment,
+				  qe_risc_allocation_e risc,
+				  int skip_page_for_first_entry)
+{
+	u32 init_enet_offset;
+	u8 i;
+	int snum;
+
+	for (i = 0; i < num_entries; i++) {
+		if ((snum = qe_get_snum()) < 0) {
+			ugeth_err("fill_init_enet_entries: Can not get SNUM.");
+			return snum;
+		}
+		if ((i == 0) && skip_page_for_first_entry)
+		/* First entry of Rx does not have page */
+			init_enet_offset = 0;
+		else {
+			init_enet_offset =
+			    qe_muram_alloc(thread_size, thread_alignment);
+			if (IS_MURAM_ERR(init_enet_offset)) {
+				ugeth_err
+		("fill_init_enet_entries: Can not allocate DPRAM memory.");
+				qe_put_snum((u8) snum);
+				return -ENOMEM;
+			}
+		}
+		*(p_start++) =
+		    ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
+		    | risc;
+	}
+
+	return 0;
+}
+
+static int return_init_enet_entries(ucc_geth_private_t *ugeth,
+				    volatile u32 *p_start,
+				    u8 num_entries,
+				    qe_risc_allocation_e risc,
+				    int skip_page_for_first_entry)
+{
+	u32 init_enet_offset;
+	u8 i;
+	int snum;
+
+	for (i = 0; i < num_entries; i++) {
+		/* Check that this entry was actually valid --
+		needed in case failed in allocations */
+		if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+			snum =
+			    (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+			    ENET_INIT_PARAM_SNUM_SHIFT;
+			qe_put_snum((u8) snum);
+			if (!((i == 0) && skip_page_for_first_entry)) {
+			/* First entry of Rx does not have page */
+				init_enet_offset =
+				    (in_be32(p_start) &
+				     ENET_INIT_PARAM_PTR_MASK);
+				qe_muram_free(init_enet_offset);
+			}
+			*(p_start++) = 0;	/* Just for cosmetics */
+		}
+	}
+
+	return 0;
+}
+
+#ifdef DEBUG
+static int dump_init_enet_entries(ucc_geth_private_t *ugeth,
+				  volatile u32 *p_start,
+				  u8 num_entries,
+				  u32 thread_size,
+				  qe_risc_allocation_e risc,
+				  int skip_page_for_first_entry)
+{
+	u32 init_enet_offset;
+	u8 i;
+	int snum;
+
+	for (i = 0; i < num_entries; i++) {
+		/* Check that this entry was actually valid --
+		needed in case failed in allocations */
+		if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
+			snum =
+			    (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
+			    ENET_INIT_PARAM_SNUM_SHIFT;
+			qe_put_snum((u8) snum);
+			if (!((i == 0) && skip_page_for_first_entry)) {
+			/* First entry of Rx does not have page */
+				init_enet_offset =
+				    (in_be32(p_start) &
+				     ENET_INIT_PARAM_PTR_MASK);
+				ugeth_info("Init enet entry %d:", i);
+				ugeth_info("Base address: 0x%08x",
+					   (u32)
+					   qe_muram_addr(init_enet_offset));
+				mem_disp(qe_muram_addr(init_enet_offset),
+					 thread_size);
+			}
+			p_start++;
+		}
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_UGETH_FILTERING
+static enet_addr_container_t *get_enet_addr_container(void)
+{
+	enet_addr_container_t *enet_addr_cont;
+
+	/* allocate memory */
+	enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL);
+	if (!enet_addr_cont) {
+		ugeth_err("%s: No memory for enet_addr_container_t object.",
+			  __FUNCTION__);
+		return NULL;
+	}
+
+	return enet_addr_cont;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont)
+{
+	kfree(enet_addr_cont);
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+				enet_addr_t *p_enet_addr, u8 paddr_num)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+	if (!(paddr_num < NUM_OF_PADDRS)) {
+		ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	p_82xx_addr_filt =
+	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    addressfiltering;
+
+	/* Ethernet frames are defined in Little Endian mode,    */
+	/* therefore to insert the address we reverse the bytes. */
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].h,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+			(u16) (*p_enet_addr)[4]));
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].m,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+			(u16) (*p_enet_addr)[2]));
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].l,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+			(u16) (*p_enet_addr)[0]));
+
+	return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+
+	if (!(paddr_num < NUM_OF_PADDRS)) {
+		ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	p_82xx_addr_filt =
+	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    addressfiltering;
+
+	/* Writing address ff.ff.ff.ff.ff.ff disables address
+	recognition for this register */
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
+	out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);
+
+	return 0;
+}
+
+static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth,
+				enet_addr_t *p_enet_addr)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	u32 cecr_subblock;
+
+	p_82xx_addr_filt =
+	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    addressfiltering;
+
+	cecr_subblock =
+	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+
+	/* Ethernet frames are defined in Little Endian mode,
+	therefor to insert */
+	/* the address to the hash (Big Endian mode), we reverse the bytes.*/
+	out_be16(&p_82xx_addr_filt->taddr.h,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
+			(u16) (*p_enet_addr)[4]));
+	out_be16(&p_82xx_addr_filt->taddr.m,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
+			(u16) (*p_enet_addr)[2]));
+	out_be16(&p_82xx_addr_filt->taddr.l,
+		 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
+			(u16) (*p_enet_addr)[0]));
+
+	qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
+		     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+}
+
+#ifdef CONFIG_UGETH_MAGIC_PACKET
+static void magic_packet_detection_enable(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_private_t *uccf;
+	ucc_geth_t *ug_regs;
+	u32 maccfg2, uccm;
+
+	uccf = ugeth->uccf;
+	ug_regs = ugeth->ug_regs;
+
+	/* Enable interrupts for magic packet detection */
+	uccm = in_be32(uccf->p_uccm);
+	uccm |= UCCE_MPD;
+	out_be32(uccf->p_uccm, uccm);
+
+	/* Enable magic packet detection */
+	maccfg2 = in_be32(&ug_regs->maccfg2);
+	maccfg2 |= MACCFG2_MPE;
+	out_be32(&ug_regs->maccfg2, maccfg2);
+}
+
+static void magic_packet_detection_disable(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_private_t *uccf;
+	ucc_geth_t *ug_regs;
+	u32 maccfg2, uccm;
+
+	uccf = ugeth->uccf;
+	ug_regs = ugeth->ug_regs;
+
+	/* Disable interrupts for magic packet detection */
+	uccm = in_be32(uccf->p_uccm);
+	uccm &= ~UCCE_MPD;
+	out_be32(uccf->p_uccm, uccm);
+
+	/* Disable magic packet detection */
+	maccfg2 = in_be32(&ug_regs->maccfg2);
+	maccfg2 &= ~MACCFG2_MPE;
+	out_be32(&ug_regs->maccfg2, maccfg2);
+}
+#endif /* MAGIC_PACKET */
+
+static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2)
+{
+	return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
+}
+
+#ifdef DEBUG
+static void get_statistics(ucc_geth_private_t *ugeth,
+			   ucc_geth_tx_firmware_statistics_t *
+			   tx_firmware_statistics,
+			   ucc_geth_rx_firmware_statistics_t *
+			   rx_firmware_statistics,
+			   ucc_geth_hardware_statistics_t *hardware_statistics)
+{
+	ucc_fast_t *uf_regs;
+	ucc_geth_t *ug_regs;
+	ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+	ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+
+	ug_regs = ugeth->ug_regs;
+	uf_regs = (ucc_fast_t *) ug_regs;
+	p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
+	p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
+
+	/* Tx firmware only if user handed pointer and driver actually
+	gathers Tx firmware statistics */
+	if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
+		tx_firmware_statistics->sicoltx =
+		    in_be32(&p_tx_fw_statistics_pram->sicoltx);
+		tx_firmware_statistics->mulcoltx =
+		    in_be32(&p_tx_fw_statistics_pram->mulcoltx);
+		tx_firmware_statistics->latecoltxfr =
+		    in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
+		tx_firmware_statistics->frabortduecol =
+		    in_be32(&p_tx_fw_statistics_pram->frabortduecol);
+		tx_firmware_statistics->frlostinmactxer =
+		    in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
+		tx_firmware_statistics->carriersenseertx =
+		    in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
+		tx_firmware_statistics->frtxok =
+		    in_be32(&p_tx_fw_statistics_pram->frtxok);
+		tx_firmware_statistics->txfrexcessivedefer =
+		    in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
+		tx_firmware_statistics->txpkts256 =
+		    in_be32(&p_tx_fw_statistics_pram->txpkts256);
+		tx_firmware_statistics->txpkts512 =
+		    in_be32(&p_tx_fw_statistics_pram->txpkts512);
+		tx_firmware_statistics->txpkts1024 =
+		    in_be32(&p_tx_fw_statistics_pram->txpkts1024);
+		tx_firmware_statistics->txpktsjumbo =
+		    in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
+	}
+
+	/* Rx firmware only if user handed pointer and driver actually
+	 * gathers Rx firmware statistics */
+	if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
+		int i;
+		rx_firmware_statistics->frrxfcser =
+		    in_be32(&p_rx_fw_statistics_pram->frrxfcser);
+		rx_firmware_statistics->fraligner =
+		    in_be32(&p_rx_fw_statistics_pram->fraligner);
+		rx_firmware_statistics->inrangelenrxer =
+		    in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
+		rx_firmware_statistics->outrangelenrxer =
+		    in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
+		rx_firmware_statistics->frtoolong =
+		    in_be32(&p_rx_fw_statistics_pram->frtoolong);
+		rx_firmware_statistics->runt =
+		    in_be32(&p_rx_fw_statistics_pram->runt);
+		rx_firmware_statistics->verylongevent =
+		    in_be32(&p_rx_fw_statistics_pram->verylongevent);
+		rx_firmware_statistics->symbolerror =
+		    in_be32(&p_rx_fw_statistics_pram->symbolerror);
+		rx_firmware_statistics->dropbsy =
+		    in_be32(&p_rx_fw_statistics_pram->dropbsy);
+		for (i = 0; i < 0x8; i++)
+			rx_firmware_statistics->res0[i] =
+			    p_rx_fw_statistics_pram->res0[i];
+		rx_firmware_statistics->mismatchdrop =
+		    in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
+		rx_firmware_statistics->underpkts =
+		    in_be32(&p_rx_fw_statistics_pram->underpkts);
+		rx_firmware_statistics->pkts256 =
+		    in_be32(&p_rx_fw_statistics_pram->pkts256);
+		rx_firmware_statistics->pkts512 =
+		    in_be32(&p_rx_fw_statistics_pram->pkts512);
+		rx_firmware_statistics->pkts1024 =
+		    in_be32(&p_rx_fw_statistics_pram->pkts1024);
+		rx_firmware_statistics->pktsjumbo =
+		    in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
+		rx_firmware_statistics->frlossinmacer =
+		    in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
+		rx_firmware_statistics->pausefr =
+		    in_be32(&p_rx_fw_statistics_pram->pausefr);
+		for (i = 0; i < 0x4; i++)
+			rx_firmware_statistics->res1[i] =
+			    p_rx_fw_statistics_pram->res1[i];
+		rx_firmware_statistics->removevlan =
+		    in_be32(&p_rx_fw_statistics_pram->removevlan);
+		rx_firmware_statistics->replacevlan =
+		    in_be32(&p_rx_fw_statistics_pram->replacevlan);
+		rx_firmware_statistics->insertvlan =
+		    in_be32(&p_rx_fw_statistics_pram->insertvlan);
+	}
+
+	/* Hardware only if user handed pointer and driver actually
+	gathers hardware statistics */
+	if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
+		hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
+		hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
+		hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
+		hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
+		hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
+		hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
+		hardware_statistics->txok = in_be32(&ug_regs->txok);
+		hardware_statistics->txcf = in_be16(&ug_regs->txcf);
+		hardware_statistics->tmca = in_be32(&ug_regs->tmca);
+		hardware_statistics->tbca = in_be32(&ug_regs->tbca);
+		hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
+		hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
+		hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
+		hardware_statistics->rmca = in_be32(&ug_regs->rmca);
+		hardware_statistics->rbca = in_be32(&ug_regs->rbca);
+	}
+}
+
+static void dump_bds(ucc_geth_private_t *ugeth)
+{
+	int i;
+	int length;
+
+	for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+		if (ugeth->p_tx_bd_ring[i]) {
+			length =
+			    (ugeth->ug_info->bdRingLenTx[i] *
+			     UCC_GETH_SIZE_OF_BD);
+			ugeth_info("TX BDs[%d]", i);
+			mem_disp(ugeth->p_tx_bd_ring[i], length);
+		}
+	}
+	for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+		if (ugeth->p_rx_bd_ring[i]) {
+			length =
+			    (ugeth->ug_info->bdRingLenRx[i] *
+			     UCC_GETH_SIZE_OF_BD);
+			ugeth_info("RX BDs[%d]", i);
+			mem_disp(ugeth->p_rx_bd_ring[i], length);
+		}
+	}
+}
+
+static void dump_regs(ucc_geth_private_t *ugeth)
+{
+	int i;
+
+	ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num);
+	ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs);
+
+	ugeth_info("maccfg1    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->maccfg1,
+		   in_be32(&ugeth->ug_regs->maccfg1));
+	ugeth_info("maccfg2    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->maccfg2,
+		   in_be32(&ugeth->ug_regs->maccfg2));
+	ugeth_info("ipgifg     : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->ipgifg,
+		   in_be32(&ugeth->ug_regs->ipgifg));
+	ugeth_info("hafdup     : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->hafdup,
+		   in_be32(&ugeth->ug_regs->hafdup));
+	ugeth_info("miimcfg    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimcfg,
+		   in_be32(&ugeth->ug_regs->miimng.miimcfg));
+	ugeth_info("miimcom    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimcom,
+		   in_be32(&ugeth->ug_regs->miimng.miimcom));
+	ugeth_info("miimadd    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimadd,
+		   in_be32(&ugeth->ug_regs->miimng.miimadd));
+	ugeth_info("miimcon    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimcon,
+		   in_be32(&ugeth->ug_regs->miimng.miimcon));
+	ugeth_info("miimstat   : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimstat,
+		   in_be32(&ugeth->ug_regs->miimng.miimstat));
+	ugeth_info("miimmind   : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->miimng.miimind,
+		   in_be32(&ugeth->ug_regs->miimng.miimind));
+	ugeth_info("ifctl      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->ifctl,
+		   in_be32(&ugeth->ug_regs->ifctl));
+	ugeth_info("ifstat     : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->ifstat,
+		   in_be32(&ugeth->ug_regs->ifstat));
+	ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->macstnaddr1,
+		   in_be32(&ugeth->ug_regs->macstnaddr1));
+	ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->macstnaddr2,
+		   in_be32(&ugeth->ug_regs->macstnaddr2));
+	ugeth_info("uempr      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->uempr,
+		   in_be32(&ugeth->ug_regs->uempr));
+	ugeth_info("utbipar    : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->utbipar,
+		   in_be32(&ugeth->ug_regs->utbipar));
+	ugeth_info("uescr      : addr - 0x%08x, val - 0x%04x",
+		   (u32) & ugeth->ug_regs->uescr,
+		   in_be16(&ugeth->ug_regs->uescr));
+	ugeth_info("tx64       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->tx64,
+		   in_be32(&ugeth->ug_regs->tx64));
+	ugeth_info("tx127      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->tx127,
+		   in_be32(&ugeth->ug_regs->tx127));
+	ugeth_info("tx255      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->tx255,
+		   in_be32(&ugeth->ug_regs->tx255));
+	ugeth_info("rx64       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rx64,
+		   in_be32(&ugeth->ug_regs->rx64));
+	ugeth_info("rx127      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rx127,
+		   in_be32(&ugeth->ug_regs->rx127));
+	ugeth_info("rx255      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rx255,
+		   in_be32(&ugeth->ug_regs->rx255));
+	ugeth_info("txok       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->txok,
+		   in_be32(&ugeth->ug_regs->txok));
+	ugeth_info("txcf       : addr - 0x%08x, val - 0x%04x",
+		   (u32) & ugeth->ug_regs->txcf,
+		   in_be16(&ugeth->ug_regs->txcf));
+	ugeth_info("tmca       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->tmca,
+		   in_be32(&ugeth->ug_regs->tmca));
+	ugeth_info("tbca       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->tbca,
+		   in_be32(&ugeth->ug_regs->tbca));
+	ugeth_info("rxfok      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rxfok,
+		   in_be32(&ugeth->ug_regs->rxfok));
+	ugeth_info("rxbok      : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rxbok,
+		   in_be32(&ugeth->ug_regs->rxbok));
+	ugeth_info("rbyt       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rbyt,
+		   in_be32(&ugeth->ug_regs->rbyt));
+	ugeth_info("rmca       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rmca,
+		   in_be32(&ugeth->ug_regs->rmca));
+	ugeth_info("rbca       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->rbca,
+		   in_be32(&ugeth->ug_regs->rbca));
+	ugeth_info("scar       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->scar,
+		   in_be32(&ugeth->ug_regs->scar));
+	ugeth_info("scam       : addr - 0x%08x, val - 0x%08x",
+		   (u32) & ugeth->ug_regs->scam,
+		   in_be32(&ugeth->ug_regs->scam));
+
+	if (ugeth->p_thread_data_tx) {
+		int numThreadsTxNumerical;
+		switch (ugeth->ug_info->numThreadsTx) {
+		case UCC_GETH_NUM_OF_THREADS_1:
+			numThreadsTxNumerical = 1;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_2:
+			numThreadsTxNumerical = 2;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_4:
+			numThreadsTxNumerical = 4;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_6:
+			numThreadsTxNumerical = 6;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_8:
+			numThreadsTxNumerical = 8;
+			break;
+		default:
+			numThreadsTxNumerical = 0;
+			break;
+		}
+
+		ugeth_info("Thread data TXs:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_thread_data_tx);
+		for (i = 0; i < numThreadsTxNumerical; i++) {
+			ugeth_info("Thread data TX[%d]:", i);
+			ugeth_info("Base address: 0x%08x",
+				   (u32) & ugeth->p_thread_data_tx[i]);
+			mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
+				 sizeof(ucc_geth_thread_data_tx_t));
+		}
+	}
+	if (ugeth->p_thread_data_rx) {
+		int numThreadsRxNumerical;
+		switch (ugeth->ug_info->numThreadsRx) {
+		case UCC_GETH_NUM_OF_THREADS_1:
+			numThreadsRxNumerical = 1;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_2:
+			numThreadsRxNumerical = 2;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_4:
+			numThreadsRxNumerical = 4;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_6:
+			numThreadsRxNumerical = 6;
+			break;
+		case UCC_GETH_NUM_OF_THREADS_8:
+			numThreadsRxNumerical = 8;
+			break;
+		default:
+			numThreadsRxNumerical = 0;
+			break;
+		}
+
+		ugeth_info("Thread data RX:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_thread_data_rx);
+		for (i = 0; i < numThreadsRxNumerical; i++) {
+			ugeth_info("Thread data RX[%d]:", i);
+			ugeth_info("Base address: 0x%08x",
+				   (u32) & ugeth->p_thread_data_rx[i]);
+			mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
+				 sizeof(ucc_geth_thread_data_rx_t));
+		}
+	}
+	if (ugeth->p_exf_glbl_param) {
+		ugeth_info("EXF global param:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_exf_glbl_param);
+		mem_disp((u8 *) ugeth->p_exf_glbl_param,
+			 sizeof(*ugeth->p_exf_glbl_param));
+	}
+	if (ugeth->p_tx_glbl_pram) {
+		ugeth_info("TX global param:");
+		ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram);
+		ugeth_info("temoder      : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_tx_glbl_pram->temoder,
+			   in_be16(&ugeth->p_tx_glbl_pram->temoder));
+		ugeth_info("sqptr        : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->sqptr,
+			   in_be32(&ugeth->p_tx_glbl_pram->sqptr));
+		ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer,
+			   in_be32(&ugeth->p_tx_glbl_pram->
+				   schedulerbasepointer));
+		ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr,
+			   in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
+		ugeth_info("tstate       : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->tstate,
+			   in_be32(&ugeth->p_tx_glbl_pram->tstate));
+		ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[0],
+			   ugeth->p_tx_glbl_pram->iphoffset[0]);
+		ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[1],
+			   ugeth->p_tx_glbl_pram->iphoffset[1]);
+		ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[2],
+			   ugeth->p_tx_glbl_pram->iphoffset[2]);
+		ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[3],
+			   ugeth->p_tx_glbl_pram->iphoffset[3]);
+		ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[4],
+			   ugeth->p_tx_glbl_pram->iphoffset[4]);
+		ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[5],
+			   ugeth->p_tx_glbl_pram->iphoffset[5]);
+		ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[6],
+			   ugeth->p_tx_glbl_pram->iphoffset[6]);
+		ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_tx_glbl_pram->iphoffset[7],
+			   ugeth->p_tx_glbl_pram->iphoffset[7]);
+		ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[0],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
+		ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[1],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
+		ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[2],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
+		ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[3],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
+		ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[4],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
+		ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[5],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
+		ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[6],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
+		ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->vtagtable[7],
+			   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
+		ugeth_info("tqptr        : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_tx_glbl_pram->tqptr,
+			   in_be32(&ugeth->p_tx_glbl_pram->tqptr));
+	}
+	if (ugeth->p_rx_glbl_pram) {
+		ugeth_info("RX global param:");
+		ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram);
+		ugeth_info("remoder         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->remoder,
+			   in_be32(&ugeth->p_rx_glbl_pram->remoder));
+		ugeth_info("rqptr           : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->rqptr,
+			   in_be32(&ugeth->p_rx_glbl_pram->rqptr));
+		ugeth_info("typeorlen       : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->typeorlen,
+			   in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
+		ugeth_info("rxgstpack       : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_rx_glbl_pram->rxgstpack,
+			   ugeth->p_rx_glbl_pram->rxgstpack);
+		ugeth_info("rxrmonbaseptr   : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+			   in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
+		ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr,
+			   in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
+		ugeth_info("rstate          : addr - 0x%08x, val - 0x%02x",
+			   (u32) & ugeth->p_rx_glbl_pram->rstate,
+			   ugeth->p_rx_glbl_pram->rstate);
+		ugeth_info("mrblr           : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->mrblr,
+			   in_be16(&ugeth->p_rx_glbl_pram->mrblr));
+		ugeth_info("rbdqptr         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->rbdqptr,
+			   in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
+		ugeth_info("mflr            : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->mflr,
+			   in_be16(&ugeth->p_rx_glbl_pram->mflr));
+		ugeth_info("minflr          : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->minflr,
+			   in_be16(&ugeth->p_rx_glbl_pram->minflr));
+		ugeth_info("maxd1           : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->maxd1,
+			   in_be16(&ugeth->p_rx_glbl_pram->maxd1));
+		ugeth_info("maxd2           : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->maxd2,
+			   in_be16(&ugeth->p_rx_glbl_pram->maxd2));
+		ugeth_info("ecamptr         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->ecamptr,
+			   in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
+		ugeth_info("l2qt            : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l2qt,
+			   in_be32(&ugeth->p_rx_glbl_pram->l2qt));
+		ugeth_info("l3qt[0]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[0],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
+		ugeth_info("l3qt[1]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[1],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
+		ugeth_info("l3qt[2]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[2],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
+		ugeth_info("l3qt[3]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[3],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
+		ugeth_info("l3qt[4]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[4],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
+		ugeth_info("l3qt[5]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[5],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
+		ugeth_info("l3qt[6]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[6],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
+		ugeth_info("l3qt[7]         : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->l3qt[7],
+			   in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
+		ugeth_info("vlantype        : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->vlantype,
+			   in_be16(&ugeth->p_rx_glbl_pram->vlantype));
+		ugeth_info("vlantci         : addr - 0x%08x, val - 0x%04x",
+			   (u32) & ugeth->p_rx_glbl_pram->vlantci,
+			   in_be16(&ugeth->p_rx_glbl_pram->vlantci));
+		for (i = 0; i < 64; i++)
+			ugeth_info
+		    ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x",
+			     i,
+			     (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i],
+			     ugeth->p_rx_glbl_pram->addressfiltering[i]);
+		ugeth_info("exfGlobalParam  : addr - 0x%08x, val - 0x%08x",
+			   (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam,
+			   in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
+	}
+	if (ugeth->p_send_q_mem_reg) {
+		ugeth_info("Send Q memory registers:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_send_q_mem_reg);
+		for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+			ugeth_info("SQQD[%d]:", i);
+			ugeth_info("Base address: 0x%08x",
+				   (u32) & ugeth->p_send_q_mem_reg->sqqd[i]);
+			mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
+				 sizeof(ucc_geth_send_queue_qd_t));
+		}
+	}
+	if (ugeth->p_scheduler) {
+		ugeth_info("Scheduler:");
+		ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler);
+		mem_disp((u8 *) ugeth->p_scheduler,
+			 sizeof(*ugeth->p_scheduler));
+	}
+	if (ugeth->p_tx_fw_statistics_pram) {
+		ugeth_info("TX FW statistics pram:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_tx_fw_statistics_pram);
+		mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
+			 sizeof(*ugeth->p_tx_fw_statistics_pram));
+	}
+	if (ugeth->p_rx_fw_statistics_pram) {
+		ugeth_info("RX FW statistics pram:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_rx_fw_statistics_pram);
+		mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
+			 sizeof(*ugeth->p_rx_fw_statistics_pram));
+	}
+	if (ugeth->p_rx_irq_coalescing_tbl) {
+		ugeth_info("RX IRQ coalescing tables:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_rx_irq_coalescing_tbl);
+		for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+			ugeth_info("RX IRQ coalescing table entry[%d]:", i);
+			ugeth_info("Base address: 0x%08x",
+				   (u32) & ugeth->p_rx_irq_coalescing_tbl->
+				   coalescingentry[i]);
+			ugeth_info
+		("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_irq_coalescing_tbl->
+			     coalescingentry[i].interruptcoalescingmaxvalue,
+			     in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+				     coalescingentry[i].
+				     interruptcoalescingmaxvalue));
+			ugeth_info
+		("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_irq_coalescing_tbl->
+			     coalescingentry[i].interruptcoalescingcounter,
+			     in_be32(&ugeth->p_rx_irq_coalescing_tbl->
+				     coalescingentry[i].
+				     interruptcoalescingcounter));
+		}
+	}
+	if (ugeth->p_rx_bd_qs_tbl) {
+		ugeth_info("RX BD QS tables:");
+		ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl);
+		for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+			ugeth_info("RX BD QS table[%d]:", i);
+			ugeth_info("Base address: 0x%08x",
+				   (u32) & ugeth->p_rx_bd_qs_tbl[i]);
+			ugeth_info
+			    ("bdbaseptr        : addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
+			     in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
+			ugeth_info
+			    ("bdptr            : addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr,
+			     in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
+			ugeth_info
+			    ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+			     in_be32(&ugeth->p_rx_bd_qs_tbl[i].
+				     externalbdbaseptr));
+			ugeth_info
+			    ("externalbdptr    : addr - 0x%08x, val - 0x%08x",
+			     (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
+			     in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
+			ugeth_info("ucode RX Prefetched BDs:");
+			ugeth_info("Base address: 0x%08x",
+				   (u32)
+				   qe_muram_addr(in_be32
+						 (&ugeth->p_rx_bd_qs_tbl[i].
+						  bdbaseptr)));
+			mem_disp((u8 *)
+				 qe_muram_addr(in_be32
+					       (&ugeth->p_rx_bd_qs_tbl[i].
+						bdbaseptr)),
+				 sizeof(ucc_geth_rx_prefetched_bds_t));
+		}
+	}
+	if (ugeth->p_init_enet_param_shadow) {
+		int size;
+		ugeth_info("Init enet param shadow:");
+		ugeth_info("Base address: 0x%08x",
+			   (u32) ugeth->p_init_enet_param_shadow);
+		mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
+			 sizeof(*ugeth->p_init_enet_param_shadow));
+
+		size = sizeof(ucc_geth_thread_rx_pram_t);
+		if (ugeth->ug_info->rxExtendedFiltering) {
+			size +=
+			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+			if (ugeth->ug_info->largestexternallookupkeysize ==
+			    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+				size +=
+			THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+			if (ugeth->ug_info->largestexternallookupkeysize ==
+			    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+				size +=
+			THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+		}
+
+		dump_init_enet_entries(ugeth,
+				       &(ugeth->p_init_enet_param_shadow->
+					 txthread[0]),
+				       ENET_INIT_PARAM_MAX_ENTRIES_TX,
+				       sizeof(ucc_geth_thread_tx_pram_t),
+				       ugeth->ug_info->riscTx, 0);
+		dump_init_enet_entries(ugeth,
+				       &(ugeth->p_init_enet_param_shadow->
+					 rxthread[0]),
+				       ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
+				       ugeth->ug_info->riscRx, 1);
+	}
+}
+#endif /* DEBUG */
+
+static void init_default_reg_vals(volatile u32 *upsmr_register,
+				  volatile u32 *maccfg1_register,
+				  volatile u32 *maccfg2_register)
+{
+	out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
+	out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
+	out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
+}
+
+static int init_half_duplex_params(int alt_beb,
+				   int back_pressure_no_backoff,
+				   int no_backoff,
+				   int excess_defer,
+				   u8 alt_beb_truncation,
+				   u8 max_retransmissions,
+				   u8 collision_window,
+				   volatile u32 *hafdup_register)
+{
+	u32 value = 0;
+
+	if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
+	    (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
+	    (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
+		return -EINVAL;
+
+	value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);
+
+	if (alt_beb)
+		value |= HALFDUP_ALT_BEB;
+	if (back_pressure_no_backoff)
+		value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
+	if (no_backoff)
+		value |= HALFDUP_NO_BACKOFF;
+	if (excess_defer)
+		value |= HALFDUP_EXCESSIVE_DEFER;
+
+	value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);
+
+	value |= collision_window;
+
+	out_be32(hafdup_register, value);
+	return 0;
+}
+
+static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
+				       u8 non_btb_ipg,
+				       u8 min_ifg,
+				       u8 btb_ipg,
+				       volatile u32 *ipgifg_register)
+{
+	u32 value = 0;
+
+	/* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
+	IPG part 2 */
+	if (non_btb_cs_ipg > non_btb_ipg)
+		return -EINVAL;
+
+	if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
+	    (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
+	    /*(min_ifg        > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
+	    (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
+		return -EINVAL;
+
+	value |=
+	    ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
+	     IPGIFG_NBTB_CS_IPG_MASK);
+	value |=
+	    ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
+	     IPGIFG_NBTB_IPG_MASK);
+	value |=
+	    ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
+	     IPGIFG_MIN_IFG_MASK);
+	value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);
+
+	out_be32(ipgifg_register, value);
+	return 0;
+}
+
+static int init_flow_control_params(u32 automatic_flow_control_mode,
+				    int rx_flow_control_enable,
+				    int tx_flow_control_enable,
+				    u16 pause_period,
+				    u16 extension_field,
+				    volatile u32 *upsmr_register,
+				    volatile u32 *uempr_register,
+				    volatile u32 *maccfg1_register)
+{
+	u32 value = 0;
+
+	/* Set UEMPR register */
+	value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
+	value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
+	out_be32(uempr_register, value);
+
+	/* Set UPSMR register */
+	value = in_be32(upsmr_register);
+	value |= automatic_flow_control_mode;
+	out_be32(upsmr_register, value);
+
+	value = in_be32(maccfg1_register);
+	if (rx_flow_control_enable)
+		value |= MACCFG1_FLOW_RX;
+	if (tx_flow_control_enable)
+		value |= MACCFG1_FLOW_TX;
+	out_be32(maccfg1_register, value);
+
+	return 0;
+}
+
+static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
+					     int auto_zero_hardware_statistics,
+					     volatile u32 *upsmr_register,
+					     volatile u16 *uescr_register)
+{
+	u32 upsmr_value = 0;
+	u16 uescr_value = 0;
+	/* Enable hardware statistics gathering if requested */
+	if (enable_hardware_statistics) {
+		upsmr_value = in_be32(upsmr_register);
+		upsmr_value |= UPSMR_HSE;
+		out_be32(upsmr_register, upsmr_value);
+	}
+
+	/* Clear hardware statistics counters */
+	uescr_value = in_be16(uescr_register);
+	uescr_value |= UESCR_CLRCNT;
+	/* Automatically zero hardware statistics counters on read,
+	if requested */
+	if (auto_zero_hardware_statistics)
+		uescr_value |= UESCR_AUTOZ;
+	out_be16(uescr_register, uescr_value);
+
+	return 0;
+}
+
+static int init_firmware_statistics_gathering_mode(int
+		enable_tx_firmware_statistics,
+		int enable_rx_firmware_statistics,
+		volatile u32 *tx_rmon_base_ptr,
+		u32 tx_firmware_statistics_structure_address,
+		volatile u32 *rx_rmon_base_ptr,
+		u32 rx_firmware_statistics_structure_address,
+		volatile u16 *temoder_register,
+		volatile u32 *remoder_register)
+{
+	/* Note: this function does not check if */
+	/* the parameters it receives are NULL   */
+	u16 temoder_value;
+	u32 remoder_value;
+
+	if (enable_tx_firmware_statistics) {
+		out_be32(tx_rmon_base_ptr,
+			 tx_firmware_statistics_structure_address);
+		temoder_value = in_be16(temoder_register);
+		temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
+		out_be16(temoder_register, temoder_value);
+	}
+
+	if (enable_rx_firmware_statistics) {
+		out_be32(rx_rmon_base_ptr,
+			 rx_firmware_statistics_structure_address);
+		remoder_value = in_be32(remoder_register);
+		remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
+		out_be32(remoder_register, remoder_value);
+	}
+
+	return 0;
+}
+
+static int init_mac_station_addr_regs(u8 address_byte_0,
+				      u8 address_byte_1,
+				      u8 address_byte_2,
+				      u8 address_byte_3,
+				      u8 address_byte_4,
+				      u8 address_byte_5,
+				      volatile u32 *macstnaddr1_register,
+				      volatile u32 *macstnaddr2_register)
+{
+	u32 value = 0;
+
+	/* Example: for a station address of 0x12345678ABCD, */
+	/* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */
+
+	/* MACSTNADDR1 Register: */
+
+	/* 0                      7   8                      15  */
+	/* station address byte 5     station address byte 4     */
+	/* 16                     23  24                     31  */
+	/* station address byte 3     station address byte 2     */
+	value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
+	value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
+	value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
+	value |= (u32) ((address_byte_5 << 24) & 0xFF000000);
+
+	out_be32(macstnaddr1_register, value);
+
+	/* MACSTNADDR2 Register: */
+
+	/* 0                      7   8                      15  */
+	/* station address byte 1     station address byte 0     */
+	/* 16                     23  24                     31  */
+	/*         reserved                   reserved           */
+	value = 0;
+	value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
+	value |= (u32) ((address_byte_1 << 24) & 0xFF000000);
+
+	out_be32(macstnaddr2_register, value);
+
+	return 0;
+}
+
+static int init_mac_duplex_mode(int full_duplex,
+				int limited_to_full_duplex,
+				volatile u32 *maccfg2_register)
+{
+	u32 value = 0;
+
+	/* some interfaces must work in full duplex mode */
+	if ((full_duplex == 0) && (limited_to_full_duplex == 1))
+		return -EINVAL;
+
+	value = in_be32(maccfg2_register);
+
+	if (full_duplex)
+		value |= MACCFG2_FDX;
+	else
+		value &= ~MACCFG2_FDX;
+
+	out_be32(maccfg2_register, value);
+	return 0;
+}
+
+static int init_check_frame_length_mode(int length_check,
+					volatile u32 *maccfg2_register)
+{
+	u32 value = 0;
+
+	value = in_be32(maccfg2_register);
+
+	if (length_check)
+		value |= MACCFG2_LC;
+	else
+		value &= ~MACCFG2_LC;
+
+	out_be32(maccfg2_register, value);
+	return 0;
+}
+
+static int init_preamble_length(u8 preamble_length,
+				volatile u32 *maccfg2_register)
+{
+	u32 value = 0;
+
+	if ((preamble_length < 3) || (preamble_length > 7))
+		return -EINVAL;
+
+	value = in_be32(maccfg2_register);
+	value &= ~MACCFG2_PREL_MASK;
+	value |= (preamble_length << MACCFG2_PREL_SHIFT);
+	out_be32(maccfg2_register, value);
+	return 0;
+}
+
+static int init_mii_management_configuration(int reset_mgmt,
+					     int preamble_supress,
+					     volatile u32 *miimcfg_register,
+					     volatile u32 *miimind_register)
+{
+	unsigned int timeout = PHY_INIT_TIMEOUT;
+	u32 value = 0;
+
+	value = in_be32(miimcfg_register);
+	if (reset_mgmt) {
+		value |= MIIMCFG_RESET_MANAGEMENT;
+		out_be32(miimcfg_register, value);
+	}
+
+	value = 0;
+
+	if (preamble_supress)
+		value |= MIIMCFG_NO_PREAMBLE;
+
+	value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT;
+	out_be32(miimcfg_register, value);
+
+	/* Wait until the bus is free */
+	while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--)
+		cpu_relax();
+
+	if (timeout <= 0) {
+		ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int init_rx_parameters(int reject_broadcast,
+			      int receive_short_frames,
+			      int promiscuous, volatile u32 *upsmr_register)
+{
+	u32 value = 0;
+
+	value = in_be32(upsmr_register);
+
+	if (reject_broadcast)
+		value |= UPSMR_BRO;
+	else
+		value &= ~UPSMR_BRO;
+
+	if (receive_short_frames)
+		value |= UPSMR_RSH;
+	else
+		value &= ~UPSMR_RSH;
+
+	if (promiscuous)
+		value |= UPSMR_PRO;
+	else
+		value &= ~UPSMR_PRO;
+
+	out_be32(upsmr_register, value);
+
+	return 0;
+}
+
+static int init_max_rx_buff_len(u16 max_rx_buf_len,
+				volatile u16 *mrblr_register)
+{
+	/* max_rx_buf_len value must be a multiple of 128 */
+	if ((max_rx_buf_len == 0)
+	    || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
+		return -EINVAL;
+
+	out_be16(mrblr_register, max_rx_buf_len);
+	return 0;
+}
+
+static int init_min_frame_len(u16 min_frame_length,
+			      volatile u16 *minflr_register,
+			      volatile u16 *mrblr_register)
+{
+	u16 mrblr_value = 0;
+
+	mrblr_value = in_be16(mrblr_register);
+	if (min_frame_length >= (mrblr_value - 4))
+		return -EINVAL;
+
+	out_be16(minflr_register, min_frame_length);
+	return 0;
+}
+
+static int adjust_enet_interface(ucc_geth_private_t *ugeth)
+{
+	ucc_geth_info_t *ug_info;
+	ucc_geth_t *ug_regs;
+	ucc_fast_t *uf_regs;
+	enet_speed_e speed;
+	int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm =
+	    0, limited_to_full_duplex = 0;
+	u32 upsmr, maccfg2, utbipar, tbiBaseAddress;
+	u16 value;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ug_info = ugeth->ug_info;
+	ug_regs = ugeth->ug_regs;
+	uf_regs = ugeth->uccf->uf_regs;
+
+	/* Analyze enet_interface according to Interface Mode Configuration
+	table */
+	ret_val =
+	    get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm,
+				  &rpm, &tbi, &limited_to_full_duplex);
+	if (ret_val != 0) {
+		ugeth_err
+		  ("%s: half duplex not supported in requested configuration.",
+		     __FUNCTION__);
+		return ret_val;
+	}
+
+	/*                    Set MACCFG2                    */
+	maccfg2 = in_be32(&ug_regs->maccfg2);
+	maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
+	if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT))
+		maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
+	else if (speed == ENET_SPEED_1000BT)
+		maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
+	maccfg2 |= ug_info->padAndCrc;
+	out_be32(&ug_regs->maccfg2, maccfg2);
+
+	/*                    Set UPSMR                      */
+	upsmr = in_be32(&uf_regs->upsmr);
+	upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
+	if (rpm)
+		upsmr |= UPSMR_RPM;
+	if (r10m)
+		upsmr |= UPSMR_R10M;
+	if (tbi)
+		upsmr |= UPSMR_TBIM;
+	if (rmm)
+		upsmr |= UPSMR_RMM;
+	out_be32(&uf_regs->upsmr, upsmr);
+
+	/*                    Set UTBIPAR                    */
+	utbipar = in_be32(&ug_regs->utbipar);
+	utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
+	if (tbi)
+		utbipar |=
+		    (ug_info->phy_address +
+		     ugeth->ug_info->uf_info.
+		     ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+	else
+		utbipar |=
+		    (0x10 +
+		     ugeth->ug_info->uf_info.
+		     ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
+	out_be32(&ug_regs->utbipar, utbipar);
+
+	/* Disable autonegotiation in tbi mode, because by default it
+	comes up in autonegotiation mode. */
+	/* Note that this depends on proper setting in utbipar register. */
+	if (tbi) {
+		tbiBaseAddress = in_be32(&ug_regs->utbipar);
+		tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
+		tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
+		value =
+		    ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress,
+					       ENET_TBI_MII_CR);
+		value &= ~0x1000;	/* Turn off autonegotiation */
+		ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress,
+					    ENET_TBI_MII_CR, value);
+	}
+
+	ret_val = init_mac_duplex_mode(1,
+				       limited_to_full_duplex,
+				       &ug_regs->maccfg2);
+	if (ret_val != 0) {
+		ugeth_err
+		("%s: half duplex not supported in requested configuration.",
+		     __FUNCTION__);
+		return ret_val;
+	}
+
+	init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
+
+	ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
+	if (ret_val != 0) {
+		ugeth_err
+		    ("%s: Preamble length must be between 3 and 7 inclusive.",
+		     __FUNCTION__);
+		return ret_val;
+	}
+
+	return 0;
+}
+
+/* Called every time the controller might need to be made
+ * aware of new link state.  The PHY code conveys this
+ * information through variables in the ugeth structure, and this
+ * function converts those variables into the appropriate
+ * register values, and can bring down the device if needed.
+ */
+static void adjust_link(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	ucc_geth_t *ug_regs;
+	u32 tempval;
+	struct ugeth_mii_info *mii_info = ugeth->mii_info;
+
+	ug_regs = ugeth->ug_regs;
+
+	if (mii_info->link) {
+		/* Now we make sure that we can be in full duplex mode.
+		 * If not, we operate in half-duplex mode. */
+		if (mii_info->duplex != ugeth->oldduplex) {
+			if (!(mii_info->duplex)) {
+				tempval = in_be32(&ug_regs->maccfg2);
+				tempval &= ~(MACCFG2_FDX);
+				out_be32(&ug_regs->maccfg2, tempval);
+
+				ugeth_info("%s: Half Duplex", dev->name);
+			} else {
+				tempval = in_be32(&ug_regs->maccfg2);
+				tempval |= MACCFG2_FDX;
+				out_be32(&ug_regs->maccfg2, tempval);
+
+				ugeth_info("%s: Full Duplex", dev->name);
+			}
+
+			ugeth->oldduplex = mii_info->duplex;
+		}
+
+		if (mii_info->speed != ugeth->oldspeed) {
+			switch (mii_info->speed) {
+			case 1000:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this when it is fixed!!! */
+				if (ugeth->ug_info->enet_interface ==
+				    ENET_1000_GMII)
+				/* Run the commands which initialize the PHY */
+				{
+					tempval =
+					    (u32) mii_info->mdio_read(ugeth->
+						dev, mii_info->mii_id, 0x1b);
+					tempval |= 0x000f;
+					mii_info->mdio_write(ugeth->dev,
+						mii_info->mii_id, 0x1b,
+						(u16) tempval);
+					tempval =
+					    (u32) mii_info->mdio_read(ugeth->
+						dev, mii_info->mii_id,
+						MII_BMCR);
+					mii_info->mdio_write(ugeth->dev,
+						mii_info->mii_id, MII_BMCR,
+						(u16) (tempval | BMCR_RESET));
+				} else if (ugeth->ug_info->enet_interface ==
+					   ENET_1000_RGMII)
+				/* Run the commands which initialize the PHY */
+				{
+					tempval =
+					    (u32) mii_info->mdio_read(ugeth->
+						dev, mii_info->mii_id, 0x1b);
+					tempval = (tempval & ~0x000f) | 0x000b;
+					mii_info->mdio_write(ugeth->dev,
+						mii_info->mii_id, 0x1b,
+						(u16) tempval);
+					tempval =
+					    (u32) mii_info->mdio_read(ugeth->
+						dev, mii_info->mii_id,
+						MII_BMCR);
+					mii_info->mdio_write(ugeth->dev,
+						mii_info->mii_id, MII_BMCR,
+						(u16) (tempval | BMCR_RESET));
+				}
+				msleep(4000);
+#endif				/* CONFIG_MPC8360 */
+				adjust_enet_interface(ugeth);
+				break;
+			case 100:
+			case 10:
+#ifdef CONFIG_MPC836x
+/* FIXME: This code is for 100Mbs BUG fixing,
+remove this lines when it will be fixed!!! */
+				ugeth->ug_info->enet_interface = ENET_100_RGMII;
+				tempval =
+				    (u32) mii_info->mdio_read(ugeth->dev,
+							      mii_info->mii_id,
+							      0x1b);
+				tempval = (tempval & ~0x000f) | 0x000b;
+				mii_info->mdio_write(ugeth->dev,
+						     mii_info->mii_id, 0x1b,
+						     (u16) tempval);
+				tempval =
+				    (u32) mii_info->mdio_read(ugeth->dev,
+							      mii_info->mii_id,
+							      MII_BMCR);
+				mii_info->mdio_write(ugeth->dev,
+						     mii_info->mii_id, MII_BMCR,
+						     (u16) (tempval |
+							    BMCR_RESET));
+				msleep(4000);
+#endif				/* CONFIG_MPC8360 */
+				adjust_enet_interface(ugeth);
+				break;
+			default:
+				ugeth_warn
+				    ("%s: Ack!  Speed (%d) is not 10/100/1000!",
+				     dev->name, mii_info->speed);
+				break;
+			}
+
+			ugeth_info("%s: Speed %dBT", dev->name,
+				   mii_info->speed);
+
+			ugeth->oldspeed = mii_info->speed;
+		}
+
+		if (!ugeth->oldlink) {
+			ugeth_info("%s: Link is up", dev->name);
+			ugeth->oldlink = 1;
+			netif_carrier_on(dev);
+			netif_schedule(dev);
+		}
+	} else {
+		if (ugeth->oldlink) {
+			ugeth_info("%s: Link is down", dev->name);
+			ugeth->oldlink = 0;
+			ugeth->oldspeed = 0;
+			ugeth->oldduplex = -1;
+			netif_carrier_off(dev);
+		}
+	}
+}
+
+/* Configure the PHY for dev.
+ * returns 0 if success.  -1 if failure
+ */
+static int init_phy(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	struct phy_info *curphy;
+	ucc_mii_mng_t *mii_regs;
+	struct ugeth_mii_info *mii_info;
+	int err;
+
+	mii_regs = &ugeth->ug_regs->miimng;
+
+	ugeth->oldlink = 0;
+	ugeth->oldspeed = 0;
+	ugeth->oldduplex = -1;
+
+	mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL);
+
+	if (NULL == mii_info) {
+		ugeth_err("%s: Could not allocate mii_info", dev->name);
+		return -ENOMEM;
+	}
+
+	mii_info->mii_regs = mii_regs;
+	mii_info->speed = SPEED_1000;
+	mii_info->duplex = DUPLEX_FULL;
+	mii_info->pause = 0;
+	mii_info->link = 0;
+
+	mii_info->advertising = (ADVERTISED_10baseT_Half |
+				 ADVERTISED_10baseT_Full |
+				 ADVERTISED_100baseT_Half |
+				 ADVERTISED_100baseT_Full |
+				 ADVERTISED_1000baseT_Full);
+	mii_info->autoneg = 1;
+
+	mii_info->mii_id = ugeth->ug_info->phy_address;
+
+	mii_info->dev = dev;
+
+	mii_info->mdio_read = &read_phy_reg;
+	mii_info->mdio_write = &write_phy_reg;
+
+	ugeth->mii_info = mii_info;
+
+	spin_lock_irq(&ugeth->lock);
+
+	/* Set this UCC to be the master of the MII managment */
+	ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+	if (init_mii_management_configuration(1,
+					      ugeth->ug_info->
+					      miiPreambleSupress,
+					      &mii_regs->miimcfg,
+					      &mii_regs->miimind)) {
+		ugeth_err("%s: The MII Bus is stuck!", dev->name);
+		err = -1;
+		goto bus_fail;
+	}
+
+	spin_unlock_irq(&ugeth->lock);
+
+	/* get info for this PHY */
+	curphy = get_phy_info(ugeth->mii_info);
+
+	if (curphy == NULL) {
+		ugeth_err("%s: No PHY found", dev->name);
+		err = -1;
+		goto no_phy;
+	}
+
+	mii_info->phyinfo = curphy;
+
+	/* Run the commands which initialize the PHY */
+	if (curphy->init) {
+		err = curphy->init(ugeth->mii_info);
+		if (err)
+			goto phy_init_fail;
+	}
+
+	return 0;
+
+      phy_init_fail:
+      no_phy:
+      bus_fail:
+	kfree(mii_info);
+
+	return err;
+}
+
+#ifdef CONFIG_UGETH_TX_ON_DEMOND
+static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_transmit_on_demand(ugeth->uccf);
+
+	return 0;
+}
+#endif
+
+static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_private_t *uccf;
+	u32 cecr_subblock;
+	u32 temp;
+
+	uccf = ugeth->uccf;
+
+	/* Mask GRACEFUL STOP TX interrupt bit and clear it */
+	temp = in_be32(uccf->p_uccm);
+	temp &= ~UCCE_GRA;
+	out_be32(uccf->p_uccm, temp);
+	out_be32(uccf->p_ucce, UCCE_GRA);	/* clear by writing 1 */
+
+	/* Issue host command */
+	cecr_subblock =
+	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+	qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+		     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+	/* Wait for command to complete */
+	do {
+		temp = in_be32(uccf->p_ucce);
+	} while (!(temp & UCCE_GRA));
+
+	uccf->stopped_tx = 1;
+
+	return 0;
+}
+
+static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth)
+{
+	ucc_fast_private_t *uccf;
+	u32 cecr_subblock;
+	u8 temp;
+
+	uccf = ugeth->uccf;
+
+	/* Clear acknowledge bit */
+	temp = ugeth->p_rx_glbl_pram->rxgstpack;
+	temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
+	ugeth->p_rx_glbl_pram->rxgstpack = temp;
+
+	/* Keep issuing command and checking acknowledge bit until
+	it is asserted, according to spec */
+	do {
+		/* Issue host command */
+		cecr_subblock =
+		    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
+						ucc_num);
+		qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
+			     (u8) QE_CR_PROTOCOL_ETHERNET, 0);
+
+		temp = ugeth->p_rx_glbl_pram->rxgstpack;
+	} while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
+
+	uccf->stopped_rx = 1;
+
+	return 0;
+}
+
+static int ugeth_restart_tx(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_private_t *uccf;
+	u32 cecr_subblock;
+
+	uccf = ugeth->uccf;
+
+	cecr_subblock =
+	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+	qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+		     0);
+	uccf->stopped_tx = 0;
+
+	return 0;
+}
+
+static int ugeth_restart_rx(ucc_geth_private_t *ugeth)
+{
+	ucc_fast_private_t *uccf;
+	u32 cecr_subblock;
+
+	uccf = ugeth->uccf;
+
+	cecr_subblock =
+	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+	qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+		     0);
+	uccf->stopped_rx = 0;
+
+	return 0;
+}
+
+static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode)
+{
+	ucc_fast_private_t *uccf;
+	int enabled_tx, enabled_rx;
+
+	uccf = ugeth->uccf;
+
+	/* check if the UCC number is in range. */
+	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+		ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	enabled_tx = uccf->enabled_tx;
+	enabled_rx = uccf->enabled_rx;
+
+	/* Get Tx and Rx going again, in case this channel was actively
+	disabled. */
+	if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
+		ugeth_restart_tx(ugeth);
+	if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
+		ugeth_restart_rx(ugeth);
+
+	ucc_fast_enable(uccf, mode);	/* OK to do even if not disabled */
+
+	return 0;
+
+}
+
+static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode)
+{
+	ucc_fast_private_t *uccf;
+
+	uccf = ugeth->uccf;
+
+	/* check if the UCC number is in range. */
+	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
+		ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* Stop any transmissions */
+	if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
+		ugeth_graceful_stop_tx(ugeth);
+
+	/* Stop any receptions */
+	if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
+		ugeth_graceful_stop_rx(ugeth);
+
+	ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
+
+	return 0;
+}
+
+static void ugeth_dump_regs(ucc_geth_private_t *ugeth)
+{
+#ifdef DEBUG
+	ucc_fast_dump_regs(ugeth->uccf);
+	dump_regs(ugeth);
+	dump_bds(ugeth);
+#endif
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t *
+					     p_UccGethTadParams,
+					     qe_fltr_tad_t *qe_fltr_tad)
+{
+	u16 temp;
+
+	/* Zero serialized TAD */
+	memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
+
+	qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V;	/* Must have this */
+	if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
+	    (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+	    || (p_UccGethTadParams->vnontag_op !=
+		UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
+	    )
+		qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
+	if (p_UccGethTadParams->reject_frame)
+		qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
+	temp =
+	    (u16) (((u16) p_UccGethTadParams->
+		    vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
+	qe_fltr_tad->serialized[0] |= (u8) (temp >> 8);	/* upper bits */
+
+	qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff);	/* lower bits */
+	if (p_UccGethTadParams->vnontag_op ==
+	    UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
+		qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
+	qe_fltr_tad->serialized[1] |=
+	    p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
+
+	qe_fltr_tad->serialized[2] |=
+	    p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
+	/* upper bits */
+	qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
+	/* lower bits */
+	qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
+
+	return 0;
+}
+
+static enet_addr_container_t
+    *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth,
+						 enet_addr_t *p_enet_addr)
+{
+	enet_addr_container_t *enet_addr_cont;
+	struct list_head *p_lh;
+	u16 i, num;
+	int32_t j;
+	u8 *p_counter;
+
+	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+		p_lh = &ugeth->group_hash_q;
+		p_counter = &(ugeth->numGroupAddrInHash);
+	} else {
+		p_lh = &ugeth->ind_hash_q;
+		p_counter = &(ugeth->numIndAddrInHash);
+	}
+
+	if (!p_lh)
+		return NULL;
+
+	num = *p_counter;
+
+	for (i = 0; i < num; i++) {
+		enet_addr_cont =
+		    (enet_addr_container_t *)
+		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+		for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
+			if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
+				break;
+			if (j == 0)
+				return enet_addr_cont;	/* Found */
+		}
+		enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */
+	}
+	return NULL;
+}
+
+static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth,
+						 enet_addr_t *p_enet_addr)
+{
+	ucc_geth_enet_address_recognition_location_e location;
+	enet_addr_container_t *enet_addr_cont;
+	struct list_head *p_lh;
+	u8 i;
+	u32 limit;
+	u8 *p_counter;
+
+	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+		p_lh = &ugeth->group_hash_q;
+		limit = ugeth->ug_info->maxGroupAddrInHash;
+		location =
+		    UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
+		p_counter = &(ugeth->numGroupAddrInHash);
+	} else {
+		p_lh = &ugeth->ind_hash_q;
+		limit = ugeth->ug_info->maxIndAddrInHash;
+		location =
+		    UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
+		p_counter = &(ugeth->numIndAddrInHash);
+	}
+
+	if ((enet_addr_cont =
+	     ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
+		list_add(p_lh, &enet_addr_cont->node);	/* Put it back */
+		return 0;
+	}
+	if ((!p_lh) || (!(*p_counter < limit)))
+		return -EBUSY;
+	if (!(enet_addr_cont = get_enet_addr_container()))
+		return -ENOMEM;
+	for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+		(enet_addr_cont->address)[i] = (*p_enet_addr)[i];
+	enet_addr_cont->location = location;
+	enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */
+	++(*p_counter);
+
+	hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+
+	return 0;
+}
+
+static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth,
+						   enet_addr_t *p_enet_addr)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	enet_addr_container_t *enet_addr_cont;
+	ucc_fast_private_t *uccf;
+	comm_dir_e comm_dir;
+	u16 i, num;
+	struct list_head *p_lh;
+	u32 *addr_h, *addr_l;
+	u8 *p_counter;
+
+	uccf = ugeth->uccf;
+
+	p_82xx_addr_filt =
+	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    addressfiltering;
+
+	if (!
+	    (enet_addr_cont =
+	     ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
+		return -ENOENT;
+
+	/* It's been found and removed from the CQ. */
+	/* Now destroy its container */
+	put_enet_addr_container(enet_addr_cont);
+
+	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
+		addr_h = &(p_82xx_addr_filt->gaddr_h);
+		addr_l = &(p_82xx_addr_filt->gaddr_l);
+		p_lh = &ugeth->group_hash_q;
+		p_counter = &(ugeth->numGroupAddrInHash);
+	} else {
+		addr_h = &(p_82xx_addr_filt->iaddr_h);
+		addr_l = &(p_82xx_addr_filt->iaddr_l);
+		p_lh = &ugeth->ind_hash_q;
+		p_counter = &(ugeth->numIndAddrInHash);
+	}
+
+	comm_dir = 0;
+	if (uccf->enabled_tx)
+		comm_dir |= COMM_DIR_TX;
+	if (uccf->enabled_rx)
+		comm_dir |= COMM_DIR_RX;
+	if (comm_dir)
+		ugeth_disable(ugeth, comm_dir);
+
+	/* Clear the hash table. */
+	out_be32(addr_h, 0x00000000);
+	out_be32(addr_l, 0x00000000);
+
+	/* Add all remaining CQ elements back into hash */
+	num = --(*p_counter);
+	for (i = 0; i < num; i++) {
+		enet_addr_cont =
+		    (enet_addr_container_t *)
+		    ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
+		hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
+		enqueue(p_lh, &enet_addr_cont->node);	/* Put it back */
+	}
+
+	if (comm_dir)
+		ugeth_enable(ugeth, comm_dir);
+
+	return 0;
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t *
+						       ugeth,
+						       enet_addr_type_e
+						       enet_addr_type)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	ucc_fast_private_t *uccf;
+	comm_dir_e comm_dir;
+	struct list_head *p_lh;
+	u16 i, num;
+	u32 *addr_h, *addr_l;
+	u8 *p_counter;
+
+	uccf = ugeth->uccf;
+
+	p_82xx_addr_filt =
+	    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
+	    addressfiltering;
+
+	if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
+		addr_h = &(p_82xx_addr_filt->gaddr_h);
+		addr_l = &(p_82xx_addr_filt->gaddr_l);
+		p_lh = &ugeth->group_hash_q;
+		p_counter = &(ugeth->numGroupAddrInHash);
+	} else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
+		addr_h = &(p_82xx_addr_filt->iaddr_h);
+		addr_l = &(p_82xx_addr_filt->iaddr_l);
+		p_lh = &ugeth->ind_hash_q;
+		p_counter = &(ugeth->numIndAddrInHash);
+	} else
+		return -EINVAL;
+
+	comm_dir = 0;
+	if (uccf->enabled_tx)
+		comm_dir |= COMM_DIR_TX;
+	if (uccf->enabled_rx)
+		comm_dir |= COMM_DIR_RX;
+	if (comm_dir)
+		ugeth_disable(ugeth, comm_dir);
+
+	/* Clear the hash table. */
+	out_be32(addr_h, 0x00000000);
+	out_be32(addr_l, 0x00000000);
+
+	if (!p_lh)
+		return 0;
+
+	num = *p_counter;
+
+	/* Delete all remaining CQ elements */
+	for (i = 0; i < num; i++)
+		put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));
+
+	*p_counter = 0;
+
+	if (comm_dir)
+		ugeth_enable(ugeth, comm_dir);
+
+	return 0;
+}
+
+#ifdef CONFIG_UGETH_FILTERING
+static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth,
+						  enet_addr_t *p_enet_addr,
+						  u8 paddr_num)
+{
+	int i;
+
+	if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
+		ugeth_warn
+		    ("%s: multicast address added to paddr will have no "
+		     "effect - is this what you wanted?",
+		     __FUNCTION__);
+
+	ugeth->indAddrRegUsed[paddr_num] = 1;	/* mark this paddr as used */
+	/* store address in our database */
+	for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
+		ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
+	/* put in hardware */
+	return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
+}
+#endif /* CONFIG_UGETH_FILTERING */
+
+static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth,
+						    u8 paddr_num)
+{
+	ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
+	return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
+}
+
+static void ucc_geth_memclean(ucc_geth_private_t *ugeth)
+{
+	u16 i, j;
+	u8 *bd;
+
+	if (!ugeth)
+		return;
+
+	if (ugeth->uccf)
+		ucc_fast_free(ugeth->uccf);
+
+	if (ugeth->p_thread_data_tx) {
+		qe_muram_free(ugeth->thread_dat_tx_offset);
+		ugeth->p_thread_data_tx = NULL;
+	}
+	if (ugeth->p_thread_data_rx) {
+		qe_muram_free(ugeth->thread_dat_rx_offset);
+		ugeth->p_thread_data_rx = NULL;
+	}
+	if (ugeth->p_exf_glbl_param) {
+		qe_muram_free(ugeth->exf_glbl_param_offset);
+		ugeth->p_exf_glbl_param = NULL;
+	}
+	if (ugeth->p_rx_glbl_pram) {
+		qe_muram_free(ugeth->rx_glbl_pram_offset);
+		ugeth->p_rx_glbl_pram = NULL;
+	}
+	if (ugeth->p_tx_glbl_pram) {
+		qe_muram_free(ugeth->tx_glbl_pram_offset);
+		ugeth->p_tx_glbl_pram = NULL;
+	}
+	if (ugeth->p_send_q_mem_reg) {
+		qe_muram_free(ugeth->send_q_mem_reg_offset);
+		ugeth->p_send_q_mem_reg = NULL;
+	}
+	if (ugeth->p_scheduler) {
+		qe_muram_free(ugeth->scheduler_offset);
+		ugeth->p_scheduler = NULL;
+	}
+	if (ugeth->p_tx_fw_statistics_pram) {
+		qe_muram_free(ugeth->tx_fw_statistics_pram_offset);
+		ugeth->p_tx_fw_statistics_pram = NULL;
+	}
+	if (ugeth->p_rx_fw_statistics_pram) {
+		qe_muram_free(ugeth->rx_fw_statistics_pram_offset);
+		ugeth->p_rx_fw_statistics_pram = NULL;
+	}
+	if (ugeth->p_rx_irq_coalescing_tbl) {
+		qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset);
+		ugeth->p_rx_irq_coalescing_tbl = NULL;
+	}
+	if (ugeth->p_rx_bd_qs_tbl) {
+		qe_muram_free(ugeth->rx_bd_qs_tbl_offset);
+		ugeth->p_rx_bd_qs_tbl = NULL;
+	}
+	if (ugeth->p_init_enet_param_shadow) {
+		return_init_enet_entries(ugeth,
+					 &(ugeth->p_init_enet_param_shadow->
+					   rxthread[0]),
+					 ENET_INIT_PARAM_MAX_ENTRIES_RX,
+					 ugeth->ug_info->riscRx, 1);
+		return_init_enet_entries(ugeth,
+					 &(ugeth->p_init_enet_param_shadow->
+					   txthread[0]),
+					 ENET_INIT_PARAM_MAX_ENTRIES_TX,
+					 ugeth->ug_info->riscTx, 0);
+		kfree(ugeth->p_init_enet_param_shadow);
+		ugeth->p_init_enet_param_shadow = NULL;
+	}
+	for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
+		bd = ugeth->p_tx_bd_ring[i];
+		for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
+			if (ugeth->tx_skbuff[i][j]) {
+				dma_unmap_single(NULL,
+						 BD_BUFFER_ARG(bd),
+						 (BD_STATUS_AND_LENGTH(bd) &
+						  BD_LENGTH_MASK),
+						 DMA_TO_DEVICE);
+				dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
+				ugeth->tx_skbuff[i][j] = NULL;
+			}
+		}
+
+		kfree(ugeth->tx_skbuff[i]);
+
+		if (ugeth->p_tx_bd_ring[i]) {
+			if (ugeth->ug_info->uf_info.bd_mem_part ==
+			    MEM_PART_SYSTEM)
+				kfree((void *)ugeth->tx_bd_ring_offset[i]);
+			else if (ugeth->ug_info->uf_info.bd_mem_part ==
+				 MEM_PART_MURAM)
+				qe_muram_free(ugeth->tx_bd_ring_offset[i]);
+			ugeth->p_tx_bd_ring[i] = NULL;
+		}
+	}
+	for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
+		if (ugeth->p_rx_bd_ring[i]) {
+			/* Return existing data buffers in ring */
+			bd = ugeth->p_rx_bd_ring[i];
+			for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
+				if (ugeth->rx_skbuff[i][j]) {
+					dma_unmap_single(NULL, BD_BUFFER(bd),
+						 ugeth->ug_info->
+						 uf_info.
+						 max_rx_buf_length +
+						 UCC_GETH_RX_DATA_BUF_ALIGNMENT,
+						 DMA_FROM_DEVICE);
+
+					dev_kfree_skb_any(ugeth->
+							  rx_skbuff[i][j]);
+					ugeth->rx_skbuff[i][j] = NULL;
+				}
+				bd += UCC_GETH_SIZE_OF_BD;
+			}
+
+			kfree(ugeth->rx_skbuff[i]);
+
+			if (ugeth->ug_info->uf_info.bd_mem_part ==
+			    MEM_PART_SYSTEM)
+				kfree((void *)ugeth->rx_bd_ring_offset[i]);
+			else if (ugeth->ug_info->uf_info.bd_mem_part ==
+				 MEM_PART_MURAM)
+				qe_muram_free(ugeth->rx_bd_ring_offset[i]);
+			ugeth->p_rx_bd_ring[i] = NULL;
+		}
+	}
+	while (!list_empty(&ugeth->group_hash_q))
+		put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+					(dequeue(&ugeth->group_hash_q)));
+	while (!list_empty(&ugeth->ind_hash_q))
+		put_enet_addr_container(ENET_ADDR_CONT_ENTRY
+					(dequeue(&ugeth->ind_hash_q)));
+
+}
+
+static void ucc_geth_set_multi(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth;
+	struct dev_mc_list *dmi;
+	ucc_fast_t *uf_regs;
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	enet_addr_t tempaddr;
+	u8 *mcptr, *tdptr;
+	int i, j;
+
+	ugeth = netdev_priv(dev);
+
+	uf_regs = ugeth->uccf->uf_regs;
+
+	if (dev->flags & IFF_PROMISC) {
+
+		uf_regs->upsmr |= UPSMR_PRO;
+
+	} else {
+
+		uf_regs->upsmr &= ~UPSMR_PRO;
+
+		p_82xx_addr_filt =
+		    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+		    p_rx_glbl_pram->addressfiltering;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
+			out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
+		} else {
+			/* Clear filter and add the addresses in the list.
+			 */
+			out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
+			out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
+
+			dmi = dev->mc_list;
+
+			for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
+
+				/* Only support group multicast for now.
+				 */
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u8 *) dmi->dmi_addr + 5;
+				tdptr = (u8 *) & tempaddr;
+				for (j = 0; j < 6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				hw_add_addr_in_hash(ugeth, &tempaddr);
+
+			}
+		}
+	}
+}
+
+static void ucc_geth_stop(ucc_geth_private_t *ugeth)
+{
+	ucc_geth_t *ug_regs = ugeth->ug_regs;
+	u32 tempval;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	/* Disable the controller */
+	ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+	/* Tell the kernel the link is down */
+	ugeth->mii_info->link = 0;
+	adjust_link(ugeth->dev);
+
+	/* Mask all interrupts */
+	out_be32(ugeth->uccf->p_ucce, 0x00000000);
+
+	/* Clear all interrupts */
+	out_be32(ugeth->uccf->p_ucce, 0xffffffff);
+
+	/* Disable Rx and Tx */
+	tempval = in_be32(&ug_regs->maccfg1);
+	tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
+	out_be32(&ug_regs->maccfg1, tempval);
+
+	if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+		/* Clear any pending interrupts */
+		mii_clear_phy_interrupt(ugeth->mii_info);
+
+		/* Disable PHY Interrupts */
+		mii_configure_phy_interrupt(ugeth->mii_info,
+					    MII_INTERRUPT_DISABLED);
+	}
+
+	free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+
+	if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+		free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev);
+	} else {
+		del_timer_sync(&ugeth->phy_info_timer);
+	}
+
+	ucc_geth_memclean(ugeth);
+}
+
+static int ucc_geth_startup(ucc_geth_private_t *ugeth)
+{
+	ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
+	ucc_geth_init_pram_t *p_init_enet_pram;
+	ucc_fast_private_t *uccf;
+	ucc_geth_info_t *ug_info;
+	ucc_fast_info_t *uf_info;
+	ucc_fast_t *uf_regs;
+	ucc_geth_t *ug_regs;
+	int ret_val = -EINVAL;
+	u32 remoder = UCC_GETH_REMODER_INIT;
+	u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
+	u32 ifstat, i, j, size, l2qt, l3qt, length;
+	u16 temoder = UCC_GETH_TEMODER_INIT;
+	u16 test;
+	u8 function_code = 0;
+	u8 *bd, *endOfRing;
+	u8 numThreadsRxNumerical, numThreadsTxNumerical;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ug_info = ugeth->ug_info;
+	uf_info = &ug_info->uf_info;
+
+	if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
+	      (uf_info->bd_mem_part == MEM_PART_MURAM))) {
+		ugeth_err("%s: Bad memory partition value.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* Rx BD lengths */
+	for (i = 0; i < ug_info->numQueuesRx; i++) {
+		if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
+		    (ug_info->bdRingLenRx[i] %
+		     UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
+			ugeth_err
+			    ("%s: Rx BD ring length must be multiple of 4,"
+				" no smaller than 8.", __FUNCTION__);
+			return -EINVAL;
+		}
+	}
+
+	/* Tx BD lengths */
+	for (i = 0; i < ug_info->numQueuesTx; i++) {
+		if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
+			ugeth_err
+			    ("%s: Tx BD ring length must be no smaller than 2.",
+			     __FUNCTION__);
+			return -EINVAL;
+		}
+	}
+
+	/* mrblr */
+	if ((uf_info->max_rx_buf_length == 0) ||
+	    (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
+		ugeth_err
+		    ("%s: max_rx_buf_length must be non-zero multiple of 128.",
+		     __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* num Tx queues */
+	if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
+		ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* num Rx queues */
+	if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
+		ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* l2qt */
+	for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
+		if (ug_info->l2qt[i] >= ug_info->numQueuesRx) {
+			ugeth_err
+			    ("%s: VLAN priority table entry must not be"
+				" larger than number of Rx queues.",
+			     __FUNCTION__);
+			return -EINVAL;
+		}
+	}
+
+	/* l3qt */
+	for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
+		if (ug_info->l3qt[i] >= ug_info->numQueuesRx) {
+			ugeth_err
+			    ("%s: IP priority table entry must not be"
+				" larger than number of Rx queues.",
+			     __FUNCTION__);
+			return -EINVAL;
+		}
+	}
+
+	if (ug_info->cam && !ug_info->ecamptr) {
+		ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
+			  __FUNCTION__);
+		return -EINVAL;
+	}
+
+	if ((ug_info->numStationAddresses !=
+	     UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
+	    && ug_info->rxExtendedFiltering) {
+		ugeth_err("%s: Number of station addresses greater than 1 "
+			  "not allowed in extended parsing mode.",
+			  __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* Generate uccm_mask for receive */
+	uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
+	for (i = 0; i < ug_info->numQueuesRx; i++)
+		uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
+
+	for (i = 0; i < ug_info->numQueuesTx; i++)
+		uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
+	/* Initialize the general fast UCC block. */
+	if (ucc_fast_init(uf_info, &uccf)) {
+		ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+	ugeth->uccf = uccf;
+
+	switch (ug_info->numThreadsRx) {
+	case UCC_GETH_NUM_OF_THREADS_1:
+		numThreadsRxNumerical = 1;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_2:
+		numThreadsRxNumerical = 2;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_4:
+		numThreadsRxNumerical = 4;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_6:
+		numThreadsRxNumerical = 6;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_8:
+		numThreadsRxNumerical = 8;
+		break;
+	default:
+		ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -EINVAL;
+		break;
+	}
+
+	switch (ug_info->numThreadsTx) {
+	case UCC_GETH_NUM_OF_THREADS_1:
+		numThreadsTxNumerical = 1;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_2:
+		numThreadsTxNumerical = 2;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_4:
+		numThreadsTxNumerical = 4;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_6:
+		numThreadsTxNumerical = 6;
+		break;
+	case UCC_GETH_NUM_OF_THREADS_8:
+		numThreadsTxNumerical = 8;
+		break;
+	default:
+		ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -EINVAL;
+		break;
+	}
+
+	/* Calculate rx_extended_features */
+	ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
+	    ug_info->ipAddressAlignment ||
+	    (ug_info->numStationAddresses !=
+	     UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
+
+	ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
+	    (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
+	    || (ug_info->vlanOperationNonTagged !=
+		UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
+
+	uf_regs = uccf->uf_regs;
+	ug_regs = (ucc_geth_t *) (uccf->uf_regs);
+	ugeth->ug_regs = ug_regs;
+
+	init_default_reg_vals(&uf_regs->upsmr,
+			      &ug_regs->maccfg1, &ug_regs->maccfg2);
+
+	/*                    Set UPSMR                      */
+	/* For more details see the hardware spec.           */
+	init_rx_parameters(ug_info->bro,
+			   ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
+
+	/* We're going to ignore other registers for now, */
+	/* except as needed to get up and running         */
+
+	/*                    Set MACCFG1                    */
+	/* For more details see the hardware spec.           */
+	init_flow_control_params(ug_info->aufc,
+				 ug_info->receiveFlowControl,
+				 1,
+				 ug_info->pausePeriod,
+				 ug_info->extensionField,
+				 &uf_regs->upsmr,
+				 &ug_regs->uempr, &ug_regs->maccfg1);
+
+	maccfg1 = in_be32(&ug_regs->maccfg1);
+	maccfg1 |= MACCFG1_ENABLE_RX;
+	maccfg1 |= MACCFG1_ENABLE_TX;
+	out_be32(&ug_regs->maccfg1, maccfg1);
+
+	/*                    Set IPGIFG                     */
+	/* For more details see the hardware spec.           */
+	ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
+					      ug_info->nonBackToBackIfgPart2,
+					      ug_info->
+					      miminumInterFrameGapEnforcement,
+					      ug_info->backToBackInterFrameGap,
+					      &ug_regs->ipgifg);
+	if (ret_val != 0) {
+		ugeth_err("%s: IPGIFG initialization parameter too large.",
+			  __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return ret_val;
+	}
+
+	/*                    Set HAFDUP                     */
+	/* For more details see the hardware spec.           */
+	ret_val = init_half_duplex_params(ug_info->altBeb,
+					  ug_info->backPressureNoBackoff,
+					  ug_info->noBackoff,
+					  ug_info->excessDefer,
+					  ug_info->altBebTruncation,
+					  ug_info->maxRetransmission,
+					  ug_info->collisionWindow,
+					  &ug_regs->hafdup);
+	if (ret_val != 0) {
+		ugeth_err("%s: Half Duplex initialization parameter too large.",
+			  __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return ret_val;
+	}
+
+	/*                    Set IFSTAT                     */
+	/* For more details see the hardware spec.           */
+	/* Read only - resets upon read                      */
+	ifstat = in_be32(&ug_regs->ifstat);
+
+	/*                    Clear UEMPR                    */
+	/* For more details see the hardware spec.           */
+	out_be32(&ug_regs->uempr, 0);
+
+	/*                    Set UESCR                      */
+	/* For more details see the hardware spec.           */
+	init_hw_statistics_gathering_mode((ug_info->statisticsMode &
+				UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
+				0, &uf_regs->upsmr, &ug_regs->uescr);
+
+	/* Allocate Tx bds */
+	for (j = 0; j < ug_info->numQueuesTx; j++) {
+		/* Allocate in multiple of
+		   UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
+		   according to spec */
+		length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD)
+			  / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+		    * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+		if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) %
+		    UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
+			length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
+		if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+			u32 align = 4;
+			if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
+				align = UCC_GETH_TX_BD_RING_ALIGNMENT;
+			ugeth->tx_bd_ring_offset[j] =
+				(u32) (kmalloc((u32) (length + align),
+				GFP_KERNEL));
+			if (ugeth->tx_bd_ring_offset[j] != 0)
+				ugeth->p_tx_bd_ring[j] =
+					(void*)((ugeth->tx_bd_ring_offset[j] +
+					align) & ~(align - 1));
+		} else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+			ugeth->tx_bd_ring_offset[j] =
+			    qe_muram_alloc(length,
+					   UCC_GETH_TX_BD_RING_ALIGNMENT);
+			if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j]))
+				ugeth->p_tx_bd_ring[j] =
+				    (u8 *) qe_muram_addr(ugeth->
+							 tx_bd_ring_offset[j]);
+		}
+		if (!ugeth->p_tx_bd_ring[j]) {
+			ugeth_err
+			    ("%s: Can not allocate memory for Tx bd rings.",
+			     __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+		/* Zero unused end of bd ring, according to spec */
+		memset(ugeth->p_tx_bd_ring[j] +
+		       ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0,
+		       length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD);
+	}
+
+	/* Allocate Rx bds */
+	for (j = 0; j < ug_info->numQueuesRx; j++) {
+		length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD;
+		if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
+			u32 align = 4;
+			if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
+				align = UCC_GETH_RX_BD_RING_ALIGNMENT;
+			ugeth->rx_bd_ring_offset[j] =
+			    (u32) (kmalloc((u32) (length + align), GFP_KERNEL));
+			if (ugeth->rx_bd_ring_offset[j] != 0)
+				ugeth->p_rx_bd_ring[j] =
+					(void*)((ugeth->rx_bd_ring_offset[j] +
+					align) & ~(align - 1));
+		} else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
+			ugeth->rx_bd_ring_offset[j] =
+			    qe_muram_alloc(length,
+					   UCC_GETH_RX_BD_RING_ALIGNMENT);
+			if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j]))
+				ugeth->p_rx_bd_ring[j] =
+				    (u8 *) qe_muram_addr(ugeth->
+							 rx_bd_ring_offset[j]);
+		}
+		if (!ugeth->p_rx_bd_ring[j]) {
+			ugeth_err
+			    ("%s: Can not allocate memory for Rx bd rings.",
+			     __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+	}
+
+	/* Init Tx bds */
+	for (j = 0; j < ug_info->numQueuesTx; j++) {
+		/* Setup the skbuff rings */
+		ugeth->tx_skbuff[j] =
+		    (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+					       ugeth->ug_info->bdRingLenTx[j],
+					       GFP_KERNEL);
+
+		if (ugeth->tx_skbuff[j] == NULL) {
+			ugeth_err("%s: Could not allocate tx_skbuff",
+				  __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
+			ugeth->tx_skbuff[j][i] = NULL;
+
+		ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
+		bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
+		for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
+			BD_BUFFER_CLEAR(bd);
+			BD_STATUS_AND_LENGTH_SET(bd, 0);
+			bd += UCC_GETH_SIZE_OF_BD;
+		}
+		bd -= UCC_GETH_SIZE_OF_BD;
+		BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */
+	}
+
+	/* Init Rx bds */
+	for (j = 0; j < ug_info->numQueuesRx; j++) {
+		/* Setup the skbuff rings */
+		ugeth->rx_skbuff[j] =
+		    (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
+					       ugeth->ug_info->bdRingLenRx[j],
+					       GFP_KERNEL);
+
+		if (ugeth->rx_skbuff[j] == NULL) {
+			ugeth_err("%s: Could not allocate rx_skbuff",
+				  __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
+			ugeth->rx_skbuff[j][i] = NULL;
+
+		ugeth->skb_currx[j] = 0;
+		bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
+		for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
+			BD_STATUS_AND_LENGTH_SET(bd, R_I);
+			BD_BUFFER_CLEAR(bd);
+			bd += UCC_GETH_SIZE_OF_BD;
+		}
+		bd -= UCC_GETH_SIZE_OF_BD;
+		BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */
+	}
+
+	/*
+	 * Global PRAM
+	 */
+	/* Tx global PRAM */
+	/* Allocate global tx parameter RAM page */
+	ugeth->tx_glbl_pram_offset =
+	    qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t),
+			   UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+	ugeth->p_tx_glbl_pram =
+	    (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth->
+							tx_glbl_pram_offset);
+	/* Zero out p_tx_glbl_pram */
+	memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t));
+
+	/* Fill global PRAM */
+
+	/* TQPTR */
+	/* Size varies with number of Tx threads */
+	ugeth->thread_dat_tx_offset =
+	    qe_muram_alloc(numThreadsTxNumerical *
+			   sizeof(ucc_geth_thread_data_tx_t) +
+			   32 * (numThreadsTxNumerical == 1),
+			   UCC_GETH_THREAD_DATA_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+
+	ugeth->p_thread_data_tx =
+	    (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth->
+							thread_dat_tx_offset);
+	out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
+
+	/* vtagtable */
+	for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
+		out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
+			 ug_info->vtagtable[i]);
+
+	/* iphoffset */
+	for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
+		ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i];
+
+	/* SQPTR */
+	/* Size varies with number of Tx queues */
+	ugeth->send_q_mem_reg_offset =
+	    qe_muram_alloc(ug_info->numQueuesTx *
+			   sizeof(ucc_geth_send_queue_qd_t),
+			   UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+
+	ugeth->p_send_q_mem_reg =
+	    (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth->
+			send_q_mem_reg_offset);
+	out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
+
+	/* Setup the table */
+	/* Assume BD rings are already established */
+	for (i = 0; i < ug_info->numQueuesTx; i++) {
+		endOfRing =
+		    ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
+					      1) * UCC_GETH_SIZE_OF_BD;
+		if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+			out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+				 (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
+			out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+				 last_bd_completed_address,
+				 (u32) virt_to_phys(endOfRing));
+		} else if (ugeth->ug_info->uf_info.bd_mem_part ==
+			   MEM_PART_MURAM) {
+			out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
+				 (u32) immrbar_virt_to_phys(ugeth->
+							    p_tx_bd_ring[i]));
+			out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
+				 last_bd_completed_address,
+				 (u32) immrbar_virt_to_phys(endOfRing));
+		}
+	}
+
+	/* schedulerbasepointer */
+
+	if (ug_info->numQueuesTx > 1) {
+	/* scheduler exists only if more than 1 tx queue */
+		ugeth->scheduler_offset =
+		    qe_muram_alloc(sizeof(ucc_geth_scheduler_t),
+				   UCC_GETH_SCHEDULER_ALIGNMENT);
+		if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
+			ugeth_err
+			 ("%s: Can not allocate DPRAM memory for p_scheduler.",
+			     __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+
+		ugeth->p_scheduler =
+		    (ucc_geth_scheduler_t *) qe_muram_addr(ugeth->
+							   scheduler_offset);
+		out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
+			 ugeth->scheduler_offset);
+		/* Zero out p_scheduler */
+		memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t));
+
+		/* Set values in scheduler */
+		out_be32(&ugeth->p_scheduler->mblinterval,
+			 ug_info->mblinterval);
+		out_be16(&ugeth->p_scheduler->nortsrbytetime,
+			 ug_info->nortsrbytetime);
+		ugeth->p_scheduler->fracsiz = ug_info->fracsiz;
+		ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq;
+		ugeth->p_scheduler->txasap = ug_info->txasap;
+		ugeth->p_scheduler->extrabw = ug_info->extrabw;
+		for (i = 0; i < NUM_TX_QUEUES; i++)
+			ugeth->p_scheduler->weightfactor[i] =
+			    ug_info->weightfactor[i];
+
+		/* Set pointers to cpucount registers in scheduler */
+		ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
+		ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
+		ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
+		ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
+		ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
+		ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
+		ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
+		ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
+	}
+
+	/* schedulerbasepointer */
+	/* TxRMON_PTR (statistics) */
+	if (ug_info->
+	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
+		ugeth->tx_fw_statistics_pram_offset =
+		    qe_muram_alloc(sizeof
+				   (ucc_geth_tx_firmware_statistics_pram_t),
+				   UCC_GETH_TX_STATISTICS_ALIGNMENT);
+		if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
+			ugeth_err
+			    ("%s: Can not allocate DPRAM memory for"
+				" p_tx_fw_statistics_pram.", __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+		ugeth->p_tx_fw_statistics_pram =
+		    (ucc_geth_tx_firmware_statistics_pram_t *)
+		    qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
+		/* Zero out p_tx_fw_statistics_pram */
+		memset(ugeth->p_tx_fw_statistics_pram,
+		       0, sizeof(ucc_geth_tx_firmware_statistics_pram_t));
+	}
+
+	/* temoder */
+	/* Already has speed set */
+
+	if (ug_info->numQueuesTx > 1)
+		temoder |= TEMODER_SCHEDULER_ENABLE;
+	if (ug_info->ipCheckSumGenerate)
+		temoder |= TEMODER_IP_CHECKSUM_GENERATE;
+	temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
+	out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
+
+	test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
+
+	/* Function code register value to be used later */
+	function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
+	/* Required for QE */
+
+	/* function code register */
+	out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
+
+	/* Rx global PRAM */
+	/* Allocate global rx parameter RAM page */
+	ugeth->rx_glbl_pram_offset =
+	    qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t),
+			   UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+	ugeth->p_rx_glbl_pram =
+	    (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth->
+							rx_glbl_pram_offset);
+	/* Zero out p_rx_glbl_pram */
+	memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t));
+
+	/* Fill global PRAM */
+
+	/* RQPTR */
+	/* Size varies with number of Rx threads */
+	ugeth->thread_dat_rx_offset =
+	    qe_muram_alloc(numThreadsRxNumerical *
+			   sizeof(ucc_geth_thread_data_rx_t),
+			   UCC_GETH_THREAD_DATA_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+
+	ugeth->p_thread_data_rx =
+	    (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth->
+							thread_dat_rx_offset);
+	out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
+
+	/* typeorlen */
+	out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
+
+	/* rxrmonbaseptr (statistics) */
+	if (ug_info->
+	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
+		ugeth->rx_fw_statistics_pram_offset =
+		    qe_muram_alloc(sizeof
+				   (ucc_geth_rx_firmware_statistics_pram_t),
+				   UCC_GETH_RX_STATISTICS_ALIGNMENT);
+		if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
+			ugeth_err
+				("%s: Can not allocate DPRAM memory for"
+				" p_rx_fw_statistics_pram.", __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+		ugeth->p_rx_fw_statistics_pram =
+		    (ucc_geth_rx_firmware_statistics_pram_t *)
+		    qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
+		/* Zero out p_rx_fw_statistics_pram */
+		memset(ugeth->p_rx_fw_statistics_pram, 0,
+		       sizeof(ucc_geth_rx_firmware_statistics_pram_t));
+	}
+
+	/* intCoalescingPtr */
+
+	/* Size varies with number of Rx queues */
+	ugeth->rx_irq_coalescing_tbl_offset =
+	    qe_muram_alloc(ug_info->numQueuesRx *
+			   sizeof(ucc_geth_rx_interrupt_coalescing_entry_t),
+			   UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for"
+			" p_rx_irq_coalescing_tbl.", __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+
+	ugeth->p_rx_irq_coalescing_tbl =
+	    (ucc_geth_rx_interrupt_coalescing_table_t *)
+	    qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
+	out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
+		 ugeth->rx_irq_coalescing_tbl_offset);
+
+	/* Fill interrupt coalescing table */
+	for (i = 0; i < ug_info->numQueuesRx; i++) {
+		out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+			 interruptcoalescingmaxvalue,
+			 ug_info->interruptcoalescingmaxvalue[i]);
+		out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
+			 interruptcoalescingcounter,
+			 ug_info->interruptcoalescingmaxvalue[i]);
+	}
+
+	/* MRBLR */
+	init_max_rx_buff_len(uf_info->max_rx_buf_length,
+			     &ugeth->p_rx_glbl_pram->mrblr);
+	/* MFLR */
+	out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
+	/* MINFLR */
+	init_min_frame_len(ug_info->minFrameLength,
+			   &ugeth->p_rx_glbl_pram->minflr,
+			   &ugeth->p_rx_glbl_pram->mrblr);
+	/* MAXD1 */
+	out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
+	/* MAXD2 */
+	out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
+
+	/* l2qt */
+	l2qt = 0;
+	for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
+		l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
+	out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
+
+	/* l3qt */
+	for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
+		l3qt = 0;
+		for (i = 0; i < 8; i++)
+			l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
+		out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt);
+	}
+
+	/* vlantype */
+	out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
+
+	/* vlantci */
+	out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
+
+	/* ecamptr */
+	out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
+
+	/* RBDQPTR */
+	/* Size varies with number of Rx queues */
+	ugeth->rx_bd_qs_tbl_offset =
+	    qe_muram_alloc(ug_info->numQueuesRx *
+			   (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+			    sizeof(ucc_geth_rx_prefetched_bds_t)),
+			   UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
+	if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+
+	ugeth->p_rx_bd_qs_tbl =
+	    (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth->
+				    rx_bd_qs_tbl_offset);
+	out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
+	/* Zero out p_rx_bd_qs_tbl */
+	memset(ugeth->p_rx_bd_qs_tbl,
+	       0,
+	       ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) +
+				       sizeof(ucc_geth_rx_prefetched_bds_t)));
+
+	/* Setup the table */
+	/* Assume BD rings are already established */
+	for (i = 0; i < ug_info->numQueuesRx; i++) {
+		if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
+			out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+				 (u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
+		} else if (ugeth->ug_info->uf_info.bd_mem_part ==
+			   MEM_PART_MURAM) {
+			out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
+				 (u32) immrbar_virt_to_phys(ugeth->
+							    p_rx_bd_ring[i]));
+		}
+		/* rest of fields handled by QE */
+	}
+
+	/* remoder */
+	/* Already has speed set */
+
+	if (ugeth->rx_extended_features)
+		remoder |= REMODER_RX_EXTENDED_FEATURES;
+	if (ug_info->rxExtendedFiltering)
+		remoder |= REMODER_RX_EXTENDED_FILTERING;
+	if (ug_info->dynamicMaxFrameLength)
+		remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH;
+	if (ug_info->dynamicMinFrameLength)
+		remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH;
+	remoder |=
+	    ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT;
+	remoder |=
+	    ug_info->
+	    vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT;
+	remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT;
+	remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT);
+	if (ug_info->ipCheckSumCheck)
+		remoder |= REMODER_IP_CHECKSUM_CHECK;
+	if (ug_info->ipAddressAlignment)
+		remoder |= REMODER_IP_ADDRESS_ALIGNMENT;
+	out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder);
+
+	/* Note that this function must be called */
+	/* ONLY AFTER p_tx_fw_statistics_pram */
+	/* andp_UccGethRxFirmwareStatisticsPram are allocated ! */
+	init_firmware_statistics_gathering_mode((ug_info->
+		statisticsMode &
+		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX),
+		(ug_info->statisticsMode &
+		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX),
+		&ugeth->p_tx_glbl_pram->txrmonbaseptr,
+		ugeth->tx_fw_statistics_pram_offset,
+		&ugeth->p_rx_glbl_pram->rxrmonbaseptr,
+		ugeth->rx_fw_statistics_pram_offset,
+		&ugeth->p_tx_glbl_pram->temoder,
+		&ugeth->p_rx_glbl_pram->remoder);
+
+	/* function code register */
+	ugeth->p_rx_glbl_pram->rstate = function_code;
+
+	/* initialize extended filtering */
+	if (ug_info->rxExtendedFiltering) {
+		if (!ug_info->extendedFilteringChainPointer) {
+			ugeth_err("%s: Null Extended Filtering Chain Pointer.",
+				  __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -EINVAL;
+		}
+
+		/* Allocate memory for extended filtering Mode Global
+		Parameters */
+		ugeth->exf_glbl_param_offset =
+		    qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t),
+		UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
+		if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) {
+			ugeth_err
+				("%s: Can not allocate DPRAM memory for"
+				" p_exf_glbl_param.", __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return -ENOMEM;
+		}
+
+		ugeth->p_exf_glbl_param =
+		    (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth->
+				 exf_glbl_param_offset);
+		out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
+			 ugeth->exf_glbl_param_offset);
+		out_be32(&ugeth->p_exf_glbl_param->l2pcdptr,
+			 (u32) ug_info->extendedFilteringChainPointer);
+
+	} else {		/* initialize 82xx style address filtering */
+
+		/* Init individual address recognition registers to disabled */
+
+		for (j = 0; j < NUM_OF_PADDRS; j++)
+			ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j);
+
+		/* Create CQs for hash tables */
+		if (ug_info->maxGroupAddrInHash > 0) {
+			INIT_LIST_HEAD(&ugeth->group_hash_q);
+		}
+		if (ug_info->maxIndAddrInHash > 0) {
+			INIT_LIST_HEAD(&ugeth->ind_hash_q);
+		}
+		p_82xx_addr_filt =
+		    (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
+		    p_rx_glbl_pram->addressfiltering;
+
+		ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+			ENET_ADDR_TYPE_GROUP);
+		ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
+			ENET_ADDR_TYPE_INDIVIDUAL);
+	}
+
+	/*
+	 * Initialize UCC at QE level
+	 */
+
+	command = QE_INIT_TX_RX;
+
+	/* Allocate shadow InitEnet command parameter structure.
+	 * This is needed because after the InitEnet command is executed,
+	 * the structure in DPRAM is released, because DPRAM is a premium
+	 * resource.
+	 * This shadow structure keeps a copy of what was done so that the
+	 * allocated resources can be released when the channel is freed.
+	 */
+	if (!(ugeth->p_init_enet_param_shadow =
+	     (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t),
+					      GFP_KERNEL))) {
+		ugeth_err
+		    ("%s: Can not allocate memory for"
+			" p_UccInitEnetParamShadows.", __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+	/* Zero out *p_init_enet_param_shadow */
+	memset((char *)ugeth->p_init_enet_param_shadow,
+	       0, sizeof(ucc_geth_init_pram_t));
+
+	/* Fill shadow InitEnet command parameter structure */
+
+	ugeth->p_init_enet_param_shadow->resinit1 =
+	    ENET_INIT_PARAM_MAGIC_RES_INIT1;
+	ugeth->p_init_enet_param_shadow->resinit2 =
+	    ENET_INIT_PARAM_MAGIC_RES_INIT2;
+	ugeth->p_init_enet_param_shadow->resinit3 =
+	    ENET_INIT_PARAM_MAGIC_RES_INIT3;
+	ugeth->p_init_enet_param_shadow->resinit4 =
+	    ENET_INIT_PARAM_MAGIC_RES_INIT4;
+	ugeth->p_init_enet_param_shadow->resinit5 =
+	    ENET_INIT_PARAM_MAGIC_RES_INIT5;
+	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+	    ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT;
+	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+	    ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT;
+
+	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
+	    ugeth->rx_glbl_pram_offset | ug_info->riscRx;
+	if ((ug_info->largestexternallookupkeysize !=
+	     QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE)
+	    && (ug_info->largestexternallookupkeysize !=
+		QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+	    && (ug_info->largestexternallookupkeysize !=
+		QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
+		ugeth_err("%s: Invalid largest External Lookup Key Size.",
+			  __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -EINVAL;
+	}
+	ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
+	    ug_info->largestexternallookupkeysize;
+	size = sizeof(ucc_geth_thread_rx_pram_t);
+	if (ug_info->rxExtendedFiltering) {
+		size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
+		if (ug_info->largestexternallookupkeysize ==
+		    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
+			size +=
+			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
+		if (ug_info->largestexternallookupkeysize ==
+		    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
+			size +=
+			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
+	}
+
+	if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth->
+		p_init_enet_param_shadow->rxthread[0]),
+		(u8) (numThreadsRxNumerical + 1)
+		/* Rx needs one extra for terminator */
+		, size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
+		ug_info->riscRx, 1)) != 0) {
+			ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+				__FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return ret_val;
+	}
+
+	ugeth->p_init_enet_param_shadow->txglobal =
+	    ugeth->tx_glbl_pram_offset | ug_info->riscTx;
+	if ((ret_val =
+	     fill_init_enet_entries(ugeth,
+				    &(ugeth->p_init_enet_param_shadow->
+				      txthread[0]), numThreadsTxNumerical,
+				    sizeof(ucc_geth_thread_tx_pram_t),
+				    UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
+				    ug_info->riscTx, 0)) != 0) {
+		ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
+			  __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return ret_val;
+	}
+
+	/* Load Rx bds with buffers */
+	for (i = 0; i < ug_info->numQueuesRx; i++) {
+		if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
+			ugeth_err("%s: Can not fill Rx bds with buffers.",
+				  __FUNCTION__);
+			ucc_geth_memclean(ugeth);
+			return ret_val;
+		}
+	}
+
+	/* Allocate InitEnet command parameter structure */
+	init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4);
+	if (IS_MURAM_ERR(init_enet_pram_offset)) {
+		ugeth_err
+		    ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
+		     __FUNCTION__);
+		ucc_geth_memclean(ugeth);
+		return -ENOMEM;
+	}
+	p_init_enet_pram =
+	    (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset);
+
+	/* Copy shadow InitEnet command parameter structure into PRAM */
+	p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1;
+	p_init_enet_pram->resinit2 = ugeth->p_init_enet_param_shadow->resinit2;
+	p_init_enet_pram->resinit3 = ugeth->p_init_enet_param_shadow->resinit3;
+	p_init_enet_pram->resinit4 = ugeth->p_init_enet_param_shadow->resinit4;
+	out_be16(&p_init_enet_pram->resinit5,
+		 ugeth->p_init_enet_param_shadow->resinit5);
+	p_init_enet_pram->largestexternallookupkeysize =
+	    ugeth->p_init_enet_param_shadow->largestexternallookupkeysize;
+	out_be32(&p_init_enet_pram->rgftgfrxglobal,
+		 ugeth->p_init_enet_param_shadow->rgftgfrxglobal);
+	for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++)
+		out_be32(&p_init_enet_pram->rxthread[i],
+			 ugeth->p_init_enet_param_shadow->rxthread[i]);
+	out_be32(&p_init_enet_pram->txglobal,
+		 ugeth->p_init_enet_param_shadow->txglobal);
+	for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++)
+		out_be32(&p_init_enet_pram->txthread[i],
+			 ugeth->p_init_enet_param_shadow->txthread[i]);
+
+	/* Issue QE command */
+	cecr_subblock =
+	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
+	qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
+		     init_enet_pram_offset);
+
+	/* Free InitEnet command parameter */
+	qe_muram_free(init_enet_pram_offset);
+
+	return 0;
+}
+
+/* returns a net_device_stats structure pointer */
+static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+	return &(ugeth->stats);
+}
+
+/* ucc_geth_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ * For now, assume that clearing out all the structures, and
+ * starting over will fix the problem. */
+static void ucc_geth_timeout(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ugeth->stats.tx_errors++;
+
+	ugeth_dump_regs(ugeth);
+
+	if (dev->flags & IFF_UP) {
+		ucc_geth_stop(ugeth);
+		ucc_geth_startup(ugeth);
+	}
+
+	netif_schedule(dev);
+}
+
+/* This is called by the kernel when a frame is ready for transmission. */
+/* It is pointed to by the dev->hard_start_xmit function pointer */
+static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	u8 *bd;			/* BD pointer */
+	u32 bd_status;
+	u8 txQ = 0;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irq(&ugeth->lock);
+
+	ugeth->stats.tx_bytes += skb->len;
+
+	/* Start from the next BD that should be filled */
+	bd = ugeth->txBd[txQ];
+	bd_status = BD_STATUS_AND_LENGTH(bd);
+	/* Save the skb pointer so we can free it later */
+	ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb;
+
+	/* Update the current skb pointer (wrapping if this was the last) */
+	ugeth->skb_curtx[txQ] =
+	    (ugeth->skb_curtx[txQ] +
+	     1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+	/* set up the buffer descriptor */
+	BD_BUFFER_SET(bd,
+		      dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE));
+
+	//printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data);
+
+	bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len;
+
+	BD_STATUS_AND_LENGTH_SET(bd, bd_status);
+
+	dev->trans_start = jiffies;
+
+	/* Move to next BD in the ring */
+	if (!(bd_status & T_W))
+		ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD;
+	else
+		ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+
+	/* If the next BD still needs to be cleaned up, then the bds
+	   are full.  We need to tell the kernel to stop sending us stuff. */
+	if (bd == ugeth->confBd[txQ]) {
+		if (!netif_queue_stopped(dev))
+			netif_stop_queue(dev);
+	}
+
+	if (ugeth->p_scheduler) {
+		ugeth->cpucount[txQ]++;
+		/* Indicate to QE that there are more Tx bds ready for
+		transmission */
+		/* This is done by writing a running counter of the bd
+		count to the scheduler PRAM. */
+		out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]);
+	}
+
+	spin_unlock_irq(&ugeth->lock);
+
+	return 0;
+}
+
+static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit)
+{
+	struct sk_buff *skb;
+	u8 *bd;
+	u16 length, howmany = 0;
+	u32 bd_status;
+	u8 *bdBuffer;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock(&ugeth->lock);
+	/* collect received buffers */
+	bd = ugeth->rxBd[rxQ];
+
+	bd_status = BD_STATUS_AND_LENGTH(bd);
+
+	/* while there are received buffers and BD is full (~R_E) */
+	while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
+		bdBuffer = (u8 *) BD_BUFFER(bd);
+		length = (u16) ((bd_status & BD_LENGTH_MASK) - 4);
+		skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]];
+
+		/* determine whether buffer is first, last, first and last
+		(single buffer frame) or middle (not first and not last) */
+		if (!skb ||
+		    (!(bd_status & (R_F | R_L))) ||
+		    (bd_status & R_ERRORS_FATAL)) {
+			ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x",
+				   __FUNCTION__, __LINE__, (u32) skb);
+			if (skb)
+				dev_kfree_skb_any(skb);
+
+			ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
+			ugeth->stats.rx_dropped++;
+		} else {
+			ugeth->stats.rx_packets++;
+			howmany++;
+
+			/* Prep the skb for the packet */
+			skb_put(skb, length);
+
+			/* Tell the skb what kind of packet this is */
+			skb->protocol = eth_type_trans(skb, ugeth->dev);
+
+			ugeth->stats.rx_bytes += length;
+			/* Send the packet up the stack */
+#ifdef CONFIG_UGETH_NAPI
+			netif_receive_skb(skb);
+#else
+			netif_rx(skb);
+#endif				/* CONFIG_UGETH_NAPI */
+		}
+
+		ugeth->dev->last_rx = jiffies;
+
+		skb = get_new_skb(ugeth, bd);
+		if (!skb) {
+			ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__);
+			spin_unlock(&ugeth->lock);
+			ugeth->stats.rx_dropped++;
+			break;
+		}
+
+		ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb;
+
+		/* update to point at the next skb */
+		ugeth->skb_currx[rxQ] =
+		    (ugeth->skb_currx[rxQ] +
+		     1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]);
+
+		if (bd_status & R_W)
+			bd = ugeth->p_rx_bd_ring[rxQ];
+		else
+			bd += UCC_GETH_SIZE_OF_BD;
+
+		bd_status = BD_STATUS_AND_LENGTH(bd);
+	}
+
+	ugeth->rxBd[rxQ] = bd;
+	spin_unlock(&ugeth->lock);
+	return howmany;
+}
+
+static int ucc_geth_tx(struct net_device *dev, u8 txQ)
+{
+	/* Start from the next BD that should be filled */
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	u8 *bd;			/* BD pointer */
+	u32 bd_status;
+
+	bd = ugeth->confBd[txQ];
+	bd_status = BD_STATUS_AND_LENGTH(bd);
+
+	/* Normal processing. */
+	while ((bd_status & T_R) == 0) {
+		/* BD contains already transmitted buffer.   */
+		/* Handle the transmitted buffer and release */
+		/* the BD to be used with the current frame  */
+
+		if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0))
+			break;
+
+		ugeth->stats.tx_packets++;
+
+		/* Free the sk buffer associated with this TxBD */
+		dev_kfree_skb_irq(ugeth->
+				  tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]);
+		ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
+		ugeth->skb_dirtytx[txQ] =
+		    (ugeth->skb_dirtytx[txQ] +
+		     1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
+
+		/* We freed a buffer, so now we can restart transmission */
+		if (netif_queue_stopped(dev))
+			netif_wake_queue(dev);
+
+		/* Advance the confirmation BD pointer */
+		if (!(bd_status & T_W))
+			ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD;
+		else
+			ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ];
+	}
+	return 0;
+}
+
+#ifdef CONFIG_UGETH_NAPI
+static int ucc_geth_poll(struct net_device *dev, int *budget)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	int howmany;
+	int rx_work_limit = *budget;
+	u8 rxQ = 0;
+
+	if (rx_work_limit > dev->quota)
+		rx_work_limit = dev->quota;
+
+	howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit);
+
+	dev->quota -= howmany;
+	rx_work_limit -= howmany;
+	*budget -= howmany;
+
+	if (rx_work_limit >= 0)
+		netif_rx_complete(dev);
+
+	return (rx_work_limit < 0) ? 1 : 0;
+}
+#endif				/* CONFIG_UGETH_NAPI */
+
+static irqreturn_t ucc_geth_irq_handler(int irq, void *info,
+					struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)info;
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	ucc_fast_private_t *uccf;
+	ucc_geth_info_t *ug_info;
+	register u32 ucce = 0;
+	register u32 bit_mask = UCCE_RXBF_SINGLE_MASK;
+	register u32 tx_mask = UCCE_TXBF_SINGLE_MASK;
+	register u8 i;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	if (!ugeth)
+		return IRQ_NONE;
+
+	uccf = ugeth->uccf;
+	ug_info = ugeth->ug_info;
+
+	do {
+		ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm));
+
+		/* clear event bits for next time */
+		/* Side effect here is to mask ucce variable
+		for future processing below. */
+		out_be32(uccf->p_ucce, ucce);	/* Clear with ones,
+						but only bits in UCCM */
+
+		/* We ignore Tx interrupts because Tx confirmation is
+		done inside Tx routine */
+
+		for (i = 0; i < ug_info->numQueuesRx; i++) {
+			if (ucce & bit_mask)
+				ucc_geth_rx(ugeth, i,
+					    (int)ugeth->ug_info->
+					    bdRingLenRx[i]);
+			ucce &= ~bit_mask;
+			bit_mask <<= 1;
+		}
+
+		for (i = 0; i < ug_info->numQueuesTx; i++) {
+			if (ucce & tx_mask)
+				ucc_geth_tx(dev, i);
+			ucce &= ~tx_mask;
+			tx_mask <<= 1;
+		}
+
+		/* Exceptions */
+		if (ucce & UCCE_BSY) {
+			ugeth_vdbg("Got BUSY irq!!!!");
+			ugeth->stats.rx_errors++;
+			ucce &= ~UCCE_BSY;
+		}
+		if (ucce & UCCE_OTHER) {
+			ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!",
+				   ucce);
+			ugeth->stats.rx_errors++;
+			ucce &= ~ucce;
+		}
+	}
+	while (ucce);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	/* Clear the interrupt */
+	mii_clear_phy_interrupt(ugeth->mii_info);
+
+	/* Disable PHY interrupts */
+	mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED);
+
+	/* Schedule the phy change */
+	schedule_work(&ugeth->tq);
+
+	return IRQ_HANDLED;
+}
+
+/* Scheduled by the phy_interrupt/timer to handle PHY changes */
+static void ugeth_phy_change(void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	ucc_geth_t *ug_regs;
+	int result = 0;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ug_regs = ugeth->ug_regs;
+
+	/* Delay to give the PHY a chance to change the
+	 * register state */
+	msleep(1);
+
+	/* Update the link, speed, duplex */
+	result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info);
+
+	/* Adjust the known status as long as the link
+	 * isn't still coming up */
+	if ((0 == result) || (ugeth->mii_info->link == 0))
+		adjust_link(dev);
+
+	/* Reenable interrupts, if needed */
+	if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR)
+		mii_configure_phy_interrupt(ugeth->mii_info,
+					    MII_INTERRUPT_ENABLED);
+}
+
+/* Called every so often on systems that don't interrupt
+ * the core for PHY changes */
+static void ugeth_phy_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+	schedule_work(&ugeth->tq);
+
+	mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to
+ * using ugeth_phy_timer to check status */
+static void ugeth_phy_startup_timer(unsigned long data)
+{
+	struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+	ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev);
+	static int secondary = UGETH_AN_TIMEOUT;
+	int result;
+
+	/* Configure the Auto-negotiation */
+	result = mii_info->phyinfo->config_aneg(mii_info);
+
+	/* If autonegotiation failed to start, and
+	 * we haven't timed out, reset the timer, and return */
+	if (result && secondary--) {
+		mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+		return;
+	} else if (result) {
+		/* Couldn't start autonegotiation.
+		 * Try switching to forced */
+		mii_info->autoneg = 0;
+		result = mii_info->phyinfo->config_aneg(mii_info);
+
+		/* Forcing failed!  Give up */
+		if (result) {
+			ugeth_err("%s: Forcing failed!", mii_info->dev->name);
+			return;
+		}
+	}
+
+	/* Kill the timer so it can be restarted */
+	del_timer_sync(&ugeth->phy_info_timer);
+
+	/* Grab the PHY interrupt, if necessary/possible */
+	if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
+		if (request_irq(ugeth->ug_info->phy_interrupt,
+				phy_interrupt,
+				SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) {
+			ugeth_err("%s: Can't get IRQ %d (PHY)",
+				  mii_info->dev->name,
+				  ugeth->ug_info->phy_interrupt);
+		} else {
+			mii_configure_phy_interrupt(ugeth->mii_info,
+						    MII_INTERRUPT_ENABLED);
+			return;
+		}
+	}
+
+	/* Start the timer again, this time in order to
+	 * handle a change in status */
+	init_timer(&ugeth->phy_info_timer);
+	ugeth->phy_info_timer.function = &ugeth_phy_timer;
+	ugeth->phy_info_timer.data = (unsigned long)mii_info->dev;
+	mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ);
+}
+
+/* Called when something needs to use the ethernet device */
+/* Returns 0 for success. */
+static int ucc_geth_open(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	int err;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	/* Test station address */
+	if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
+		ugeth_err("%s: Multicast address used for station address"
+			  " - is this what you wanted?", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	err = ucc_geth_startup(ugeth);
+	if (err) {
+		ugeth_err("%s: Cannot configure net device, aborting.",
+			  dev->name);
+		return err;
+	}
+
+	err = adjust_enet_interface(ugeth);
+	if (err) {
+		ugeth_err("%s: Cannot configure net device, aborting.",
+			  dev->name);
+		return err;
+	}
+
+	/*       Set MACSTNADDR1, MACSTNADDR2                */
+	/* For more details see the hardware spec.           */
+	init_mac_station_addr_regs(dev->dev_addr[0],
+				   dev->dev_addr[1],
+				   dev->dev_addr[2],
+				   dev->dev_addr[3],
+				   dev->dev_addr[4],
+				   dev->dev_addr[5],
+				   &ugeth->ug_regs->macstnaddr1,
+				   &ugeth->ug_regs->macstnaddr2);
+
+	err = init_phy(dev);
+	if (err) {
+		ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name);
+		return err;
+	}
+#ifndef CONFIG_UGETH_NAPI
+	err =
+	    request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
+			"UCC Geth", dev);
+	if (err) {
+		ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+			  dev->name);
+		ucc_geth_stop(ugeth);
+		return err;
+	}
+#endif				/* CONFIG_UGETH_NAPI */
+
+	/* Set up the PHY change work queue */
+	INIT_WORK(&ugeth->tq, ugeth_phy_change, dev);
+
+	init_timer(&ugeth->phy_info_timer);
+	ugeth->phy_info_timer.function = &ugeth_phy_startup_timer;
+	ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info;
+	mod_timer(&ugeth->phy_info_timer, jiffies + HZ);
+
+	err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+	if (err) {
+		ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
+		ucc_geth_stop(ugeth);
+		return err;
+	}
+
+	netif_start_queue(dev);
+
+	return err;
+}
+
+/* Stops the kernel queue, and halts the controller */
+static int ucc_geth_close(struct net_device *dev)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ucc_geth_stop(ugeth);
+
+	/* Shutdown the PHY */
+	if (ugeth->mii_info->phyinfo->close)
+		ugeth->mii_info->phyinfo->close(ugeth->mii_info);
+
+	kfree(ugeth->mii_info);
+
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+struct ethtool_ops ucc_geth_ethtool_ops = {
+	.get_settings = NULL,
+	.get_drvinfo = NULL,
+	.get_regs_len = NULL,
+	.get_regs = NULL,
+	.get_link = NULL,
+	.get_coalesce = NULL,
+	.set_coalesce = NULL,
+	.get_ringparam = NULL,
+	.set_ringparam = NULL,
+	.get_strings = NULL,
+	.get_stats_count = NULL,
+	.get_ethtool_stats = NULL,
+};
+
+static int ucc_geth_probe(struct device *device)
+{
+	struct platform_device *pdev = to_platform_device(device);
+	struct ucc_geth_platform_data *ugeth_pdata;
+	struct net_device *dev = NULL;
+	struct ucc_geth_private *ugeth = NULL;
+	struct ucc_geth_info *ug_info;
+	int err;
+	static int mii_mng_configured = 0;
+
+	ugeth_vdbg("%s: IN", __FUNCTION__);
+
+	ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data;
+
+	ug_info = &ugeth_info[pdev->id];
+	ug_info->uf_info.ucc_num = pdev->id;
+	ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock;
+	ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock;
+	ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr;
+	ug_info->uf_info.irq = platform_get_irq(pdev, 0);
+	ug_info->phy_address = ugeth_pdata->phy_id;
+	ug_info->enet_interface = ugeth_pdata->phy_interface;
+	ug_info->board_flags = ugeth_pdata->board_flags;
+	ug_info->phy_interrupt = ugeth_pdata->phy_interrupt;
+
+	printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n",
+		ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs,
+		ug_info->uf_info.irq);
+
+	if (ug_info == NULL) {
+		ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__,
+			  pdev->id);
+		return -ENODEV;
+	}
+
+	if (!mii_mng_configured) {
+		ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num);
+		mii_mng_configured = 1;
+	}
+
+	/* Create an ethernet device instance */
+	dev = alloc_etherdev(sizeof(*ugeth));
+
+	if (dev == NULL)
+		return -ENOMEM;
+
+	ugeth = netdev_priv(dev);
+	spin_lock_init(&ugeth->lock);
+
+	dev_set_drvdata(device, dev);
+
+	/* Set the dev->base_addr to the gfar reg region */
+	dev->base_addr = (unsigned long)(ug_info->uf_info.regs);
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, device);
+
+	/* Fill in the dev structure */
+	dev->open = ucc_geth_open;
+	dev->hard_start_xmit = ucc_geth_start_xmit;
+	dev->tx_timeout = ucc_geth_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_UGETH_NAPI
+	dev->poll = ucc_geth_poll;
+	dev->weight = UCC_GETH_DEV_WEIGHT;
+#endif				/* CONFIG_UGETH_NAPI */
+	dev->stop = ucc_geth_close;
+	dev->get_stats = ucc_geth_get_stats;
+//    dev->change_mtu = ucc_geth_change_mtu;
+	dev->mtu = 1500;
+	dev->set_multicast_list = ucc_geth_set_multi;
+	dev->ethtool_ops = &ucc_geth_ethtool_ops;
+
+	err = register_netdev(dev);
+	if (err) {
+		ugeth_err("%s: Cannot register net device, aborting.",
+			  dev->name);
+		free_netdev(dev);
+		return err;
+	}
+
+	ugeth->ug_info = ug_info;
+	ugeth->dev = dev;
+	memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6);
+
+	return 0;
+}
+
+static int ucc_geth_remove(struct device *device)
+{
+	struct net_device *dev = dev_get_drvdata(device);
+	struct ucc_geth_private *ugeth = netdev_priv(dev);
+
+	dev_set_drvdata(device, NULL);
+	ucc_geth_memclean(ugeth);
+	free_netdev(dev);
+
+	return 0;
+}
+
+/* Structure for a device driver */
+static struct device_driver ucc_geth_driver = {
+	.name = DRV_NAME,
+	.bus = &platform_bus_type,
+	.probe = ucc_geth_probe,
+	.remove = ucc_geth_remove,
+};
+
+static int __init ucc_geth_init(void)
+{
+	int i;
+	printk(KERN_INFO "ucc_geth: " DRV_DESC "\n");
+	for (i = 0; i < 8; i++)
+		memcpy(&(ugeth_info[i]), &ugeth_primary_info,
+		       sizeof(ugeth_primary_info));
+
+	return driver_register(&ucc_geth_driver);
+}
+
+static void __exit ucc_geth_exit(void)
+{
+	driver_unregister(&ucc_geth_driver);
+}
+
+module_init(ucc_geth_init);
+module_exit(ucc_geth_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
new file mode 100644
index 0000000..005965f
--- /dev/null
+++ b/drivers/net/ucc_geth.h
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * Internal header file for UCC Gigabit Ethernet unit routines.
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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.
+ */
+#ifndef __UCC_GETH_H__
+#define __UCC_GETH_H__
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+#define NUM_TX_QUEUES                   8
+#define NUM_RX_QUEUES                   8
+#define NUM_BDS_IN_PREFETCHED_BDS       4
+#define TX_IP_OFFSET_ENTRY_MAX          8
+#define NUM_OF_PADDRS                   4
+#define ENET_INIT_PARAM_MAX_ENTRIES_RX  9
+#define ENET_INIT_PARAM_MAX_ENTRIES_TX  8
+
+typedef struct ucc_mii_mng {
+	u32 miimcfg;		/* MII management configuration reg */
+	u32 miimcom;		/* MII management command reg */
+	u32 miimadd;		/* MII management address reg */
+	u32 miimcon;		/* MII management control reg */
+	u32 miimstat;		/* MII management status reg */
+	u32 miimind;		/* MII management indication reg */
+} __attribute__ ((packed)) ucc_mii_mng_t;
+
+typedef struct ucc_geth {
+	ucc_fast_t uccf;
+
+	u32 maccfg1;		/* mac configuration reg. 1 */
+	u32 maccfg2;		/* mac configuration reg. 2 */
+	u32 ipgifg;		/* interframe gap reg.  */
+	u32 hafdup;		/* half-duplex reg.  */
+	u8 res1[0x10];
+	ucc_mii_mng_t miimng;	/* MII management structure */
+	u32 ifctl;		/* interface control reg */
+	u32 ifstat;		/* interface statux reg */
+	u32 macstnaddr1;	/* mac station address part 1 reg */
+	u32 macstnaddr2;	/* mac station address part 2 reg */
+	u8 res2[0x8];
+	u32 uempr;		/* UCC Ethernet Mac parameter reg */
+	u32 utbipar;		/* UCC tbi address reg */
+	u16 uescr;		/* UCC Ethernet statistics control reg */
+	u8 res3[0x180 - 0x15A];
+	u32 tx64;		/* Total number of frames (including bad
+				   frames) transmitted that were exactly of the
+				   minimal length (64 for un tagged, 68 for
+				   tagged, or with length exactly equal to the
+				   parameter MINLength */
+	u32 tx127;		/* Total number of frames (including bad
+				   frames) transmitted that were between
+				   MINLength (Including FCS length==4) and 127
+				   octets */
+	u32 tx255;		/* Total number of frames (including bad
+				   frames) transmitted that were between 128
+				   (Including FCS length==4) and 255 octets */
+	u32 rx64;		/* Total number of frames received including
+				   bad frames that were exactly of the mninimal
+				   length (64 bytes) */
+	u32 rx127;		/* Total number of frames (including bad
+				   frames) received that were between MINLength
+				   (Including FCS length==4) and 127 octets */
+	u32 rx255;		/* Total number of frames (including bad
+				   frames) received that were between 128
+				   (Including FCS length==4) and 255 octets */
+	u32 txok;		/* Total number of octets residing in frames
+				   that where involved in succesfull
+				   transmission */
+	u16 txcf;		/* Total number of PAUSE control frames
+				   transmitted by this MAC */
+	u8 res4[0x2];
+	u32 tmca;		/* Total number of frames that were transmitted
+				   succesfully with the group address bit set
+				   that are not broadcast frames */
+	u32 tbca;		/* Total number of frames transmitted
+				   succesfully that had destination address
+				   field equal to the broadcast address */
+	u32 rxfok;		/* Total number of frames received OK */
+	u32 rxbok;		/* Total number of octets received OK */
+	u32 rbyt;		/* Total number of octets received including
+				   octets in bad frames. Must be implemented in
+				   HW because it includes octets in frames that
+				   never even reach the UCC */
+	u32 rmca;		/* Total number of frames that were received
+				   succesfully with the group address bit set
+				   that are not broadcast frames */
+	u32 rbca;		/* Total number of frames received succesfully
+				   that had destination address equal to the
+				   broadcast address */
+	u32 scar;		/* Statistics carry register */
+	u32 scam;		/* Statistics caryy mask register */
+	u8 res5[0x200 - 0x1c4];
+} __attribute__ ((packed)) ucc_geth_t;
+
+/* UCC GETH TEMODR Register */
+#define TEMODER_TX_RMON_STATISTICS_ENABLE       0x0100	/* enable Tx statistics
+							 */
+#define TEMODER_SCHEDULER_ENABLE                0x2000	/* enable scheduler */
+#define TEMODER_IP_CHECKSUM_GENERATE            0x0400	/* generate IPv4
+							   checksums */
+#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1  0x0200	/* enable performance
+							   optimization
+							   enhancement (mode1) */
+#define TEMODER_RMON_STATISTICS                 0x0100	/* enable tx statistics
+							 */
+#define TEMODER_NUM_OF_QUEUES_SHIFT             (15-15)	/* Number of queues <<
+							   shift */
+
+/* UCC GETH TEMODR Register */
+#define REMODER_RX_RMON_STATISTICS_ENABLE       0x00001000	/* enable Rx
+								   statistics */
+#define REMODER_RX_EXTENDED_FEATURES            0x80000000	/* enable
+								   extended
+								   features */
+#define REMODER_VLAN_OPERATION_TAGGED_SHIFT     (31-9 )	/* vlan operation
+							   tagged << shift */
+#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10)	/* vlan operation non
+							   tagged << shift */
+#define REMODER_RX_QOS_MODE_SHIFT               (31-15)	/* rx QoS mode << shift
+							 */
+#define REMODER_RMON_STATISTICS                 0x00001000	/* enable rx
+								   statistics */
+#define REMODER_RX_EXTENDED_FILTERING           0x00000800	/* extended
+								   filtering
+								   vs.
+								   mpc82xx-like
+								   filtering */
+#define REMODER_NUM_OF_QUEUES_SHIFT             (31-23)	/* Number of queues <<
+							   shift */
+#define REMODER_DYNAMIC_MAX_FRAME_LENGTH        0x00000008	/* enable
+								   dynamic max
+								   frame length
+								 */
+#define REMODER_DYNAMIC_MIN_FRAME_LENGTH        0x00000004	/* enable
+								   dynamic min
+								   frame length
+								 */
+#define REMODER_IP_CHECKSUM_CHECK               0x00000002	/* check IPv4
+								   checksums */
+#define REMODER_IP_ADDRESS_ALIGNMENT            0x00000001	/* align ip
+								   address to
+								   4-byte
+								   boundary */
+
+/* UCC GETH Event Register */
+#define UCCE_MPD                                0x80000000	/* Magic packet
+								   detection */
+#define UCCE_SCAR                               0x40000000
+#define UCCE_GRA                                0x20000000	/* Tx graceful
+								   stop
+								   complete */
+#define UCCE_CBPR                               0x10000000
+#define UCCE_BSY                                0x08000000
+#define UCCE_RXC                                0x04000000
+#define UCCE_TXC                                0x02000000
+#define UCCE_TXE                                0x01000000
+#define UCCE_TXB7                               0x00800000
+#define UCCE_TXB6                               0x00400000
+#define UCCE_TXB5                               0x00200000
+#define UCCE_TXB4                               0x00100000
+#define UCCE_TXB3                               0x00080000
+#define UCCE_TXB2                               0x00040000
+#define UCCE_TXB1                               0x00020000
+#define UCCE_TXB0                               0x00010000
+#define UCCE_RXB7                               0x00008000
+#define UCCE_RXB6                               0x00004000
+#define UCCE_RXB5                               0x00002000
+#define UCCE_RXB4                               0x00001000
+#define UCCE_RXB3                               0x00000800
+#define UCCE_RXB2                               0x00000400
+#define UCCE_RXB1                               0x00000200
+#define UCCE_RXB0                               0x00000100
+#define UCCE_RXF7                               0x00000080
+#define UCCE_RXF6                               0x00000040
+#define UCCE_RXF5                               0x00000020
+#define UCCE_RXF4                               0x00000010
+#define UCCE_RXF3                               0x00000008
+#define UCCE_RXF2                               0x00000004
+#define UCCE_RXF1                               0x00000002
+#define UCCE_RXF0                               0x00000001
+
+#define UCCE_RXBF_SINGLE_MASK                   (UCCE_RXF0)
+#define UCCE_TXBF_SINGLE_MASK                   (UCCE_TXB0)
+
+#define UCCE_TXB         (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\
+			UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0)
+#define UCCE_RXB         (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\
+			UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0)
+#define UCCE_RXF         (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\
+			UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0)
+#define UCCE_OTHER       (UCCE_SCAR | UCCE_GRA  | UCCE_CBPR | UCCE_BSY  |\
+			UCCE_RXC  | UCCE_TXC  | UCCE_TXE)
+
+/* UCC GETH UPSMR (Protocol Specific Mode Register) */
+#define UPSMR_ECM                               0x04000000	/* Enable CAM
+								   Miss or
+								   Enable
+								   Filtering
+								   Miss */
+#define UPSMR_HSE                               0x02000000	/* Hardware
+								   Statistics
+								   Enable */
+#define UPSMR_PRO                               0x00400000	/* Promiscuous*/
+#define UPSMR_CAP                               0x00200000	/* CAM polarity
+								 */
+#define UPSMR_RSH                               0x00100000	/* Receive
+								   Short Frames
+								 */
+#define UPSMR_RPM                               0x00080000	/* Reduced Pin
+								   Mode
+								   interfaces */
+#define UPSMR_R10M                              0x00040000	/* RGMII/RMII
+								   10 Mode */
+#define UPSMR_RLPB                              0x00020000	/* RMII
+								   Loopback
+								   Mode */
+#define UPSMR_TBIM                              0x00010000	/* Ten-bit
+								   Interface
+								   Mode */
+#define UPSMR_RMM                               0x00001000	/* RMII/RGMII
+								   Mode */
+#define UPSMR_CAM                               0x00000400	/* CAM Address
+								   Matching */
+#define UPSMR_BRO                               0x00000200	/* Broadcast
+								   Address */
+#define UPSMR_RES1                              0x00002000	/* Reserved
+								   feild - must
+								   be 1 */
+
+/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */
+#define MACCFG1_FLOW_RX                         0x00000020	/* Flow Control
+								   Rx */
+#define MACCFG1_FLOW_TX                         0x00000010	/* Flow Control
+								   Tx */
+#define MACCFG1_ENABLE_SYNCHED_RX               0x00000008	/* Rx Enable
+								   synchronized
+								   to Rx stream
+								 */
+#define MACCFG1_ENABLE_RX                       0x00000004	/* Enable Rx */
+#define MACCFG1_ENABLE_SYNCHED_TX               0x00000002	/* Tx Enable
+								   synchronized
+								   to Tx stream
+								 */
+#define MACCFG1_ENABLE_TX                       0x00000001	/* Enable Tx */
+
+/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */
+#define MACCFG2_PREL_SHIFT                      (31 - 19)	/* Preamble
+								   Length <<
+								   shift */
+#define MACCFG2_PREL_MASK                       0x0000f000	/* Preamble
+								   Length mask */
+#define MACCFG2_SRP                             0x00000080	/* Soft Receive
+								   Preamble */
+#define MACCFG2_STP                             0x00000040	/* Soft
+								   Transmit
+								   Preamble */
+#define MACCFG2_RESERVED_1                      0x00000020	/* Reserved -
+								   must be set
+								   to 1 */
+#define MACCFG2_LC                              0x00000010	/* Length Check
+								 */
+#define MACCFG2_MPE                             0x00000008	/* Magic packet
+								   detect */
+#define MACCFG2_FDX                             0x00000001	/* Full Duplex */
+#define MACCFG2_FDX_MASK                        0x00000001	/* Full Duplex
+								   mask */
+#define MACCFG2_PAD_CRC                         0x00000004
+#define MACCFG2_CRC_EN                          0x00000002
+#define MACCFG2_PAD_AND_CRC_MODE_NONE           0x00000000	/* Neither
+								   Padding
+								   short frames
+								   nor CRC */
+#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY       0x00000002	/* Append CRC
+								   only */
+#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC    0x00000004
+#define MACCFG2_INTERFACE_MODE_NIBBLE           0x00000100	/* nibble mode
+								   (MII/RMII/RGMII
+								   10/100bps) */
+#define MACCFG2_INTERFACE_MODE_BYTE             0x00000200	/* byte mode
+								   (GMII/TBI/RTB/RGMII
+								   1000bps ) */
+#define MACCFG2_INTERFACE_MODE_MASK             0x00000300	/* mask
+								   covering all
+								   relevant
+								   bits */
+
+/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 -  7)	/* Non
+								   back-to-back
+								   inter frame
+								   gap part 1.
+								   << shift */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15)	/* Non
+								   back-to-back
+								   inter frame
+								   gap part 2.
+								   << shift */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT    (31 - 23)	/* Mimimum IFG
+								   Enforcement
+								   << shift */
+#define IPGIFG_BACK_TO_BACK_IFG_SHIFT           (31 - 31)	/* back-to-back
+								   inter frame
+								   gap << shift
+								 */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX   127	/* Non back-to-back
+							   inter frame gap part
+							   1. max val */
+#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX   127	/* Non back-to-back
+							   inter frame gap part
+							   2. max val */
+#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX      255	/* Mimimum IFG
+							   Enforcement max val */
+#define IPGIFG_BACK_TO_BACK_IFG_MAX             127	/* back-to-back inter
+							   frame gap max val */
+#define IPGIFG_NBTB_CS_IPG_MASK                 0x7F000000
+#define IPGIFG_NBTB_IPG_MASK                    0x007F0000
+#define IPGIFG_MIN_IFG_MASK                     0x0000FF00
+#define IPGIFG_BTB_IPG_MASK                     0x0000007F
+
+/* UCC GETH HAFDUP (Half Duplex Register) */
+#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT        (31 - 11)	/* Alternate
+								   Binary
+								   Exponential
+								   Backoff
+								   Truncation
+								   << shift */
+#define HALFDUP_ALT_BEB_TRUNCATION_MAX          0xf	/* Alternate Binary
+							   Exponential Backoff
+							   Truncation max val */
+#define HALFDUP_ALT_BEB                         0x00080000	/* Alternate
+								   Binary
+								   Exponential
+								   Backoff */
+#define HALFDUP_BACK_PRESSURE_NO_BACKOFF        0x00040000	/* Back
+								   pressure no
+								   backoff */
+#define HALFDUP_NO_BACKOFF                      0x00020000	/* No Backoff */
+#define HALFDUP_EXCESSIVE_DEFER                 0x00010000	/* Excessive
+								   Defer */
+#define HALFDUP_MAX_RETRANSMISSION_SHIFT        (31 - 19)	/* Maximum
+								   Retransmission
+								   << shift */
+#define HALFDUP_MAX_RETRANSMISSION_MAX          0xf	/* Maximum
+							   Retransmission max
+							   val */
+#define HALFDUP_COLLISION_WINDOW_SHIFT          (31 - 31)	/* Collision
+								   Window <<
+								   shift */
+#define HALFDUP_COLLISION_WINDOW_MAX            0x3f	/* Collision Window max
+							   val */
+#define HALFDUP_ALT_BEB_TR_MASK                 0x00F00000
+#define HALFDUP_RETRANS_MASK                    0x0000F000
+#define HALFDUP_COL_WINDOW_MASK                 0x0000003F
+
+/* UCC GETH UCCS (Ethernet Status Register) */
+#define UCCS_BPR                                0x02	/* Back pressure (in
+							   half duplex mode) */
+#define UCCS_PAU                                0x02	/* Pause state (in full
+							   duplex mode) */
+#define UCCS_MPD                                0x01	/* Magic Packet
+							   Detected */
+
+/* UCC GETH MIIMCFG (MII Management Configuration Register) */
+#define MIIMCFG_RESET_MANAGEMENT                0x80000000	/* Reset
+								   management */
+#define MIIMCFG_NO_PREAMBLE                     0x00000010	/* Preamble
+								   suppress */
+#define MIIMCFG_CLOCK_DIVIDE_SHIFT              (31 - 31)	/* clock divide
+								   << shift */
+#define MIIMCFG_CLOCK_DIVIDE_MAX                0xf	/* clock divide max val
+							 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2    0x00000000	/* divide by 2 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4    0x00000001	/* divide by 4 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6    0x00000002	/* divide by 6 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8    0x00000003	/* divide by 8 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10   0x00000004	/* divide by 10
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14   0x00000005	/* divide by 14
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16   0x00000008	/* divide by 16
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20   0x00000006	/* divide by 20
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28   0x00000007	/* divide by 28
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32   0x00000009	/* divide by 32
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48   0x0000000a	/* divide by 48
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64   0x0000000b	/* divide by 64
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80   0x0000000c	/* divide by 80
+								 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112  0x0000000d	/* divide by
+								   112 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160  0x0000000e	/* divide by
+								   160 */
+#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224  0x0000000f	/* divide by
+								   224 */
+
+/* UCC GETH MIIMCOM (MII Management Command Register) */
+#define MIIMCOM_SCAN_CYCLE                      0x00000002	/* Scan cycle */
+#define MIIMCOM_READ_CYCLE                      0x00000001	/* Read cycle */
+
+/* UCC GETH MIIMADD (MII Management Address Register) */
+#define MIIMADD_PHY_ADDRESS_SHIFT               (31 - 23)	/* PHY Address
+								   << shift */
+#define MIIMADD_PHY_REGISTER_SHIFT              (31 - 31)	/* PHY Register
+								   << shift */
+
+/* UCC GETH MIIMCON (MII Management Control Register) */
+#define MIIMCON_PHY_CONTROL_SHIFT               (31 - 31)	/* PHY Control
+								   << shift */
+#define MIIMCON_PHY_STATUS_SHIFT                (31 - 31)	/* PHY Status
+								   << shift */
+
+/* UCC GETH MIIMIND (MII Management Indicator Register) */
+#define MIIMIND_NOT_VALID                       0x00000004	/* Not valid */
+#define MIIMIND_SCAN                            0x00000002	/* Scan in
+								   progress */
+#define MIIMIND_BUSY                            0x00000001
+
+/* UCC GETH IFSTAT (Interface Status Register) */
+#define IFSTAT_EXCESS_DEFER                     0x00000200	/* Excessive
+								   transmission
+								   defer */
+
+/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */
+#define MACSTNADDR1_OCTET_6_SHIFT               (31 -  7)	/* Station
+								   address 6th
+								   octet <<
+								   shift */
+#define MACSTNADDR1_OCTET_5_SHIFT               (31 - 15)	/* Station
+								   address 5th
+								   octet <<
+								   shift */
+#define MACSTNADDR1_OCTET_4_SHIFT               (31 - 23)	/* Station
+								   address 4th
+								   octet <<
+								   shift */
+#define MACSTNADDR1_OCTET_3_SHIFT               (31 - 31)	/* Station
+								   address 3rd
+								   octet <<
+								   shift */
+
+/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */
+#define MACSTNADDR2_OCTET_2_SHIFT               (31 -  7)	/* Station
+								   address 2nd
+								   octet <<
+								   shift */
+#define MACSTNADDR2_OCTET_1_SHIFT               (31 - 15)	/* Station
+								   address 1st
+								   octet <<
+								   shift */
+
+/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */
+#define UEMPR_PAUSE_TIME_VALUE_SHIFT            (31 - 15)	/* Pause time
+								   value <<
+								   shift */
+#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT   (31 - 31)	/* Extended
+								   pause time
+								   value <<
+								   shift */
+
+/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */
+#define UTBIPAR_PHY_ADDRESS_SHIFT               (31 - 31)	/* Phy address
+								   << shift */
+#define UTBIPAR_PHY_ADDRESS_MASK                0x0000001f	/* Phy address
+								   mask */
+
+/* UCC GETH UESCR (Ethernet Statistics Control Register) */
+#define UESCR_AUTOZ                             0x8000	/* Automatically zero
+							   addressed
+							   statistical counter
+							   values */
+#define UESCR_CLRCNT                            0x4000	/* Clear all statistics
+							   counters */
+#define UESCR_MAXCOV_SHIFT                      (15 -  7)	/* Max
+								   Coalescing
+								   Value <<
+								   shift */
+#define UESCR_SCOV_SHIFT                        (15 - 15)	/* Status
+								   Coalescing
+								   Value <<
+								   shift */
+
+/* UCC GETH UDSR (Data Synchronization Register) */
+#define UDSR_MAGIC                              0x067E
+
+typedef struct ucc_geth_thread_data_tx {
+	u8 res0[104];
+} __attribute__ ((packed)) ucc_geth_thread_data_tx_t;
+
+typedef struct ucc_geth_thread_data_rx {
+	u8 res0[40];
+} __attribute__ ((packed)) ucc_geth_thread_data_rx_t;
+
+/* Send Queue Queue-Descriptor */
+typedef struct ucc_geth_send_queue_qd {
+	u32 bd_ring_base;	/* pointer to BD ring base address */
+	u8 res0[0x8];
+	u32 last_bd_completed_address;/* initialize to last entry in BD ring */
+	u8 res1[0x30];
+} __attribute__ ((packed)) ucc_geth_send_queue_qd_t;
+
+typedef struct ucc_geth_send_queue_mem_region {
+	ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES];
+} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t;
+
+typedef struct ucc_geth_thread_tx_pram {
+	u8 res0[64];
+} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t;
+
+typedef struct ucc_geth_thread_rx_pram {
+	u8 res0[128];
+} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t;
+
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING        64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8      64
+#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16     96
+
+typedef struct ucc_geth_scheduler {
+	u16 cpucount0;		/* CPU packet counter */
+	u16 cpucount1;		/* CPU packet counter */
+	u16 cecount0;		/* QE packet counter */
+	u16 cecount1;		/* QE packet counter */
+	u16 cpucount2;		/* CPU packet counter */
+	u16 cpucount3;		/* CPU packet counter */
+	u16 cecount2;		/* QE packet counter */
+	u16 cecount3;		/* QE packet counter */
+	u16 cpucount4;		/* CPU packet counter */
+	u16 cpucount5;		/* CPU packet counter */
+	u16 cecount4;		/* QE packet counter */
+	u16 cecount5;		/* QE packet counter */
+	u16 cpucount6;		/* CPU packet counter */
+	u16 cpucount7;		/* CPU packet counter */
+	u16 cecount6;		/* QE packet counter */
+	u16 cecount7;		/* QE packet counter */
+	u32 weightstatus[NUM_TX_QUEUES];	/* accumulated weight factor */
+	u32 rtsrshadow;		/* temporary variable handled by QE */
+	u32 time;		/* temporary variable handled by QE */
+	u32 ttl;		/* temporary variable handled by QE */
+	u32 mblinterval;	/* max burst length interval */
+	u16 nortsrbytetime;	/* normalized value of byte time in tsr units */
+	u8 fracsiz;		/* radix 2 log value of denom. of
+				   NorTSRByteTime */
+	u8 res0[1];
+	u8 strictpriorityq;	/* Strict Priority Mask register */
+	u8 txasap;		/* Transmit ASAP register */
+	u8 extrabw;		/* Extra BandWidth register */
+	u8 oldwfqmask;		/* temporary variable handled by QE */
+	u8 weightfactor[NUM_TX_QUEUES];
+				      /**< weight factor for queues   */
+	u32 minw;		/* temporary variable handled by QE */
+	u8 res1[0x70 - 0x64];
+} __attribute__ ((packed)) ucc_geth_scheduler_t;
+
+typedef struct ucc_geth_tx_firmware_statistics_pram {
+	u32 sicoltx;		/* single collision */
+	u32 mulcoltx;		/* multiple collision */
+	u32 latecoltxfr;	/* late collision */
+	u32 frabortduecol;	/* frames aborted due to transmit collision */
+	u32 frlostinmactxer;	/* frames lost due to internal MAC error
+				   transmission that are not counted on any
+				   other counter */
+	u32 carriersenseertx;	/* carrier sense error */
+	u32 frtxok;		/* frames transmitted OK */
+	u32 txfrexcessivedefer;	/* frames with defferal time greater than
+				   specified threshold */
+	u32 txpkts256;		/* total packets (including bad) between 256
+				   and 511 octets */
+	u32 txpkts512;		/* total packets (including bad) between 512
+				   and 1023 octets */
+	u32 txpkts1024;		/* total packets (including bad) between 1024
+				   and 1518 octets */
+	u32 txpktsjumbo;	/* total packets (including bad) between 1024
+				   and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_firmware_statistics_pram {
+	u32 frrxfcser;		/* frames with crc error */
+	u32 fraligner;		/* frames with alignment error */
+	u32 inrangelenrxer;	/* in range length error */
+	u32 outrangelenrxer;	/* out of range length error */
+	u32 frtoolong;		/* frame too long */
+	u32 runt;		/* runt */
+	u32 verylongevent;	/* very long event */
+	u32 symbolerror;	/* symbol error */
+	u32 dropbsy;		/* drop because of BD not ready */
+	u8 res0[0x8];
+	u32 mismatchdrop;	/* drop because of MAC filtering (e.g. address
+				   or type mismatch) */
+	u32 underpkts;		/* total frames less than 64 octets */
+	u32 pkts256;		/* total frames (including bad) between 256 and
+				   511 octets */
+	u32 pkts512;		/* total frames (including bad) between 512 and
+				   1023 octets */
+	u32 pkts1024;		/* total frames (including bad) between 1024
+				   and 1518 octets */
+	u32 pktsjumbo;		/* total frames (including bad) between 1024
+				   and MAXLength octets */
+	u32 frlossinmacer;	/* frames lost because of internal MAC error
+				   that is not counted in any other counter */
+	u32 pausefr;		/* pause frames */
+	u8 res1[0x4];
+	u32 removevlan;		/* total frames that had their VLAN tag removed
+				 */
+	u32 replacevlan;	/* total frames that had their VLAN tag
+				   replaced */
+	u32 insertvlan;		/* total frames that had their VLAN tag
+				   inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_entry {
+	u32 interruptcoalescingmaxvalue;	/* interrupt coalescing max
+						   value */
+	u32 interruptcoalescingcounter;	/* interrupt coalescing counter,
+					   initialize to
+					   interruptcoalescingmaxvalue */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t;
+
+typedef struct ucc_geth_rx_interrupt_coalescing_table {
+	ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES];
+				       /**< interrupt coalescing entry */
+} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t;
+
+typedef struct ucc_geth_rx_prefetched_bds {
+	qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS];	/* prefetched bd */
+} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t;
+
+typedef struct ucc_geth_rx_bd_queues_entry {
+	u32 bdbaseptr;		/* BD base pointer */
+	u32 bdptr;		/* BD pointer */
+	u32 externalbdbaseptr;	/* external BD base pointer */
+	u32 externalbdptr;	/* external BD pointer */
+} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t;
+
+typedef struct ucc_geth_tx_global_pram {
+	u16 temoder;
+	u8 res0[0x38 - 0x02];
+	u32 sqptr;		/* a base pointer to send queue memory region */
+	u32 schedulerbasepointer;	/* a base pointer to scheduler memory
+					   region */
+	u32 txrmonbaseptr;	/* base pointer to Tx RMON statistics counter */
+	u32 tstate;		/* tx internal state. High byte contains
+				   function code */
+	u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+	u32 vtagtable[0x8];	/* 8 4-byte VLAN tags */
+	u32 tqptr;		/* a base pointer to the Tx Queues Memory
+				   Region */
+	u8 res2[0x80 - 0x74];
+} __attribute__ ((packed)) ucc_geth_tx_global_pram_t;
+
+/* structure representing Extended Filtering Global Parameters in PRAM */
+typedef struct ucc_geth_exf_global_pram {
+	u32 l2pcdptr;		/* individual address filter, high */
+	u8 res0[0x10 - 0x04];
+} __attribute__ ((packed)) ucc_geth_exf_global_pram_t;
+
+typedef struct ucc_geth_rx_global_pram {
+	u32 remoder;		/* ethernet mode reg. */
+	u32 rqptr;		/* base pointer to the Rx Queues Memory Region*/
+	u32 res0[0x1];
+	u8 res1[0x20 - 0xC];
+	u16 typeorlen;		/* cutoff point less than which, type/len field
+				   is considered length */
+	u8 res2[0x1];
+	u8 rxgstpack;		/* acknowledgement on GRACEFUL STOP RX command*/
+	u32 rxrmonbaseptr;	/* base pointer to Rx RMON statistics counter */
+	u8 res3[0x30 - 0x28];
+	u32 intcoalescingptr;	/* Interrupt coalescing table pointer */
+	u8 res4[0x36 - 0x34];
+	u8 rstate;		/* rx internal state. High byte contains
+				   function code */
+	u8 res5[0x46 - 0x37];
+	u16 mrblr;		/* max receive buffer length reg. */
+	u32 rbdqptr;		/* base pointer to RxBD parameter table
+				   description */
+	u16 mflr;		/* max frame length reg. */
+	u16 minflr;		/* min frame length reg. */
+	u16 maxd1;		/* max dma1 length reg. */
+	u16 maxd2;		/* max dma2 length reg. */
+	u32 ecamptr;		/* external CAM address */
+	u32 l2qt;		/* VLAN priority mapping table. */
+	u32 l3qt[0x8];		/* IP priority mapping table. */
+	u16 vlantype;		/* vlan type */
+	u16 vlantci;		/* default vlan tci */
+	u8 addressfiltering[64];	/* address filtering data structure */
+	u32 exfGlobalParam;	/* base address for extended filtering global
+				   parameters */
+	u8 res6[0x100 - 0xC4];	/* Initialize to zero */
+} __attribute__ ((packed)) ucc_geth_rx_global_pram_t;
+
+#define GRACEFUL_STOP_ACKNOWLEDGE_RX            0x01
+
+/* structure representing InitEnet command */
+typedef struct ucc_geth_init_pram {
+	u8 resinit1;
+	u8 resinit2;
+	u8 resinit3;
+	u8 resinit4;
+	u16 resinit5;
+	u8 res1[0x1];
+	u8 largestexternallookupkeysize;
+	u32 rgftgfrxglobal;
+	u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX];	/* rx threads */
+	u8 res2[0x38 - 0x30];
+	u32 txglobal;		/* tx global */
+	u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX];	/* tx threads */
+	u8 res3[0x1];
+} __attribute__ ((packed)) ucc_geth_init_pram_t;
+
+#define ENET_INIT_PARAM_RGF_SHIFT               (32 - 4)
+#define ENET_INIT_PARAM_TGF_SHIFT               (32 - 8)
+
+#define ENET_INIT_PARAM_RISC_MASK               0x0000003f
+#define ENET_INIT_PARAM_PTR_MASK                0x00ffffc0
+#define ENET_INIT_PARAM_SNUM_MASK               0xff000000
+#define ENET_INIT_PARAM_SNUM_SHIFT              24
+
+#define ENET_INIT_PARAM_MAGIC_RES_INIT1         0x06
+#define ENET_INIT_PARAM_MAGIC_RES_INIT2         0x30
+#define ENET_INIT_PARAM_MAGIC_RES_INIT3         0xff
+#define ENET_INIT_PARAM_MAGIC_RES_INIT4         0x00
+#define ENET_INIT_PARAM_MAGIC_RES_INIT5         0x0400
+
+/* structure representing 82xx Address Filtering Enet Address in PRAM */
+typedef struct ucc_geth_82xx_enet_address {
+	u8 res1[0x2];
+	u16 h;			/* address (MSB) */
+	u16 m;			/* address */
+	u16 l;			/* address (LSB) */
+} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t;
+
+/* structure representing 82xx Address Filtering PRAM */
+typedef struct ucc_geth_82xx_address_filtering_pram {
+	u32 iaddr_h;		/* individual address filter, high */
+	u32 iaddr_l;		/* individual address filter, low */
+	u32 gaddr_h;		/* group address filter, high */
+	u32 gaddr_l;		/* group address filter, low */
+	ucc_geth_82xx_enet_address_t taddr;
+	ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS];
+	u8 res0[0x40 - 0x38];
+} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t;
+
+/* GETH Tx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_tx_firmware_statistics {
+	u32 sicoltx;		/* single collision */
+	u32 mulcoltx;		/* multiple collision */
+	u32 latecoltxfr;	/* late collision */
+	u32 frabortduecol;	/* frames aborted due to transmit collision */
+	u32 frlostinmactxer;	/* frames lost due to internal MAC error
+				   transmission that are not counted on any
+				   other counter */
+	u32 carriersenseertx;	/* carrier sense error */
+	u32 frtxok;		/* frames transmitted OK */
+	u32 txfrexcessivedefer;	/* frames with defferal time greater than
+				   specified threshold */
+	u32 txpkts256;		/* total packets (including bad) between 256
+				   and 511 octets */
+	u32 txpkts512;		/* total packets (including bad) between 512
+				   and 1023 octets */
+	u32 txpkts1024;		/* total packets (including bad) between 1024
+				   and 1518 octets */
+	u32 txpktsjumbo;	/* total packets (including bad) between 1024
+				   and MAXLength octets */
+} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t;
+
+/* GETH Rx firmware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_rx_firmware_statistics {
+	u32 frrxfcser;		/* frames with crc error */
+	u32 fraligner;		/* frames with alignment error */
+	u32 inrangelenrxer;	/* in range length error */
+	u32 outrangelenrxer;	/* out of range length error */
+	u32 frtoolong;		/* frame too long */
+	u32 runt;		/* runt */
+	u32 verylongevent;	/* very long event */
+	u32 symbolerror;	/* symbol error */
+	u32 dropbsy;		/* drop because of BD not ready */
+	u8 res0[0x8];
+	u32 mismatchdrop;	/* drop because of MAC filtering (e.g. address
+				   or type mismatch) */
+	u32 underpkts;		/* total frames less than 64 octets */
+	u32 pkts256;		/* total frames (including bad) between 256 and
+				   511 octets */
+	u32 pkts512;		/* total frames (including bad) between 512 and
+				   1023 octets */
+	u32 pkts1024;		/* total frames (including bad) between 1024
+				   and 1518 octets */
+	u32 pktsjumbo;		/* total frames (including bad) between 1024
+				   and MAXLength octets */
+	u32 frlossinmacer;	/* frames lost because of internal MAC error
+				   that is not counted in any other counter */
+	u32 pausefr;		/* pause frames */
+	u8 res1[0x4];
+	u32 removevlan;		/* total frames that had their VLAN tag removed
+				 */
+	u32 replacevlan;	/* total frames that had their VLAN tag
+				   replaced */
+	u32 insertvlan;		/* total frames that had their VLAN tag
+				   inserted */
+} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t;
+
+/* GETH hardware statistics structure, used when calling
+   UCC_GETH_GetStatistics. */
+typedef struct ucc_geth_hardware_statistics {
+	u32 tx64;		/* Total number of frames (including bad
+				   frames) transmitted that were exactly of the
+				   minimal length (64 for un tagged, 68 for
+				   tagged, or with length exactly equal to the
+				   parameter MINLength */
+	u32 tx127;		/* Total number of frames (including bad
+				   frames) transmitted that were between
+				   MINLength (Including FCS length==4) and 127
+				   octets */
+	u32 tx255;		/* Total number of frames (including bad
+				   frames) transmitted that were between 128
+				   (Including FCS length==4) and 255 octets */
+	u32 rx64;		/* Total number of frames received including
+				   bad frames that were exactly of the mninimal
+				   length (64 bytes) */
+	u32 rx127;		/* Total number of frames (including bad
+				   frames) received that were between MINLength
+				   (Including FCS length==4) and 127 octets */
+	u32 rx255;		/* Total number of frames (including bad
+				   frames) received that were between 128
+				   (Including FCS length==4) and 255 octets */
+	u32 txok;		/* Total number of octets residing in frames
+				   that where involved in succesfull
+				   transmission */
+	u16 txcf;		/* Total number of PAUSE control frames
+				   transmitted by this MAC */
+	u32 tmca;		/* Total number of frames that were transmitted
+				   succesfully with the group address bit set
+				   that are not broadcast frames */
+	u32 tbca;		/* Total number of frames transmitted
+				   succesfully that had destination address
+				   field equal to the broadcast address */
+	u32 rxfok;		/* Total number of frames received OK */
+	u32 rxbok;		/* Total number of octets received OK */
+	u32 rbyt;		/* Total number of octets received including
+				   octets in bad frames. Must be implemented in
+				   HW because it includes octets in frames that
+				   never even reach the UCC */
+	u32 rmca;		/* Total number of frames that were received
+				   succesfully with the group address bit set
+				   that are not broadcast frames */
+	u32 rbca;		/* Total number of frames received succesfully
+				   that had destination address equal to the
+				   broadcast address */
+} __attribute__ ((packed)) ucc_geth_hardware_statistics_t;
+
+/* UCC GETH Tx errors returned via TxConf callback */
+#define TX_ERRORS_DEF      0x0200
+#define TX_ERRORS_EXDEF    0x0100
+#define TX_ERRORS_LC       0x0080
+#define TX_ERRORS_RL       0x0040
+#define TX_ERRORS_RC_MASK  0x003C
+#define TX_ERRORS_RC_SHIFT 2
+#define TX_ERRORS_UN       0x0002
+#define TX_ERRORS_CSL      0x0001
+
+/* UCC GETH Rx errors returned via RxStore callback */
+#define RX_ERRORS_CMR      0x0200
+#define RX_ERRORS_M        0x0100
+#define RX_ERRORS_BC       0x0080
+#define RX_ERRORS_MC       0x0040
+
+/* Transmit BD. These are in addition to values defined in uccf. */
+#define T_VID      0x003c0000	/* insert VLAN id index mask. */
+#define T_DEF      (((u32) TX_ERRORS_DEF     ) << 16)
+#define T_EXDEF    (((u32) TX_ERRORS_EXDEF   ) << 16)
+#define T_LC       (((u32) TX_ERRORS_LC      ) << 16)
+#define T_RL       (((u32) TX_ERRORS_RL      ) << 16)
+#define T_RC_MASK  (((u32) TX_ERRORS_RC_MASK ) << 16)
+#define T_UN       (((u32) TX_ERRORS_UN      ) << 16)
+#define T_CSL      (((u32) TX_ERRORS_CSL     ) << 16)
+#define T_ERRORS_REPORT  (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \
+		| T_UN | T_CSL)	/* transmit errors to report */
+
+/* Receive BD. These are in addition to values defined in uccf. */
+#define R_LG    0x00200000	/* Frame length violation.  */
+#define R_NO    0x00100000	/* Non-octet aligned frame.  */
+#define R_SH    0x00080000	/* Short frame.  */
+#define R_CR    0x00040000	/* CRC error.  */
+#define R_OV    0x00020000	/* Overrun.  */
+#define R_IPCH  0x00010000	/* IP checksum check failed. */
+#define R_CMR   (((u32) RX_ERRORS_CMR  ) << 16)
+#define R_M     (((u32) RX_ERRORS_M    ) << 16)
+#define R_BC    (((u32) RX_ERRORS_BC   ) << 16)
+#define R_MC    (((u32) RX_ERRORS_MC   ) << 16)
+#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC)	/* receive errors to
+							   report */
+#define R_ERRORS_FATAL  (R_LG  | R_NO | R_SH | R_CR | \
+		R_OV | R_IPCH)	/* receive errors to discard */
+
+/* Alignments */
+#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT	256
+#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT       128
+#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT       64
+#define UCC_GETH_THREAD_DATA_ALIGNMENT          256	/* spec gives values
+							   based on num of
+							   threads, but always
+							   using the maximum is
+							   easier */
+#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT	32
+#define UCC_GETH_SCHEDULER_ALIGNMENT		4	/* This is a guess */
+#define UCC_GETH_TX_STATISTICS_ALIGNMENT	4	/* This is a guess */
+#define UCC_GETH_RX_STATISTICS_ALIGNMENT	4	/* This is a guess */
+#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT	4	/* This is a
+								   guess */
+#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT		8	/* This is a guess */
+#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT	128	/* This is a guess */
+#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 4	/* This
+									   is a
+									   guess
+									 */
+#define UCC_GETH_RX_BD_RING_ALIGNMENT		32
+#define UCC_GETH_TX_BD_RING_ALIGNMENT		32
+#define UCC_GETH_MRBLR_ALIGNMENT		128
+#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT	4
+#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT	32
+#define UCC_GETH_RX_DATA_BUF_ALIGNMENT		64
+
+#define UCC_GETH_TAD_EF                         0x80
+#define UCC_GETH_TAD_V                          0x40
+#define UCC_GETH_TAD_REJ                        0x20
+#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT        2
+#define UCC_GETH_TAD_VTAG_OP_SHIFT              6
+#define UCC_GETH_TAD_V_NON_VTAG_OP              0x20
+#define UCC_GETH_TAD_RQOS_SHIFT                 0
+#define UCC_GETH_TAD_V_PRIORITY_SHIFT           5
+#define UCC_GETH_TAD_CFI                        0x10
+
+#define UCC_GETH_VLAN_PRIORITY_MAX              8
+#define UCC_GETH_IP_PRIORITY_MAX                64
+#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX        8
+#define UCC_GETH_RX_BD_RING_SIZE_MIN            8
+#define UCC_GETH_TX_BD_RING_SIZE_MIN            2
+
+#define UCC_GETH_SIZE_OF_BD                     QE_SIZEOF_BD
+
+/* Driver definitions */
+#define TX_BD_RING_LEN                          0x10
+#define RX_BD_RING_LEN                          0x10
+#define UCC_GETH_DEV_WEIGHT                     TX_BD_RING_LEN
+
+#define TX_RING_MOD_MASK(size)                  (size-1)
+#define RX_RING_MOD_MASK(size)                  (size-1)
+
+#define ENET_NUM_OCTETS_PER_ADDRESS             6
+#define ENET_GROUP_ADDR                         0x01	/* Group address mask
+							   for ethernet
+							   addresses */
+
+#define TX_TIMEOUT                              (1*HZ)
+#define SKB_ALLOC_TIMEOUT                       100000
+#define PHY_INIT_TIMEOUT                        100000
+#define PHY_CHANGE_TIME                         2
+
+/* Fast Ethernet (10/100 Mbps) */
+#define UCC_GETH_URFS_INIT                      512	/* Rx virtual FIFO size
+							 */
+#define UCC_GETH_URFET_INIT                     256	/* 1/2 urfs */
+#define UCC_GETH_URFSET_INIT                    384	/* 3/4 urfs */
+#define UCC_GETH_UTFS_INIT                      512	/* Tx virtual FIFO size
+							 */
+#define UCC_GETH_UTFET_INIT                     256	/* 1/2 utfs */
+#define UCC_GETH_UTFTT_INIT                     128
+/* Gigabit Ethernet (1000 Mbps) */
+#define UCC_GETH_URFS_GIGA_INIT                 4096/*2048*/	/* Rx virtual
+								   FIFO size */
+#define UCC_GETH_URFET_GIGA_INIT                2048/*1024*/	/* 1/2 urfs */
+#define UCC_GETH_URFSET_GIGA_INIT               3072/*1536*/	/* 3/4 urfs */
+#define UCC_GETH_UTFS_GIGA_INIT                 8192/*2048*/	/* Tx virtual
+								   FIFO size */
+#define UCC_GETH_UTFET_GIGA_INIT                4096/*1024*/	/* 1/2 utfs */
+#define UCC_GETH_UTFTT_GIGA_INIT                0x400/*0x40*/	/* */
+
+#define UCC_GETH_REMODER_INIT                   0	/* bits that must be
+							   set */
+#define UCC_GETH_TEMODER_INIT                   0xC000	/* bits that must */
+#define UCC_GETH_UPSMR_INIT                     (UPSMR_RES1)	/* Start value
+								   for this
+								   register */
+#define UCC_GETH_MACCFG1_INIT                   0
+#define UCC_GETH_MACCFG2_INIT                   (MACCFG2_RESERVED_1)
+#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT    \
+				(MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112)
+
+/* Ethernet speed */
+typedef enum enet_speed {
+	ENET_SPEED_10BT,	/* 10 Base T */
+	ENET_SPEED_100BT,	/* 100 Base T */
+	ENET_SPEED_1000BT	/* 1000 Base T */
+} enet_speed_e;
+
+/* Ethernet Address Type. */
+typedef enum enet_addr_type {
+	ENET_ADDR_TYPE_INDIVIDUAL,
+	ENET_ADDR_TYPE_GROUP,
+	ENET_ADDR_TYPE_BROADCAST
+} enet_addr_type_e;
+
+/* TBI / MII Set Register */
+typedef enum enet_tbi_mii_reg {
+	ENET_TBI_MII_CR = 0x00,	/* Control (CR ) */
+	ENET_TBI_MII_SR = 0x01,	/* Status (SR ) */
+	ENET_TBI_MII_ANA = 0x04,	/* AN advertisement (ANA ) */
+	ENET_TBI_MII_ANLPBPA = 0x05,	/* AN link partner base page ability
+					   (ANLPBPA) */
+	ENET_TBI_MII_ANEX = 0x06,	/* AN expansion (ANEX ) */
+	ENET_TBI_MII_ANNPT = 0x07,	/* AN next page transmit (ANNPT ) */
+	ENET_TBI_MII_ANLPANP = 0x08,	/* AN link partner ability next page
+					   (ANLPANP) */
+	ENET_TBI_MII_EXST = 0x0F,	/* Extended status (EXST ) */
+	ENET_TBI_MII_JD = 0x10,	/* Jitter diagnostics (JD ) */
+	ENET_TBI_MII_TBICON = 0x11	/* TBI control (TBICON ) */
+} enet_tbi_mii_reg_e;
+
+/* UCC GETH 82xx Ethernet Address Recognition Location */
+typedef enum ucc_geth_enet_address_recognition_location {
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station
+								      address */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST,	/* additional
+								   station
+								   address
+								   paddr1 */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2,	/* additional
+								   station
+								   address
+								   paddr2 */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3,	/* additional
+								   station
+								   address
+								   paddr3 */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST,	/* additional
+								   station
+								   address
+								   paddr4 */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH,	/* group hash */
+	UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual
+								      hash */
+} ucc_geth_enet_address_recognition_location_e;
+
+/* UCC GETH vlan operation tagged */
+typedef enum ucc_geth_vlan_operation_tagged {
+	UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0,	/* Tagged - nop */
+	UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG
+		= 0x1,	/* Tagged - replace vid portion of q tag */
+	UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE
+		= 0x2,	/* Tagged - if vid0 replace vid with default value  */
+	UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME
+		= 0x3	/* Tagged - extract q tag from frame */
+} ucc_geth_vlan_operation_tagged_e;
+
+/* UCC GETH vlan operation non-tagged */
+typedef enum ucc_geth_vlan_operation_non_tagged {
+	UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0,	/* Non tagged - nop */
+	UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1	/* Non tagged -
+								   q tag insert
+								 */
+} ucc_geth_vlan_operation_non_tagged_e;
+
+/* UCC GETH Rx Quality of Service Mode */
+typedef enum ucc_geth_qos_mode {
+	UCC_GETH_QOS_MODE_DEFAULT = 0x0,	/* default queue */
+	UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1,	/* queue
+								   determined
+								   by L2
+								   criteria */
+	UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2	/* queue
+								   determined
+								   by L3
+								   criteria */
+} ucc_geth_qos_mode_e;
+
+/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together
+   for combined functionality */
+typedef enum ucc_geth_statistics_gathering_mode {
+	UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000,	/* No
+								   statistics
+								   gathering */
+	UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable
+								    hardware
+								    statistics
+								    gathering
+								  */
+	UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable
+								      firmware
+								      tx
+								      statistics
+								      gathering
+								     */
+	UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable
+								      firmware
+								      rx
+								      statistics
+								      gathering
+								    */
+} ucc_geth_statistics_gathering_mode_e;
+
+/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */
+typedef enum ucc_geth_maccfg2_pad_and_crc_mode {
+	UCC_GETH_PAD_AND_CRC_MODE_NONE
+		= MACCFG2_PAD_AND_CRC_MODE_NONE,	/* Neither Padding
+							   short frames
+							   nor CRC */
+	UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY
+		= MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY,	/* Append
+							   CRC only */
+	UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC =
+	    MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC
+} ucc_geth_maccfg2_pad_and_crc_mode_e;
+
+/* UCC GETH upsmr Flow Control Mode */
+typedef enum ucc_geth_flow_control_mode {
+	UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000,	/* No automatic
+								   flow control
+								 */
+	UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY
+		= 0x00004000	/* Send pause frame when RxFIFO reaches its
+				   emergency threshold */
+} ucc_geth_flow_control_mode_e;
+
+/* UCC GETH number of threads */
+typedef enum ucc_geth_num_of_threads {
+	UCC_GETH_NUM_OF_THREADS_1 = 0x1,	/* 1 */
+	UCC_GETH_NUM_OF_THREADS_2 = 0x2,	/* 2 */
+	UCC_GETH_NUM_OF_THREADS_4 = 0x0,	/* 4 */
+	UCC_GETH_NUM_OF_THREADS_6 = 0x3,	/* 6 */
+	UCC_GETH_NUM_OF_THREADS_8 = 0x4	/* 8 */
+} ucc_geth_num_of_threads_e;
+
+/* UCC GETH number of station addresses */
+typedef enum ucc_geth_num_of_station_addresses {
+	UCC_GETH_NUM_OF_STATION_ADDRESSES_1,	/* 1 */
+	UCC_GETH_NUM_OF_STATION_ADDRESSES_5	/* 5 */
+} ucc_geth_num_of_station_addresses_e;
+
+typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/* UCC GETH 82xx Ethernet Address Container */
+typedef struct enet_addr_container {
+	enet_addr_t address;	/* ethernet address */
+	ucc_geth_enet_address_recognition_location_e location;	/* location in
+								   82xx address
+								   recognition
+								   hardware */
+	struct list_head node;
+} enet_addr_container_t;
+
+#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node)
+
+/* UCC GETH Termination Action Descriptor (TAD) structure. */
+typedef struct ucc_geth_tad_params {
+	int rx_non_dynamic_extended_features_mode;
+	int reject_frame;
+	ucc_geth_vlan_operation_tagged_e vtag_op;
+	ucc_geth_vlan_operation_non_tagged_e vnontag_op;
+	ucc_geth_qos_mode_e rqos;
+	u8 vpri;
+	u16 vid;
+} ucc_geth_tad_params_t;
+
+/* GETH protocol initialization structure */
+typedef struct ucc_geth_info {
+	ucc_fast_info_t uf_info;
+	u8 numQueuesTx;
+	u8 numQueuesRx;
+	int ipCheckSumCheck;
+	int ipCheckSumGenerate;
+	int rxExtendedFiltering;
+	u32 extendedFilteringChainPointer;
+	u16 typeorlen;
+	int dynamicMaxFrameLength;
+	int dynamicMinFrameLength;
+	u8 nonBackToBackIfgPart1;
+	u8 nonBackToBackIfgPart2;
+	u8 miminumInterFrameGapEnforcement;
+	u8 backToBackInterFrameGap;
+	int ipAddressAlignment;
+	int lengthCheckRx;
+	u32 mblinterval;
+	u16 nortsrbytetime;
+	u8 fracsiz;
+	u8 strictpriorityq;
+	u8 txasap;
+	u8 extrabw;
+	int miiPreambleSupress;
+	u8 altBebTruncation;
+	int altBeb;
+	int backPressureNoBackoff;
+	int noBackoff;
+	int excessDefer;
+	u8 maxRetransmission;
+	u8 collisionWindow;
+	int pro;
+	int cap;
+	int rsh;
+	int rlpb;
+	int cam;
+	int bro;
+	int ecm;
+	int receiveFlowControl;
+	u8 maxGroupAddrInHash;
+	u8 maxIndAddrInHash;
+	u8 prel;
+	u16 maxFrameLength;
+	u16 minFrameLength;
+	u16 maxD1Length;
+	u16 maxD2Length;
+	u16 vlantype;
+	u16 vlantci;
+	u32 ecamptr;
+	u32 eventRegMask;
+	u16 pausePeriod;
+	u16 extensionField;
+	u8 phy_address;
+	u32 board_flags;
+	u32 phy_interrupt;
+	u8 weightfactor[NUM_TX_QUEUES];
+	u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
+	u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX];
+	u8 l3qt[UCC_GETH_IP_PRIORITY_MAX];
+	u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX];
+	u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX];
+	u16 bdRingLenTx[NUM_TX_QUEUES];
+	u16 bdRingLenRx[NUM_RX_QUEUES];
+	enet_interface_e enet_interface;
+	ucc_geth_num_of_station_addresses_e numStationAddresses;
+	 qe_fltr_largest_external_tbl_lookup_key_size_e
+	    largestexternallookupkeysize;
+	ucc_geth_statistics_gathering_mode_e statisticsMode;
+	ucc_geth_vlan_operation_tagged_e vlanOperationTagged;
+	ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged;
+	ucc_geth_qos_mode_e rxQoSMode;
+	ucc_geth_flow_control_mode_e aufc;
+	ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc;
+	ucc_geth_num_of_threads_e numThreadsTx;
+	ucc_geth_num_of_threads_e numThreadsRx;
+	qe_risc_allocation_e riscTx;
+	qe_risc_allocation_e riscRx;
+} ucc_geth_info_t;
+
+/* structure representing UCC GETH */
+typedef struct ucc_geth_private {
+	ucc_geth_info_t *ug_info;
+	ucc_fast_private_t *uccf;
+	struct net_device *dev;
+	struct net_device_stats stats;	/* linux network statistics */
+	ucc_geth_t *ug_regs;
+	ucc_geth_init_pram_t *p_init_enet_param_shadow;
+	ucc_geth_exf_global_pram_t *p_exf_glbl_param;
+	u32 exf_glbl_param_offset;
+	ucc_geth_rx_global_pram_t *p_rx_glbl_pram;
+	u32 rx_glbl_pram_offset;
+	ucc_geth_tx_global_pram_t *p_tx_glbl_pram;
+	u32 tx_glbl_pram_offset;
+	ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg;
+	u32 send_q_mem_reg_offset;
+	ucc_geth_thread_data_tx_t *p_thread_data_tx;
+	u32 thread_dat_tx_offset;
+	ucc_geth_thread_data_rx_t *p_thread_data_rx;
+	u32 thread_dat_rx_offset;
+	ucc_geth_scheduler_t *p_scheduler;
+	u32 scheduler_offset;
+	ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
+	u32 tx_fw_statistics_pram_offset;
+	ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
+	u32 rx_fw_statistics_pram_offset;
+	ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl;
+	u32 rx_irq_coalescing_tbl_offset;
+	ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl;
+	u32 rx_bd_qs_tbl_offset;
+	u8 *p_tx_bd_ring[NUM_TX_QUEUES];
+	u32 tx_bd_ring_offset[NUM_TX_QUEUES];
+	u8 *p_rx_bd_ring[NUM_RX_QUEUES];
+	u32 rx_bd_ring_offset[NUM_RX_QUEUES];
+	u8 *confBd[NUM_TX_QUEUES];
+	u8 *txBd[NUM_TX_QUEUES];
+	u8 *rxBd[NUM_RX_QUEUES];
+	int badFrame[NUM_RX_QUEUES];
+	u16 cpucount[NUM_TX_QUEUES];
+	volatile u16 *p_cpucount[NUM_TX_QUEUES];
+	int indAddrRegUsed[NUM_OF_PADDRS];
+	enet_addr_t paddr[NUM_OF_PADDRS];
+	u8 numGroupAddrInHash;
+	u8 numIndAddrInHash;
+	u8 numIndAddrInReg;
+	int rx_extended_features;
+	int rx_non_dynamic_extended_features;
+	struct list_head conf_skbs;
+	struct list_head group_hash_q;
+	struct list_head ind_hash_q;
+	u32 saved_uccm;
+	spinlock_t lock;
+	/* pointers to arrays of skbuffs for tx and rx */
+	struct sk_buff **tx_skbuff[NUM_TX_QUEUES];
+	struct sk_buff **rx_skbuff[NUM_RX_QUEUES];
+	/* indices pointing to the next free sbk in skb arrays */
+	u16 skb_curtx[NUM_TX_QUEUES];
+	u16 skb_currx[NUM_RX_QUEUES];
+	/* index of the first skb which hasn't been transmitted yet. */
+	u16 skb_dirtytx[NUM_TX_QUEUES];
+
+	struct work_struct tq;
+	struct timer_list phy_info_timer;
+	struct ugeth_mii_info *mii_info;
+	int oldspeed;
+	int oldduplex;
+	int oldlink;
+} ucc_geth_private_t;
+
+#endif				/* __UCC_GETH_H__ */
diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c
new file mode 100644
index 0000000..f91028c
--- /dev/null
+++ b/drivers/net/ucc_geth_phy.c
@@ -0,0 +1,801 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "ucc_geth.h"
+#include "ucc_geth_phy.h"
+#include <platforms/83xx/mpc8360e_pb.h>
+
+#define ugphy_printk(level, format, arg...)  \
+        printk(level format "\n", ## arg)
+
+#define ugphy_dbg(format, arg...)            \
+        ugphy_printk(KERN_DEBUG, format , ## arg)
+#define ugphy_err(format, arg...)            \
+        ugphy_printk(KERN_ERR, format , ## arg)
+#define ugphy_info(format, arg...)           \
+        ugphy_printk(KERN_INFO, format , ## arg)
+#define ugphy_warn(format, arg...)           \
+        ugphy_printk(KERN_WARNING, format , ## arg)
+
+#ifdef UGETH_VERBOSE_DEBUG
+#define ugphy_vdbg ugphy_dbg
+#else
+#define ugphy_vdbg(fmt, args...) do { } while (0)
+#endif				/* UGETH_VERBOSE_DEBUG */
+
+static void config_genmii_advert(struct ugeth_mii_info *mii_info);
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info);
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info);
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info);
+static int genmii_update_link(struct ugeth_mii_info *mii_info);
+static int genmii_read_status(struct ugeth_mii_info *mii_info);
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum);
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val);
+
+static u8 *bcsr_regs = NULL;
+
+/* Write value to the PHY for this device to the register at regnum, */
+/* waiting until the write is done before it returns.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	ucc_mii_mng_t *mii_regs;
+	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+	u32 tmp_reg;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irq(&ugeth->lock);
+
+	mii_regs = ugeth->mii_info->mii_regs;
+
+	/* Set this UCC to be the master of the MII managment */
+	ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
+
+	/* Stop the MII management read cycle */
+	out_be32(&mii_regs->miimcom, 0);
+	/* Setting up the MII Mangement Address Register */
+	tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+	out_be32(&mii_regs->miimadd, tmp_reg);
+
+	/* Setting up the MII Mangement Control Register with the value */
+	out_be32(&mii_regs->miimcon, (u32) value);
+
+	/* Wait till MII management write is complete */
+	while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+		cpu_relax();
+
+	spin_unlock_irq(&ugeth->lock);
+
+	udelay(10000);
+}
+
+/* Reads from register regnum in the PHY for device dev, */
+/* returning the value.  Clears miimcom first.  All PHY */
+/* configuration has to be done through the TSEC1 MIIM regs */
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
+{
+	ucc_geth_private_t *ugeth = netdev_priv(dev);
+	ucc_mii_mng_t *mii_regs;
+	enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
+	u32 tmp_reg;
+	u16 value;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irq(&ugeth->lock);
+
+	mii_regs = ugeth->mii_info->mii_regs;
+
+	/* Setting up the MII Mangement Address Register */
+	tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
+	out_be32(&mii_regs->miimadd, tmp_reg);
+
+	/* Perform an MII management read cycle */
+	out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE);
+
+	/* Wait till MII management write is complete */
+	while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY)
+		cpu_relax();
+
+	udelay(10000);
+
+	/* Read MII management status  */
+	value = (u16) in_be32(&mii_regs->miimstat);
+	out_be32(&mii_regs->miimcom, 0);
+	if (value == 0xffff)
+		ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x",
+			   mii_id, mii_reg, (u32) & (mii_regs->miimcfg));
+
+	spin_unlock_irq(&ugeth->lock);
+
+	return (value);
+}
+
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->phyinfo->ack_interrupt)
+		mii_info->phyinfo->ack_interrupt(mii_info);
+}
+
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+				 u32 interrupts)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	mii_info->interrupts = interrupts;
+	if (mii_info->phyinfo->config_intr)
+		mii_info->phyinfo->config_intr(mii_info);
+}
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised
+ */
+static void config_genmii_advert(struct ugeth_mii_info *mii_info)
+{
+	u32 advertise;
+	u16 adv;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Only allow advertising what this PHY supports */
+	mii_info->advertising &= mii_info->phyinfo->features;
+	advertise = mii_info->advertising;
+
+	/* Setup standard advertisement */
+	adv = phy_read(mii_info, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(mii_info, MII_ADVERTISE, adv);
+}
+
+static void genmii_setup_forced(struct ugeth_mii_info *mii_info)
+{
+	u16 ctrl;
+	u32 features = mii_info->phyinfo->features;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	ctrl = phy_read(mii_info, MII_BMCR);
+
+	ctrl &=
+	    ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE);
+	ctrl |= BMCR_RESET;
+
+	switch (mii_info->speed) {
+	case SPEED_1000:
+		if (features & (SUPPORTED_1000baseT_Half
+				| SUPPORTED_1000baseT_Full)) {
+			ctrl |= BMCR_SPEED1000;
+			break;
+		}
+		mii_info->speed = SPEED_100;
+	case SPEED_100:
+		if (features & (SUPPORTED_100baseT_Half
+				| SUPPORTED_100baseT_Full)) {
+			ctrl |= BMCR_SPEED100;
+			break;
+		}
+		mii_info->speed = SPEED_10;
+	case SPEED_10:
+		if (features & (SUPPORTED_10baseT_Half
+				| SUPPORTED_10baseT_Full))
+			break;
+	default:		/* Unsupported speed! */
+		ugphy_err("%s: Bad speed!", mii_info->dev->name);
+		break;
+	}
+
+	phy_write(mii_info, MII_BMCR, ctrl);
+}
+
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct ugeth_mii_info *mii_info)
+{
+	u16 ctl;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	ctl = phy_read(mii_info, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(mii_info, MII_BMCR, ctl);
+}
+
+static int gbit_config_aneg(struct ugeth_mii_info *mii_info)
+{
+	u16 adv;
+	u32 advertise;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->autoneg) {
+		/* Configure the ADVERTISE register */
+		config_genmii_advert(mii_info);
+		advertise = mii_info->advertising;
+
+		adv = phy_read(mii_info, MII_1000BASETCONTROL);
+		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+			 MII_1000BASETCONTROL_HALFDUPLEXCAP);
+		if (advertise & SUPPORTED_1000baseT_Half)
+			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+		if (advertise & SUPPORTED_1000baseT_Full)
+			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+		phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+		/* Start/Restart aneg */
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
+
+	return 0;
+}
+
+static int genmii_config_aneg(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->autoneg) {
+		config_genmii_advert(mii_info);
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
+
+	return 0;
+}
+
+static int genmii_update_link(struct ugeth_mii_info *mii_info)
+{
+	u16 status;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Do a fake read */
+	phy_read(mii_info, MII_BMSR);
+
+	/* Read link and autonegotiation status */
+	status = phy_read(mii_info, MII_BMSR);
+	if ((status & BMSR_LSTATUS) == 0)
+		mii_info->link = 0;
+	else
+		mii_info->link = 1;
+
+	/* If we are autonegotiating, and not done,
+	 * return an error */
+	if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int genmii_read_status(struct ugeth_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	if (mii_info->autoneg) {
+		status = phy_read(mii_info, MII_LPA);
+
+		if (status & (LPA_10FULL | LPA_100FULL))
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+		if (status & (LPA_100FULL | LPA_100HALF))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+		mii_info->pause = 0;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
+
+	return 0;
+}
+
+static int marvell_init(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	phy_write(mii_info, 0x14, 0x0cd2);
+	phy_write(mii_info, MII_BMCR,
+		  phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+	msleep(4000);
+
+	return 0;
+}
+
+static int marvell_config_aneg(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* The Marvell PHY has an errata which requires
+	 * that certain registers get written in order
+	 * to restart autonegotiation */
+	phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+	phy_write(mii_info, 0x1d, 0x1f);
+	phy_write(mii_info, 0x1e, 0x200c);
+	phy_write(mii_info, 0x1d, 0x5);
+	phy_write(mii_info, 0x1e, 0);
+	phy_write(mii_info, 0x1e, 0x100);
+
+	gbit_config_aneg(mii_info);
+
+	return 0;
+}
+
+static int marvell_read_status(struct ugeth_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+		status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
+
+		/* Get the duplexity */
+		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+
+		/* Get the speed */
+		speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+		switch (speed) {
+		case MII_M1011_PHY_SPEC_STATUS_1000:
+			mii_info->speed = SPEED_1000;
+			break;
+		case MII_M1011_PHY_SPEC_STATUS_100:
+			mii_info->speed = SPEED_100;
+			break;
+		default:
+			mii_info->speed = SPEED_10;
+			break;
+		}
+		mii_info->pause = 0;
+	}
+
+	return 0;
+}
+
+static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Clear the interrupts by reading the reg */
+	phy_read(mii_info, MII_M1011_IEVENT);
+
+	return 0;
+}
+
+static int marvell_config_intr(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
+	else
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+	return 0;
+}
+
+static int cis820x_init(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	phy_write(mii_info, MII_CIS8201_AUX_CONSTAT,
+		  MII_CIS8201_AUXCONSTAT_INIT);
+	phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT);
+
+	return 0;
+}
+
+static int cis820x_read_status(struct ugeth_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+
+		status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+		if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+
+		speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
+
+		switch (speed) {
+		case MII_CIS8201_AUXCONSTAT_GBIT:
+			mii_info->speed = SPEED_1000;
+			break;
+		case MII_CIS8201_AUXCONSTAT_100:
+			mii_info->speed = SPEED_100;
+			break;
+		default:
+			mii_info->speed = SPEED_10;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	phy_read(mii_info, MII_CIS8201_ISTAT);
+
+	return 0;
+}
+
+static int cis820x_config_intr(struct ugeth_mii_info *mii_info)
+{
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
+	else
+		phy_write(mii_info, MII_CIS8201_IMASK, 0);
+
+	return 0;
+}
+
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct ugeth_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		status = phy_read(mii_info, MII_DM9161_SCSR);
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+	}
+
+	return 0;
+}
+
+static int dm9161_config_aneg(struct ugeth_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (0 == priv->resetdone)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static void dm9161_timer(unsigned long data)
+{
+	struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data;
+	struct dm9161_private *priv = mii_info->priv;
+	u16 status = phy_read(mii_info, MII_BMSR);
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (status & BMSR_ANEGCOMPLETE) {
+		priv->resetdone = 1;
+	} else
+		mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct ugeth_mii_info *mii_info)
+{
+	struct dm9161_private *priv;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Allocate the private data structure */
+	priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+	if (NULL == priv)
+		return -ENOMEM;
+
+	mii_info->priv = priv;
+
+	/* Reset is not done yet */
+	priv->resetdone = 0;
+
+	phy_write(mii_info, MII_BMCR,
+		  phy_read(mii_info, MII_BMCR) | BMCR_RESET);
+
+	phy_write(mii_info, MII_BMCR,
+		  phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE);
+
+	config_genmii_advert(mii_info);
+	/* Start/Restart aneg */
+	genmii_config_aneg(mii_info);
+
+	/* Start a timer for DM9161_DELAY seconds to wait
+	 * for the PHY to be ready */
+	init_timer(&priv->timer);
+	priv->timer.function = &dm9161_timer;
+	priv->timer.data = (unsigned long)mii_info;
+	mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+
+	return 0;
+}
+
+static void dm9161_close(struct ugeth_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	del_timer_sync(&priv->timer);
+	kfree(priv);
+}
+
+static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+	if (bcsr_regs == NULL)
+		bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+	bcsr_regs[14] |= 0x40;
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Clear the interrupts by reading the reg */
+	phy_read(mii_info, MII_DM9161_INTR);
+
+
+	return 0;
+}
+
+static int dm9161_config_intr(struct ugeth_mii_info *mii_info)
+{
+/* FIXME: This lines are for BUG fixing in the mpc8325.
+Remove this from here when it's fixed */
+	if (bcsr_regs == NULL) {
+		bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+		bcsr_regs[14] &= ~0x40;
+	}
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
+	else
+		phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
+
+	return 0;
+}
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+	.phy_id = 0x000fc440,
+	.name = "Cicada Cis8204",
+	.phy_id_mask = 0x000fffc0,
+	.features = MII_GBIT_FEATURES,
+	.init = &cis820x_init,
+	.config_aneg = &gbit_config_aneg,
+	.read_status = &cis820x_read_status,
+	.ack_interrupt = &cis820x_ack_interrupt,
+	.config_intr = &cis820x_config_intr,
+};
+
+static struct phy_info phy_info_dm9161 = {
+	.phy_id = 0x0181b880,
+	.phy_id_mask = 0x0ffffff0,
+	.name = "Davicom DM9161E",
+	.init = dm9161_init,
+	.config_aneg = dm9161_config_aneg,
+	.read_status = dm9161_read_status,
+	.close = dm9161_close,
+};
+
+static struct phy_info phy_info_dm9161a = {
+	.phy_id = 0x0181b8a0,
+	.phy_id_mask = 0x0ffffff0,
+	.name = "Davicom DM9161A",
+	.features = MII_BASIC_FEATURES,
+	.init = dm9161_init,
+	.config_aneg = dm9161_config_aneg,
+	.read_status = dm9161_read_status,
+	.ack_interrupt = dm9161_ack_interrupt,
+	.config_intr = dm9161_config_intr,
+	.close = dm9161_close,
+};
+
+static struct phy_info phy_info_marvell = {
+	.phy_id = 0x01410c00,
+	.phy_id_mask = 0xffffff00,
+	.name = "Marvell 88E11x1",
+	.features = MII_GBIT_FEATURES,
+	.init = &marvell_init,
+	.config_aneg = &marvell_config_aneg,
+	.read_status = &marvell_read_status,
+	.ack_interrupt = &marvell_ack_interrupt,
+	.config_intr = &marvell_config_intr,
+};
+
+static struct phy_info phy_info_genmii = {
+	.phy_id = 0x00000000,
+	.phy_id_mask = 0x00000000,
+	.name = "Generic MII",
+	.features = MII_BASIC_FEATURES,
+	.config_aneg = genmii_config_aneg,
+	.read_status = genmii_read_status,
+};
+
+static struct phy_info *phy_info[] = {
+	&phy_info_cis820x,
+	&phy_info_marvell,
+	&phy_info_dm9161,
+	&phy_info_dm9161a,
+	&phy_info_genmii,
+	NULL
+};
+
+u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum)
+{
+	u16 retval;
+	unsigned long flags;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+	return retval;
+}
+
+void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val)
+{
+	unsigned long flags;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
+/* Use the PHY ID registers to determine what type of PHY is attached
+ * to device dev.  return a struct phy_info structure describing that PHY
+ */
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info)
+{
+	u16 phy_reg;
+	u32 phy_ID;
+	int i;
+	struct phy_info *theInfo = NULL;
+	struct net_device *dev = mii_info->dev;
+
+	ugphy_vdbg("%s: IN", __FUNCTION__);
+
+	/* Grab the bits from PHYIR1, and put them in the upper half */
+	phy_reg = phy_read(mii_info, MII_PHYSID1);
+	phy_ID = (phy_reg & 0xffff) << 16;
+
+	/* Grab the bits from PHYIR2, and put them in the lower half */
+	phy_reg = phy_read(mii_info, MII_PHYSID2);
+	phy_ID |= (phy_reg & 0xffff);
+
+	/* loop through all the known PHY types, and find one that */
+	/* matches the ID we read from the PHY. */
+	for (i = 0; phy_info[i]; i++)
+		if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){
+			theInfo = phy_info[i];
+			break;
+		}
+
+	/* This shouldn't happen, as we have generic PHY support */
+	if (theInfo == NULL) {
+		ugphy_info("%s: PHY id %x is not supported!", dev->name,
+			   phy_ID);
+		return NULL;
+	} else {
+		ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name,
+			   phy_ID);
+	}
+
+	return theInfo;
+}
diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h
new file mode 100644
index 0000000..2f98b8f
--- /dev/null
+++ b/drivers/net/ucc_geth_phy.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
+ *
+ * Author: Shlomi Gridish <gridish@freescale.com>
+ *
+ * Description:
+ * UCC GETH Driver -- PHY handling
+ *
+ * Changelog:
+ * Jun 28, 2006 Li Yang <LeoLi@freescale.com>
+ * - Rearrange code and style fixes
+ *
+ * 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.
+ *
+ */
+#ifndef __UCC_GETH_PHY_H__
+#define __UCC_GETH_PHY_H__
+
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
+
+#define MIIMIND_BUSY            0x00000001
+#define MIIMIND_NOTVALID        0x00000004
+
+#define UGETH_AN_TIMEOUT        2000
+
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL                  0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP    0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP    0x0100
+
+/* Cicada Extended Control Register 1 */
+#define MII_CIS8201_EXT_CON1        0x17
+#define MII_CIS8201_EXTCON1_INIT    0x0000
+
+/* Cicada Interrupt Mask Register */
+#define MII_CIS8201_IMASK           0x19
+#define MII_CIS8201_IMASK_IEN       0x8000
+#define MII_CIS8201_IMASK_SPEED     0x4000
+#define MII_CIS8201_IMASK_LINK      0x2000
+#define MII_CIS8201_IMASK_DUPLEX    0x1000
+#define MII_CIS8201_IMASK_MASK      0xf000
+
+/* Cicada Interrupt Status Register */
+#define MII_CIS8201_ISTAT           0x1a
+#define MII_CIS8201_ISTAT_STATUS    0x8000
+#define MII_CIS8201_ISTAT_SPEED     0x4000
+#define MII_CIS8201_ISTAT_LINK      0x2000
+#define MII_CIS8201_ISTAT_DUPLEX    0x1000
+
+/* Cicada Auxiliary Control/Status Register */
+#define MII_CIS8201_AUX_CONSTAT        0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MII_CIS8201_AUXCONSTAT_100     0x0008
+
+/* 88E1011 PHY Status Register */
+#define MII_M1011_PHY_SPEC_STATUS               0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000          0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100           0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK      0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX    0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED      0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK          0x0400
+
+#define MII_M1011_IEVENT                0x13
+#define MII_M1011_IEVENT_CLEAR          0x0000
+
+#define MII_M1011_IMASK                 0x12
+#define MII_M1011_IMASK_INIT            0x6400
+#define MII_M1011_IMASK_CLEAR           0x0000
+
+#define MII_DM9161_SCR                  0x10
+#define MII_DM9161_SCR_INIT             0x0610
+
+/* DM9161 Specified Configuration and Status Register */
+#define MII_DM9161_SCSR                 0x11
+#define MII_DM9161_SCSR_100F            0x8000
+#define MII_DM9161_SCSR_100H            0x4000
+#define MII_DM9161_SCSR_10F             0x2000
+#define MII_DM9161_SCSR_10H             0x1000
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR                 0x15
+#define MII_DM9161_INTR_PEND            0x8000
+#define MII_DM9161_INTR_DPLX_MASK       0x0800
+#define MII_DM9161_INTR_SPD_MASK        0x0400
+#define MII_DM9161_INTR_LINK_MASK       0x0200
+#define MII_DM9161_INTR_MASK            0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE     0x0010
+#define MII_DM9161_INTR_SPD_CHANGE      0x0008
+#define MII_DM9161_INTR_LINK_CHANGE     0x0004
+#define MII_DM9161_INTR_INIT            0x0000
+#define MII_DM9161_INTR_STOP    \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR              0x12
+#define MII_DM9161_10BTCSR_INIT         0x7800
+
+#define MII_BASIC_FEATURES    (SUPPORTED_10baseT_Half | \
+                 SUPPORTED_10baseT_Full | \
+                 SUPPORTED_100baseT_Half | \
+                 SUPPORTED_100baseT_Full | \
+                 SUPPORTED_Autoneg | \
+                 SUPPORTED_TP | \
+                 SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES    (MII_BASIC_FEATURES | \
+                 SUPPORTED_1000baseT_Half | \
+                 SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND                0x00000001
+
+#define MII_INTERRUPT_DISABLED          0x0
+#define MII_INTERRUPT_ENABLED           0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct ugeth_mii_info {
+	/* Information about the PHY type */
+	/* And management functions */
+	struct phy_info *phyinfo;
+
+	ucc_mii_mng_t *mii_regs;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int speed;
+	int duplex;
+	int pause;
+
+	/* The most recently read link state */
+	int link;
+
+	/* Enabled Interrupts */
+	u32 interrupts;
+
+	u32 advertising;
+	int autoneg;
+	int mii_id;
+
+	/* private data pointer */
+	/* For use by PHYs to maintain extra state */
+	void *priv;
+
+	/* Provided by host chip */
+	struct net_device *dev;
+
+	/* A lock to ensure that only one thing can read/write
+	 * the MDIO bus at a time */
+	spinlock_t mdio_lock;
+
+	/* Provided by ethernet driver */
+	int (*mdio_read) (struct net_device * dev, int mii_id, int reg);
+	void (*mdio_write) (struct net_device * dev, int mii_id, int reg,
+			    int val);
+};
+
+/* struct phy_info: a structure which defines attributes for a PHY
+ *
+ * id will contain a number which represents the PHY.  During
+ * startup, the driver will poll the PHY to find out what its
+ * UID--as defined by registers 2 and 3--is.  The 32-bit result
+ * gotten from the PHY will be ANDed with phy_id_mask to
+ * discard any bits which may change based on revision numbers
+ * unimportant to functionality
+ *
+ * There are 6 commands which take a ugeth_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
+ */
+struct phy_info {
+	u32 phy_id;
+	char *name;
+	unsigned int phy_id_mask;
+	u32 features;
+
+	/* Called to initialize the PHY */
+	int (*init) (struct ugeth_mii_info * mii_info);
+
+	/* Called to suspend the PHY for power */
+	int (*suspend) (struct ugeth_mii_info * mii_info);
+
+	/* Reconfigures autonegotiation (or disables it) */
+	int (*config_aneg) (struct ugeth_mii_info * mii_info);
+
+	/* Determines the negotiated speed and duplex */
+	int (*read_status) (struct ugeth_mii_info * mii_info);
+
+	/* Clears any pending interrupts */
+	int (*ack_interrupt) (struct ugeth_mii_info * mii_info);
+
+	/* Enables or disables interrupts */
+	int (*config_intr) (struct ugeth_mii_info * mii_info);
+
+	/* Clears up any memory if needed */
+	void (*close) (struct ugeth_mii_info * mii_info);
+};
+
+struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info,
+				 u32 interrupts);
+
+struct dm9161_private {
+	struct timer_list timer;
+	int resetdone;
+};
+
+#endif				/* __UCC_GETH_PHY_H__ */
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index d3d0ec9..f7bc44f 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -30,8 +30,8 @@
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.4.0"
-#define DRV_RELDATE	"June-27-2006"
+#define DRV_VERSION	"1.4.2"
+#define DRV_RELDATE	"Sept-11-2006"
 
 
 /* A few user-configurable values.
@@ -44,6 +44,10 @@
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
+/* Work-around for broken BIOSes: they are unable to get the chip back out of
+   power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */
+static int avoid_D3;
+
 /*
  * In case you are looking for 'options[]' or 'full_duplex[]', they
  * are gone. Use ethtool(8) instead.
@@ -63,7 +67,11 @@
    There are no ill effects from too-large receive rings. */
 #define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10	/* Limit ring entries actually used. */
+#ifdef CONFIG_VIA_RHINE_NAPI
+#define RX_RING_SIZE	64
+#else
 #define RX_RING_SIZE	16
+#endif
 
 
 /* Operational parameters that usually are not changed. */
@@ -116,9 +124,11 @@
 module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
 module_param(rx_copybreak, int, 0);
+module_param(avoid_D3, bool, 0);
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
+MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)");
 
 /*
 		Theory of Operation
@@ -396,7 +406,7 @@
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static void rhine_tx(struct net_device *dev);
-static void rhine_rx(struct net_device *dev);
+static int rhine_rx(struct net_device *dev, int limit);
 static void rhine_error(struct net_device *dev, int intr_status);
 static void rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *rhine_get_stats(struct net_device *dev);
@@ -564,6 +574,32 @@
 }
 #endif
 
+#ifdef CONFIG_VIA_RHINE_NAPI
+static int rhine_napipoll(struct net_device *dev, int *budget)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	void __iomem *ioaddr = rp->base;
+	int done, limit = min(dev->quota, *budget);
+
+	done = rhine_rx(dev, limit);
+	*budget -= done;
+	dev->quota -= done;
+
+	if (done < limit) {
+		netif_rx_complete(dev);
+
+		iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
+			  IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
+			  IntrTxDone | IntrTxError | IntrTxUnderrun |
+			  IntrPCIErr | IntrStatsMax | IntrLinkChange,
+			  ioaddr + IntrEnable);
+		return 0;
+	}
+	else
+		return 1;
+}
+#endif
+
 static void rhine_hw_init(struct net_device *dev, long pioaddr)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -744,6 +780,10 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller = rhine_poll;
 #endif
+#ifdef CONFIG_VIA_RHINE_NAPI
+	dev->poll = rhine_napipoll;
+	dev->weight = 64;
+#endif
 	if (rp->quirks & rqRhineI)
 		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 
@@ -789,6 +829,9 @@
 		}
 	}
 	rp->mii_if.phy_id = phy_id;
+	if (debug > 1 && avoid_D3)
+		printk(KERN_INFO "%s: No D3 power state at shutdown.\n",
+		       dev->name);
 
 	return 0;
 
@@ -1014,6 +1057,8 @@
 
 	rhine_set_rx_mode(dev);
 
+	netif_poll_enable(dev);
+
 	/* Enable interrupts by setting the interrupt mask. */
 	iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
 	       IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -1268,8 +1313,18 @@
 			       dev->name, intr_status);
 
 		if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped |
-		    IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf))
-			rhine_rx(dev);
+				   IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) {
+#ifdef CONFIG_VIA_RHINE_NAPI
+			iowrite16(IntrTxAborted |
+				  IntrTxDone | IntrTxError | IntrTxUnderrun |
+				  IntrPCIErr | IntrStatsMax | IntrLinkChange,
+				  ioaddr + IntrEnable);
+
+			netif_rx_schedule(dev);
+#else
+			rhine_rx(dev, RX_RING_SIZE);
+#endif
+		}
 
 		if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
 			if (intr_status & IntrTxErrSummary) {
@@ -1367,13 +1422,12 @@
 	spin_unlock(&rp->lock);
 }
 
-/* This routine is logically part of the interrupt handler, but isolated
-   for clarity and better register allocation. */
-static void rhine_rx(struct net_device *dev)
+/* Process up to limit frames from receive ring */
+static int rhine_rx(struct net_device *dev, int limit)
 {
 	struct rhine_private *rp = netdev_priv(dev);
+	int count;
 	int entry = rp->cur_rx % RX_RING_SIZE;
-	int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx;
 
 	if (debug > 4) {
 		printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n",
@@ -1382,16 +1436,18 @@
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
+	for (count = 0; count < limit; ++count) {
 		struct rx_desc *desc = rp->rx_head_desc;
 		u32 desc_status = le32_to_cpu(desc->rx_status);
 		int data_size = desc_status >> 16;
 
+		if (desc_status & DescOwn)
+			break;
+
 		if (debug > 4)
 			printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n",
 			       desc_status);
-		if (--boguscnt < 0)
-			break;
+
 		if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) {
 			if ((desc_status & RxWholePkt) != RxWholePkt) {
 				printk(KERN_WARNING "%s: Oversized Ethernet "
@@ -1460,7 +1516,11 @@
 						 PCI_DMA_FROMDEVICE);
 			}
 			skb->protocol = eth_type_trans(skb, dev);
+#ifdef CONFIG_VIA_RHINE_NAPI
+			netif_receive_skb(skb);
+#else
 			netif_rx(skb);
+#endif
 			dev->last_rx = jiffies;
 			rp->stats.rx_bytes += pkt_len;
 			rp->stats.rx_packets++;
@@ -1487,6 +1547,8 @@
 		}
 		rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
 	}
+
+	return count;
 }
 
 /*
@@ -1617,9 +1679,6 @@
 	u8 rx_mode;		/* Note: 0x02=accept runt, 0x01=accept errs */
 
 	if (dev->flags & IFF_PROMISC) {		/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-		       dev->name);
 		rx_mode = 0x1C;
 		iowrite32(0xffffffff, ioaddr + MulticastFilter0);
 		iowrite32(0xffffffff, ioaddr + MulticastFilter1);
@@ -1776,6 +1835,7 @@
 	spin_lock_irq(&rp->lock);
 
 	netif_stop_queue(dev);
+	netif_poll_disable(dev);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: Shutting down ethercard, "
@@ -1857,7 +1917,8 @@
 	}
 
 	/* Hit power state D3 (sleep) */
-	iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+	if (!avoid_D3)
+		iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
 
 	/* TODO: Check use of pci_enable_wake() */
 
@@ -1941,7 +2002,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init(&rhine_driver);
+	return pci_register_driver(&rhine_driver);
 }
 
 
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f5b0078..f23d207 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -2109,8 +2109,6 @@
 	struct dev_mc_list *mclist;
 
 	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		writel(0xffffffff, &regs->MARCAM[0]);
 		writel(0xffffffff, &regs->MARCAM[4]);
 		rx_mode = (RCR_AM | RCR_AB | RCR_PROM);
@@ -2250,7 +2248,7 @@
 	int ret;
 
 	velocity_register_notifier();
-	ret = pci_module_init(&velocity_driver);
+	ret = pci_register_driver(&velocity_driver);
 	if (ret < 0)
 		velocity_unregister_notifier();
 	return ret;
@@ -2742,7 +2740,7 @@
 
 	if (PHYSR0 & PHYSR0_SPDG)
 		status |= VELOCITY_SPEED_1000;
-	if (PHYSR0 & PHYSR0_SPD10)
+	else if (PHYSR0 & PHYSR0_SPD10)
 		status |= VELOCITY_SPEED_10;
 	else
 		status |= VELOCITY_SPEED_100;
@@ -2851,8 +2849,17 @@
 	u32 status;
 	status = check_connection_type(vptr->mac_regs);
 
-	cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
-	if (status & VELOCITY_SPEED_100)
+	cmd->supported = SUPPORTED_TP |
+			SUPPORTED_Autoneg |
+			SUPPORTED_10baseT_Half |
+			SUPPORTED_10baseT_Full |
+			SUPPORTED_100baseT_Half |
+			SUPPORTED_100baseT_Full |
+			SUPPORTED_1000baseT_Half |
+			SUPPORTED_1000baseT_Full;
+	if (status & VELOCITY_SPEED_1000)
+		cmd->speed = SPEED_1000;
+	else if (status & VELOCITY_SPEED_100)
 		cmd->speed = SPEED_100;
 	else
 		cmd->speed = SPEED_10;
@@ -2896,7 +2903,7 @@
 {
 	struct velocity_info *vptr = netdev_priv(dev);
 	struct mac_regs __iomem * regs = vptr->mac_regs;
-	return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0)  ? 0 : 1;
+	return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, &regs->PHYSR0) ? 1 : 0;
 }
 
 static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 496c3d5..82968e4 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -29,7 +29,7 @@
 
 #define VELOCITY_NAME          "via-velocity"
 #define VELOCITY_FULL_DRV_NAM  "VIA Networking Velocity Family Gigabit Ethernet Adapter Driver"
-#define VELOCITY_VERSION       "1.13"
+#define VELOCITY_VERSION       "1.14"
 
 #define VELOCITY_IO_SIZE	256
 
@@ -262,25 +262,6 @@
 	dma_addr_t skb_dma;
 };
 
-/**
- *	alloc_rd_info		-	allocate an rd info block
- *
- *	Alocate and initialize a receive info structure used for keeping
- *	track of kernel side information related to each receive
- *	descriptor we are using
- */
-
-static inline struct velocity_rd_info *alloc_rd_info(void)
-{
-	struct velocity_rd_info *ptr;
-	if ((ptr = kmalloc(sizeof(struct velocity_rd_info), GFP_ATOMIC)) == NULL)
-		return NULL;
-	else {
-		memset(ptr, 0, sizeof(struct velocity_rd_info));
-		return ptr;
-	}
-}
-
 /*
  *	Used to track transmit side buffers.
  */
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 435e91e..6b63b35 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -118,7 +118,7 @@
 
 static inline void set_carrier(port_t *port)
 {
-	if (!sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD)
+	if (!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD))
 		netif_carrier_on(port_to_dev(port));
 	else
 		netif_carrier_off(port_to_dev(port));
@@ -127,10 +127,10 @@
 
 static void sca_msci_intr(port_t *port)
 {
-	u8 stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI ST1 status */
+	u8 stat = sca_in(MSCI0_OFFSET + ST1, port); /* read MSCI ST1 status */
 
-	/* Reset MSCI TX underrun status bit */
-	sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, port);
+	/* Reset MSCI TX underrun and CDCD (ignored) status bit */
+	sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port);
 
 	if (stat & ST1_UDRN) {
 		struct net_device_stats *stats = hdlc_stats(port_to_dev(port));
@@ -138,6 +138,7 @@
 		stats->tx_fifo_errors++;
 	}
 
+	stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */
 	/* Reset MSCI CDCD status bit - uses ch#2 DCD input */
 	sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port);
 
diff --git a/drivers/net/wan/cycx_main.c b/drivers/net/wan/cycx_main.c
index 430b1f6..a5e7ce1 100644
--- a/drivers/net/wan/cycx_main.c
+++ b/drivers/net/wan/cycx_main.c
@@ -40,7 +40,6 @@
 * 1998/08/08	acme		Initial version.
 */
 
-#include <linux/config.h>	/* OS configuration options */
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index 6e1ec5b..7369875 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -28,7 +28,6 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h> /* for CONFIG_DLCI_COUNT */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 684af43..af4d415 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -2062,7 +2062,7 @@
 
 static int __init dscc4_init_module(void)
 {
-	return pci_module_init(&dscc4_driver);
+	return pci_register_driver(&dscc4_driver);
 }
 
 static void __exit dscc4_cleanup_module(void)
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 3705db04a..564351aa 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -2697,7 +2697,7 @@
 	for (i = 0; i < FST_MAX_CARDS; i++)
 		fst_card_array[i] = NULL;
 	spin_lock_init(&fst_work_q_lock);
-	return pci_module_init(&fst_driver);
+	return pci_register_driver(&fst_driver);
 }
 
 static void __exit
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 39f4424..7b5d81d 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1790,7 +1790,7 @@
 
 static int __init init_lmc(void)
 {
-    return pci_module_init(&lmc_driver);
+    return pci_register_driver(&lmc_driver);
 }
 
 static void __exit exit_lmc(void)
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 567efff..56e6940 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -3677,7 +3677,7 @@
 
 static int __init cpc_init(void)
 {
-	return pci_module_init(&cpc_driver);
+	return pci_register_driver(&cpc_driver);
 }
 
 static void __exit cpc_cleanup_module(void)
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index 4df61fa..a6b9c33 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -476,7 +476,7 @@
 		printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
 		return -EINVAL;
 	}
-	return pci_module_init(&pci200_pci_driver);
+	return pci_register_driver(&pci200_pci_driver);
 }
 
 
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 7628c2d..0ba018f 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -32,7 +32,6 @@
  *		2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h> /* for CONFIG_DLCI_MAX */
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index b2031df..ec68f7d 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -837,7 +837,7 @@
 #ifdef MODULE
 	printk(KERN_INFO "%s\n", version);
 #endif
-	return pci_module_init(&wanxl_pci_driver);
+	return pci_register_driver(&wanxl_pci_driver);
 }
 
 static void __exit wanxl_cleanup_module(void)
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 7caa8dc..b1ba187 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -500,8 +500,8 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
-init_module(void)
+
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index fa9d2c4..bd4a68c 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -271,25 +271,14 @@
 	bool "Enable full debugging output in IPW2200 module."
 	depends on IPW2200
 	---help---
-	  This option will enable debug tracing output for the IPW2200.  
+	  This option will enable low level debug tracing output for IPW2200.
 
-	  This will result in the kernel module being ~100k larger.  You can 
-	  control which debug output is sent to the kernel log by setting the 
-	  value in 
+	  Note, normal debug code is already compiled in. This low level
+	  debug option enables debug on hot paths (e.g Tx, Rx, ISR) and
+	  will result in the kernel module being ~70 larger.  Most users
+	  will typically not need this high verbosity debug information.
 
-	  /sys/bus/pci/drivers/ipw2200/debug_level
-
-	  This entry will only exist if this option is enabled.
-
-	  To set a value, simply echo an 8-byte hex value to the same file:
-
-	  % echo 0x00000FFO > /sys/bus/pci/drivers/ipw2200/debug_level
-
-	  You can find the list of debug mask values in 
-	  drivers/net/wireless/ipw2200.h
-
-	  If you are not trying to debug or develop the IPW2200 driver, you 
-	  most likely want to say N here.
+	  If you are not sure, say N here.
 
 config AIRO
 	tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
@@ -447,6 +436,7 @@
 	tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
 	depends on NET_RADIO && PCMCIA && (BROKEN || !M32R)
 	select CRYPTO
+	select CRYPTO_AES
 	---help---
 	  This is the standard Linux driver to support Cisco/Aironet PCMCIA
 	  802.11 wireless cards.  This driver is the same as the Aironet
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index a4dd139..e088cee 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -47,6 +47,7 @@
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 #include <net/ieee80211.h>
+#include <linux/kthread.h>
 
 #include "airo.h"
 
@@ -1187,11 +1188,10 @@
 			int whichbap);
 	unsigned short *flash;
 	tdsRssiEntry *rssi;
-	struct task_struct *task;
+	struct task_struct *list_bss_task;
+	struct task_struct *airo_thread_task;
 	struct semaphore sem;
-	pid_t thr_pid;
 	wait_queue_head_t thr_wait;
-	struct completion thr_exited;
 	unsigned long expires;
 	struct {
 		struct sk_buff *skb;
@@ -1733,12 +1733,12 @@
 		cmd.cmd=CMD_LISTBSS;
 		if (down_interruptible(&ai->sem))
 			return -ERESTARTSYS;
+		ai->list_bss_task = current;
 		issuecommand(ai, &cmd, &rsp);
 		up(&ai->sem);
 		/* Let the command take effect */
-		ai->task = current;
-		ssleep(3);
-		ai->task = NULL;
+		schedule_timeout_uninterruptible(3 * HZ);
+		ai->list_bss_task = NULL;
 	}
 	rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
 			    list, ai->bssListRidLen, 1);
@@ -2400,8 +2400,7 @@
 		clear_bit(FLAG_REGISTERED, &ai->flags);
 	}
 	set_bit(JOB_DIE, &ai->jobs);
-	kill_proc(ai->thr_pid, SIGTERM, 1);
-	wait_for_completion(&ai->thr_exited);
+	kthread_stop(ai->airo_thread_task);
 
 	/*
 	 * Clean out tx queue
@@ -2811,9 +2810,8 @@
 	ai->config.len = 0;
 	ai->pci = pci;
 	init_waitqueue_head (&ai->thr_wait);
-	init_completion (&ai->thr_exited);
-	ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
-	if (ai->thr_pid < 0)
+	ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name);
+	if (IS_ERR(ai->airo_thread_task))
 		goto err_out_free;
 	ai->tfm = NULL;
 	rc = add_airo_dev( dev );
@@ -2930,8 +2928,7 @@
 	del_airo_dev(dev);
 err_out_thr:
 	set_bit(JOB_DIE, &ai->jobs);
-	kill_proc(ai->thr_pid, SIGTERM, 1);
-	wait_for_completion(&ai->thr_exited);
+	kthread_stop(ai->airo_thread_task);
 err_out_free:
 	free_netdev(dev);
 	return NULL;
@@ -3063,13 +3060,7 @@
 	struct airo_info *ai = dev->priv;
 	int locked;
 	
-	daemonize("%s", dev->name);
-	allow_signal(SIGTERM);
-
 	while(1) {
-		if (signal_pending(current))
-			flush_signals(current);
-
 		/* make swsusp happy with our thread */
 		try_to_freeze();
 
@@ -3097,7 +3088,7 @@
 						set_bit(JOB_AUTOWEP, &ai->jobs);
 						break;
 					}
-					if (!signal_pending(current)) {
+					if (!kthread_should_stop()) {
 						unsigned long wake_at;
 						if (!ai->expires || !ai->scan_timeout) {
 							wake_at = max(ai->expires,
@@ -3109,7 +3100,7 @@
 						schedule_timeout(wake_at - jiffies);
 						continue;
 					}
-				} else if (!signal_pending(current)) {
+				} else if (!kthread_should_stop()) {
 					schedule();
 					continue;
 				}
@@ -3154,7 +3145,8 @@
 		else  /* Shouldn't get here, but we make sure to unlock */
 			up(&ai->sem);
 	}
-	complete_and_exit (&ai->thr_exited, 0);
+
+	return 0;
 }
 
 static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) {
@@ -3235,8 +3227,8 @@
 			if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
 				if (auto_wep)
 					apriv->expires = 0;
-				if (apriv->task)
-					wake_up_process (apriv->task);
+				if (apriv->list_bss_task)
+					wake_up_process(apriv->list_bss_task);
 				set_bit(FLAG_UPDATE_UNI, &apriv->flags);
 				set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
 
@@ -3950,13 +3942,11 @@
 	pRsp->rsp0 = IN4500(ai, RESP0);
 	pRsp->rsp1 = IN4500(ai, RESP1);
 	pRsp->rsp2 = IN4500(ai, RESP2);
-	if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) {
-		airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd);
-		airo_print_err(ai->dev->name, "status= %x\n", pRsp->status);
-		airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0);
-		airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1);
-		airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
-	}
+	if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET)
+		airo_print_err(ai->dev->name,
+			"cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x",
+			pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1,
+			pRsp->rsp2);
 
 	// clear stuck command busy if necessary
 	if (IN4500(ai, COMMAND) & COMMAND_BUSY) {
diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
index d425c3c..3bfa791 100644
--- a/drivers/net/wireless/atmel_pci.c
+++ b/drivers/net/wireless/atmel_pci.c
@@ -76,7 +76,7 @@
 
 static int __init atmel_init_module(void)
 {
-	return pci_module_init(&atmel_driver);
+	return pci_register_driver(&atmel_driver);
 }
 
 static void __exit atmel_cleanup_module(void)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 17a5682..6d4ea36 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -33,14 +33,18 @@
 #define BCM43xx_PCICFG_ICR		0x94
 
 /* MMIO offsets */
-#define BCM43xx_MMIO_DMA1_REASON	0x20
-#define BCM43xx_MMIO_DMA1_IRQ_MASK	0x24
-#define BCM43xx_MMIO_DMA2_REASON	0x28
-#define BCM43xx_MMIO_DMA2_IRQ_MASK	0x2C
-#define BCM43xx_MMIO_DMA3_REASON	0x30
-#define BCM43xx_MMIO_DMA3_IRQ_MASK	0x34
-#define BCM43xx_MMIO_DMA4_REASON	0x38
-#define BCM43xx_MMIO_DMA4_IRQ_MASK	0x3C
+#define BCM43xx_MMIO_DMA0_REASON	0x20
+#define BCM43xx_MMIO_DMA0_IRQ_MASK	0x24
+#define BCM43xx_MMIO_DMA1_REASON	0x28
+#define BCM43xx_MMIO_DMA1_IRQ_MASK	0x2C
+#define BCM43xx_MMIO_DMA2_REASON	0x30
+#define BCM43xx_MMIO_DMA2_IRQ_MASK	0x34
+#define BCM43xx_MMIO_DMA3_REASON	0x38
+#define BCM43xx_MMIO_DMA3_IRQ_MASK	0x3C
+#define BCM43xx_MMIO_DMA4_REASON	0x40
+#define BCM43xx_MMIO_DMA4_IRQ_MASK	0x44
+#define BCM43xx_MMIO_DMA5_REASON	0x48
+#define BCM43xx_MMIO_DMA5_IRQ_MASK	0x4C
 #define BCM43xx_MMIO_STATUS_BITFIELD	0x120
 #define BCM43xx_MMIO_STATUS2_BITFIELD	0x124
 #define BCM43xx_MMIO_GEN_IRQ_REASON	0x128
@@ -56,14 +60,27 @@
 #define BCM43xx_MMIO_XMITSTAT_1		0x174
 #define BCM43xx_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
 #define BCM43xx_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
-#define BCM43xx_MMIO_DMA1_BASE		0x200
-#define BCM43xx_MMIO_DMA2_BASE		0x220
-#define BCM43xx_MMIO_DMA3_BASE		0x240
-#define BCM43xx_MMIO_DMA4_BASE		0x260
+
+/* 32-bit DMA */
+#define BCM43xx_MMIO_DMA32_BASE0	0x200
+#define BCM43xx_MMIO_DMA32_BASE1	0x220
+#define BCM43xx_MMIO_DMA32_BASE2	0x240
+#define BCM43xx_MMIO_DMA32_BASE3	0x260
+#define BCM43xx_MMIO_DMA32_BASE4	0x280
+#define BCM43xx_MMIO_DMA32_BASE5	0x2A0
+/* 64-bit DMA */
+#define BCM43xx_MMIO_DMA64_BASE0	0x200
+#define BCM43xx_MMIO_DMA64_BASE1	0x240
+#define BCM43xx_MMIO_DMA64_BASE2	0x280
+#define BCM43xx_MMIO_DMA64_BASE3	0x2C0
+#define BCM43xx_MMIO_DMA64_BASE4	0x300
+#define BCM43xx_MMIO_DMA64_BASE5	0x340
+/* PIO */
 #define BCM43xx_MMIO_PIO1_BASE		0x300
 #define BCM43xx_MMIO_PIO2_BASE		0x310
 #define BCM43xx_MMIO_PIO3_BASE		0x320
 #define BCM43xx_MMIO_PIO4_BASE		0x330
+
 #define BCM43xx_MMIO_PHY_VER		0x3E0
 #define BCM43xx_MMIO_PHY_RADIO		0x3E2
 #define BCM43xx_MMIO_ANTENNA		0x3E8
@@ -233,8 +250,14 @@
 #define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK	0x20000
 
 /* sbtmstatehigh state flags */
-#define BCM43xx_SBTMSTATEHIGH_SERROR		0x1
-#define BCM43xx_SBTMSTATEHIGH_BUSY		0x4
+#define BCM43xx_SBTMSTATEHIGH_SERROR		0x00000001
+#define BCM43xx_SBTMSTATEHIGH_BUSY		0x00000004
+#define BCM43xx_SBTMSTATEHIGH_TIMEOUT		0x00000020
+#define BCM43xx_SBTMSTATEHIGH_COREFLAGS		0x1FFF0000
+#define BCM43xx_SBTMSTATEHIGH_DMA64BIT		0x10000000
+#define BCM43xx_SBTMSTATEHIGH_GATEDCLK		0x20000000
+#define BCM43xx_SBTMSTATEHIGH_BISTFAILED	0x40000000
+#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE	0x80000000
 
 /* sbimstate flags */
 #define BCM43xx_SBIMSTATE_IB_ERROR		0x20000
@@ -283,6 +306,13 @@
 #define BCM43xx_SBF_TIME_UPDATE		0x10000000
 #define BCM43xx_SBF_80000000		0x80000000 /*FIXME: fix name*/
 
+/* Microcode */
+#define BCM43xx_UCODE_REVISION		0x0000
+#define BCM43xx_UCODE_PATCHLEVEL	0x0002
+#define BCM43xx_UCODE_DATE		0x0004
+#define BCM43xx_UCODE_TIME		0x0006
+#define BCM43xx_UCODE_STATUS		0x0040
+
 /* MicrocodeFlagsBitfield (addr + lo-word values?)*/
 #define BCM43xx_UCODEFLAGS_OFFSET	0x005E
 
@@ -504,6 +534,12 @@
 	 * This lock is only used by bcm43xx_phy_{un}lock()
 	 */
 	spinlock_t lock;
+
+	/* Firmware. */
+	const struct firmware *ucode;
+	const struct firmware *pcm;
+	const struct firmware *initvals0;
+	const struct firmware *initvals1;
 };
 
 
@@ -568,8 +604,11 @@
 	struct bcm43xx_dmaring *tx_ring1;
 	struct bcm43xx_dmaring *tx_ring2;
 	struct bcm43xx_dmaring *tx_ring3;
+	struct bcm43xx_dmaring *tx_ring4;
+	struct bcm43xx_dmaring *tx_ring5;
+
 	struct bcm43xx_dmaring *rx_ring0;
-	struct bcm43xx_dmaring *rx_ring1; /* only available on core.rev < 5 */
+	struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */
 };
 
 /* Data structures for PIO transmission, per 80211 core. */
@@ -593,12 +632,14 @@
 	u8 available:1,
 	   enabled:1,
 	   initialized:1;
-	/** core_id ID number */
-	u16 id;
 	/** core_rev revision number */
 	u8 rev;
 	/** Index number for _switch_core() */
 	u8 index;
+	/** core_id ID number */
+	u16 id;
+	/** Core-specific data. */
+	void *priv;
 };
 
 /* Additional information for each 80211 core. */
@@ -647,7 +688,23 @@
 	BCM43xx_STAT_RESTARTING,	/* controller_restart() called. */
 };
 #define bcm43xx_status(bcm)		atomic_read(&(bcm)->init_status)
-#define bcm43xx_set_status(bcm, stat)	atomic_set(&(bcm)->init_status, (stat))
+#define bcm43xx_set_status(bcm, stat)	do {			\
+		atomic_set(&(bcm)->init_status, (stat));	\
+		smp_wmb();					\
+					} while (0)
+
+/*    *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
+ *                   and the device registers. This mutex does _not_ protect
+ *                   against concurrency from the IRQ handler.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * Please note that, if you only take the irq_lock, you are not protected
+ * against concurrency from the periodic work handlers.
+ * Most times you want to take _both_ locks.
+ */
 
 struct bcm43xx_private {
 	struct ieee80211_device *ieee;
@@ -659,7 +716,6 @@
 
 	void __iomem *mmio_addr;
 
-	/* Locking, see "theory of locking" text below. */
 	spinlock_t irq_lock;
 	struct mutex mutex;
 
@@ -691,6 +747,7 @@
 	struct bcm43xx_sprominfo sprom;
 #define BCM43xx_NR_LEDS		4
 	struct bcm43xx_led leds[BCM43xx_NR_LEDS];
+	spinlock_t leds_lock;
 
 	/* The currently active core. */
 	struct bcm43xx_coreinfo *current_core;
@@ -708,10 +765,6 @@
 	struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ];
 	/* Additional information, specific to the 80211 cores. */
 	struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ];
-	/* Index of the current 80211 core. If current_core is not
-	 * an 80211 core, this is -1.
-	 */
-	int current_80211_core_idx;
 	/* Number of available 80211 cores. */
 	int nr_80211_available;
 
@@ -719,11 +772,13 @@
 
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
-	u32 dma_reason[4];
+	u32 dma_reason[6];
 	/* saved irq enable/disable state bitfield. */
 	u32 irq_savedstate;
 	/* Link Quality calculation context. */
 	struct bcm43xx_noise_calculation noisecalc;
+	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
+	int mac_suspended;
 
 	/* Threshold values. */
 	//TODO: The RTS thr has to be _used_. Currently, it is only set via WX.
@@ -746,12 +801,6 @@
 	struct bcm43xx_key key[54];
 	u8 default_key_idx;
 
-	/* Firmware. */
-	const struct firmware *ucode;
-	const struct firmware *pcm;
-	const struct firmware *initvals0;
-	const struct firmware *initvals1;
-
 	/* Random Number Generator. */
 	struct hwrng rng;
 	char rng_name[20 + 1];
@@ -763,55 +812,6 @@
 };
 
 
-/*    *** THEORY OF LOCKING ***
- *
- * We have two different locks in the bcm43xx driver.
- * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
- *                   and the device registers.
- * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
- *
- * We have three types of helper function pairs to utilize these locks.
- *     (Always use the helper functions.)
- * 1) bcm43xx_{un}lock_noirq():
- *     Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
- *     so it is almost always unsafe, if device IRQs are enabled.
- *     So only use this, if device IRQs are masked.
- *     Locking may sleep.
- *     You can sleep within the critical section.
- * 2) bcm43xx_{un}lock_irqonly():
- *     Takes bcm->irq_lock. Does _not_ protect against
- *     bcm43xx_lock_noirq() critical sections.
- *     Does only protect against the IRQ handler path and other
- *     irqonly() critical sections.
- *     Locking does not sleep.
- *     You must not sleep within the critical section.
- * 3) bcm43xx_{un}lock_irqsafe():
- *     This is the cummulative lock and takes both, mutex and irq_lock.
- *     Protects against noirq() and irqonly() critical sections (and
- *     the IRQ handler path).
- *     Locking may sleep.
- *     You must not sleep within the critical section.
- */
-
-/* Lock type 1 */
-#define bcm43xx_lock_noirq(bcm)		mutex_lock(&(bcm)->mutex)
-#define bcm43xx_unlock_noirq(bcm)	mutex_unlock(&(bcm)->mutex)
-/* Lock type 2 */
-#define bcm43xx_lock_irqonly(bcm, flags)	\
-	spin_lock_irqsave(&(bcm)->irq_lock, flags)
-#define bcm43xx_unlock_irqonly(bcm, flags)	\
-	spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
-/* Lock type 3 */
-#define bcm43xx_lock_irqsafe(bcm, flags) do {	\
-	bcm43xx_lock_noirq(bcm);		\
-	bcm43xx_lock_irqonly(bcm, flags);	\
-		} while (0)
-#define bcm43xx_unlock_irqsafe(bcm, flags) do {	\
-	bcm43xx_unlock_irqonly(bcm, flags);	\
-	bcm43xx_unlock_noirq(bcm);		\
-		} while (0)
-
-
 static inline
 struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
 {
@@ -863,34 +863,33 @@
  * any of these functions.
  */
 static inline
+struct bcm43xx_coreinfo_80211 *
+bcm43xx_current_80211_priv(struct bcm43xx_private *bcm)
+{
+	assert(bcm->current_core->id == BCM43xx_COREID_80211);
+	return bcm->current_core->priv;
+}
+static inline
 struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm)
 {
 	assert(bcm43xx_using_pio(bcm));
-	assert(bcm->current_80211_core_idx >= 0);
-	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].pio);
+	return &(bcm43xx_current_80211_priv(bcm)->pio);
 }
 static inline
 struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm)
 {
 	assert(!bcm43xx_using_pio(bcm));
-	assert(bcm->current_80211_core_idx >= 0);
-	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].dma);
+	return &(bcm43xx_current_80211_priv(bcm)->dma);
 }
 static inline
 struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm)
 {
-	assert(bcm->current_80211_core_idx >= 0);
-	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].phy);
+	return &(bcm43xx_current_80211_priv(bcm)->phy);
 }
 static inline
 struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm)
 {
-	assert(bcm->current_80211_core_idx >= 0);
-	assert(bcm->current_80211_core_idx < BCM43xx_MAX_80211_CORES);
-	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
+	return &(bcm43xx_current_80211_priv(bcm)->radio);
 }
 
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index ce2e40b..923275e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -77,7 +77,8 @@
 
 	down(&big_buffer_sem);
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
@@ -121,7 +122,8 @@
 	fappend("\n");
 
 out:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -159,7 +161,8 @@
 	unsigned long flags;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
@@ -169,7 +172,8 @@
 	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
 
 out:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -188,7 +192,8 @@
 	u64 tsf;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
@@ -199,7 +204,8 @@
 		(unsigned int)(tsf & 0xFFFFFFFFULL));
 
 out:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -221,7 +227,8 @@
 	        res = -EFAULT;
 		goto out_up;
 	}
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
 		res = -EFAULT;
@@ -237,7 +244,8 @@
 	res = buf_size;
 	
 out_unlock:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 out_up:
 	up(&big_buffer_sem);
 	return res;
@@ -258,7 +266,8 @@
 	int i, cnt, j = 0;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 
 	fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
 		BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -294,14 +303,51 @@
 			i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
 	}
 
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-	bcm43xx_lock_irqsafe(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (*ppos == pos) {
 		/* Done. Drop the copied data. */
 		e->xmitstatus_printing = 0;
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
+	up(&big_buffer_sem);
+	return res;
+}
+
+static ssize_t restart_write_file(struct file *file, const char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	struct bcm43xx_private *bcm = file->private_data;
+	char *buf = really_big_buffer;
+	ssize_t buf_size;
+	ssize_t res;
+	unsigned long flags;
+
+	buf_size = min(count, sizeof (really_big_buffer) - 1);
+	down(&big_buffer_sem);
+	if (copy_from_user(buf, user_buf, buf_size)) {
+	        res = -EFAULT;
+		goto out_up;
+	}
+	mutex_lock(&(bcm)->mutex);
+	spin_lock_irqsave(&(bcm)->irq_lock, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
+		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
+		res = -EFAULT;
+		goto out_unlock;
+	}
+	if (count > 0 && buf[0] == '1') {
+		bcm43xx_controller_restart(bcm, "manually restarted");
+		res = count;
+	} else
+		res = -EINVAL;
+
+out_unlock:
+	spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
+	mutex_unlock(&(bcm)->mutex);
+out_up:
 	up(&big_buffer_sem);
 	return res;
 }
@@ -339,6 +385,11 @@
 	.open = open_file_generic,
 };
 
+static struct file_operations restart_fops = {
+	.write = restart_write_file,
+	.open = open_file_generic,
+};
+
 
 void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm)
 {
@@ -390,6 +441,10 @@
 						bcm, &txstat_fops);
 	if (!e->dentry_txstat)
 		printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir);
+	e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir,
+						bcm, &restart_fops);
+	if (!e->dentry_restart)
+		printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir);
 }
 
 void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm)
@@ -405,6 +460,7 @@
 	debugfs_remove(e->dentry_devinfo);
 	debugfs_remove(e->dentry_tsf);
 	debugfs_remove(e->dentry_txstat);
+	debugfs_remove(e->dentry_restart);
 	debugfs_remove(e->subdir);
 	kfree(e->xmitstatus_buffer);
 	kfree(e->xmitstatus_print_buffer);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
index 50ce267..a40d1af 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h
@@ -20,6 +20,7 @@
 	struct dentry *dentry_spromdump;
 	struct dentry *dentry_tsf;
 	struct dentry *dentry_txstat;
+	struct dentry *dentry_restart;
 
 	struct bcm43xx_private *bcm;
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
index d0318e5..76e3aed 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c
@@ -4,7 +4,7 @@
 
   DMA ringbuffer and descriptor allocation/management
 
-  Copyright (c) 2005 Michael Buesch <mbuesch@freenet.de>
+  Copyright (c) 2005, 2006 Michael Buesch <mbuesch@freenet.de>
 
   Some code in this file is derived from the b44.c driver
   Copyright (C) 2002 David S. Miller
@@ -109,6 +109,35 @@
 	}
 }
 
+u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx)
+{
+	static const u16 map64[] = {
+		BCM43xx_MMIO_DMA64_BASE0,
+		BCM43xx_MMIO_DMA64_BASE1,
+		BCM43xx_MMIO_DMA64_BASE2,
+		BCM43xx_MMIO_DMA64_BASE3,
+		BCM43xx_MMIO_DMA64_BASE4,
+		BCM43xx_MMIO_DMA64_BASE5,
+	};
+	static const u16 map32[] = {
+		BCM43xx_MMIO_DMA32_BASE0,
+		BCM43xx_MMIO_DMA32_BASE1,
+		BCM43xx_MMIO_DMA32_BASE2,
+		BCM43xx_MMIO_DMA32_BASE3,
+		BCM43xx_MMIO_DMA32_BASE4,
+		BCM43xx_MMIO_DMA32_BASE5,
+	};
+
+	if (dma64bit) {
+		assert(controller_idx >= 0 &&
+		       controller_idx < ARRAY_SIZE(map64));
+		return map64[controller_idx];
+	}
+	assert(controller_idx >= 0 &&
+	       controller_idx < ARRAY_SIZE(map32));
+	return map32[controller_idx];
+}
+
 static inline
 dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring,
 			  unsigned char *buf,
@@ -172,7 +201,6 @@
 /* Unmap and free a descriptor buffer. */
 static inline
 void free_descriptor_buffer(struct bcm43xx_dmaring *ring,
-			    struct bcm43xx_dmadesc *desc,
 			    struct bcm43xx_dmadesc_meta *meta,
 			    int irq_context)
 {
@@ -188,23 +216,13 @@
 {
 	struct device *dev = &(ring->bcm->pci_dev->dev);
 
-	ring->vbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-					 &(ring->dmabase), GFP_KERNEL);
-	if (!ring->vbase) {
+	ring->descbase = dma_alloc_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
+					    &(ring->dmabase), GFP_KERNEL);
+	if (!ring->descbase) {
 		printk(KERN_ERR PFX "DMA ringmemory allocation failed\n");
 		return -ENOMEM;
 	}
-	if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) {
-		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RINGMEMORY >1G "
-				    "(0x%llx, len: %lu)\n",
-				(unsigned long long)ring->dmabase,
-				BCM43xx_DMA_RINGMEMSIZE);
-		dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-				  ring->vbase, ring->dmabase);
-		return -ENOMEM;
-	}
-	assert(!(ring->dmabase & 0x000003FF));
-	memset(ring->vbase, 0, BCM43xx_DMA_RINGMEMSIZE);
+	memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE);
 
 	return 0;
 }
@@ -214,26 +232,34 @@
 	struct device *dev = &(ring->bcm->pci_dev->dev);
 
 	dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE,
-			  ring->vbase, ring->dmabase);
+			  ring->descbase, ring->dmabase);
 }
 
 /* Reset the RX DMA channel */
 int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-				   u16 mmio_base)
+				   u16 mmio_base, int dma64)
 {
 	int i;
 	u32 value;
+	u16 offset;
 
-	bcm43xx_write32(bcm,
-			mmio_base + BCM43xx_DMA_RX_CONTROL,
-			0x00000000);
+	offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL;
+	bcm43xx_write32(bcm, mmio_base + offset, 0);
 	for (i = 0; i < 1000; i++) {
-		value = bcm43xx_read32(bcm,
-				       mmio_base + BCM43xx_DMA_RX_STATUS);
-		value &= BCM43xx_DMA_RXSTAT_STAT_MASK;
-		if (value == BCM43xx_DMA_RXSTAT_STAT_DISABLED) {
-			i = -1;
-			break;
+		offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS;
+		value = bcm43xx_read32(bcm, mmio_base + offset);
+		if (dma64) {
+			value &= BCM43xx_DMA64_RXSTAT;
+			if (value == BCM43xx_DMA64_RXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		} else {
+			value &= BCM43xx_DMA32_RXSTATE;
+			if (value == BCM43xx_DMA32_RXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
 		}
 		udelay(10);
 	}
@@ -247,31 +273,47 @@
 
 /* Reset the RX DMA channel */
 int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-				   u16 mmio_base)
+				   u16 mmio_base, int dma64)
 {
 	int i;
 	u32 value;
+	u16 offset;
 
 	for (i = 0; i < 1000; i++) {
-		value = bcm43xx_read32(bcm,
-				       mmio_base + BCM43xx_DMA_TX_STATUS);
-		value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
-		if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED ||
-		    value == BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT ||
-		    value == BCM43xx_DMA_TXSTAT_STAT_STOPPED)
-			break;
+		offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+		value = bcm43xx_read32(bcm, mmio_base + offset);
+		if (dma64) {
+			value &= BCM43xx_DMA64_TXSTAT;
+			if (value == BCM43xx_DMA64_TXSTAT_DISABLED ||
+			    value == BCM43xx_DMA64_TXSTAT_IDLEWAIT ||
+			    value == BCM43xx_DMA64_TXSTAT_STOPPED)
+				break;
+		} else {
+			value &= BCM43xx_DMA32_TXSTATE;
+			if (value == BCM43xx_DMA32_TXSTAT_DISABLED ||
+			    value == BCM43xx_DMA32_TXSTAT_IDLEWAIT ||
+			    value == BCM43xx_DMA32_TXSTAT_STOPPED)
+				break;
+		}
 		udelay(10);
 	}
-	bcm43xx_write32(bcm,
-			mmio_base + BCM43xx_DMA_TX_CONTROL,
-			0x00000000);
+	offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL;
+	bcm43xx_write32(bcm, mmio_base + offset, 0);
 	for (i = 0; i < 1000; i++) {
-		value = bcm43xx_read32(bcm,
-				       mmio_base + BCM43xx_DMA_TX_STATUS);
-		value &= BCM43xx_DMA_TXSTAT_STAT_MASK;
-		if (value == BCM43xx_DMA_TXSTAT_STAT_DISABLED) {
-			i = -1;
-			break;
+		offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS;
+		value = bcm43xx_read32(bcm, mmio_base + offset);
+		if (dma64) {
+			value &= BCM43xx_DMA64_TXSTAT;
+			if (value == BCM43xx_DMA64_TXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
+		} else {
+			value &= BCM43xx_DMA32_TXSTATE;
+			if (value == BCM43xx_DMA32_TXSTAT_DISABLED) {
+				i = -1;
+				break;
+			}
 		}
 		udelay(10);
 	}
@@ -285,47 +327,98 @@
 	return 0;
 }
 
+static void fill_descriptor(struct bcm43xx_dmaring *ring,
+			    struct bcm43xx_dmadesc_generic *desc,
+			    dma_addr_t dmaaddr,
+			    u16 bufsize,
+			    int start, int end, int irq)
+{
+	int slot;
+
+	slot = bcm43xx_dma_desc2idx(ring, desc);
+	assert(slot >= 0 && slot < ring->nr_slots);
+
+	if (ring->dma64) {
+		u32 ctl0 = 0, ctl1 = 0;
+		u32 addrlo, addrhi;
+		u32 addrext;
+
+		addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
+		addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING);
+		addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+		addrhi |= ring->routing;
+		if (slot == ring->nr_slots - 1)
+			ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND;
+		if (start)
+			ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART;
+		if (end)
+			ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND;
+		if (irq)
+			ctl0 |= BCM43xx_DMA64_DCTL0_IRQ;
+		ctl1 |= (bufsize - ring->frameoffset)
+			& BCM43xx_DMA64_DCTL1_BYTECNT;
+		ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT)
+			& BCM43xx_DMA64_DCTL1_ADDREXT_MASK;
+
+		desc->dma64.control0 = cpu_to_le32(ctl0);
+		desc->dma64.control1 = cpu_to_le32(ctl1);
+		desc->dma64.address_low = cpu_to_le32(addrlo);
+		desc->dma64.address_high = cpu_to_le32(addrhi);
+	} else {
+		u32 ctl;
+		u32 addr;
+		u32 addrext;
+
+		addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING);
+		addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING)
+			   >> BCM43xx_DMA32_ROUTING_SHIFT;
+		addr |= ring->routing;
+		ctl = (bufsize - ring->frameoffset)
+		      & BCM43xx_DMA32_DCTL_BYTECNT;
+		if (slot == ring->nr_slots - 1)
+			ctl |= BCM43xx_DMA32_DCTL_DTABLEEND;
+		if (start)
+			ctl |= BCM43xx_DMA32_DCTL_FRAMESTART;
+		if (end)
+			ctl |= BCM43xx_DMA32_DCTL_FRAMEEND;
+		if (irq)
+			ctl |= BCM43xx_DMA32_DCTL_IRQ;
+		ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT)
+		       & BCM43xx_DMA32_DCTL_ADDREXT_MASK;
+
+		desc->dma32.control = cpu_to_le32(ctl);
+		desc->dma32.address = cpu_to_le32(addr);
+	}
+}
+
 static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring,
-			       struct bcm43xx_dmadesc *desc,
+			       struct bcm43xx_dmadesc_generic *desc,
 			       struct bcm43xx_dmadesc_meta *meta,
 			       gfp_t gfp_flags)
 {
 	struct bcm43xx_rxhdr *rxhdr;
+	struct bcm43xx_hwxmitstatus *xmitstat;
 	dma_addr_t dmaaddr;
-	u32 desc_addr;
-	u32 desc_ctl;
-	const int slot = (int)(desc - ring->vbase);
 	struct sk_buff *skb;
 
-	assert(slot >= 0 && slot < ring->nr_slots);
 	assert(!ring->tx);
 
 	skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags);
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
-	if (unlikely(dmaaddr + ring->rx_buffersize > BCM43xx_DMA_BUSADDRMAX)) {
-		unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0);
-		dev_kfree_skb_any(skb);
-		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA RX SKB >1G "
-				    "(0x%llx, len: %u)\n",
-			(unsigned long long)dmaaddr, ring->rx_buffersize);
-		return -ENOMEM;
-	}
 	meta->skb = skb;
 	meta->dmaaddr = dmaaddr;
 	skb->dev = ring->bcm->net_dev;
-	desc_addr = (u32)(dmaaddr + ring->memoffset);
-	desc_ctl = (BCM43xx_DMADTOR_BYTECNT_MASK &
-		    (u32)(ring->rx_buffersize - ring->frameoffset));
-	if (slot == ring->nr_slots - 1)
-		desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
-	set_desc_addr(desc, desc_addr);
-	set_desc_ctl(desc, desc_ctl);
+
+	fill_descriptor(ring, desc, dmaaddr,
+			ring->rx_buffersize, 0, 0, 0);
 
 	rxhdr = (struct bcm43xx_rxhdr *)(skb->data);
 	rxhdr->frame_length = 0;
 	rxhdr->flags1 = 0;
+	xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data);
+	xmitstat->cookie = 0;
 
 	return 0;
 }
@@ -336,17 +429,17 @@
 static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring)
 {
 	int i, err = -ENOMEM;
-	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 
 	for (i = 0; i < ring->nr_slots; i++) {
-		desc = ring->vbase + i;
-		meta = ring->meta + i;
+		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
 
 		err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
 		if (err)
 			goto err_unwind;
 	}
+	mb();
 	ring->used_slots = ring->nr_slots;
 	err = 0;
 out:
@@ -354,8 +447,7 @@
 
 err_unwind:
 	for (i--; i >= 0; i--) {
-		desc = ring->vbase + i;
-		meta = ring->meta + i;
+		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
 
 		unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
 		dev_kfree_skb(meta->skb);
@@ -371,27 +463,67 @@
 {
 	int err = 0;
 	u32 value;
+	u32 addrext;
 
 	if (ring->tx) {
-		/* Set Transmit Control register to "transmit enable" */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
-				  BCM43xx_DMA_TXCTRL_ENABLE);
-		/* Set Transmit Descriptor ring address. */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING,
-				  ring->dmabase + ring->memoffset);
+		if (ring->dma64) {
+			u64 ringbase = (u64)(ring->dmabase);
+
+			addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+			value = BCM43xx_DMA64_TXENABLE;
+			value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT)
+				& BCM43xx_DMA64_TXADDREXT_MASK;
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value);
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO,
+					(ringbase & 0xFFFFFFFF));
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI,
+					((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+					| ring->routing);
+		} else {
+			u32 ringbase = (u32)(ring->dmabase);
+
+			addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+			value = BCM43xx_DMA32_TXENABLE;
+			value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT)
+				& BCM43xx_DMA32_TXADDREXT_MASK;
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value);
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING,
+					(ringbase & ~BCM43xx_DMA32_ROUTING)
+					| ring->routing);
+		}
 	} else {
 		err = alloc_initial_descbuffers(ring);
 		if (err)
 			goto out;
-		/* Set Receive Control "receive enable" and frame offset */
-		value = (ring->frameoffset << BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT);
-		value |= BCM43xx_DMA_RXCTRL_ENABLE;
-		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_CONTROL, value);
-		/* Set Receive Descriptor ring address. */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING,
-				  ring->dmabase + ring->memoffset);
-		/* Init the descriptor pointer. */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX, 200);
+		if (ring->dma64) {
+			u64 ringbase = (u64)(ring->dmabase);
+
+			addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT);
+			value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT);
+			value |= BCM43xx_DMA64_RXENABLE;
+			value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT)
+				& BCM43xx_DMA64_RXADDREXT_MASK;
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value);
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO,
+					(ringbase & 0xFFFFFFFF));
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI,
+					((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING)
+					| ring->routing);
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200);
+		} else {
+			u32 ringbase = (u32)(ring->dmabase);
+
+			addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT);
+			value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT);
+			value |= BCM43xx_DMA32_RXENABLE;
+			value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT)
+				& BCM43xx_DMA32_RXADDREXT_MASK;
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value);
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING,
+					(ringbase & ~BCM43xx_DMA32_ROUTING)
+					| ring->routing);
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200);
+		}
 	}
 
 out:
@@ -402,27 +534,32 @@
 static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring)
 {
 	if (ring->tx) {
-		bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base);
-		/* Zero out Transmit Descriptor ring address. */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_RING, 0);
+		bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+		if (ring->dma64) {
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0);
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0);
+		} else
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0);
 	} else {
-		bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base);
-		/* Zero out Receive Descriptor ring address. */
-		bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_RING, 0);
+		bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64);
+		if (ring->dma64) {
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0);
+			bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0);
+		} else
+			bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0);
 	}
 }
 
 static void free_all_descbuffers(struct bcm43xx_dmaring *ring)
 {
-	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	int i;
 
 	if (!ring->used_slots)
 		return;
 	for (i = 0; i < ring->nr_slots; i++) {
-		desc = ring->vbase + i;
-		meta = ring->meta + i;
+		desc = bcm43xx_dma_idx2desc(ring, i, &meta);
 
 		if (!meta->skb) {
 			assert(ring->tx);
@@ -430,62 +567,67 @@
 		}
 		if (ring->tx) {
 			unmap_descbuffer(ring, meta->dmaaddr,
-					 meta->skb->len, 1);
+					meta->skb->len, 1);
 		} else {
 			unmap_descbuffer(ring, meta->dmaaddr,
-					 ring->rx_buffersize, 0);
+					ring->rx_buffersize, 0);
 		}
-		free_descriptor_buffer(ring, desc, meta, 0);
+		free_descriptor_buffer(ring, meta, 0);
 	}
 }
 
 /* Main initialization function. */
 static
 struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm,
-					       u16 dma_controller_base,
-					       int nr_descriptor_slots,
-					       int tx)
+					       int controller_index,
+					       int for_tx,
+					       int dma64)
 {
 	struct bcm43xx_dmaring *ring;
 	int err;
+	int nr_slots;
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
 		goto out;
 
-	ring->meta = kzalloc(sizeof(*ring->meta) * nr_descriptor_slots,
+	nr_slots = BCM43xx_RXRING_SLOTS;
+	if (for_tx)
+		nr_slots = BCM43xx_TXRING_SLOTS;
+
+	ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta),
 			     GFP_KERNEL);
 	if (!ring->meta)
 		goto err_kfree_ring;
 
-	ring->memoffset = BCM43xx_DMA_DMABUSADDROFFSET;
+	ring->routing = BCM43xx_DMA32_CLIENTTRANS;
+	if (dma64)
+		ring->routing = BCM43xx_DMA64_CLIENTTRANS;
 #ifdef CONFIG_BCM947XX
 	if (bcm->pci_dev->bus->number == 0)
-		ring->memoffset = 0;
+		ring->routing = dma64 ? BCM43xx_DMA64_NOTRANS : BCM43xx_DMA32_NOTRANS;
 #endif
 
 	ring->bcm = bcm;
-	ring->nr_slots = nr_descriptor_slots;
+	ring->nr_slots = nr_slots;
 	ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100;
 	ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100;
 	assert(ring->suspend_mark < ring->resume_mark);
-	ring->mmio_base = dma_controller_base;
-	if (tx) {
+	ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index);
+	ring->index = controller_index;
+	ring->dma64 = !!dma64;
+	if (for_tx) {
 		ring->tx = 1;
 		ring->current_slot = -1;
 	} else {
-		switch (dma_controller_base) {
-		case BCM43xx_MMIO_DMA1_BASE:
-			ring->rx_buffersize = BCM43xx_DMA1_RXBUFFERSIZE;
-			ring->frameoffset = BCM43xx_DMA1_RX_FRAMEOFFSET;
-			break;
-		case BCM43xx_MMIO_DMA4_BASE:
-			ring->rx_buffersize = BCM43xx_DMA4_RXBUFFERSIZE;
-			ring->frameoffset = BCM43xx_DMA4_RX_FRAMEOFFSET;
-			break;
-		default:
+		if (ring->index == 0) {
+			ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE;
+			ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET;
+		} else if (ring->index == 3) {
+			ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE;
+			ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET;
+		} else
 			assert(0);
-		}
 	}
 
 	err = alloc_ringmemory(ring);
@@ -514,7 +656,8 @@
 	if (!ring)
 		return;
 
-	dprintk(KERN_INFO PFX "DMA 0x%04x (%s) max used slots: %d/%d\n",
+	dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
+		(ring->dma64) ? "64" : "32",
 		ring->mmio_base,
 		(ring->tx) ? "TX" : "RX",
 		ring->max_used_slots, ring->nr_slots);
@@ -537,10 +680,15 @@
 		return;
 	dma = bcm43xx_current_dma(bcm);
 
-	bcm43xx_destroy_dmaring(dma->rx_ring1);
-	dma->rx_ring1 = NULL;
+	bcm43xx_destroy_dmaring(dma->rx_ring3);
+	dma->rx_ring3 = NULL;
 	bcm43xx_destroy_dmaring(dma->rx_ring0);
 	dma->rx_ring0 = NULL;
+
+	bcm43xx_destroy_dmaring(dma->tx_ring5);
+	dma->tx_ring5 = NULL;
+	bcm43xx_destroy_dmaring(dma->tx_ring4);
+	dma->tx_ring4 = NULL;
 	bcm43xx_destroy_dmaring(dma->tx_ring3);
 	dma->tx_ring3 = NULL;
 	bcm43xx_destroy_dmaring(dma->tx_ring2);
@@ -556,48 +704,59 @@
 	struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm);
 	struct bcm43xx_dmaring *ring;
 	int err = -ENOMEM;
+	int dma64 = 0;
+	u32 sbtmstatehi;
+
+	sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH);
+	if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT)
+		dma64 = 1;
 
 	/* setup TX DMA channels. */
-	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
-				     BCM43xx_TXRING_SLOTS, 1);
+	ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64);
 	if (!ring)
 		goto out;
 	dma->tx_ring0 = ring;
 
-	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA2_BASE,
-				     BCM43xx_TXRING_SLOTS, 1);
+	ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64);
 	if (!ring)
 		goto err_destroy_tx0;
 	dma->tx_ring1 = ring;
 
-	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA3_BASE,
-				     BCM43xx_TXRING_SLOTS, 1);
+	ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64);
 	if (!ring)
 		goto err_destroy_tx1;
 	dma->tx_ring2 = ring;
 
-	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
-				     BCM43xx_TXRING_SLOTS, 1);
+	ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64);
 	if (!ring)
 		goto err_destroy_tx2;
 	dma->tx_ring3 = ring;
 
-	/* setup RX DMA channels. */
-	ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA1_BASE,
-				     BCM43xx_RXRING_SLOTS, 0);
+	ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64);
 	if (!ring)
 		goto err_destroy_tx3;
+	dma->tx_ring4 = ring;
+
+	ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64);
+	if (!ring)
+		goto err_destroy_tx4;
+	dma->tx_ring5 = ring;
+
+	/* setup RX DMA channels. */
+	ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64);
+	if (!ring)
+		goto err_destroy_tx5;
 	dma->rx_ring0 = ring;
 
 	if (bcm->current_core->rev < 5) {
-		ring = bcm43xx_setup_dmaring(bcm, BCM43xx_MMIO_DMA4_BASE,
-					     BCM43xx_RXRING_SLOTS, 0);
+		ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64);
 		if (!ring)
 			goto err_destroy_rx0;
-		dma->rx_ring1 = ring;
+		dma->rx_ring3 = ring;
 	}
 
-	dprintk(KERN_INFO PFX "DMA initialized\n");
+	dprintk(KERN_INFO PFX "%s DMA initialized\n",
+			dma64 ? "64-bit" : "32-bit");
 	err = 0;
 out:
 	return err;
@@ -605,6 +764,12 @@
 err_destroy_rx0:
 	bcm43xx_destroy_dmaring(dma->rx_ring0);
 	dma->rx_ring0 = NULL;
+err_destroy_tx5:
+	bcm43xx_destroy_dmaring(dma->tx_ring5);
+	dma->tx_ring5 = NULL;
+err_destroy_tx4:
+	bcm43xx_destroy_dmaring(dma->tx_ring4);
+	dma->tx_ring4 = NULL;
 err_destroy_tx3:
 	bcm43xx_destroy_dmaring(dma->tx_ring3);
 	dma->tx_ring3 = NULL;
@@ -624,7 +789,7 @@
 static u16 generate_cookie(struct bcm43xx_dmaring *ring,
 			   int slot)
 {
-	u16 cookie = 0xF000;
+	u16 cookie = 0x1000;
 
 	/* Use the upper 4 bits of the cookie as
 	 * DMA controller ID and store the slot number
@@ -632,21 +797,25 @@
 	 * Note that the cookie must never be 0, as this
 	 * is a special value used in RX path.
 	 */
-	switch (ring->mmio_base) {
-	default:
-		assert(0);
-	case BCM43xx_MMIO_DMA1_BASE:
+	switch (ring->index) {
+	case 0:
 		cookie = 0xA000;
 		break;
-	case BCM43xx_MMIO_DMA2_BASE:
+	case 1:
 		cookie = 0xB000;
 		break;
-	case BCM43xx_MMIO_DMA3_BASE:
+	case 2:
 		cookie = 0xC000;
 		break;
-	case BCM43xx_MMIO_DMA4_BASE:
+	case 3:
 		cookie = 0xD000;
 		break;
+	case 4:
+		cookie = 0xE000;
+		break;
+	case 5:
+		cookie = 0xF000;
+		break;
 	}
 	assert(((u16)slot & 0xF000) == 0x0000);
 	cookie |= (u16)slot;
@@ -675,6 +844,12 @@
 	case 0xD000:
 		ring = dma->tx_ring3;
 		break;
+	case 0xE000:
+		ring = dma->tx_ring4;
+		break;
+	case 0xF000:
+		ring = dma->tx_ring5;
+		break;
 	default:
 		assert(0);
 	}
@@ -687,6 +862,9 @@
 static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring,
 				  int slot)
 {
+	u16 offset;
+	int descsize;
+
 	/* Everything is ready to start. Buffers are DMA mapped and
 	 * associated with slots.
 	 * "slot" is the last slot of the new frame we want to transmit.
@@ -694,25 +872,26 @@
 	 */
 	wmb();
 	slot = next_slot(ring, slot);
-	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_DESC_INDEX,
-			  (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+	offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX;
+	descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64)
+		: sizeof(struct bcm43xx_dmadesc32);
+	bcm43xx_dma_write(ring, offset,
+			(u32)(slot * descsize));
 }
 
-static int dma_tx_fragment(struct bcm43xx_dmaring *ring,
-			   struct sk_buff *skb,
-			   u8 cur_frag)
+static void dma_tx_fragment(struct bcm43xx_dmaring *ring,
+			    struct sk_buff *skb,
+			    u8 cur_frag)
 {
 	int slot;
-	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
-	u32 desc_ctl;
-	u32 desc_addr;
+	dma_addr_t dmaaddr;
 
 	assert(skb_shinfo(skb)->nr_frags == 0);
 
 	slot = request_slot(ring);
-	desc = ring->vbase + slot;
-	meta = ring->meta + slot;
+	desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
 
 	/* Add a device specific TX header. */
 	assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr));
@@ -729,29 +908,14 @@
 			       generate_cookie(ring, slot));
 
 	meta->skb = skb;
-	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
-	if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) {
-		return_slot(ring, slot);
-		printk(KERN_ERR PFX ">>>FATAL ERROR<<<  DMA TX SKB >1G "
-				    "(0x%llx, len: %u)\n",
-			(unsigned long long)meta->dmaaddr, skb->len);
-		return -ENOMEM;
-	}
+	dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+	meta->dmaaddr = dmaaddr;
 
-	desc_addr = (u32)(meta->dmaaddr + ring->memoffset);
-	desc_ctl = BCM43xx_DMADTOR_FRAMESTART | BCM43xx_DMADTOR_FRAMEEND;
-	desc_ctl |= BCM43xx_DMADTOR_COMPIRQ;
-	desc_ctl |= (BCM43xx_DMADTOR_BYTECNT_MASK &
-		     (u32)(meta->skb->len - ring->frameoffset));
-	if (slot == ring->nr_slots - 1)
-		desc_ctl |= BCM43xx_DMADTOR_DTABLEEND;
+	fill_descriptor(ring, desc, dmaaddr,
+			skb->len, 1, 1, 1);
 
-	set_desc_ctl(desc, desc_ctl);
-	set_desc_addr(desc, desc_addr);
 	/* Now transfer the whole frame. */
 	dmacontroller_poke_tx(ring, slot);
-
-	return 0;
 }
 
 int bcm43xx_dma_tx(struct bcm43xx_private *bcm,
@@ -781,7 +945,6 @@
 		/* Take skb from ieee80211_txb_free */
 		txb->fragments[i] = NULL;
 		dma_tx_fragment(ring, skb, i);
-		//TODO: handle failure of dma_tx_fragment
 	}
 	ieee80211_txb_free(txb);
 
@@ -792,23 +955,28 @@
 				   struct bcm43xx_xmitstatus *status)
 {
 	struct bcm43xx_dmaring *ring;
-	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	int is_last_fragment;
 	int slot;
+	u32 tmp;
 
 	ring = parse_cookie(bcm, status->cookie, &slot);
 	assert(ring);
 	assert(ring->tx);
-	assert(get_desc_ctl(ring->vbase + slot) & BCM43xx_DMADTOR_FRAMESTART);
 	while (1) {
 		assert(slot >= 0 && slot < ring->nr_slots);
-		desc = ring->vbase + slot;
-		meta = ring->meta + slot;
+		desc = bcm43xx_dma_idx2desc(ring, slot, &meta);
 
-		is_last_fragment = !!(get_desc_ctl(desc) & BCM43xx_DMADTOR_FRAMEEND);
+		if (ring->dma64) {
+			tmp = le32_to_cpu(desc->dma64.control0);
+			is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND);
+		} else {
+			tmp = le32_to_cpu(desc->dma32.control);
+			is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND);
+		}
 		unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
-		free_descriptor_buffer(ring, desc, meta, 1);
+		free_descriptor_buffer(ring, meta, 1);
 		/* Everything belonging to the slot is unmapped
 		 * and freed, so we can return it.
 		 */
@@ -824,7 +992,7 @@
 static void dma_rx(struct bcm43xx_dmaring *ring,
 		   int *slot)
 {
-	struct bcm43xx_dmadesc *desc;
+	struct bcm43xx_dmadesc_generic *desc;
 	struct bcm43xx_dmadesc_meta *meta;
 	struct bcm43xx_rxhdr *rxhdr;
 	struct sk_buff *skb;
@@ -832,13 +1000,12 @@
 	int err;
 	dma_addr_t dmaaddr;
 
-	desc = ring->vbase + *slot;
-	meta = ring->meta + *slot;
+	desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
 
 	sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
 	skb = meta->skb;
 
-	if (ring->mmio_base == BCM43xx_MMIO_DMA4_BASE) {
+	if (ring->index == 3) {
 		/* We received an xmit status. */
 		struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data;
 		struct bcm43xx_xmitstatus stat;
@@ -894,8 +1061,7 @@
 		s32 tmp = len;
 
 		while (1) {
-			desc = ring->vbase + *slot;
-			meta = ring->meta + *slot;
+			desc = bcm43xx_dma_idx2desc(ring, *slot, &meta);
 			/* recycle the descriptor buffer. */
 			sync_descbuffer_for_device(ring, meta->dmaaddr,
 						   ring->rx_buffersize);
@@ -906,8 +1072,8 @@
 				break;
 		}
 		printkl(KERN_ERR PFX "DMA RX buffer too small "
-				     "(len: %u, buffer: %u, nr-dropped: %d)\n",
-		        len, ring->rx_buffersize, cnt);
+			"(len: %u, buffer: %u, nr-dropped: %d)\n",
+			len, ring->rx_buffersize, cnt);
 		goto drop;
 	}
 	len -= IEEE80211_FCS_LEN;
@@ -945,9 +1111,15 @@
 #endif
 
 	assert(!ring->tx);
-	status = bcm43xx_dma_read(ring, BCM43xx_DMA_RX_STATUS);
-	descptr = (status & BCM43xx_DMA_RXSTAT_DPTR_MASK);
-	current_slot = descptr / sizeof(struct bcm43xx_dmadesc);
+	if (ring->dma64) {
+		status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS);
+		descptr = (status & BCM43xx_DMA64_RXSTATDPTR);
+		current_slot = descptr / sizeof(struct bcm43xx_dmadesc64);
+	} else {
+		status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS);
+		descptr = (status & BCM43xx_DMA32_RXDPTR);
+		current_slot = descptr / sizeof(struct bcm43xx_dmadesc32);
+	}
 	assert(current_slot >= 0 && current_slot < ring->nr_slots);
 
 	slot = ring->current_slot;
@@ -958,8 +1130,13 @@
 			ring->max_used_slots = used_slots;
 #endif
 	}
-	bcm43xx_dma_write(ring, BCM43xx_DMA_RX_DESC_INDEX,
-			  (u32)(slot * sizeof(struct bcm43xx_dmadesc)));
+	if (ring->dma64) {
+		bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX,
+				(u32)(slot * sizeof(struct bcm43xx_dmadesc64)));
+	} else {
+		bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX,
+				(u32)(slot * sizeof(struct bcm43xx_dmadesc32)));
+	}
 	ring->current_slot = slot;
 }
 
@@ -967,16 +1144,28 @@
 {
 	assert(ring->tx);
 	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1);
-	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
-			  bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
-			  | BCM43xx_DMA_TXCTRL_SUSPEND);
+	if (ring->dma64) {
+		bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+				bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+				| BCM43xx_DMA64_TXSUSPEND);
+	} else {
+		bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+				bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+				| BCM43xx_DMA32_TXSUSPEND);
+	}
 }
 
 void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring)
 {
 	assert(ring->tx);
-	bcm43xx_dma_write(ring, BCM43xx_DMA_TX_CONTROL,
-			  bcm43xx_dma_read(ring, BCM43xx_DMA_TX_CONTROL)
-			  & ~BCM43xx_DMA_TXCTRL_SUSPEND);
+	if (ring->dma64) {
+		bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL,
+				bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL)
+				& ~BCM43xx_DMA64_TXSUSPEND);
+	} else {
+		bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL,
+				bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL)
+				& ~BCM43xx_DMA32_TXSUSPEND);
+	}
 	bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1);
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
index b7d7763..e04bcad 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h
@@ -14,63 +14,179 @@
 #define BCM43xx_DMAIRQ_NONFATALMASK	(1 << 13)
 #define BCM43xx_DMAIRQ_RX_DONE		(1 << 16)
 
-/* DMA controller register offsets. (relative to BCM43xx_DMA#_BASE) */
-#define BCM43xx_DMA_TX_CONTROL		0x00
-#define BCM43xx_DMA_TX_DESC_RING	0x04
-#define BCM43xx_DMA_TX_DESC_INDEX	0x08
-#define BCM43xx_DMA_TX_STATUS		0x0c
-#define BCM43xx_DMA_RX_CONTROL		0x10
-#define BCM43xx_DMA_RX_DESC_RING	0x14
-#define BCM43xx_DMA_RX_DESC_INDEX	0x18
-#define BCM43xx_DMA_RX_STATUS		0x1c
 
-/* DMA controller channel control word values. */
-#define BCM43xx_DMA_TXCTRL_ENABLE		(1 << 0)
-#define BCM43xx_DMA_TXCTRL_SUSPEND		(1 << 1)
-#define BCM43xx_DMA_TXCTRL_LOOPBACK		(1 << 2)
-#define BCM43xx_DMA_TXCTRL_FLUSH		(1 << 4)
-#define BCM43xx_DMA_RXCTRL_ENABLE		(1 << 0)
-#define BCM43xx_DMA_RXCTRL_FRAMEOFF_MASK	0x000000fe
-#define BCM43xx_DMA_RXCTRL_FRAMEOFF_SHIFT	1
-#define BCM43xx_DMA_RXCTRL_PIO			(1 << 8)
-/* DMA controller channel status word values. */
-#define BCM43xx_DMA_TXSTAT_DPTR_MASK		0x00000fff
-#define BCM43xx_DMA_TXSTAT_STAT_MASK		0x0000f000
-#define BCM43xx_DMA_TXSTAT_STAT_DISABLED	0x00000000
-#define BCM43xx_DMA_TXSTAT_STAT_ACTIVE		0x00001000
-#define BCM43xx_DMA_TXSTAT_STAT_IDLEWAIT	0x00002000
-#define BCM43xx_DMA_TXSTAT_STAT_STOPPED		0x00003000
-#define BCM43xx_DMA_TXSTAT_STAT_SUSP		0x00004000
-#define BCM43xx_DMA_TXSTAT_ERROR_MASK		0x000f0000
-#define BCM43xx_DMA_TXSTAT_FLUSHED		(1 << 20)
-#define BCM43xx_DMA_RXSTAT_DPTR_MASK		0x00000fff
-#define BCM43xx_DMA_RXSTAT_STAT_MASK		0x0000f000
-#define BCM43xx_DMA_RXSTAT_STAT_DISABLED	0x00000000
-#define BCM43xx_DMA_RXSTAT_STAT_ACTIVE		0x00001000
-#define BCM43xx_DMA_RXSTAT_STAT_IDLEWAIT	0x00002000
-#define BCM43xx_DMA_RXSTAT_STAT_RESERVED	0x00003000
-#define BCM43xx_DMA_RXSTAT_STAT_ERRORS		0x00004000
-#define BCM43xx_DMA_RXSTAT_ERROR_MASK		0x000f0000
+/*** 32-bit DMA Engine. ***/
 
-/* DMA descriptor control field values. */
-#define BCM43xx_DMADTOR_BYTECNT_MASK		0x00001fff
-#define BCM43xx_DMADTOR_DTABLEEND		(1 << 28) /* End of descriptor table */
-#define BCM43xx_DMADTOR_COMPIRQ			(1 << 29) /* IRQ on completion request */
-#define BCM43xx_DMADTOR_FRAMEEND		(1 << 30)
-#define BCM43xx_DMADTOR_FRAMESTART		(1 << 31)
+/* 32-bit DMA controller registers. */
+#define BCM43xx_DMA32_TXCTL				0x00
+#define		BCM43xx_DMA32_TXENABLE			0x00000001
+#define		BCM43xx_DMA32_TXSUSPEND			0x00000002
+#define		BCM43xx_DMA32_TXLOOPBACK		0x00000004
+#define		BCM43xx_DMA32_TXFLUSH			0x00000010
+#define		BCM43xx_DMA32_TXADDREXT_MASK		0x00030000
+#define		BCM43xx_DMA32_TXADDREXT_SHIFT		16
+#define BCM43xx_DMA32_TXRING				0x04
+#define BCM43xx_DMA32_TXINDEX				0x08
+#define BCM43xx_DMA32_TXSTATUS				0x0C
+#define		BCM43xx_DMA32_TXDPTR			0x00000FFF
+#define		BCM43xx_DMA32_TXSTATE			0x0000F000
+#define			BCM43xx_DMA32_TXSTAT_DISABLED	0x00000000
+#define			BCM43xx_DMA32_TXSTAT_ACTIVE	0x00001000
+#define			BCM43xx_DMA32_TXSTAT_IDLEWAIT	0x00002000
+#define			BCM43xx_DMA32_TXSTAT_STOPPED	0x00003000
+#define			BCM43xx_DMA32_TXSTAT_SUSP	0x00004000
+#define		BCM43xx_DMA32_TXERROR			0x000F0000
+#define			BCM43xx_DMA32_TXERR_NOERR	0x00000000
+#define			BCM43xx_DMA32_TXERR_PROT	0x00010000
+#define			BCM43xx_DMA32_TXERR_UNDERRUN	0x00020000
+#define			BCM43xx_DMA32_TXERR_BUFREAD	0x00030000
+#define			BCM43xx_DMA32_TXERR_DESCREAD	0x00040000
+#define		BCM43xx_DMA32_TXACTIVE			0xFFF00000
+#define BCM43xx_DMA32_RXCTL				0x10
+#define		BCM43xx_DMA32_RXENABLE			0x00000001
+#define		BCM43xx_DMA32_RXFROFF_MASK		0x000000FE
+#define		BCM43xx_DMA32_RXFROFF_SHIFT		1
+#define		BCM43xx_DMA32_RXDIRECTFIFO		0x00000100
+#define		BCM43xx_DMA32_RXADDREXT_MASK		0x00030000
+#define		BCM43xx_DMA32_RXADDREXT_SHIFT		16
+#define BCM43xx_DMA32_RXRING				0x14
+#define BCM43xx_DMA32_RXINDEX				0x18
+#define BCM43xx_DMA32_RXSTATUS				0x1C
+#define		BCM43xx_DMA32_RXDPTR			0x00000FFF
+#define		BCM43xx_DMA32_RXSTATE			0x0000F000
+#define			BCM43xx_DMA32_RXSTAT_DISABLED	0x00000000
+#define			BCM43xx_DMA32_RXSTAT_ACTIVE	0x00001000
+#define			BCM43xx_DMA32_RXSTAT_IDLEWAIT	0x00002000
+#define			BCM43xx_DMA32_RXSTAT_STOPPED	0x00003000
+#define		BCM43xx_DMA32_RXERROR			0x000F0000
+#define			BCM43xx_DMA32_RXERR_NOERR	0x00000000
+#define			BCM43xx_DMA32_RXERR_PROT	0x00010000
+#define			BCM43xx_DMA32_RXERR_OVERFLOW	0x00020000
+#define			BCM43xx_DMA32_RXERR_BUFWRITE	0x00030000
+#define			BCM43xx_DMA32_RXERR_DESCREAD	0x00040000
+#define		BCM43xx_DMA32_RXACTIVE			0xFFF00000
+
+/* 32-bit DMA descriptor. */
+struct bcm43xx_dmadesc32 {
+	__le32 control;
+	__le32 address;
+} __attribute__((__packed__));
+#define BCM43xx_DMA32_DCTL_BYTECNT		0x00001FFF
+#define BCM43xx_DMA32_DCTL_ADDREXT_MASK		0x00030000
+#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT	16
+#define BCM43xx_DMA32_DCTL_DTABLEEND		0x10000000
+#define BCM43xx_DMA32_DCTL_IRQ			0x20000000
+#define BCM43xx_DMA32_DCTL_FRAMEEND		0x40000000
+#define BCM43xx_DMA32_DCTL_FRAMESTART		0x80000000
+
+/* Address field Routing value. */
+#define BCM43xx_DMA32_ROUTING			0xC0000000
+#define BCM43xx_DMA32_ROUTING_SHIFT		30
+#define		BCM43xx_DMA32_NOTRANS		0x00000000
+#define		BCM43xx_DMA32_CLIENTTRANS	0x40000000
+
+
+
+/*** 64-bit DMA Engine. ***/
+
+/* 64-bit DMA controller registers. */
+#define BCM43xx_DMA64_TXCTL				0x00
+#define		BCM43xx_DMA64_TXENABLE			0x00000001
+#define		BCM43xx_DMA64_TXSUSPEND			0x00000002
+#define		BCM43xx_DMA64_TXLOOPBACK		0x00000004
+#define		BCM43xx_DMA64_TXFLUSH			0x00000010
+#define		BCM43xx_DMA64_TXADDREXT_MASK		0x00030000
+#define		BCM43xx_DMA64_TXADDREXT_SHIFT		16
+#define BCM43xx_DMA64_TXINDEX				0x04
+#define BCM43xx_DMA64_TXRINGLO				0x08
+#define BCM43xx_DMA64_TXRINGHI				0x0C
+#define BCM43xx_DMA64_TXSTATUS				0x10
+#define		BCM43xx_DMA64_TXSTATDPTR		0x00001FFF
+#define		BCM43xx_DMA64_TXSTAT			0xF0000000
+#define			BCM43xx_DMA64_TXSTAT_DISABLED	0x00000000
+#define			BCM43xx_DMA64_TXSTAT_ACTIVE	0x10000000
+#define			BCM43xx_DMA64_TXSTAT_IDLEWAIT	0x20000000
+#define			BCM43xx_DMA64_TXSTAT_STOPPED	0x30000000
+#define			BCM43xx_DMA64_TXSTAT_SUSP	0x40000000
+#define BCM43xx_DMA64_TXERROR				0x14
+#define		BCM43xx_DMA64_TXERRDPTR			0x0001FFFF
+#define		BCM43xx_DMA64_TXERR			0xF0000000
+#define			BCM43xx_DMA64_TXERR_NOERR	0x00000000
+#define			BCM43xx_DMA64_TXERR_PROT	0x10000000
+#define			BCM43xx_DMA64_TXERR_UNDERRUN	0x20000000
+#define			BCM43xx_DMA64_TXERR_TRANSFER	0x30000000
+#define			BCM43xx_DMA64_TXERR_DESCREAD	0x40000000
+#define			BCM43xx_DMA64_TXERR_CORE	0x50000000
+#define BCM43xx_DMA64_RXCTL				0x20
+#define		BCM43xx_DMA64_RXENABLE			0x00000001
+#define		BCM43xx_DMA64_RXFROFF_MASK		0x000000FE
+#define		BCM43xx_DMA64_RXFROFF_SHIFT		1
+#define		BCM43xx_DMA64_RXDIRECTFIFO		0x00000100
+#define		BCM43xx_DMA64_RXADDREXT_MASK		0x00030000
+#define		BCM43xx_DMA64_RXADDREXT_SHIFT		16
+#define BCM43xx_DMA64_RXINDEX				0x24
+#define BCM43xx_DMA64_RXRINGLO				0x28
+#define BCM43xx_DMA64_RXRINGHI				0x2C
+#define BCM43xx_DMA64_RXSTATUS				0x30
+#define		BCM43xx_DMA64_RXSTATDPTR		0x00001FFF
+#define		BCM43xx_DMA64_RXSTAT			0xF0000000
+#define			BCM43xx_DMA64_RXSTAT_DISABLED	0x00000000
+#define			BCM43xx_DMA64_RXSTAT_ACTIVE	0x10000000
+#define			BCM43xx_DMA64_RXSTAT_IDLEWAIT	0x20000000
+#define			BCM43xx_DMA64_RXSTAT_STOPPED	0x30000000
+#define			BCM43xx_DMA64_RXSTAT_SUSP	0x40000000
+#define BCM43xx_DMA64_RXERROR				0x34
+#define		BCM43xx_DMA64_RXERRDPTR			0x0001FFFF
+#define		BCM43xx_DMA64_RXERR			0xF0000000
+#define			BCM43xx_DMA64_RXERR_NOERR	0x00000000
+#define			BCM43xx_DMA64_RXERR_PROT	0x10000000
+#define			BCM43xx_DMA64_RXERR_UNDERRUN	0x20000000
+#define			BCM43xx_DMA64_RXERR_TRANSFER	0x30000000
+#define			BCM43xx_DMA64_RXERR_DESCREAD	0x40000000
+#define			BCM43xx_DMA64_RXERR_CORE	0x50000000
+
+/* 64-bit DMA descriptor. */
+struct bcm43xx_dmadesc64 {
+	__le32 control0;
+	__le32 control1;
+	__le32 address_low;
+	__le32 address_high;
+} __attribute__((__packed__));
+#define BCM43xx_DMA64_DCTL0_DTABLEEND		0x10000000
+#define BCM43xx_DMA64_DCTL0_IRQ			0x20000000
+#define BCM43xx_DMA64_DCTL0_FRAMEEND		0x40000000
+#define BCM43xx_DMA64_DCTL0_FRAMESTART		0x80000000
+#define BCM43xx_DMA64_DCTL1_BYTECNT		0x00001FFF
+#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK	0x00030000
+#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT	16
+
+/* Address field Routing value. */
+#define BCM43xx_DMA64_ROUTING			0xC0000000
+#define BCM43xx_DMA64_ROUTING_SHIFT		30
+#define		BCM43xx_DMA64_NOTRANS		0x00000000
+#define		BCM43xx_DMA64_CLIENTTRANS	0x80000000
+
+
+
+struct bcm43xx_dmadesc_generic {
+	union {
+		struct bcm43xx_dmadesc32 dma32;
+		struct bcm43xx_dmadesc64 dma64;
+	} __attribute__((__packed__));
+} __attribute__((__packed__));
+
 
 /* Misc DMA constants */
 #define BCM43xx_DMA_RINGMEMSIZE		PAGE_SIZE
-#define BCM43xx_DMA_BUSADDRMAX		0x3FFFFFFF
-#define BCM43xx_DMA_DMABUSADDROFFSET	(1 << 30)
-#define BCM43xx_DMA1_RX_FRAMEOFFSET	30
-#define BCM43xx_DMA4_RX_FRAMEOFFSET	0
+#define BCM43xx_DMA0_RX_FRAMEOFFSET	30
+#define BCM43xx_DMA3_RX_FRAMEOFFSET	0
+
 
 /* DMA engine tuning knobs */
 #define BCM43xx_TXRING_SLOTS		512
 #define BCM43xx_RXRING_SLOTS		64
-#define BCM43xx_DMA1_RXBUFFERSIZE	(2304 + 100)
-#define BCM43xx_DMA4_RXBUFFERSIZE	16
+#define BCM43xx_DMA0_RX_BUFFERSIZE	(2304 + 100)
+#define BCM43xx_DMA3_RX_BUFFERSIZE	16
 /* Suspend the tx queue, if less than this percent slots are free. */
 #define BCM43xx_TXSUSPEND_PERCENT	20
 /* Resume the tx queue, if more than this percent slots are free. */
@@ -86,17 +202,6 @@
 struct bcm43xx_xmitstatus;
 
 
-struct bcm43xx_dmadesc {
-	__le32 _control;
-	__le32 _address;
-} __attribute__((__packed__));
-
-/* Macros to access the bcm43xx_dmadesc struct */
-#define get_desc_ctl(desc)		le32_to_cpu((desc)->_control)
-#define set_desc_ctl(desc, ctl)		do { (desc)->_control = cpu_to_le32(ctl); } while (0)
-#define get_desc_addr(desc)		le32_to_cpu((desc)->_address)
-#define set_desc_addr(desc, addr)	do { (desc)->_address = cpu_to_le32(addr); } while (0)
-
 struct bcm43xx_dmadesc_meta {
 	/* The kernel DMA-able buffer. */
 	struct sk_buff *skb;
@@ -105,15 +210,14 @@
 };
 
 struct bcm43xx_dmaring {
-	struct bcm43xx_private *bcm;
 	/* Kernel virtual base address of the ring memory. */
-	struct bcm43xx_dmadesc *vbase;
-	/* DMA memory offset */
-	dma_addr_t memoffset;
-	/* (Unadjusted) DMA base bus-address of the ring memory. */
-	dma_addr_t dmabase;
+	void *descbase;
 	/* Meta data about all descriptors. */
 	struct bcm43xx_dmadesc_meta *meta;
+	/* DMA Routing value. */
+	u32 routing;
+	/* (Unadjusted) DMA base bus-address of the ring memory. */
+	dma_addr_t dmabase;
 	/* Number of descriptor slots in the ring. */
 	int nr_slots;
 	/* Number of used descriptor slots. */
@@ -127,12 +231,17 @@
 	u32 frameoffset;
 	/* Descriptor buffer size. */
 	u16 rx_buffersize;
-	/* The MMIO base register of the DMA controller, this
-	 * ring is posted to.
-	 */
+	/* The MMIO base register of the DMA controller. */
 	u16 mmio_base;
-	u8 tx:1,	/* TRUE, if this is a TX ring. */
-	   suspended:1;	/* TRUE, if transfers are suspended on this ring. */
+	/* DMA controller index number (0-5). */
+	int index;
+	/* Boolean. Is this a TX ring? */
+	u8 tx;
+	/* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
+	u8 dma64;
+	/* Boolean. Are transfers suspended on this ring? */
+	u8 suspended;
+	struct bcm43xx_private *bcm;
 #ifdef CONFIG_BCM43XX_DEBUG
 	/* Maximum number of used slots. */
 	int max_used_slots;
@@ -141,6 +250,34 @@
 
 
 static inline
+int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring,
+			 struct bcm43xx_dmadesc_generic *desc)
+{
+	if (ring->dma64) {
+		struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+		return (int)(&(desc->dma64) - dd64);
+	} else {
+		struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+		return (int)(&(desc->dma32) - dd32);
+	}
+}
+
+static inline
+struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring,
+						      int slot,
+						      struct bcm43xx_dmadesc_meta **meta)
+{
+	*meta = &(ring->meta[slot]);
+	if (ring->dma64) {
+		struct bcm43xx_dmadesc64 *dd64 = ring->descbase;
+		return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot]));
+	} else {
+		struct bcm43xx_dmadesc32 *dd32 = ring->descbase;
+		return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot]));
+	}
+}
+
+static inline
 u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring,
 		     u16 offset)
 {
@@ -159,9 +296,13 @@
 void bcm43xx_dma_free(struct bcm43xx_private *bcm);
 
 int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-				   u16 dmacontroller_mmio_base);
+				   u16 dmacontroller_mmio_base,
+				   int dma64);
 int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-				   u16 dmacontroller_mmio_base);
+				   u16 dmacontroller_mmio_base,
+				   int dma64);
+
+u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx);
 
 void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring);
 void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring);
@@ -173,7 +314,6 @@
 		   struct ieee80211_txb *txb);
 void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring);
 
-
 #else /* CONFIG_BCM43XX_DMA */
 
 
@@ -188,13 +328,15 @@
 }
 static inline
 int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm,
-				   u16 dmacontroller_mmio_base)
+				   u16 dmacontroller_mmio_base,
+				   int dma64)
 {
 	return 0;
 }
 static inline
 int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm,
-				   u16 dmacontroller_mmio_base)
+				   u16 dmacontroller_mmio_base,
+				   int dma64)
 {
 	return 0;
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index ec80692..c3f90c8 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -51,12 +51,12 @@
 	struct bcm43xx_private *bcm = led->bcm;
 	unsigned long flags;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->leds_lock, flags);
 	if (led->blink_interval) {
 		bcm43xx_led_changestate(led);
 		mod_timer(&led->blink_timer, jiffies + led->blink_interval);
 	}
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
 
 static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
@@ -177,7 +177,9 @@
 	int i, turn_on;
 	unsigned long interval = 0;
 	u16 ledctl;
+	unsigned long flags;
 
+	spin_lock_irqsave(&bcm->leds_lock, flags);
 	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
 	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
 		led = &(bcm->leds[i]);
@@ -266,6 +268,7 @@
 			ledctl &= ~(1 << i);
 	}
 	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+	spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
 
 void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on)
@@ -274,7 +277,9 @@
 	u16 ledctl;
 	int i;
 	int bit_on;
+	unsigned long flags;
 
+	spin_lock_irqsave(&bcm->leds_lock, flags);
 	ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL);
 	for (i = 0; i < BCM43xx_NR_LEDS; i++) {
 		led = &(bcm->leds[i]);
@@ -290,4 +295,5 @@
 			ledctl &= ~(1 << i);
 	}
 	bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl);
+	spin_unlock_irqrestore(&bcm->leds_lock, flags);
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 3889f79..cb9a3ae 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -509,23 +509,20 @@
 }
 
 /* Make sure we don't receive more data from the device. */
-static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
+static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm)
 {
 	unsigned long flags;
-	u32 old;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
-		bcm43xx_unlock_irqonly(bcm, flags);
+		spin_unlock_irqrestore(&bcm->irq_lock, flags);
 		return -EBUSY;
 	}
-	old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-	bcm43xx_unlock_irqonly(bcm, flags);
+	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 	bcm43xx_synchronize_irq(bcm);
 
-	if (oldstate)
-		*oldstate = old;
-
 	return 0;
 }
 
@@ -537,7 +534,6 @@
 	u16 manufact;
 	u16 version;
 	u8 revision;
-	s8 i;
 
 	if (bcm->chip_id == 0x4317) {
 		if (bcm->chip_rev == 0x00)
@@ -580,20 +576,11 @@
 	radio->version = version;
 	radio->revision = revision;
 
-	/* Set default attenuation values. */
-	radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
-	radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
-	radio->txctl1 = bcm43xx_default_txctl1(bcm);
-	radio->txctl2 = 0xFFFF;
 	if (phy->type == BCM43xx_PHYTYPE_A)
 		radio->txpower_desired = bcm->sprom.maxpower_aphy;
 	else
 		radio->txpower_desired = bcm->sprom.maxpower_bgphy;
 
-	/* Initialize the in-memory nrssi Lookup Table. */
-	for (i = 0; i < 64; i++)
-		radio->nrssi_lt[i] = i;
-
 	return 0;
 
 err_unsupported_radio:
@@ -1250,10 +1237,6 @@
 		goto out;
 
 	bcm->current_core = new_core;
-	bcm->current_80211_core_idx = -1;
-	if (new_core->id == BCM43xx_COREID_80211)
-		bcm->current_80211_core_idx = (int)(new_core - &(bcm->core_80211[0]));
-
 out:
 	return err;
 }
@@ -1389,6 +1372,7 @@
 	if ((bcm43xx_core_enabled(bcm)) &&
 	    !bcm43xx_using_pio(bcm)) {
 //FIXME: Do we _really_ want #ifndef CONFIG_BCM947XX here?
+#if 0
 #ifndef CONFIG_BCM947XX
 		/* reset all used DMA controllers. */
 		bcm43xx_dmacontroller_tx_reset(bcm, BCM43xx_MMIO_DMA1_BASE);
@@ -1399,6 +1383,7 @@
 		if (bcm->current_core->rev < 5)
 			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
 #endif
+#endif
 	}
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
@@ -1423,43 +1408,23 @@
 	bcm43xx_core_disable(bcm, 0);
 }
 
-/* Mark the current 80211 core inactive.
- * "active_80211_core" is the other 80211 core, which is used.
- */
-static int bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm,
-					       struct bcm43xx_coreinfo *active_80211_core)
+/* Mark the current 80211 core inactive. */
+static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm)
 {
 	u32 sbtmstatelow;
-	struct bcm43xx_coreinfo *old_core;
-	int err = 0;
 
 	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 	bcm43xx_radio_turn_off(bcm);
 	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-	sbtmstatelow &= ~0x200a0000;
-	sbtmstatelow |= 0xa0000;
+	sbtmstatelow &= 0xDFF5FFFF;
+	sbtmstatelow |= 0x000A0000;
 	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
 	udelay(1);
 	sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-	sbtmstatelow &= ~0xa0000;
-	sbtmstatelow |= 0x80000;
+	sbtmstatelow &= 0xFFF5FFFF;
+	sbtmstatelow |= 0x00080000;
 	bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
 	udelay(1);
-
-	if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G) {
-		old_core = bcm->current_core;
-		err = bcm43xx_switch_core(bcm, active_80211_core);
-		if (err)
-			goto out;
-		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
-		sbtmstatelow &= ~0x20000000;
-		sbtmstatelow |= 0x20000000;
-		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
-		err = bcm43xx_switch_core(bcm, old_core);
-	}
-
-out:
-	return err;
 }
 
 static void handle_irq_transmit_status(struct bcm43xx_private *bcm)
@@ -1581,17 +1546,7 @@
 		else
 			average -= 48;
 
-/* FIXME: This is wrong, but people want fancy stats. well... */
-bcm->stats.noise = average;
-		if (average > -65)
-			bcm->stats.link_quality = 0;
-		else if (average > -75)
-			bcm->stats.link_quality = 1;
-		else if (average > -85)
-			bcm->stats.link_quality = 2;
-		else
-			bcm->stats.link_quality = 3;
-//		dprintk(KERN_INFO PFX "Link Quality: %u (avg was %d)\n", bcm->stats.link_quality, average);
+		bcm->stats.noise = average;
 drop_calculation:
 		bcm->noisecalc.calculation_running = 0;
 		return;
@@ -1709,8 +1664,9 @@
 static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm)
 {
 	u32 reason;
-	u32 dma_reason[4];
-	int activity = 0;
+	u32 dma_reason[6];
+	u32 merged_dma_reason = 0;
+	int i, activity = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_BCM43XX_DEBUG
@@ -1720,12 +1676,12 @@
 # define bcmirq_handled(irq)	do { /* nothing */ } while (0)
 #endif /* CONFIG_BCM43XX_DEBUG*/
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	reason = bcm->irq_reason;
-	dma_reason[0] = bcm->dma_reason[0];
-	dma_reason[1] = bcm->dma_reason[1];
-	dma_reason[2] = bcm->dma_reason[2];
-	dma_reason[3] = bcm->dma_reason[3];
+	for (i = 5; i >= 0; i--) {
+		dma_reason[i] = bcm->dma_reason[i];
+		merged_dma_reason |= dma_reason[i];
+	}
 
 	if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) {
 		/* TX error. We get this when Template Ram is written in wrong endianess
@@ -1736,27 +1692,25 @@
 		printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n");
 		bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR);
 	}
-	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_FATALMASK) |
-		     (dma_reason[1] & BCM43xx_DMAIRQ_FATALMASK) |
-		     (dma_reason[2] & BCM43xx_DMAIRQ_FATALMASK) |
-		     (dma_reason[3] & BCM43xx_DMAIRQ_FATALMASK))) {
+	if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) {
 		printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: "
-				     "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+				     "0x%08X, 0x%08X, 0x%08X, "
+				     "0x%08X, 0x%08X, 0x%08X\n",
 		        dma_reason[0], dma_reason[1],
-			dma_reason[2], dma_reason[3]);
+			dma_reason[2], dma_reason[3],
+			dma_reason[4], dma_reason[5]);
 		bcm43xx_controller_restart(bcm, "DMA error");
 		mmiowb();
-		bcm43xx_unlock_irqonly(bcm, flags);
+		spin_unlock_irqrestore(&bcm->irq_lock, flags);
 		return;
 	}
-	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
-		     (dma_reason[1] & BCM43xx_DMAIRQ_NONFATALMASK) |
-		     (dma_reason[2] & BCM43xx_DMAIRQ_NONFATALMASK) |
-		     (dma_reason[3] & BCM43xx_DMAIRQ_NONFATALMASK))) {
+	if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) {
 		printkl(KERN_ERR PFX "DMA error: "
-				     "0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+				     "0x%08X, 0x%08X, 0x%08X, "
+				     "0x%08X, 0x%08X, 0x%08X\n",
 		        dma_reason[0], dma_reason[1],
-			dma_reason[2], dma_reason[3]);
+			dma_reason[2], dma_reason[3],
+			dma_reason[4], dma_reason[5]);
 	}
 
 	if (reason & BCM43xx_IRQ_PS) {
@@ -1791,8 +1745,6 @@
 	}
 
 	/* Check the DMA reason registers for received data. */
-	assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
-	assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
 	if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) {
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0);
@@ -1800,13 +1752,17 @@
 			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0);
 		/* We intentionally don't set "activity" to 1, here. */
 	}
+	assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE));
+	assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE));
 	if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) {
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3);
 		else
-			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring1);
+			bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3);
 		activity = 1;
 	}
+	assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE));
+	assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE));
 	bcmirq_handled(BCM43xx_IRQ_RX);
 
 	if (reason & BCM43xx_IRQ_XMIT_STATUS) {
@@ -1834,7 +1790,7 @@
 		bcm43xx_leds_update(bcm, activity);
 	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
 	mmiowb();
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1863,14 +1819,18 @@
 
 	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason);
 
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON,
 			bcm->dma_reason[0]);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON,
 			bcm->dma_reason[1]);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON,
 			bcm->dma_reason[2]);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON,
 			bcm->dma_reason[3]);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON,
+			bcm->dma_reason[4]);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON,
+			bcm->dma_reason[5]);
 }
 
 /* Interrupt handler top-half */
@@ -1885,14 +1845,8 @@
 
 	spin_lock(&bcm->irq_lock);
 
-	/* Only accept IRQs, if we are initialized properly.
-	 * This avoids an RX race while initializing.
-	 * We should probably not enable IRQs before we are initialized
-	 * completely, but some careful work is needed to fix this. I think it
-	 * is best to stay with this cheap workaround for now... .
-	 */
-	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED))
-		goto out;
+	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	assert(bcm->current_core->id == BCM43xx_COREID_80211);
 
 	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) {
@@ -1904,14 +1858,18 @@
 	if (!reason)
 		goto out;
 
-	bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
-			     & 0x0001dc00;
-	bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
-			     & 0x0000dc00;
-	bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
-			     & 0x0000dc00;
-	bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
-			     & 0x0001dc00;
+	bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON)
+			     & 0x0001DC00;
+	bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON)
+			     & 0x0000DC00;
+	bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON)
+			     & 0x0000DC00;
+	bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON)
+			     & 0x0001DC00;
+	bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON)
+			     & 0x0000DC00;
+	bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON)
+			     & 0x0000DC00;
 
 	bcm43xx_interrupt_ack(bcm, reason);
 
@@ -1930,16 +1888,18 @@
 
 static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force)
 {
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+
 	if (bcm->firmware_norelease && !force)
 		return; /* Suspending or controller reset. */
-	release_firmware(bcm->ucode);
-	bcm->ucode = NULL;
-	release_firmware(bcm->pcm);
-	bcm->pcm = NULL;
-	release_firmware(bcm->initvals0);
-	bcm->initvals0 = NULL;
-	release_firmware(bcm->initvals1);
-	bcm->initvals1 = NULL;
+	release_firmware(phy->ucode);
+	phy->ucode = NULL;
+	release_firmware(phy->pcm);
+	phy->pcm = NULL;
+	release_firmware(phy->initvals0);
+	phy->initvals0 = NULL;
+	release_firmware(phy->initvals1);
+	phy->initvals1 = NULL;
 }
 
 static int bcm43xx_request_firmware(struct bcm43xx_private *bcm)
@@ -1950,11 +1910,11 @@
 	int nr;
 	char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 };
 
-	if (!bcm->ucode) {
+	if (!phy->ucode) {
 		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw",
 			 (rev >= 5 ? 5 : rev),
 			 modparam_fwpostfix);
-		err = request_firmware(&bcm->ucode, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX 
 			       "Error: Microcode \"%s\" not available or load failed.\n",
@@ -1963,12 +1923,12 @@
 		}
 	}
 
-	if (!bcm->pcm) {
+	if (!phy->pcm) {
 		snprintf(buf, ARRAY_SIZE(buf),
 			 "bcm43xx_pcm%d%s.fw",
 			 (rev < 5 ? 4 : 5),
 			 modparam_fwpostfix);
-		err = request_firmware(&bcm->pcm, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX
 			       "Error: PCM \"%s\" not available or load failed.\n",
@@ -1977,7 +1937,7 @@
 		}
 	}
 
-	if (!bcm->initvals0) {
+	if (!phy->initvals0) {
 		if (rev == 2 || rev == 4) {
 			switch (phy->type) {
 			case BCM43xx_PHYTYPE_A:
@@ -2008,20 +1968,20 @@
 		snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
 			 nr, modparam_fwpostfix);
 
-		err = request_firmware(&bcm->initvals0, buf, &bcm->pci_dev->dev);
+		err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev);
 		if (err) {
 			printk(KERN_ERR PFX 
 			       "Error: InitVals \"%s\" not available or load failed.\n",
 			        buf);
 			goto error;
 		}
-		if (bcm->initvals0->size % sizeof(struct bcm43xx_initval)) {
+		if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) {
 			printk(KERN_ERR PFX "InitVals fileformat error.\n");
 			goto error;
 		}
 	}
 
-	if (!bcm->initvals1) {
+	if (!phy->initvals1) {
 		if (rev >= 5) {
 			u32 sbtmstatehigh;
 
@@ -2043,14 +2003,14 @@
 			snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw",
 				 nr, modparam_fwpostfix);
 
-			err = request_firmware(&bcm->initvals1, buf, &bcm->pci_dev->dev);
+			err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev);
 			if (err) {
 				printk(KERN_ERR PFX 
 				       "Error: InitVals \"%s\" not available or load failed.\n",
 			        	buf);
 				goto error;
 			}
-			if (bcm->initvals1->size % sizeof(struct bcm43xx_initval)) {
+			if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) {
 				printk(KERN_ERR PFX "InitVals fileformat error.\n");
 				goto error;
 			}
@@ -2070,12 +2030,13 @@
 
 static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
 {
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	const u32 *data;
 	unsigned int i, len;
 
 	/* Upload Microcode. */
-	data = (u32 *)(bcm->ucode->data);
-	len = bcm->ucode->size / sizeof(u32);
+	data = (u32 *)(phy->ucode->data);
+	len = phy->ucode->size / sizeof(u32);
 	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
 	for (i = 0; i < len; i++) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA,
@@ -2084,8 +2045,8 @@
 	}
 
 	/* Upload PCM data. */
-	data = (u32 *)(bcm->pcm->data);
-	len = bcm->pcm->size / sizeof(u32);
+	data = (u32 *)(phy->pcm->data);
+	len = phy->pcm->size / sizeof(u32);
 	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
 	bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
 	bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb);
@@ -2131,15 +2092,16 @@
 
 static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm)
 {
+	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	int err;
 
-	err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals0->data,
-				     bcm->initvals0->size / sizeof(struct bcm43xx_initval));
+	err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data,
+				     phy->initvals0->size / sizeof(struct bcm43xx_initval));
 	if (err)
 		goto out;
-	if (bcm->initvals1) {
-		err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)bcm->initvals1->data,
-					     bcm->initvals1->size / sizeof(struct bcm43xx_initval));
+	if (phy->initvals1) {
+		err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data,
+					     phy->initvals1->size / sizeof(struct bcm43xx_initval));
 		if (err)
 			goto out;
 	}
@@ -2156,9 +2118,7 @@
 
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
 {
-	int res;
-	unsigned int i;
-	u32 data;
+	int err;
 
 	bcm->irq = bcm->pci_dev->irq;
 #ifdef CONFIG_BCM947XX
@@ -2175,32 +2135,12 @@
 		}
 	}
 #endif
-	res = request_irq(bcm->irq, bcm43xx_interrupt_handler,
+	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
 			  IRQF_SHARED, KBUILD_MODNAME, bcm);
-	if (res) {
+	if (err)
 		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
-		return -ENODEV;
-	}
-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xffffffff);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
-	i = 0;
-	while (1) {
-		data = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-		if (data == BCM43xx_IRQ_READY)
-			break;
-		i++;
-		if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
-			printk(KERN_ERR PFX "Card IRQ register not responding. "
-					    "Giving up.\n");
-			free_irq(bcm->irq, bcm);
-			return -ENODEV;
-		}
-		udelay(10);
-	}
-	// dummy read
-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 
-	return 0;
+	return err;
 }
 
 /* Switch to the core used to write the GPIO register.
@@ -2298,13 +2238,17 @@
 /* http://bcm-specs.sipsolutions.net/EnableMac */
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm)
 {
-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-			| BCM43xx_SBF_MAC_ENABLED);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
-	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-	bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	bcm->mac_suspended--;
+	assert(bcm->mac_suspended >= 0);
+	if (bcm->mac_suspended == 0) {
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				| BCM43xx_SBF_MAC_ENABLED);
+		bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY);
+		bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+		bcm43xx_power_saving_ctl_bits(bcm, -1, -1);
+	}
 }
 
 /* http://bcm-specs.sipsolutions.net/SuspendMAC */
@@ -2313,18 +2257,23 @@
 	int i;
 	u32 tmp;
 
-	bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
-	                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
-			& ~BCM43xx_SBF_MAC_ENABLED);
-	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
-	for (i = 100000; i; i--) {
-		tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
-		if (tmp & BCM43xx_IRQ_READY)
-			return;
-		udelay(10);
+	assert(bcm->mac_suspended >= 0);
+	if (bcm->mac_suspended == 0) {
+		bcm43xx_power_saving_ctl_bits(bcm, -1, 1);
+		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
+		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
+				& ~BCM43xx_SBF_MAC_ENABLED);
+		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+		for (i = 10000; i; i--) {
+			tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+			if (tmp & BCM43xx_IRQ_READY)
+				goto out;
+			udelay(1);
+		}
+		printkl(KERN_ERR PFX "MAC suspend failed\n");
 	}
-	printkl(KERN_ERR PFX "MAC suspend failed\n");
+out:
+	bcm->mac_suspended++;
 }
 
 void bcm43xx_set_iwmode(struct bcm43xx_private *bcm,
@@ -2394,7 +2343,6 @@
 	if (!modparam_noleds)
 		bcm43xx_leds_exit(bcm);
 	bcm43xx_gpio_cleanup(bcm);
-	free_irq(bcm->irq, bcm);
 	bcm43xx_release_firmware(bcm, 0);
 }
 
@@ -2406,7 +2354,7 @@
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	int err;
-	int tmp;
+	int i, tmp;
 	u32 value32;
 	u16 value16;
 
@@ -2419,13 +2367,53 @@
 		goto out;
 	bcm43xx_upload_microcode(bcm);
 
-	err = bcm43xx_initialize_irq(bcm);
-	if (err)
+	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402);
+	i = 0;
+	while (1) {
+		value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
+		if (value32 == BCM43xx_IRQ_READY)
+			break;
+		i++;
+		if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) {
+			printk(KERN_ERR PFX "IRQ_READY timeout\n");
+			err = -ENODEV;
+			goto err_release_fw;
+		}
+		udelay(10);
+	}
+	bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+
+	value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				     BCM43xx_UCODE_REVISION);
+
+	dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x "
+		"(20%.2i-%.2i-%.2i  %.2i:%.2i:%.2i)\n", value16,
+		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				   BCM43xx_UCODE_PATCHLEVEL),
+		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				    BCM43xx_UCODE_DATE) >> 12) & 0xf,
+		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				    BCM43xx_UCODE_DATE) >> 8) & 0xf,
+		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				   BCM43xx_UCODE_DATE) & 0xff,
+		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				   BCM43xx_UCODE_TIME) >> 11) & 0x1f,
+		(bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				   BCM43xx_UCODE_TIME) >> 5) & 0x3f,
+		bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				   BCM43xx_UCODE_TIME) & 0x1f);
+
+	if ( value16 > 0x128 ) {
+		dprintk(KERN_ERR PFX
+			"Firmware: no support for microcode rev > 0x128\n");
+		err = -1;
 		goto err_release_fw;
+	}
 
 	err = bcm43xx_gpio_init(bcm);
 	if (err)
-		goto err_free_irq;
+		goto err_release_fw;
 
 	err = bcm43xx_upload_initvals(bcm);
 	if (err)
@@ -2489,10 +2477,12 @@
 		bcm43xx_write32(bcm, 0x018C, 0x02000000);
 	}
 	bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0001DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
 	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0000DC00);
-	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0001DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00);
+	bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
 
 	value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
 	value32 |= 0x00100000;
@@ -2509,8 +2499,6 @@
 	bcm43xx_radio_turn_off(bcm);
 err_gpio_cleanup:
 	bcm43xx_gpio_cleanup(bcm);
-err_free_irq:
-	free_irq(bcm->irq, bcm);
 err_release_fw:
 	bcm43xx_release_firmware(bcm, 1);
 	goto out;
@@ -2550,11 +2538,9 @@
 {
 	/* Initialize a "phyinfo" structure. The structure is already
 	 * zeroed out.
+	 * This is called on insmod time to initialize members.
 	 */
-	phy->antenna_diversity = 0xFFFF;
 	phy->savedpctlreg = 0xFFFF;
-	phy->minlowsig[0] = 0xFFFF;
-	phy->minlowsig[1] = 0xFFFF;
 	spin_lock_init(&phy->lock);
 }
 
@@ -2562,14 +2548,11 @@
 {
 	/* Initialize a "radioinfo" structure. The structure is already
 	 * zeroed out.
+	 * This is called on insmod time to initialize members.
 	 */
 	radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE;
 	radio->channel = 0xFF;
 	radio->initial_channel = 0xFF;
-	radio->lofcal = 0xFFFF;
-	radio->initval = 0xFFFF;
-	radio->nrssi[0] = -1000;
-	radio->nrssi[1] = -1000;
 }
 
 static int bcm43xx_probe_cores(struct bcm43xx_private *bcm)
@@ -2587,7 +2570,6 @@
 				    * BCM43xx_MAX_80211_CORES);
 	memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211)
 					* BCM43xx_MAX_80211_CORES);
-	bcm->current_80211_core_idx = -1;
 	bcm->nr_80211_available = 0;
 	bcm->current_core = NULL;
 	bcm->active_80211_core = NULL;
@@ -2757,6 +2739,7 @@
 				goto out;
 			}
 			bcm->nr_80211_available++;
+			core->priv = ext_80211;
 			bcm43xx_init_struct_phyinfo(&ext_80211->phy);
 			bcm43xx_init_struct_radioinfo(&ext_80211->radio);
 			break;
@@ -2857,7 +2840,8 @@
 }
 
 /* http://bcm-specs.sipsolutions.net/80211Init */
-static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm)
+static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm,
+				      int active_wlcore)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
@@ -2939,19 +2923,26 @@
 	if (bcm->current_core->rev >= 5)
 		bcm43xx_write16(bcm, 0x043C, 0x000C);
 
-	if (bcm43xx_using_pio(bcm))
-		err = bcm43xx_pio_init(bcm);
-	else
-		err = bcm43xx_dma_init(bcm);
-	if (err)
-		goto err_chip_cleanup;
+	if (active_wlcore) {
+		if (bcm43xx_using_pio(bcm))
+			err = bcm43xx_pio_init(bcm);
+		else
+			err = bcm43xx_dma_init(bcm);
+		if (err)
+			goto err_chip_cleanup;
+	}
 	bcm43xx_write16(bcm, 0x0612, 0x0050);
 	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050);
 	bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4);
 
-	bcm43xx_mac_enable(bcm);
-	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+	if (active_wlcore) {
+		if (radio->initial_channel != 0xFF)
+			bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0);
+	}
 
+	/* Don't enable MAC/IRQ here, as it will race with the IRQ handler.
+	 * We enable it later.
+	 */
 	bcm->current_core->initialized = 1;
 out:
 	return err;
@@ -3066,11 +3057,6 @@
 	return err;
 }
 
-static void bcm43xx_softmac_init(struct bcm43xx_private *bcm)
-{
-	ieee80211softmac_start(bcm->net_dev);
-}
-
 static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -3182,47 +3168,46 @@
 		/* Periodic work will take a long time, so we want it to
 		 * be preemtible.
 		 */
-		bcm43xx_lock_irqonly(bcm, flags);
+		mutex_lock(&bcm->mutex);
 		netif_stop_queue(bcm->net_dev);
+		synchronize_net();
+		spin_lock_irqsave(&bcm->irq_lock, flags);
+		bcm43xx_mac_suspend(bcm);
 		if (bcm43xx_using_pio(bcm))
 			bcm43xx_pio_freeze_txqueues(bcm);
 		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-		bcm43xx_unlock_irqonly(bcm, flags);
-		bcm43xx_lock_noirq(bcm);
+		spin_unlock_irqrestore(&bcm->irq_lock, flags);
 		bcm43xx_synchronize_irq(bcm);
 	} else {
 		/* Periodic work should take short time, so we want low
 		 * locking overhead.
 		 */
-		bcm43xx_lock_irqsafe(bcm, flags);
+		mutex_lock(&bcm->mutex);
+		spin_lock_irqsave(&bcm->irq_lock, flags);
 	}
 
 	do_periodic_work(bcm);
 
 	if (badness > BADNESS_LIMIT) {
-		bcm43xx_lock_irqonly(bcm, flags);
-		if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
-			tasklet_enable(&bcm->isr_tasklet);
-			bcm43xx_interrupt_enable(bcm, savedirqs);
-			if (bcm43xx_using_pio(bcm))
-				bcm43xx_pio_thaw_txqueues(bcm);
-		}
+		spin_lock_irqsave(&bcm->irq_lock, flags);
+		tasklet_enable(&bcm->isr_tasklet);
+		bcm43xx_interrupt_enable(bcm, savedirqs);
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_thaw_txqueues(bcm);
+		bcm43xx_mac_enable(bcm);
 		netif_wake_queue(bcm->net_dev);
-		mmiowb();
-		bcm43xx_unlock_irqonly(bcm, flags);
-		bcm43xx_unlock_noirq(bcm);
-	} else {
-		mmiowb();
-		bcm43xx_unlock_irqsafe(bcm, flags);
 	}
+	mmiowb();
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 }
 
-static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
+void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
 {
 	cancel_rearming_delayed_work(&bcm->periodic_work);
 }
 
-static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
+void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
 	struct work_struct *work = &(bcm->periodic_work);
 
@@ -3243,9 +3228,9 @@
 	struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
 	unsigned long flags;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&(bcm)->irq_lock, flags);
 	*data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&(bcm)->irq_lock, flags);
 
 	return (sizeof(u16));
 }
@@ -3271,139 +3256,329 @@
 	return err;
 }
 
+static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
+{
+	int ret = 0;
+	int i, err;
+	struct bcm43xx_coreinfo *core;
+
+	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		core = &(bcm->core_80211[i]);
+		assert(core->available);
+		if (!core->initialized)
+			continue;
+		err = bcm43xx_switch_core(bcm, core);
+		if (err) {
+			dprintk(KERN_ERR PFX "shutdown_all_wireless_cores "
+					     "switch_core failed (%d)\n", err);
+			ret = err;
+			continue;
+		}
+		bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+		bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */
+		bcm43xx_wireless_core_cleanup(bcm);
+		if (core == bcm->active_80211_core)
+			bcm->active_80211_core = NULL;
+	}
+	free_irq(bcm->irq, bcm);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+
+	return ret;
+}
+
 /* This is the opposite of bcm43xx_init_board() */
 static void bcm43xx_free_board(struct bcm43xx_private *bcm)
 {
-	int i, err;
-
-	bcm43xx_lock_noirq(bcm);
+	bcm43xx_rng_exit(bcm);
 	bcm43xx_sysfs_unregister(bcm);
 	bcm43xx_periodic_tasks_delete(bcm);
 
-	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
+	mutex_lock(&(bcm)->mutex);
+	bcm43xx_shutdown_all_wireless_cores(bcm);
+	bcm43xx_pctl_set_crystal(bcm, 0);
+	mutex_unlock(&(bcm)->mutex);
+}
 
-	bcm43xx_rng_exit(bcm);
+static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy)
+{
+	phy->antenna_diversity = 0xFFFF;
+	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
+	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
+
+	/* Flags */
+	phy->calibrated = 0;
+	phy->is_locked = 0;
+
+	if (phy->_lo_pairs) {
+		memset(phy->_lo_pairs, 0,
+		       sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT);
+	}
+	memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain));
+}
+
+static void prepare_radiodata_for_init(struct bcm43xx_private *bcm,
+				       struct bcm43xx_radioinfo *radio)
+{
+	int i;
+
+	/* Set default attenuation values. */
+	radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm);
+	radio->radio_atten = bcm43xx_default_radio_attenuation(bcm);
+	radio->txctl1 = bcm43xx_default_txctl1(bcm);
+	radio->txctl2 = 0xFFFF;
+	radio->txpwr_offset = 0;
+
+	/* NRSSI */
+	radio->nrssislope = 0;
+	for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++)
+		radio->nrssi[i] = -1000;
+	for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++)
+		radio->nrssi_lt[i] = i;
+
+	radio->lofcal = 0xFFFF;
+	radio->initval = 0xFFFF;
+
+	radio->aci_enable = 0;
+	radio->aci_wlan_automatic = 0;
+	radio->aci_hw_rssi = 0;
+}
+
+static void prepare_priv_for_init(struct bcm43xx_private *bcm)
+{
+	int i;
+	struct bcm43xx_coreinfo *core;
+	struct bcm43xx_coreinfo_80211 *wlext;
+
+	assert(!bcm->active_80211_core);
+
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+
+	/* Flags */
+	bcm->was_initialized = 0;
+	bcm->reg124_set_0x4 = 0;
+
+	/* Stats */
+	memset(&bcm->stats, 0, sizeof(bcm->stats));
+
+	/* Wireless core data */
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
-		if (!bcm->core_80211[i].available)
-			continue;
-		if (!bcm->core_80211[i].initialized)
-			continue;
+		core = &(bcm->core_80211[i]);
+		wlext = core->priv;
 
-		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
-		assert(err == 0);
-		bcm43xx_wireless_core_cleanup(bcm);
+		if (!core->available)
+			continue;
+		assert(wlext == &(bcm->core_80211_ext[i]));
+
+		prepare_phydata_for_init(&wlext->phy);
+		prepare_radiodata_for_init(bcm, &wlext->radio);
 	}
 
-	bcm43xx_pctl_set_crystal(bcm, 0);
+	/* IRQ related flags */
+	bcm->irq_reason = 0;
+	memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason));
+	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
 
+	bcm->mac_suspended = 1;
+
+	/* Noise calculation context */
+	memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc));
+
+	/* Periodic work context */
+	bcm->periodic_state = 0;
+}
+
+static int wireless_core_up(struct bcm43xx_private *bcm,
+			    int active_wlcore)
+{
+	int err;
+
+	if (!bcm43xx_core_enabled(bcm))
+		bcm43xx_wireless_core_reset(bcm, 1);
+	if (!active_wlcore)
+		bcm43xx_wireless_core_mark_inactive(bcm);
+	err = bcm43xx_wireless_core_init(bcm, active_wlcore);
+	if (err)
+		goto out;
+	if (!active_wlcore)
+		bcm43xx_radio_turn_off(bcm);
+out:
+	return err;
+}
+
+/* Select and enable the "to be used" wireless core.
+ * Locking: bcm->mutex must be aquired before calling this.
+ *          bcm->irq_lock must not be aquired.
+ */
+int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+				 int phytype)
+{
+	int i, err;
+	struct bcm43xx_coreinfo *active_core = NULL;
+	struct bcm43xx_coreinfo_80211 *active_wlext = NULL;
+	struct bcm43xx_coreinfo *core;
+	struct bcm43xx_coreinfo_80211 *wlext;
+	int adjust_active_sbtmstatelow = 0;
+
+	might_sleep();
+
+	if (phytype < 0) {
+		/* If no phytype is requested, select the first core. */
+		assert(bcm->core_80211[0].available);
+		wlext = bcm->core_80211[0].priv;
+		phytype = wlext->phy.type;
+	}
+	/* Find the requested core. */
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		core = &(bcm->core_80211[i]);
+		wlext = core->priv;
+		if (wlext->phy.type == phytype) {
+			active_core = core;
+			active_wlext = wlext;
+			break;
+		}
+	}
+	if (!active_core)
+		return -ESRCH; /* No such PHYTYPE on this board. */
+
+	if (bcm->active_80211_core) {
+		/* We already selected a wl core in the past.
+		 * So first clean up everything.
+		 */
+		dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n");
+		ieee80211softmac_stop(bcm->net_dev);
+		bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+		err = bcm43xx_disable_interrupts_sync(bcm);
+		assert(!err);
+		tasklet_enable(&bcm->isr_tasklet);
+		err = bcm43xx_shutdown_all_wireless_cores(bcm);
+		if (err)
+			goto error;
+		/* Ok, everything down, continue to re-initialize. */
+		bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
+	}
+
+	/* Reset all data structures. */
+	prepare_priv_for_init(bcm);
+
+	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+	if (err)
+		goto error;
+
+	/* Mark all unused cores "inactive". */
+	for (i = 0; i < bcm->nr_80211_available; i++) {
+		core = &(bcm->core_80211[i]);
+		wlext = core->priv;
+
+		if (core == active_core)
+			continue;
+		err = bcm43xx_switch_core(bcm, core);
+		if (err) {
+			dprintk(KERN_ERR PFX "Could not switch to inactive "
+					     "802.11 core (%d)\n", err);
+			goto error;
+		}
+		err = wireless_core_up(bcm, 0);
+		if (err) {
+			dprintk(KERN_ERR PFX "core_up for inactive 802.11 core "
+					     "failed (%d)\n", err);
+			goto error;
+		}
+		adjust_active_sbtmstatelow = 1;
+	}
+
+	/* Now initialize the active 802.11 core. */
+	err = bcm43xx_switch_core(bcm, active_core);
+	if (err) {
+		dprintk(KERN_ERR PFX "Could not switch to active "
+				     "802.11 core (%d)\n", err);
+		goto error;
+	}
+	if (adjust_active_sbtmstatelow &&
+	    active_wlext->phy.type == BCM43xx_PHYTYPE_G) {
+		u32 sbtmstatelow;
+
+		sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW);
+		sbtmstatelow |= 0x20000000;
+		bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow);
+	}
+	err = wireless_core_up(bcm, 1);
+	if (err) {
+		dprintk(KERN_ERR PFX "core_up for active 802.11 core "
+				     "failed (%d)\n", err);
+		goto error;
+	}
+	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
+	if (err)
+		goto error;
+	bcm->active_80211_core = active_core;
+
+	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
+	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
+	bcm43xx_security_init(bcm);
+	ieee80211softmac_start(bcm->net_dev);
+
+	/* Let's go! Be careful after enabling the IRQs.
+	 * Don't switch cores, for example.
+	 */
+	bcm43xx_mac_enable(bcm);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
+	err = bcm43xx_initialize_irq(bcm);
+	if (err)
+		goto error;
+	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
+
+	dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n",
+		active_wlext->phy.type);
+
+	return 0;
+
+error:
 	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
-	bcm43xx_unlock_noirq(bcm);
+	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW);
+	return err;
 }
 
 static int bcm43xx_init_board(struct bcm43xx_private *bcm)
 {
-	int i, err;
-	int connect_phy;
+	int err;
 
-	might_sleep();
+	mutex_lock(&(bcm)->mutex);
 
-	bcm43xx_lock_noirq(bcm);
-	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
-
+	tasklet_enable(&bcm->isr_tasklet);
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
-		goto out;
+		goto err_tasklet;
 	err = bcm43xx_pctl_init(bcm);
 	if (err)
 		goto err_crystal_off;
-	err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST);
+	err = bcm43xx_select_wireless_core(bcm, -1);
 	if (err)
 		goto err_crystal_off;
-
-	tasklet_enable(&bcm->isr_tasklet);
-	for (i = 0; i < bcm->nr_80211_available; i++) {
-		err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]);
-		assert(err != -ENODEV);
-		if (err)
-			goto err_80211_unwind;
-
-		/* Enable the selected wireless core.
-		 * Connect PHY only on the first core.
-		 */
-		if (!bcm43xx_core_enabled(bcm)) {
-			if (bcm->nr_80211_available == 1) {
-				connect_phy = bcm43xx_current_phy(bcm)->connected;
-			} else {
-				if (i == 0)
-					connect_phy = 1;
-				else
-					connect_phy = 0;
-			}
-			bcm43xx_wireless_core_reset(bcm, connect_phy);
-		}
-
-		if (i != 0)
-			bcm43xx_wireless_core_mark_inactive(bcm, &bcm->core_80211[0]);
-
-		err = bcm43xx_wireless_core_init(bcm);
-		if (err)
-			goto err_80211_unwind;
-
-		if (i != 0) {
-			bcm43xx_mac_suspend(bcm);
-			bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-			bcm43xx_radio_turn_off(bcm);
-		}
-	}
-	bcm->active_80211_core = &bcm->core_80211[0];
-	if (bcm->nr_80211_available >= 2) {
-		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
-		bcm43xx_mac_enable(bcm);
-	}
+	err = bcm43xx_sysfs_register(bcm);
+	if (err)
+		goto err_wlshutdown;
 	err = bcm43xx_rng_init(bcm);
 	if (err)
-		goto err_80211_unwind;
-	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
-	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
-	dprintk(KERN_INFO PFX "80211 cores initialized\n");
-	bcm43xx_security_init(bcm);
-	bcm43xx_softmac_init(bcm);
-
-	bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC);
-
-	if (bcm43xx_current_radio(bcm)->initial_channel != 0xFF) {
-		bcm43xx_mac_suspend(bcm);
-		bcm43xx_radio_selectchannel(bcm, bcm43xx_current_radio(bcm)->initial_channel, 0);
-		bcm43xx_mac_enable(bcm);
-	}
-
-	/* Initialization of the board is done. Flag it as such. */
-	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
-
+		goto err_sysfs_unreg;
 	bcm43xx_periodic_tasks_setup(bcm);
-	bcm43xx_sysfs_register(bcm);
-	//FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though...
 
 	/*FIXME: This should be handled by softmac instead. */
 	schedule_work(&bcm->softmac->associnfo.work);
 
-	assert(err == 0);
 out:
-	bcm43xx_unlock_noirq(bcm);
+	mutex_unlock(&(bcm)->mutex);
 
 	return err;
 
-err_80211_unwind:
-	tasklet_disable(&bcm->isr_tasklet);
-	/* unwind all 80211 initialization */
-	for (i = 0; i < bcm->nr_80211_available; i++) {
-		if (!bcm->core_80211[i].initialized)
-			continue;
-		bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-		bcm43xx_wireless_core_cleanup(bcm);
-	}
+err_sysfs_unreg:
+	bcm43xx_sysfs_unregister(bcm);
+err_wlshutdown:
+	bcm43xx_shutdown_all_wireless_cores(bcm);
 err_crystal_off:
 	bcm43xx_pctl_set_crystal(bcm, 0);
+err_tasklet:
+	tasklet_disable(&bcm->isr_tasklet);
 	goto out;
 }
 
@@ -3647,7 +3822,8 @@
 	struct bcm43xx_radioinfo *radio;
 	unsigned long flags;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		bcm43xx_mac_suspend(bcm);
 		bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -3656,7 +3832,8 @@
 		radio = bcm43xx_current_radio(bcm);
 		radio->initial_channel = channel;
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 }
 
 /* set_security() callback in struct ieee80211_device */
@@ -3670,7 +3847,8 @@
 	
 	dprintk(KERN_INFO PFX "set security called");
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 
 	for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
 		if (sec->flags & (1<<keyidx)) {
@@ -3701,7 +3879,7 @@
 	}
 	if (sec->flags & SEC_AUTH_MODE) {
 		secinfo->auth_mode = sec->auth_mode;
-		dprintk(", .auth_mode = %d\n", sec->auth_mode);
+		dprintk(", .auth_mode = %d", sec->auth_mode);
 	}
 	dprintk("\n");
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
@@ -3739,7 +3917,8 @@
 		} else
 				bcm43xx_clear_keys(bcm);
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 }
 
 /* hard_start_xmit() callback in struct ieee80211_device */
@@ -3751,12 +3930,14 @@
 	int err = -ENODEV;
 	unsigned long flags;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
 		err = bcm43xx_tx(bcm, txb);
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 
-	return err;
+	if (unlikely(err))
+		return NETDEV_TX_BUSY;
+	return NETDEV_TX_OK;
 }
 
 static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev)
@@ -3769,9 +3950,9 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	bcm43xx_controller_restart(bcm, "TX timeout");
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3781,7 +3962,8 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
+		bcm43xx_interrupt_handler(bcm->irq, bcm, NULL);
 	local_irq_restore(flags);
 }
 #endif /* CONFIG_NET_POLL_CONTROLLER */
@@ -3799,9 +3981,10 @@
 	int err;
 
 	ieee80211softmac_stop(net_dev);
-	err = bcm43xx_disable_interrupts_sync(bcm, NULL);
+	err = bcm43xx_disable_interrupts_sync(bcm);
 	assert(!err);
 	bcm43xx_free_board(bcm);
+	flush_scheduled_work();
 
 	return 0;
 }
@@ -3818,10 +4001,12 @@
 	bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
 
 	bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+	bcm->mac_suspended = 1;
 	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
 	spin_lock_init(&bcm->irq_lock);
+	spin_lock_init(&bcm->leds_lock);
 	mutex_init(&bcm->mutex);
 	tasklet_init(&bcm->isr_tasklet,
 		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
@@ -3940,7 +4125,6 @@
 	bcm43xx_debugfs_remove_device(bcm);
 	unregister_netdev(net_dev);
 	bcm43xx_detach_board(bcm);
-	assert(bcm->ucode == NULL);
 	free_ieee80211softmac(net_dev);
 }
 
@@ -3950,47 +4134,31 @@
 static void bcm43xx_chip_reset(void *_bcm)
 {
 	struct bcm43xx_private *bcm = _bcm;
-	struct net_device *net_dev = bcm->net_dev;
-	struct pci_dev *pci_dev = bcm->pci_dev;
-	int err;
-	int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	struct bcm43xx_phyinfo *phy;
+	int err = -ENODEV;
 
-	netif_stop_queue(bcm->net_dev);
-	tasklet_disable(&bcm->isr_tasklet);
-
-	bcm->firmware_norelease = 1;
-	if (was_initialized)
-		bcm43xx_free_board(bcm);
-	bcm->firmware_norelease = 0;
-	bcm43xx_detach_board(bcm);
-	err = bcm43xx_init_private(bcm, net_dev, pci_dev);
-	if (err)
-		goto failure;
-	err = bcm43xx_attach_board(bcm);
-	if (err)
-		goto failure;
-	if (was_initialized) {
-		err = bcm43xx_init_board(bcm);
-		if (err)
-			goto failure;
+	mutex_lock(&(bcm)->mutex);
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+		bcm43xx_periodic_tasks_delete(bcm);
+		phy = bcm43xx_current_phy(bcm);
+		err = bcm43xx_select_wireless_core(bcm, phy->type);
+		if (!err)
+			bcm43xx_periodic_tasks_setup(bcm);
 	}
-	netif_wake_queue(bcm->net_dev);
-	printk(KERN_INFO PFX "Controller restarted\n");
+	mutex_unlock(&(bcm)->mutex);
 
-	return;
-failure:
-	printk(KERN_ERR PFX "Controller restart failed\n");
+	printk(KERN_ERR PFX "Controller restart%s\n",
+	       (err == 0) ? "ed" : " failed");
 }
 
 /* Hard-reset the chip.
  * This can be called from interrupt or process context.
- * Make sure to _not_ re-enable device interrupts after this has been called.
-*/
+ * bcm->irq_lock must be locked.
+ */
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
 {
-	bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
-	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
+		return;
 	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
 	INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset, bcm);
 	schedule_work(&bcm->restart_work);
@@ -4002,21 +4170,16 @@
 {
 	struct net_device *net_dev = pci_get_drvdata(pdev);
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
-	int try_to_shutdown = 0, err;
+	int err;
 
 	dprintk(KERN_INFO PFX "Suspending...\n");
 
-	bcm43xx_lock_irqsafe(bcm, flags);
-	bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
-	if (bcm->was_initialized)
-		try_to_shutdown = 1;
-	bcm43xx_unlock_irqsafe(bcm, flags);
-
 	netif_device_detach(net_dev);
-	if (try_to_shutdown) {
+	bcm->was_initialized = 0;
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
+		bcm->was_initialized = 1;
 		ieee80211softmac_stop(net_dev);
-		err = bcm43xx_disable_interrupts_sync(bcm, &bcm->irq_savedstate);
+		err = bcm43xx_disable_interrupts_sync(bcm);
 		if (unlikely(err)) {
 			dprintk(KERN_ERR PFX "Suspend failed.\n");
 			return -EAGAIN;
@@ -4049,17 +4212,14 @@
 	pci_restore_state(pdev);
 
 	bcm43xx_chipset_attach(bcm);
-	if (bcm->was_initialized) {
-		bcm->irq_savedstate = BCM43xx_IRQ_INITIAL;
+	if (bcm->was_initialized)
 		err = bcm43xx_init_board(bcm);
-	}
 	if (err) {
 		printk(KERN_ERR PFX "Resume failed!\n");
 		return err;
 	}
-
 	netif_device_attach(net_dev);
-	
+
 	dprintk(KERN_INFO PFX "Device resumed.\n");
 
 	return 0;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
index 1164936..f763571 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.h
@@ -133,11 +133,17 @@
 
 int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core);
 
+int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm,
+				 int phytype);
+
 void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
 
 void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
 
+void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm);
+void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
+
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
 
 int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index f8200de..eafd0f6 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -81,6 +81,16 @@
 static void bcm43xx_phy_initg(struct bcm43xx_private *bcm);
 
 
+static inline
+void bcm43xx_voluntary_preempt(void)
+{
+	assert(!in_atomic() && !in_irq() &&
+	       !in_interrupt() && !irqs_disabled());
+#ifndef CONFIG_PREEMPT
+	cond_resched();
+#endif /* CONFIG_PREEMPT */
+}
+
 void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
@@ -133,22 +143,14 @@
 void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
-	unsigned long flags;
 
 	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */
 	if (phy->calibrated)
 		return;
 	if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) {
-		/* We do not want to be preempted while calibrating
-		 * the hardware.
-		 */
-		local_irq_save(flags);
-
 		bcm43xx_wireless_core_reset(bcm, 0);
 		bcm43xx_phy_initg(bcm);
 		bcm43xx_wireless_core_reset(bcm, 1);
-
-		local_irq_restore(flags);
 	}
 	phy->calibrated = 1;
 }
@@ -1299,7 +1301,9 @@
 {
 	int i;
 	u16 ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	for (i = 0; i < 10; i++){
 		bcm43xx_phy_write(bcm, 0x0015, 0xAFA0);
 		udelay(1);
@@ -1309,6 +1313,8 @@
 		udelay(40);
 		ret += bcm43xx_phy_read(bcm, 0x002C);
 	}
+	local_irq_restore(flags);
+	bcm43xx_voluntary_preempt();
 
 	return ret;
 }
@@ -1435,6 +1441,7 @@
 	}
 	ret = bcm43xx_phy_read(bcm, 0x002D);
 	local_irq_restore(flags);
+	bcm43xx_voluntary_preempt();
 
 	return ret;
 }
@@ -1760,6 +1767,7 @@
 			bcm43xx_radio_write16(bcm, 0x43, i);
 			bcm43xx_radio_write16(bcm, 0x52, radio->txctl2);
 			udelay(10);
+			bcm43xx_voluntary_preempt();
 
 			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1803,6 +1811,7 @@
 					      radio->txctl2
 					      | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above?
 			udelay(10);
+			bcm43xx_voluntary_preempt();
 
 			bcm43xx_phy_set_baseband_attenuation(bcm, j * 2);
 
@@ -1824,6 +1833,7 @@
 		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2);
 		udelay(2);
 		bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3);
+		bcm43xx_voluntary_preempt();
 	} else
 		bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0);
 	bcm43xx_phy_lo_adjust(bcm, is_initializing);
@@ -2188,12 +2198,6 @@
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	int err = -ENODEV;
-	unsigned long flags;
-
-	/* We do not want to be preempted while calibrating
-	 * the hardware.
-	 */
-	local_irq_save(flags);
 
 	switch (phy->type) {
 	case BCM43xx_PHYTYPE_A:
@@ -2227,7 +2231,6 @@
 		err = 0;
 		break;
 	}
-	local_irq_restore(flags);
 	if (err)
 		printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n");
 
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index 574085c..c60c174 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -262,7 +262,7 @@
 	int err;
 	u16 txctl;
 
-	bcm43xx_lock_irqonly(bcm, flags);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 
 	if (queue->tx_frozen)
 		goto out_unlock;
@@ -300,7 +300,7 @@
 		continue;
 	}
 out_unlock:
-	bcm43xx_unlock_irqonly(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
 }
 
 static void setup_txqueues(struct bcm43xx_pioqueue *queue)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index 6a23bdc..c71b998 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -120,12 +120,14 @@
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	err = bcm43xx_sprom_read(bcm, sprom);
 	if (!err)
 		err = sprom2hex(sprom, buf, PAGE_SIZE);
 	mmiowb();
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 	kfree(sprom);
 
 	return err;
@@ -150,10 +152,14 @@
 	err = hex2sprom(sprom, buf, count);
 	if (err)
 		goto out_kfree;
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
+	spin_lock(&bcm->leds_lock);
 	err = bcm43xx_sprom_write(bcm, sprom);
 	mmiowb();
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock(&bcm->leds_lock);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 out_kfree:
 	kfree(sprom);
 
@@ -170,13 +176,12 @@
 					    char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	int err;
 	ssize_t count = 0;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock_noirq(bcm);
+	mutex_lock(&bcm->mutex);
 
 	switch (bcm43xx_current_radio(bcm)->interfmode) {
 	case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -191,11 +196,10 @@
 	default:
 		assert(0);
 	}
-	err = 0;
 
-	bcm43xx_unlock_noirq(bcm);
+	mutex_unlock(&bcm->mutex);
 
-	return err ? err : count;
+	return count;
 
 }
 
@@ -229,7 +233,8 @@
 		return -EINVAL;
 	}
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 
 	err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
 	if (err) {
@@ -237,7 +242,8 @@
 				    "supported by device\n");
 	}
 	mmiowb();
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err ? err : count;
 }
@@ -251,23 +257,21 @@
 					  char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	int err;
 	ssize_t count;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock_noirq(bcm);
+	mutex_lock(&bcm->mutex);
 
 	if (bcm->short_preamble)
 		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
 	else
 		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
 
-	err = 0;
-	bcm43xx_unlock_noirq(bcm);
+	mutex_unlock(&bcm->mutex);
 
-	return err ? err : count;
+	return count;
 }
 
 static ssize_t bcm43xx_attr_preamble_store(struct device *dev,
@@ -276,7 +280,6 @@
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
 	unsigned long flags;
-	int err;
 	int value;
 
 	if (!capable(CAP_NET_ADMIN))
@@ -285,20 +288,141 @@
 	value = get_boolean(buf, count);
 	if (value < 0)
 		return value;
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 
 	bcm->short_preamble = !!value;
 
-	err = 0;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
-	return err ? err : count;
+	return count;
 }
 
 static DEVICE_ATTR(shortpreamble, 0644,
 		   bcm43xx_attr_preamble_show,
 		   bcm43xx_attr_preamble_store);
 
+static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+	int phytype;
+	int err = -EINVAL;
+
+	if (count < 1)
+		goto out;
+	switch (buf[0]) {
+	case 'a':  case 'A':
+		phytype = BCM43xx_PHYTYPE_A;
+		break;
+	case 'b':  case 'B':
+		phytype = BCM43xx_PHYTYPE_B;
+		break;
+	case 'g':  case 'G':
+		phytype = BCM43xx_PHYTYPE_G;
+		break;
+	default:
+		goto out;
+	}
+
+	bcm43xx_periodic_tasks_delete(bcm);
+	mutex_lock(&(bcm)->mutex);
+	err = bcm43xx_select_wireless_core(bcm, phytype);
+	if (!err)
+		bcm43xx_periodic_tasks_setup(bcm);
+	mutex_unlock(&(bcm)->mutex);
+	if (err == -ESRCH)
+		err = -ENODEV;
+
+out:
+	return err ? err : count;
+}
+
+static ssize_t bcm43xx_attr_phymode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+	ssize_t count = 0;
+
+	mutex_lock(&(bcm)->mutex);
+	switch (bcm43xx_current_phy(bcm)->type) {
+	case BCM43xx_PHYTYPE_A:
+		snprintf(buf, PAGE_SIZE, "A");
+		break;
+	case BCM43xx_PHYTYPE_B:
+		snprintf(buf, PAGE_SIZE, "B");
+		break;
+	case BCM43xx_PHYTYPE_G:
+		snprintf(buf, PAGE_SIZE, "G");
+		break;
+	default:
+		assert(0);
+	}
+	mutex_unlock(&(bcm)->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(phymode, 0644,
+		   bcm43xx_attr_phymode_show,
+		   bcm43xx_attr_phymode_store);
+
+static ssize_t bcm43xx_attr_microcode_show(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	unsigned long flags;
+	struct bcm43xx_private *bcm = dev_to_bcm(dev);
+	ssize_t count = 0;
+	u16 status;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&(bcm)->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
+	status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED,
+				    BCM43xx_UCODE_STATUS);
+
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&(bcm)->mutex);
+	switch (status) {
+	case 0x0000:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n",
+				 status);
+		break;
+	case 0x0001:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n",
+				 status);
+		break;
+	case 0x0002:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n",
+				 status);
+		break;
+	case 0x0003:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n",
+				 status);
+		break;
+	case 0x0004:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n",
+				 status);
+		break;
+	default:
+		count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n",
+				 status);
+		break;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(microcodestatus, 0444,
+		   bcm43xx_attr_microcode_show,
+		   NULL);
+
 int bcm43xx_sysfs_register(struct bcm43xx_private *bcm)
 {
 	struct device *dev = &bcm->pci_dev->dev;
@@ -315,9 +439,19 @@
 	err = device_create_file(dev, &dev_attr_shortpreamble);
 	if (err)
 		goto err_remove_interfmode;
+	err = device_create_file(dev, &dev_attr_phymode);
+	if (err)
+		goto err_remove_shortpreamble;
+	err = device_create_file(dev, &dev_attr_microcodestatus);
+	if (err)
+		goto err_remove_phymode;
 
 out:
 	return err;
+err_remove_phymode:
+	device_remove_file(dev, &dev_attr_phymode);
+err_remove_shortpreamble:
+	device_remove_file(dev, &dev_attr_shortpreamble);
 err_remove_interfmode:
 	device_remove_file(dev, &dev_attr_interference);
 err_remove_sprom:
@@ -329,6 +463,8 @@
 {
 	struct device *dev = &bcm->pci_dev->dev;
 
+	device_remove_file(dev, &dev_attr_microcodestatus);
+	device_remove_file(dev, &dev_attr_phymode);
 	device_remove_file(dev, &dev_attr_shortpreamble);
 	device_remove_file(dev, &dev_attr_interference);
 	device_remove_file(dev, &dev_attr_sprom);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index 5c36e29..888077f 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -47,6 +47,8 @@
 #define BCM43xx_WX_VERSION	18
 
 #define MAX_WX_STRING		80
+/* FIXME: the next line is a guess as to what the maximum RSSI value might be */
+#define RX_RSSI_MAX		60
 
 
 static int bcm43xx_wx_get_name(struct net_device *net_dev,
@@ -56,12 +58,11 @@
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	int i;
-	unsigned long flags;
 	struct bcm43xx_phyinfo *phy;
 	char suffix[7] = { 0 };
 	int have_a = 0, have_b = 0, have_g = 0;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	for (i = 0; i < bcm->nr_80211_available; i++) {
 		phy = &(bcm->core_80211_ext[i].phy);
 		switch (phy->type) {
@@ -77,7 +78,7 @@
 			assert(0);
 		}
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	i = 0;
 	if (have_a) {
@@ -111,7 +112,9 @@
 	int freq;
 	int err = -EINVAL;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
+
 	if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
 		channel = data->freq.m;
 		freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -131,7 +134,8 @@
 		err = 0;
 	}
 out_unlock:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -143,11 +147,10 @@
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	struct bcm43xx_radioinfo *radio;
-	unsigned long flags;
 	int err = -ENODEV;
 	u16 channel;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	radio = bcm43xx_current_radio(bcm);
 	channel = radio->channel;
 	if (channel == 0xFF) {
@@ -162,7 +165,7 @@
 
 	err = 0;
 out_unlock:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -180,13 +183,15 @@
 	if (mode == IW_MODE_AUTO)
 		mode = BCM43xx_INITIAL_IWMODE;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		if (bcm->ieee->iw_mode != mode)
 			bcm43xx_set_iwmode(bcm, mode);
 	} else
 		bcm->ieee->iw_mode = mode;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -197,11 +202,10 @@
 			       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	data->mode = bcm->ieee->iw_mode;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -214,7 +218,6 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	struct iw_range *range = (struct iw_range *)extra;
 	const struct ieee80211_geo *geo;
-	unsigned long flags;
 	int i, j;
 	struct bcm43xx_phyinfo *phy;
 
@@ -226,15 +229,14 @@
 	range->throughput = 27 * 1000 * 1000;
 
 	range->max_qual.qual = 100;
-	/* TODO: Real max RSSI */
-	range->max_qual.level = 3;
-	range->max_qual.noise = 100;
-	range->max_qual.updated = 7;
+	range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */
+	range->max_qual.noise = 146;
+	range->max_qual.updated = IW_QUAL_ALL_UPDATED;
 
-	range->avg_qual.qual = 70;
-	range->avg_qual.level = 2;
-	range->avg_qual.noise = 40;
-	range->avg_qual.updated = 7;
+	range->avg_qual.qual = 50;
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = IW_QUAL_ALL_UPDATED;
 
 	range->min_rts = BCM43xx_MIN_RTS_THRESHOLD;
 	range->max_rts = BCM43xx_MAX_RTS_THRESHOLD;
@@ -254,7 +256,7 @@
 			  IW_ENC_CAPA_CIPHER_TKIP |
 			  IW_ENC_CAPA_CIPHER_CCMP;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	phy = bcm43xx_current_phy(bcm);
 
 	range->num_bitrates = 0;
@@ -301,7 +303,7 @@
 	}
 	range->num_frequency = j;
 
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -314,11 +316,11 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	size_t len;
 
-	bcm43xx_lock_noirq(bcm);
+	mutex_lock(&bcm->mutex);
 	len =  min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
 	memcpy(bcm->nick, extra, len);
 	bcm->nick[len] = '\0';
-	bcm43xx_unlock_noirq(bcm);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -331,12 +333,12 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	size_t len;
 
-	bcm43xx_lock_noirq(bcm);
+	mutex_lock(&bcm->mutex);
 	len = strlen(bcm->nick) + 1;
 	memcpy(extra, bcm->nick, len);
 	data->data.length = (__u16)len;
 	data->data.flags = 1;
-	bcm43xx_unlock_noirq(bcm);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -350,7 +352,8 @@
 	unsigned long flags;
 	int err = -EINVAL;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (data->rts.disabled) {
 		bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
 		err = 0;
@@ -361,7 +364,8 @@
 			err = 0;
 		}
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -372,13 +376,12 @@
 			      char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	data->rts.value = bcm->rts_threshold;
 	data->rts.fixed = 0;
 	data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -392,7 +395,8 @@
 	unsigned long flags;
 	int err = -EINVAL;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (data->frag.disabled) {
 		bcm->ieee->fts = MAX_FRAG_THRESHOLD;
 		err = 0;
@@ -403,7 +407,8 @@
 			err = 0;
 		}
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -414,13 +419,12 @@
 			       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	data->frag.value = bcm->ieee->fts;
 	data->frag.fixed = 0;
 	data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -442,7 +446,8 @@
 		return -EOPNOTSUPP;
 	}
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		goto out_unlock;
 	radio = bcm43xx_current_radio(bcm);
@@ -466,7 +471,8 @@
 	err = 0;
 
 out_unlock:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -478,10 +484,9 @@
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	struct bcm43xx_radioinfo *radio;
-	unsigned long flags;
 	int err = -ENODEV;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		goto out_unlock;
 	radio = bcm43xx_current_radio(bcm);
@@ -493,7 +498,7 @@
 
 	err = 0;
 out_unlock:
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -580,7 +585,8 @@
 		return -EINVAL;
 	}
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
 		if (err) {
@@ -595,7 +601,8 @@
 		} else
 			bcm43xx_current_radio(bcm)->interfmode = mode;
 	}
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return err;
 }
@@ -606,12 +613,11 @@
 				     char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	int mode;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	mode = bcm43xx_current_radio(bcm)->interfmode;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	switch (mode) {
 	case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -641,9 +647,11 @@
 	int on;
 
 	on = *((int *)extra);
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	bcm->short_preamble = !!on;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -654,12 +662,11 @@
 					char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	int on;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	on = bcm->short_preamble;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	if (on)
 		strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -681,11 +688,13 @@
 	
 	on = *((int *)extra);
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	bcm->ieee->host_encrypt = !!on;
 	bcm->ieee->host_decrypt = !!on;
 	bcm->ieee->host_build_iv = !on;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 
 	return 0;
 }
@@ -696,12 +705,11 @@
 				       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	int on;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
 	on = bcm->ieee->host_encrypt;
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	mutex_unlock(&bcm->mutex);
 
 	if (on)
 		strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -764,11 +772,13 @@
 	if (!sprom)
 		goto out;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
 	err = -ENODEV;
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		err = bcm43xx_sprom_read(bcm, sprom);
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 	if (!err)
 		data->data.length = sprom2hex(sprom, extra);
 	kfree(sprom);
@@ -809,11 +819,15 @@
 	if (err)
 		goto out_kfree;
 
-	bcm43xx_lock_irqsafe(bcm, flags);
+	mutex_lock(&bcm->mutex);
+	spin_lock_irqsave(&bcm->irq_lock, flags);
+	spin_lock(&bcm->leds_lock);
 	err = -ENODEV;
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		err = bcm43xx_sprom_write(bcm, sprom);
-	bcm43xx_unlock_irqsafe(bcm, flags);
+	spin_unlock(&bcm->leds_lock);
+	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+	mutex_unlock(&bcm->mutex);
 out_kfree:
 	kfree(sprom);
 out:
@@ -827,6 +841,10 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
 	struct iw_statistics *wstats;
+	struct ieee80211_network *network = NULL;
+	static int tmp_level = 0;
+	static int tmp_qual = 0;
+	unsigned long flags;
 
 	wstats = &bcm->stats.wstats;
 	if (!mac->associated) {
@@ -844,16 +862,28 @@
 		wstats->qual.level = 0;
 		wstats->qual.noise = 0;
 		wstats->qual.updated = 7;
-		wstats->qual.updated |= IW_QUAL_NOISE_INVALID |
-			IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+		wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 		return wstats;
 	}
 	/* fill in the real statistics when iface associated */
-	wstats->qual.qual = 100;     // TODO: get the real signal quality
-	wstats->qual.level = 3 - bcm->stats.link_quality;
+	spin_lock_irqsave(&mac->ieee->lock, flags);
+	list_for_each_entry(network, &mac->ieee->network_list, list) {
+		if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) {
+			if (!tmp_level)	{	/* get initial values */
+				tmp_level = network->stats.signal;
+				tmp_qual = network->stats.rssi;
+			} else {		/* smooth results */
+				tmp_level = (15 * tmp_level + network->stats.signal)/16;
+				tmp_qual = (15 * tmp_qual + network->stats.rssi)/16;
+			}
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&mac->ieee->lock, flags);
+	wstats->qual.level = tmp_level;
+	wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX;
 	wstats->qual.noise = bcm->stats.noise;
-	wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
-			IW_QUAL_NOISE_UPDATED;
+	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 	wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable;
 	wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded;
 	wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index 6dbd855..c0efbfe 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -492,16 +492,15 @@
 
 	memset(&stats, 0, sizeof(stats));
 	stats.mac_time = le16_to_cpu(rxhdr->mactime);
-	stats.rssi = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
+	stats.rssi = rxhdr->rssi;
+	stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
 					      !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
 					      !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-	stats.signal = rxhdr->signal_quality;	//FIXME
 //TODO	stats.noise = 
 	if (is_ofdm)
 		stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
 	else
 		stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
-//printk("RX ofdm %d, rate == %u\n", is_ofdm, stats.rate);
 	stats.received_channel = radio->channel;
 //TODO	stats.control = 
 	stats.mask = IEEE80211_STATMASK_SIGNAL |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 52e6df5..686d895 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -847,6 +847,7 @@
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005),
 	PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010),
+	PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002),
 	PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL",
 					 0x74c5e40d),
 	PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil",
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index dafaa5f..d500012 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -1042,6 +1042,9 @@
 		       dev->name, local->fragm_threshold);
 	}
 
+	/* Some firmwares lose antenna selection settings on reset */
+	(void) hostap_set_antsel(local);
+
 	return res;
 }
 
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index e955db4..d2db8eb 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -6254,13 +6254,14 @@
 	 * member to call a function that then just turns and calls ipw2100_up.
 	 * net_dev->init is called after name allocation but before the
 	 * notifier chain is called */
-	mutex_lock(&priv->action_mutex);
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_WARNING DRV_NAME
 		       "Error calling register_netdev.\n");
-		goto fail_unlock;
+		goto fail;
 	}
+
+	mutex_lock(&priv->action_mutex);
 	registered = 1;
 
 	IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev));
@@ -6531,7 +6532,7 @@
 	printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
 	printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT);
 
-	ret = pci_module_init(&ipw2100_pci_driver);
+	ret = pci_register_driver(&ipw2100_pci_driver);
 
 #ifdef CONFIG_IPW2100_DEBUG
 	ipw2100_debug_level = debug;
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index b3300ff..f29ec0e 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -70,7 +70,7 @@
 #define VQ
 #endif
 
-#define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ
+#define IPW2200_VERSION "1.1.4" VK VD VM VP VR VQ
 #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2200/2915 Network Driver"
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
 #define DRV_VERSION     IPW2200_VERSION
@@ -83,9 +83,7 @@
 MODULE_LICENSE("GPL");
 
 static int cmdlog = 0;
-#ifdef CONFIG_IPW2200_DEBUG
 static int debug = 0;
-#endif
 static int channel = 0;
 static int mode = 0;
 
@@ -567,7 +565,6 @@
 	spin_unlock_irqrestore(&priv->irq_lock, flags);
 }
 
-#ifdef CONFIG_IPW2200_DEBUG
 static char *ipw_error_desc(u32 val)
 {
 	switch (val) {
@@ -634,7 +631,6 @@
 			  error->log[i].time,
 			  error->log[i].data, error->log[i].event);
 }
-#endif
 
 static inline int ipw_is_init(struct ipw_priv *priv)
 {
@@ -1435,9 +1431,7 @@
 			      const char *buf, size_t count)
 {
 	struct ipw_priv *priv = dev_get_drvdata(d);
-#ifdef CONFIG_IPW2200_DEBUG
 	struct net_device *dev = priv->net_dev;
-#endif
 	char buffer[] = "00000000";
 	unsigned long len =
 	    (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1;
@@ -1958,14 +1952,12 @@
 		IPW_WARNING("Firmware error detected.  Restarting.\n");
 		if (priv->error) {
 			IPW_DEBUG_FW("Sysfs 'error' log already exists.\n");
-#ifdef CONFIG_IPW2200_DEBUG
 			if (ipw_debug_level & IPW_DL_FW_ERRORS) {
 				struct ipw_fw_error *error =
 				    ipw_alloc_error_log(priv);
 				ipw_dump_error_log(priv, error);
 				kfree(error);
 			}
-#endif
 		} else {
 			priv->error = ipw_alloc_error_log(priv);
 			if (priv->error)
@@ -1973,10 +1965,8 @@
 			else
 				IPW_DEBUG_FW("Error allocating sysfs 'error' "
 					     "log.\n");
-#ifdef CONFIG_IPW2200_DEBUG
 			if (ipw_debug_level & IPW_DL_FW_ERRORS)
 				ipw_dump_error_log(priv, priv->error);
-#endif
 		}
 
 		/* XXX: If hardware encryption is for WPA/WPA2,
@@ -2287,7 +2277,7 @@
 static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
 {
 	struct ipw_sensitivity_calib calib = {
-		.beacon_rssi_raw = sens,
+		.beacon_rssi_raw = cpu_to_le16(sens),
 	};
 
 	return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib),
@@ -2353,6 +2343,7 @@
 		return -1;
 	}
 
+	phy_off = cpu_to_le32(phy_off);
 	return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off),
 				&phy_off);
 }
@@ -2414,7 +2405,7 @@
 static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts)
 {
 	struct ipw_rts_threshold rts_threshold = {
-		.rts_threshold = rts,
+		.rts_threshold = cpu_to_le16(rts),
 	};
 
 	if (!priv) {
@@ -2429,7 +2420,7 @@
 static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
 {
 	struct ipw_frag_threshold frag_threshold = {
-		.frag_threshold = frag,
+		.frag_threshold = cpu_to_le16(frag),
 	};
 
 	if (!priv) {
@@ -2464,6 +2455,7 @@
 		break;
 	}
 
+	param = cpu_to_le32(mode);
 	return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param),
 				&param);
 }
@@ -2667,7 +2659,7 @@
 
 	IPW_DEBUG_FW(">> :\n");
 
-	//set the Stop and Abort bit
+	/* set the Stop and Abort bit */
 	control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT;
 	ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control);
 	priv->sram_desc.last_cb_index = 0;
@@ -3002,8 +2994,6 @@
 	if (rc < 0)
 		return rc;
 
-//      spin_lock_irqsave(&priv->lock, flags);
-
 	for (addr = IPW_SHARED_LOWER_BOUND;
 	     addr < IPW_REGISTER_DOMAIN1_END; addr += 4) {
 		ipw_write32(priv, addr, 0);
@@ -3097,8 +3087,6 @@
 	   firmware have problem getting alive resp. */
 	ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0);
 
-//      spin_unlock_irqrestore(&priv->lock, flags);
-
 	return rc;
 }
 
@@ -3919,7 +3907,6 @@
 	{0x2E, "Cipher suite is rejected per security policy"},
 };
 
-#ifdef CONFIG_IPW2200_DEBUG
 static const char *ipw_get_status_code(u16 status)
 {
 	int i;
@@ -3928,7 +3915,6 @@
 			return ipw_status_codes[i].reason;
 	return "Unknown status value.";
 }
-#endif
 
 static void inline average_init(struct average *avg)
 {
@@ -4398,7 +4384,6 @@
 					if (priv->
 					    status & (STATUS_ASSOCIATED |
 						      STATUS_AUTH)) {
-#ifdef CONFIG_IPW2200_DEBUG
 						struct notif_authenticate *auth
 						    = &notif->u.auth;
 						IPW_DEBUG(IPW_DL_NOTIF |
@@ -4416,7 +4401,6 @@
 							  ipw_get_status_code
 							  (ntohs
 							   (auth->status)));
-#endif
 
 						priv->status &=
 						    ~(STATUS_ASSOCIATING |
@@ -5059,7 +5043,6 @@
 		}
 		list_del(element);
 
-		rxb->rxb = (struct ipw_rx_buffer *)rxb->skb->data;
 		rxb->dma_addr =
 		    pci_map_single(priv->pci_dev, rxb->skb->data,
 				   IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
@@ -5838,8 +5821,8 @@
 	key.station_index = 0;	/* always 0 for BSS */
 	key.flags = 0;
 	/* 0 for new key; previous value of counter (after fatal error) */
-	key.tx_counter[0] = 0;
-	key.tx_counter[1] = 0;
+	key.tx_counter[0] = cpu_to_le32(0);
+	key.tx_counter[1] = cpu_to_le32(0);
 
 	ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key);
 }
@@ -5973,7 +5956,6 @@
 	mutex_unlock(&priv->mutex);
 }
 
-#ifdef CONFIG_IPW2200_DEBUG
 static void ipw_debug_config(struct ipw_priv *priv)
 {
 	IPW_DEBUG_INFO("Scan completed, no valid APs matched "
@@ -5998,9 +5980,6 @@
 		IPW_DEBUG_INFO("PRIVACY off\n");
 	IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask);
 }
-#else
-#define ipw_debug_config(x) do {} while (0)
-#endif
 
 static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode)
 {
@@ -6188,7 +6167,7 @@
 	}
 }
 
-static int ipw_request_scan(struct ipw_priv *priv)
+static int ipw_request_scan_helper(struct ipw_priv *priv, int type)
 {
 	struct ipw_scan_request_ext scan;
 	int err = 0, scan_type;
@@ -6219,19 +6198,29 @@
 	}
 
 	memset(&scan, 0, sizeof(scan));
+	scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
 
-	if (priv->config & CFG_SPEED_SCAN)
+	if (type == IW_SCAN_TYPE_PASSIVE) {
+	  	IPW_DEBUG_WX("use passive scanning\n");
+	  	scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
+		scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
+			cpu_to_le16(120);
+		ipw_add_scan_channels(priv, &scan, scan_type);
+		goto send_request;
+	}
+
+	/* Use active scan by default. */
+  	if (priv->config & CFG_SPEED_SCAN)
 		scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
-		    cpu_to_le16(30);
+			cpu_to_le16(30);
 	else
 		scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
-		    cpu_to_le16(20);
+			cpu_to_le16(20);
 
 	scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
-	    cpu_to_le16(20);
-	scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
+		cpu_to_le16(20);
 
-	scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
+  	scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
 
 #ifdef CONFIG_IPW2200_MONITOR
 	if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
@@ -6268,7 +6257,7 @@
 		 *
 		 * TODO: Move SPEED SCAN support to all modes and bands */
 		scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
-		    cpu_to_le16(2000);
+			cpu_to_le16(2000);
 	} else {
 #endif				/* CONFIG_IPW2200_MONITOR */
 		/* If we are roaming, then make this a directed scan for the
@@ -6294,6 +6283,7 @@
 	}
 #endif
 
+send_request:
 	err = ipw_send_scan_request_ext(priv, &scan);
 	if (err) {
 		IPW_DEBUG_HC("Sending scan command failed: %08X\n", err);
@@ -6304,11 +6294,19 @@
 	priv->status &= ~STATUS_SCAN_PENDING;
 	queue_delayed_work(priv->workqueue, &priv->scan_check,
 			   IPW_SCAN_CHECK_WATCHDOG);
-      done:
+done:
 	mutex_unlock(&priv->mutex);
 	return err;
 }
 
+static int ipw_request_passive_scan(struct ipw_priv *priv) {
+  	return ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE);
+}
+
+static int ipw_request_scan(struct ipw_priv *priv) {
+	return ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE);
+}
+
 static void ipw_bg_abort_scan(void *data)
 {
 	struct ipw_priv *priv = data;
@@ -6387,13 +6385,6 @@
 	    (wrqu->data.length && extra == NULL))
 		return -EINVAL;
 
-	//mutex_lock(&priv->mutex);
-
-	//if (!ieee->wpa_enabled) {
-	//      err = -EOPNOTSUPP;
-	//      goto out;
-	//}
-
 	if (wrqu->data.length) {
 		buf = kmalloc(wrqu->data.length, GFP_KERNEL);
 		if (buf == NULL) {
@@ -6413,7 +6404,6 @@
 
 	ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
       out:
-	//mutex_unlock(&priv->mutex);
 	return err;
 }
 
@@ -6426,13 +6416,6 @@
 	struct ieee80211_device *ieee = priv->ieee;
 	int err = 0;
 
-	//mutex_lock(&priv->mutex);
-
-	//if (!ieee->wpa_enabled) {
-	//      err = -EOPNOTSUPP;
-	//      goto out;
-	//}
-
 	if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
 		wrqu->data.length = 0;
 		goto out;
@@ -6447,7 +6430,6 @@
 	memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
 
       out:
-	//mutex_unlock(&priv->mutex);
 	return err;
 }
 
@@ -6558,7 +6540,6 @@
 		ieee->ieee802_1x = param->value;
 		break;
 
-		//case IW_AUTH_ROAMING_CONTROL:
 	case IW_AUTH_PRIVACY_INVOKED:
 		ieee->privacy_invoked = param->value;
 		break;
@@ -6680,7 +6661,7 @@
 
 	switch (mlme->cmd) {
 	case IW_MLME_DEAUTH:
-		// silently ignore
+		/* silently ignore */
 		break;
 
 	case IW_MLME_DISASSOC:
@@ -6811,7 +6792,7 @@
 		burst_duration = ipw_qos_get_burst_duration(priv);
 		for (i = 0; i < QOS_QUEUE_NUM; i++)
 			qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] =
-			    (u16) burst_duration;
+			    (u16)burst_duration;
 	} else if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
 		if (type == IEEE_B) {
 			IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n",
@@ -6843,11 +6824,20 @@
 			burst_duration = ipw_qos_get_burst_duration(priv);
 			for (i = 0; i < QOS_QUEUE_NUM; i++)
 				qos_parameters[QOS_PARAM_SET_ACTIVE].
-				    tx_op_limit[i] = (u16) burst_duration;
+				    tx_op_limit[i] = (u16)burst_duration;
 		}
 	}
 
 	IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n");
+	for (i = 0; i < 3; i++) {
+		int j;
+		for (j = 0; j < QOS_QUEUE_NUM; j++) {
+			qos_parameters[i].cw_min[j] = cpu_to_le16(qos_parameters[i].cw_min[j]);
+			qos_parameters[i].cw_max[j] = cpu_to_le16(qos_parameters[i].cw_max[j]);
+			qos_parameters[i].tx_op_limit[j] = cpu_to_le16(qos_parameters[i].tx_op_limit[j]);
+		}
+	}
+
 	err = ipw_send_qos_params_command(priv,
 					  (struct ieee80211_qos_parameters *)
 					  &(qos_parameters[0]));
@@ -7086,7 +7076,7 @@
 
 	if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) {
 		tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
-		tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK;
+		tfd->tfd.tfd_26.mchdr.qos_ctrl |= cpu_to_le16(CTRL_QOS_NO_ACK);
 	}
 	return 0;
 }
@@ -7667,7 +7657,6 @@
 	/* Big bitfield of all the fields we provide in radiotap */
 	ipw_rt->rt_hdr.it_present =
 	    ((1 << IEEE80211_RADIOTAP_FLAGS) |
-	     (1 << IEEE80211_RADIOTAP_TSFT) |
 	     (1 << IEEE80211_RADIOTAP_RATE) |
 	     (1 << IEEE80211_RADIOTAP_CHANNEL) |
 	     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
@@ -7676,6 +7665,7 @@
 
 	/* Zero the flags, we'll add to them as we go */
 	ipw_rt->rt_flags = 0;
+	ipw_rt->rt_tsf = 0ULL;
 
 	/* Convert signal to DBM */
 	ipw_rt->rt_dbmsignal = antsignal;
@@ -7794,7 +7784,6 @@
 	s8 noise = frame->noise;
 	u8 rate = frame->rate;
 	short len = le16_to_cpu(pkt->u.frame.length);
-	u64 tsf = 0;
 	struct sk_buff *skb;
 	int hdr_only = 0;
 	u16 filter = priv->prom_priv->filter;
@@ -7829,17 +7818,17 @@
 	}
 
 	hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
-	if (ieee80211_is_management(hdr->frame_ctl)) {
+	if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_MGMT)
 			return;
 		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_control(hdr->frame_ctl)) {
+	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_CTL)
 			return;
 		if (filter & IPW_PROM_CTL_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_data(hdr->frame_ctl)) {
+	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_DATA)
 			return;
 		if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -7857,7 +7846,7 @@
 	ipw_rt = (void *)skb->data;
 
 	if (hdr_only)
-		len = ieee80211_get_hdrlen(hdr->frame_ctl);
+		len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
 	memcpy(ipw_rt->payload, hdr, len);
 
@@ -7880,7 +7869,6 @@
 	/* Big bitfield of all the fields we provide in radiotap */
 	ipw_rt->rt_hdr.it_present =
 	    ((1 << IEEE80211_RADIOTAP_FLAGS) |
-	     (1 << IEEE80211_RADIOTAP_TSFT) |
 	     (1 << IEEE80211_RADIOTAP_RATE) |
 	     (1 << IEEE80211_RADIOTAP_CHANNEL) |
 	     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
@@ -7889,8 +7877,7 @@
 
 	/* Zero the flags, we'll add to them as we go */
 	ipw_rt->rt_flags = 0;
-
-	ipw_rt->rt_tsf = tsf;
+	ipw_rt->rt_tsf = 0ULL;
 
 	/* Convert to DBM */
 	ipw_rt->rt_dbmsignal = signal;
@@ -8163,8 +8150,7 @@
 		switch (pkt->header.message_type) {
 		case RX_FRAME_TYPE:	/* 802.11 frame */  {
 				struct ieee80211_rx_stats stats = {
-					.rssi =
-					    le16_to_cpu(pkt->u.frame.rssi_dbm) -
+					.rssi = pkt->u.frame.rssi_dbm -
 					    IPW_RSSI_TO_DBM,
 					.signal =
 					    le16_to_cpu(pkt->u.frame.rssi_dbm) -
@@ -8599,9 +8585,26 @@
 	 * configured CHANNEL then return that; otherwise return ANY */
 	mutex_lock(&priv->mutex);
 	if (priv->config & CFG_STATIC_CHANNEL ||
-	    priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED))
-		wrqu->freq.m = priv->channel;
-	else
+	    priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) {
+		int i;
+
+		i = ieee80211_channel_to_index(priv->ieee, priv->channel);
+		BUG_ON(i == -1);
+		wrqu->freq.e = 1;
+
+		switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) {
+		case IEEE80211_52GHZ_BAND:
+			wrqu->freq.m = priv->ieee->geo.a[i].freq * 100000;
+			break;
+
+		case IEEE80211_24GHZ_BAND:
+			wrqu->freq.m = priv->ieee->geo.bg[i].freq * 100000;
+			break;
+
+		default:
+			BUG();
+		}
+	} else
 		wrqu->freq.m = 0;
 
 	mutex_unlock(&priv->mutex);
@@ -8857,42 +8860,38 @@
 			    union iwreq_data *wrqu, char *extra)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
-	char *essid = "";	/* ANY */
-	int length = 0;
-	mutex_lock(&priv->mutex);
-	if (wrqu->essid.flags && wrqu->essid.length) {
-		length = wrqu->essid.length - 1;
-		essid = extra;
-	}
-	if (length == 0) {
-		IPW_DEBUG_WX("Setting ESSID to ANY\n");
-		if ((priv->config & CFG_STATIC_ESSID) &&
-		    !(priv->status & (STATUS_ASSOCIATED |
-				      STATUS_ASSOCIATING))) {
-			IPW_DEBUG_ASSOC("Attempting to associate with new "
-					"parameters.\n");
-			priv->config &= ~CFG_STATIC_ESSID;
-			ipw_associate(priv);
-		}
-		mutex_unlock(&priv->mutex);
-		return 0;
-	}
+        int length;
 
-	length = min(length, IW_ESSID_MAX_SIZE);
+        mutex_lock(&priv->mutex);
+
+        if (!wrqu->essid.flags)
+        {
+                IPW_DEBUG_WX("Setting ESSID to ANY\n");
+                ipw_disassociate(priv);
+                priv->config &= ~CFG_STATIC_ESSID;
+                ipw_associate(priv);
+                mutex_unlock(&priv->mutex);
+                return 0;
+        }
+
+	length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE);
+	if (!extra[length - 1])
+		length--;
 
 	priv->config |= CFG_STATIC_ESSID;
 
-	if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) {
+	if (priv->essid_len == length && !memcmp(priv->essid, extra, length)
+	    && (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) {
 		IPW_DEBUG_WX("ESSID set to current ESSID.\n");
 		mutex_unlock(&priv->mutex);
 		return 0;
 	}
 
-	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
+	IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(extra, length),
 		     length);
 
 	priv->essid_len = length;
-	memcpy(priv->essid, essid, priv->essid_len);
+	memcpy(priv->essid, extra, priv->essid_len);
 
 	/* Network configuration changed -- force [re]association */
 	IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n");
@@ -9273,7 +9272,7 @@
 	if (!(wrqu->retry.flags & IW_RETRY_LIMIT))
 		return 0;
 
-	if (wrqu->retry.value < 0 || wrqu->retry.value > 255)
+	if (wrqu->retry.value < 0 || wrqu->retry.value >= 255)
 		return -EINVAL;
 
 	mutex_lock(&priv->mutex);
@@ -9396,15 +9395,19 @@
 			   union iwreq_data *wrqu, char *extra)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
-	struct iw_scan_req *req = NULL;
-	if (wrqu->data.length
-	    && wrqu->data.length == sizeof(struct iw_scan_req)) {
-		req = (struct iw_scan_req *)extra;
+	struct iw_scan_req *req = (struct iw_scan_req *)extra;
+
+	if (wrqu->data.length == sizeof(struct iw_scan_req)) {
 		if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
 			ipw_request_direct_scan(priv, req->essid,
 						req->essid_len);
 			return 0;
 		}
+		if (req->scan_type == IW_SCAN_TYPE_PASSIVE) {
+			queue_work(priv->workqueue,
+				   &priv->request_passive_scan);
+			return 0;
+		}
 	}
 
 	IPW_DEBUG_WX("Start scan\n");
@@ -9766,7 +9769,7 @@
 	return 0;
 }
 
-#endif				// CONFIG_IPW2200_MONITOR
+#endif				/* CONFIG_IPW2200_MONITOR */
 
 static int ipw_wx_reset(struct net_device *dev,
 			struct iw_request_info *info,
@@ -10009,7 +10012,7 @@
 	sys_config->dot11g_auto_detection = 0;
 	sys_config->enable_cts_to_self = 0;
 	sys_config->bt_coexist_collision_thr = 0;
-	sys_config->pass_noise_stats_to_host = 1;	//1 -- fix for 256
+	sys_config->pass_noise_stats_to_host = 1;	/* 1 -- fix for 256 */
 	sys_config->silence_threshold = 0x1e;
 }
 
@@ -10113,7 +10116,7 @@
 		switch (priv->ieee->sec.level) {
 		case SEC_LEVEL_3:
 			tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
-			    IEEE80211_FCTL_PROTECTED;
+			    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 			/* XXX: ACK flag must be set for CCMP even if it
 			 * is a multicast/broadcast packet, because CCMP
 			 * group communication encrypted by GTK is
@@ -10128,14 +10131,14 @@
 			break;
 		case SEC_LEVEL_2:
 			tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
-			    IEEE80211_FCTL_PROTECTED;
+			    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 			tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP;
 			tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP;
 			tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE;
 			break;
 		case SEC_LEVEL_1:
 			tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
-			    IEEE80211_FCTL_PROTECTED;
+			    cpu_to_le16(IEEE80211_FCTL_PROTECTED);
 			tfd->u.data.key_index = priv->ieee->tx_keyidx;
 			if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <=
 			    40)
@@ -10267,17 +10270,17 @@
 
 	/* Filtering of fragment chains is done agains the first fragment */
 	hdr = (void *)txb->fragments[0]->data;
-	if (ieee80211_is_management(hdr->frame_ctl)) {
+	if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_MGMT)
 			return;
 		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_control(hdr->frame_ctl)) {
+	} else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_CTL)
 			return;
 		if (filter & IPW_PROM_CTL_HEADER_ONLY)
 			hdr_only = 1;
-	} else if (ieee80211_is_data(hdr->frame_ctl)) {
+	} else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
 		if (filter & IPW_PROM_NO_DATA)
 			return;
 		if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -10292,7 +10295,7 @@
 
 		if (hdr_only) {
 			hdr = (void *)src->data;
-			len = ieee80211_get_hdrlen(hdr->frame_ctl);
+			len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 		} else
 			len = src->len;
 
@@ -10636,6 +10639,8 @@
 	INIT_WORK(&priv->down, (void (*)(void *))ipw_bg_down, priv);
 	INIT_WORK(&priv->request_scan,
 		  (void (*)(void *))ipw_request_scan, priv);
+	INIT_WORK(&priv->request_passive_scan,
+		  (void (*)(void *))ipw_request_passive_scan, priv);
 	INIT_WORK(&priv->gather_stats,
 		  (void (*)(void *))ipw_bg_gather_stats, priv);
 	INIT_WORK(&priv->abort_scan, (void (*)(void *))ipw_bg_abort_scan, priv);
@@ -11488,9 +11493,7 @@
 
 	priv->net_dev = net_dev;
 	priv->pci_dev = pdev;
-#ifdef CONFIG_IPW2200_DEBUG
 	ipw_debug_level = debug;
-#endif
 	spin_lock_init(&priv->irq_lock);
 	spin_lock_init(&priv->lock);
 	for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++)
@@ -11755,6 +11758,16 @@
 }
 #endif
 
+static void ipw_pci_shutdown(struct pci_dev *pdev)
+{
+	struct ipw_priv *priv = pci_get_drvdata(pdev);
+
+	/* Take down the device; powers it off, etc. */
+	ipw_down(priv);
+
+	pci_disable_device(pdev);
+}
+
 /* driver initialization stuff */
 static struct pci_driver ipw_driver = {
 	.name = DRV_NAME,
@@ -11765,6 +11778,7 @@
 	.suspend = ipw_pci_suspend,
 	.resume = ipw_pci_resume,
 #endif
+	.shutdown = ipw_pci_shutdown,
 };
 
 static int __init ipw_init(void)
@@ -11774,7 +11788,7 @@
 	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
 	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
 
-	ret = pci_module_init(&ipw_driver);
+	ret = pci_register_driver(&ipw_driver);
 	if (ret) {
 		IPW_ERROR("Unable to initialize PCI module\n");
 		return ret;
@@ -11808,10 +11822,8 @@
 module_param(led, int, 0444);
 MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)\n");
 
-#ifdef CONFIG_IPW2200_DEBUG
 module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "debug output mask");
-#endif
 
 module_param(channel, int, 0444);
 MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 8b1cd7c..dad5eed 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -713,7 +713,6 @@
 
 struct ipw_rx_mem_buffer {
 	dma_addr_t dma_addr;
-	struct ipw_rx_buffer *rxb;
 	struct sk_buff *skb;
 	struct list_head list;
 };				/* Not transferred over network, so not  __attribute__ ((packed)) */
@@ -1297,6 +1296,7 @@
 	struct work_struct system_config;
 	struct work_struct rx_replenish;
 	struct work_struct request_scan;
+  	struct work_struct request_passive_scan;
 	struct work_struct adapter_restart;
 	struct work_struct rf_kill;
 	struct work_struct up;
@@ -1381,13 +1381,18 @@
 BIT_ARG16(x)
 
 
-#ifdef CONFIG_IPW2200_DEBUG
 #define IPW_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
   printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
          in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+
+#ifdef CONFIG_IPW2200_DEBUG
+#define IPW_LL_DEBUG(level, fmt, args...) \
+do { if (ipw_debug_level & (level)) \
+  printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \
+         in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
 #else
-#define IPW_DEBUG(level, fmt, args...) do {} while (0)
+#define IPW_LL_DEBUG(level, fmt, args...) do {} while (0)
 #endif				/* CONFIG_IPW2200_DEBUG */
 
 /*
@@ -1457,28 +1462,27 @@
 
 #define IPW_DEBUG_WX(f, a...)     IPW_DEBUG(IPW_DL_WX, f, ## a)
 #define IPW_DEBUG_SCAN(f, a...)   IPW_DEBUG(IPW_DL_SCAN, f, ## a)
-#define IPW_DEBUG_STATUS(f, a...) IPW_DEBUG(IPW_DL_STATUS, f, ## a)
-#define IPW_DEBUG_TRACE(f, a...)  IPW_DEBUG(IPW_DL_TRACE, f, ## a)
-#define IPW_DEBUG_RX(f, a...)     IPW_DEBUG(IPW_DL_RX, f, ## a)
-#define IPW_DEBUG_TX(f, a...)     IPW_DEBUG(IPW_DL_TX, f, ## a)
-#define IPW_DEBUG_ISR(f, a...)    IPW_DEBUG(IPW_DL_ISR, f, ## a)
+#define IPW_DEBUG_TRACE(f, a...)  IPW_LL_DEBUG(IPW_DL_TRACE, f, ## a)
+#define IPW_DEBUG_RX(f, a...)     IPW_LL_DEBUG(IPW_DL_RX, f, ## a)
+#define IPW_DEBUG_TX(f, a...)     IPW_LL_DEBUG(IPW_DL_TX, f, ## a)
+#define IPW_DEBUG_ISR(f, a...)    IPW_LL_DEBUG(IPW_DL_ISR, f, ## a)
 #define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a)
-#define IPW_DEBUG_LED(f, a...) IPW_DEBUG(IPW_DL_LED, f, ## a)
-#define IPW_DEBUG_WEP(f, a...)    IPW_DEBUG(IPW_DL_WEP, f, ## a)
-#define IPW_DEBUG_HC(f, a...) IPW_DEBUG(IPW_DL_HOST_COMMAND, f, ## a)
-#define IPW_DEBUG_FRAG(f, a...) IPW_DEBUG(IPW_DL_FRAG, f, ## a)
-#define IPW_DEBUG_FW(f, a...) IPW_DEBUG(IPW_DL_FW, f, ## a)
+#define IPW_DEBUG_LED(f, a...) IPW_LL_DEBUG(IPW_DL_LED, f, ## a)
+#define IPW_DEBUG_WEP(f, a...)    IPW_LL_DEBUG(IPW_DL_WEP, f, ## a)
+#define IPW_DEBUG_HC(f, a...) IPW_LL_DEBUG(IPW_DL_HOST_COMMAND, f, ## a)
+#define IPW_DEBUG_FRAG(f, a...) IPW_LL_DEBUG(IPW_DL_FRAG, f, ## a)
+#define IPW_DEBUG_FW(f, a...) IPW_LL_DEBUG(IPW_DL_FW, f, ## a)
 #define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a)
 #define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a)
-#define IPW_DEBUG_IO(f, a...) IPW_DEBUG(IPW_DL_IO, f, ## a)
-#define IPW_DEBUG_ORD(f, a...) IPW_DEBUG(IPW_DL_ORD, f, ## a)
-#define IPW_DEBUG_FW_INFO(f, a...) IPW_DEBUG(IPW_DL_FW_INFO, f, ## a)
+#define IPW_DEBUG_IO(f, a...) IPW_LL_DEBUG(IPW_DL_IO, f, ## a)
+#define IPW_DEBUG_ORD(f, a...) IPW_LL_DEBUG(IPW_DL_ORD, f, ## a)
+#define IPW_DEBUG_FW_INFO(f, a...) IPW_LL_DEBUG(IPW_DL_FW_INFO, f, ## a)
 #define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a)
 #define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
 #define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a)
-#define IPW_DEBUG_STATS(f, a...) IPW_DEBUG(IPW_DL_STATS, f, ## a)
-#define IPW_DEBUG_MERGE(f, a...) IPW_DEBUG(IPW_DL_MERGE, f, ## a)
-#define IPW_DEBUG_QOS(f, a...)   IPW_DEBUG(IPW_DL_QOS, f, ## a)
+#define IPW_DEBUG_STATS(f, a...) IPW_LL_DEBUG(IPW_DL_STATS, f, ## a)
+#define IPW_DEBUG_MERGE(f, a...) IPW_LL_DEBUG(IPW_DL_MERGE, f, ## a)
+#define IPW_DEBUG_QOS(f, a...)   IPW_LL_DEBUG(IPW_DL_QOS, f, ## a)
 
 #include <linux/ctype.h>
 
@@ -1947,10 +1951,17 @@
 	u32 *param;
 } __attribute__ ((packed));
 
+struct cmdlog_host_cmd {
+	u8 cmd;
+	u8 len;
+	u16 reserved;
+	char param[124];
+} __attribute__ ((packed));
+
 struct ipw_cmd_log {
 	unsigned long jiffies;
 	int retcode;
-	struct host_cmd cmd;
+	struct cmdlog_host_cmd cmd;
 };
 
 /* SysConfig command parameters ... */
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index d6ed578..1174ff5 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -82,6 +82,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 #include <net/ieee80211.h>
@@ -2875,7 +2876,7 @@
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
 
-	if (erq->pointer) {
+	if (erq->length > 0) {
 		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
 			index = priv->tx_key;
 
@@ -2918,7 +2919,7 @@
 	if (erq->flags & IW_ENCODE_RESTRICTED)
 		restricted = 1;
 
-	if (erq->pointer) {
+	if (erq->pointer && erq->length > 0) {
 		priv->keys[index].len = cpu_to_le16(xlen);
 		memset(priv->keys[index].data, 0,
 		       sizeof(priv->keys[index].data));
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 16db3e1..fb5700d 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -134,11 +134,7 @@
 /* Locking and synchronization functions                            */
 /********************************************************************/
 
-/* These functions *must* be inline or they will break horribly on
- * SPARC, due to its weird semantics for save/restore flags. extern
- * inline should prevent the kernel from linking or module from
- * loading if they are not inlined. */
-extern inline int orinoco_lock(struct orinoco_private *priv,
+static inline int orinoco_lock(struct orinoco_private *priv,
 			       unsigned long *flags)
 {
 	spin_lock_irqsave(&priv->lock, *flags);
@@ -151,7 +147,7 @@
 	return 0;
 }
 
-extern inline void orinoco_unlock(struct orinoco_private *priv,
+static inline void orinoco_unlock(struct orinoco_private *priv,
 				  unsigned long *flags)
 {
 	spin_unlock_irqrestore(&priv->lock, *flags);
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index bf05b90..eaf3d13 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -304,7 +304,7 @@
 static int __init orinoco_nortel_init(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
-	return pci_module_init(&orinoco_nortel_driver);
+	return pci_register_driver(&orinoco_nortel_driver);
 }
 
 static void __exit orinoco_nortel_exit(void)
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 1759c54..97a8b4f 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -244,7 +244,7 @@
 static int __init orinoco_pci_init(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
-	return pci_module_init(&orinoco_pci_driver);
+	return pci_register_driver(&orinoco_pci_driver);
 }
 
 static void __exit orinoco_pci_exit(void)
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 7f006f6..31162ac 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -351,7 +351,7 @@
 static int __init orinoco_plx_init(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
-	return pci_module_init(&orinoco_plx_driver);
+	return pci_register_driver(&orinoco_plx_driver);
 }
 
 static void __exit orinoco_plx_exit(void)
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 0831721..7c7b960 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -228,7 +228,7 @@
 static int __init orinoco_tmd_init(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
-	return pci_module_init(&orinoco_tmd_driver);
+	return pci_register_driver(&orinoco_tmd_driver);
 }
 
 static void __exit orinoco_tmd_exit(void)
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 989599a..c09fbf7 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -35,13 +35,21 @@
 
 #include <net/iw_handler.h>	/* New driver API */
 
+#define KEY_SIZE_WEP104 13	/* 104/128-bit WEP keys */
+#define KEY_SIZE_WEP40  5	/* 40/64-bit WEP keys */
+/* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */
+#define KEY_SIZE_TKIP   32	/* TKIP keys */
 
-static void prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
+static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
 				u8 *wpa_ie, size_t wpa_ie_len);
-static size_t prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
+static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie);
 static int prism54_set_wpa(struct net_device *, struct iw_request_info *,
 				__u32 *, char *);
 
+/* In 500 kbps */
+static const unsigned char scan_rate_list[] = { 2, 4, 11, 22,
+						12, 18, 24, 36,
+						48, 72, 96, 108 };
 
 /**
  * prism54_mib_mode_helper - MIB change mode helper function
@@ -468,6 +476,9 @@
 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
 	range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM);
 
+	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
+		IW_ENC_CAPA_CIPHER_TKIP;
+
 	if (islpci_get_state(priv) < PRV_STATE_INIT)
 		return 0;
 
@@ -567,6 +578,8 @@
 	struct iw_event iwe;	/* Temporary buffer */
 	short cap;
 	islpci_private *priv = netdev_priv(ndev);
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
 
 	/* The first entry must be the MAC address */
 	memcpy(iwe.u.ap_addr.sa_data, bss->address, 6);
@@ -627,28 +640,40 @@
 	current_ev =
 	    iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
 
-	if (priv->wpa) {
-		u8 wpa_ie[MAX_WPA_IE_LEN];
-		char *buf, *p;
-		size_t wpa_ie_len;
-		int i;
-
-		wpa_ie_len = prism54_wpa_ie_get(priv, bss->address, wpa_ie);
-		if (wpa_ie_len > 0 &&
-		    (buf = kmalloc(wpa_ie_len * 2 + 10, GFP_ATOMIC))) {
-			p = buf;
-			p += sprintf(p, "wpa_ie=");
-			for (i = 0; i < wpa_ie_len; i++) {
-				p += sprintf(p, "%02x", wpa_ie[i]);
-			}
-			memset(&iwe, 0, sizeof (iwe));
-			iwe.cmd = IWEVCUSTOM;
-			iwe.u.data.length = strlen(buf);
-			current_ev = iwe_stream_add_point(current_ev, end_buf,
-							  &iwe, buf);
-			kfree(buf);
-		}
+	/* Add WPA/RSN Information Element, if any */
+	wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie);
+	if (wpa_ie_len > 0) {
+		iwe.cmd = IWEVGENIE;
+		iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN);
+		current_ev = iwe_stream_add_point(current_ev, end_buf,
+				&iwe, wpa_ie);
 	}
+	/* Do the bitrates */
+	{
+		char *	current_val = current_ev + IW_EV_LCP_LEN;
+		int i;
+		int mask;
+
+		iwe.cmd = SIOCGIWRATE;
+		/* Those two flags are ignored... */
+		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+		/* Parse the bitmask */
+		mask = 0x1;
+		for(i = 0; i < sizeof(scan_rate_list); i++) {
+			if(bss->rates & mask) {
+				iwe.u.bitrate.value = (scan_rate_list[i] * 500000);
+				current_val = iwe_stream_add_value(current_ev, current_val,
+								   end_buf, &iwe,
+								   IW_EV_PARAM_LEN);
+			}
+			mask <<= 1;
+		}
+		/* Check if we added any event */
+		if ((current_val - current_ev) > IW_EV_LCP_LEN)
+			current_ev = current_val;
+	}
+
 	return current_ev;
 }
 
@@ -1051,12 +1076,24 @@
 		current_index = r.u;
 		/* Verify that the key is not marked as invalid */
 		if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
-			key.length = dwrq->length > sizeof (key.key) ?
-			    sizeof (key.key) : dwrq->length;
-			memcpy(key.key, extra, key.length);
-			if (key.length == 32)
-				/* we want WPA-PSK */
+			if (dwrq->length > KEY_SIZE_TKIP) {
+				/* User-provided key data too big */
+				return -EINVAL;
+			}
+			if (dwrq->length > KEY_SIZE_WEP104) {
+				/* WPA-PSK TKIP */
 				key.type = DOT11_PRIV_TKIP;
+				key.length = KEY_SIZE_TKIP;
+			} else if (dwrq->length > KEY_SIZE_WEP40) {
+				/* WEP 104/128 */
+				key.length = KEY_SIZE_WEP104;
+			} else {
+				/* WEP 40/64 */
+				key.length = KEY_SIZE_WEP40;
+			}
+			memset(key.key, 0, sizeof (key.key));
+			memcpy(key.key, extra, dwrq->length);
+
 			if ((index < 0) || (index > 3))
 				/* no index provided use the current one */
 				index = current_index;
@@ -1210,6 +1247,489 @@
 	}
 }
 
+static int prism54_set_genie(struct net_device *ndev,
+			     struct iw_request_info *info,
+			     struct iw_point *data, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int alen, ret = 0;
+	struct obj_attachment *attach;
+
+	if (data->length > MAX_WPA_IE_LEN ||
+	    (data->length && extra == NULL))
+		return -EINVAL;
+
+	memcpy(priv->wpa_ie, extra, data->length);
+	priv->wpa_ie_len = data->length;
+
+	alen = sizeof(*attach) + priv->wpa_ie_len;
+	attach = kzalloc(alen, GFP_KERNEL);
+	if (attach == NULL)
+		return -ENOMEM;
+
+#define WLAN_FC_TYPE_MGMT 0
+#define WLAN_FC_STYPE_ASSOC_REQ 0
+#define WLAN_FC_STYPE_REASSOC_REQ 2
+
+	/* Note: endianness is covered by mgt_set_varlen */
+	attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+               (WLAN_FC_STYPE_ASSOC_REQ << 4);
+	attach->id = -1;
+	attach->size = priv->wpa_ie_len;
+	memcpy(attach->data, extra, priv->wpa_ie_len);
+
+	ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
+		priv->wpa_ie_len);
+	if (ret == 0) {
+		attach->type = (WLAN_FC_TYPE_MGMT << 2) |
+			(WLAN_FC_STYPE_REASSOC_REQ << 4);
+
+		ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach,
+			priv->wpa_ie_len);
+		if (ret == 0)
+			printk(KERN_DEBUG "%s: WPA IE Attachment was set\n",
+				ndev->name);
+	}
+
+	kfree(attach);
+	return ret;
+}
+
+
+static int prism54_get_genie(struct net_device *ndev,
+			     struct iw_request_info *info,
+			     struct iw_point *data, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	int len = priv->wpa_ie_len;
+
+	if (len <= 0) {
+		data->length = 0;
+		return 0;
+	}
+
+	if (data->length < len)
+		return -E2BIG;
+
+	data->length = len;
+	memcpy(extra, priv->wpa_ie, len);
+
+	return 0;
+}
+
+static int prism54_set_auth(struct net_device *ndev,
+			       struct iw_request_info *info,
+			       union iwreq_data *wrqu, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct iw_param *param = &wrqu->param;
+	u32 mlmelevel = 0, authen = 0, dot1x = 0;
+	u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
+	u32 old_wpa;
+	int ret = 0;
+	union oid_res_t r;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	/* first get the flags */
+	down_write(&priv->mib_sem);
+	wpa = old_wpa = priv->wpa;
+	up_write(&priv->mib_sem);
+	ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+	authen = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+	privinvoked = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+	exunencrypt = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
+	dot1x = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r);
+	mlmelevel = r.u;
+
+	if (ret < 0)
+		goto out;
+
+	switch (param->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+	case IW_AUTH_CIPHER_GROUP:
+	case IW_AUTH_KEY_MGMT:
+		break;
+
+	case IW_AUTH_WPA_ENABLED:
+		/* Do the same thing as IW_AUTH_WPA_VERSION */
+		if (param->value) {
+			wpa = 1;
+			privinvoked = 1; /* For privacy invoked */
+			exunencrypt = 1; /* Filter out all unencrypted frames */
+			dot1x = 0x01; /* To enable eap filter */
+			mlmelevel = DOT11_MLME_EXTENDED;
+			authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
+		} else {
+			wpa = 0;
+			privinvoked = 0;
+			exunencrypt = 0; /* Do not filter un-encrypted data */
+			dot1x = 0;
+			mlmelevel = DOT11_MLME_AUTO;
+		}
+		break;
+
+	case IW_AUTH_WPA_VERSION:
+		if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
+			wpa = 0;
+			privinvoked = 0;
+			exunencrypt = 0; /* Do not filter un-encrypted data */
+			dot1x = 0;
+			mlmelevel = DOT11_MLME_AUTO;
+		} else {
+			if (param->value & IW_AUTH_WPA_VERSION_WPA)
+				wpa = 1;
+			else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
+				wpa = 2;
+			privinvoked = 1; /* For privacy invoked */
+			exunencrypt = 1; /* Filter out all unencrypted frames */
+			dot1x = 0x01; /* To enable eap filter */
+			mlmelevel = DOT11_MLME_EXTENDED;
+			authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
+		}
+		break;
+
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+		dot1x = param->value ? 1 : 0;
+		break;
+
+	case IW_AUTH_PRIVACY_INVOKED:
+		privinvoked = param->value ? 1 : 0;
+
+	case IW_AUTH_DROP_UNENCRYPTED:
+		exunencrypt = param->value ? 1 : 0;
+		break;
+
+	case IW_AUTH_80211_AUTH_ALG:
+		if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+			/* Only WEP uses _SK and _BOTH */
+			if (wpa > 0) {
+				ret = -EINVAL;
+				goto out;
+			}
+			authen = DOT11_AUTH_SK;
+		} else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+			authen = DOT11_AUTH_OS;
+		} else {
+			ret = -EINVAL;
+			goto out;
+		}
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	/* Set all the values */
+	down_write(&priv->mib_sem);
+	priv->wpa = wpa;
+	up_write(&priv->mib_sem);
+	mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen);
+	mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked);
+	mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt);
+	mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x);
+	mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel);
+
+out:
+	return ret;
+}
+
+static int prism54_get_auth(struct net_device *ndev,
+			    struct iw_request_info *info,
+			    union iwreq_data *wrqu, char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct iw_param *param = &wrqu->param;
+	u32 wpa = 0;
+	int ret = 0;
+	union oid_res_t r;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	/* first get the flags */
+	down_write(&priv->mib_sem);
+	wpa = priv->wpa;
+	up_write(&priv->mib_sem);
+
+	switch (param->flags & IW_AUTH_INDEX) {
+	case IW_AUTH_CIPHER_PAIRWISE:
+	case IW_AUTH_CIPHER_GROUP:
+	case IW_AUTH_KEY_MGMT:
+		/*
+		 * wpa_supplicant will control these internally
+		 */
+		ret = -EOPNOTSUPP;
+		break;
+
+	case IW_AUTH_WPA_VERSION:
+		switch (wpa) {
+		case 1:
+			param->value = IW_AUTH_WPA_VERSION_WPA;
+			break;
+		case 2:
+			param->value = IW_AUTH_WPA_VERSION_WPA2;
+			break;
+		case 0:
+		default:
+			param->value = IW_AUTH_WPA_VERSION_DISABLED;
+			break;
+		}
+		break;
+
+	case IW_AUTH_DROP_UNENCRYPTED:
+		ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+		if (ret >= 0)
+			param->value = r.u > 0 ? 1 : 0;
+		break;
+
+	case IW_AUTH_80211_AUTH_ALG:
+		ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+		if (ret >= 0) {
+			switch (r.u) {
+			case DOT11_AUTH_OS:
+				param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+				break;
+			case DOT11_AUTH_BOTH:
+			case DOT11_AUTH_SK:
+				param->value = IW_AUTH_ALG_SHARED_KEY;
+			case DOT11_AUTH_NONE:
+			default:
+				param->value = 0;
+				break;
+			}
+		}
+		break;
+
+	case IW_AUTH_WPA_ENABLED:
+		param->value = wpa > 0 ? 1 : 0;
+		break;
+
+	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+		ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r);
+		if (ret >= 0)
+			param->value = r.u > 0 ? 1 : 0;
+		break;
+
+	case IW_AUTH_PRIVACY_INVOKED:
+		ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+		if (ret >= 0)
+			param->value = r.u > 0 ? 1 : 0;
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+	return ret;
+}
+
+static int prism54_set_encodeext(struct net_device *ndev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu,
+				 char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	int idx, alg = ext->alg, set_key = 1;
+	union oid_res_t r;
+	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
+	int ret = 0;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	/* Determine and validate the key index */
+	idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+	if (idx) {
+		if (idx < 0 || idx > 3)
+			return -EINVAL;
+	} else {
+		ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+		if (ret < 0)
+			goto out;
+		idx = r.u;
+	}
+
+	if (encoding->flags & IW_ENCODE_DISABLED)
+		alg = IW_ENCODE_ALG_NONE;
+
+	if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+		/* Only set transmit key index here, actual
+		 * key is set below if needed.
+		 */
+		ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx);
+		set_key = ext->key_len > 0 ? 1 : 0;
+	}
+
+	if (set_key) {
+		struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
+		switch (alg) {
+		case IW_ENCODE_ALG_NONE:
+			break;
+		case IW_ENCODE_ALG_WEP:
+			if (ext->key_len > KEY_SIZE_WEP104) {
+				ret = -EINVAL;
+				goto out;
+			}
+			if (ext->key_len > KEY_SIZE_WEP40)
+				key.length = KEY_SIZE_WEP104;
+			else
+				key.length = KEY_SIZE_WEP40;
+			break;
+		case IW_ENCODE_ALG_TKIP:
+			if (ext->key_len > KEY_SIZE_TKIP) {
+				ret = -EINVAL;
+				goto out;
+			}
+			key.type = DOT11_PRIV_TKIP;
+			key.length = KEY_SIZE_TKIP;
+		default:
+			return -EINVAL;
+		}
+
+		if (key.length) {
+			memset(key.key, 0, sizeof(key.key));
+			memcpy(key.key, ext->key, ext->key_len);
+			ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx,
+					    &key);
+			if (ret < 0)
+				goto out;
+		}
+	}
+
+	/* Read the flags */
+	if (encoding->flags & IW_ENCODE_DISABLED) {
+		/* Encoding disabled,
+		 * authen = DOT11_AUTH_OS;
+		 * invoke = 0;
+		 * exunencrypt = 0; */
+	}
+	if (encoding->flags & IW_ENCODE_OPEN) {
+		/* Encode but accept non-encoded packets. No auth */
+		invoke = 1;
+	}
+	if (encoding->flags & IW_ENCODE_RESTRICTED) {
+		/* Refuse non-encoded packets. Auth */
+		authen = DOT11_AUTH_BOTH;
+		invoke = 1;
+		exunencrypt = 1;
+	}
+
+	/* do the change if requested  */
+	if (encoding->flags & IW_ENCODE_MODE) {
+		ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0,
+				      &authen);
+		ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0,
+				      &invoke);
+		ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0,
+				      &exunencrypt);
+	}
+
+out:
+	return ret;
+}
+
+
+static int prism54_get_encodeext(struct net_device *ndev,
+				 struct iw_request_info *info,
+				 union iwreq_data *wrqu,
+				 char *extra)
+{
+	islpci_private *priv = netdev_priv(ndev);
+	struct iw_point *encoding = &wrqu->encoding;
+	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+	int idx, max_key_len;
+	union oid_res_t r;
+	int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
+	int ret = 0;
+
+	if (islpci_get_state(priv) < PRV_STATE_INIT)
+		return 0;
+
+	/* first get the flags */
+	ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r);
+	authen = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r);
+	invoke = r.u;
+	ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r);
+	exunencrypt = r.u;
+	if (ret < 0)
+		goto out;
+
+	max_key_len = encoding->length - sizeof(*ext);
+	if (max_key_len < 0)
+		return -EINVAL;
+
+	idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
+	if (idx) {
+		if (idx < 0 || idx > 3)
+			return -EINVAL;
+	} else {
+		ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r);
+		if (ret < 0)
+			goto out;
+		idx = r.u;
+	}
+
+	encoding->flags = idx + 1;
+	memset(ext, 0, sizeof(*ext));
+
+	switch (authen) {
+	case DOT11_AUTH_BOTH:
+	case DOT11_AUTH_SK:
+		wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
+	case DOT11_AUTH_OS:
+	default:
+		wrqu->encoding.flags |= IW_ENCODE_OPEN;
+		break;
+	}
+
+	down_write(&priv->mib_sem);
+	wpa = priv->wpa;
+	up_write(&priv->mib_sem);
+
+	if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
+		/* No encryption */
+		ext->alg = IW_ENCODE_ALG_NONE;
+		ext->key_len = 0;
+		wrqu->encoding.flags |= IW_ENCODE_DISABLED;
+	} else {
+		struct obj_key *key;
+
+		ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r);
+		if (ret < 0)
+			goto out;
+		key = r.ptr;
+		if (max_key_len < key->length) {
+			ret = -E2BIG;
+			goto out;
+		}
+		memcpy(ext->key, key->key, key->length);
+		ext->key_len = key->length;
+
+		switch (key->type) {
+		case DOT11_PRIV_TKIP:
+			ext->alg = IW_ENCODE_ALG_TKIP;
+			break;
+		default:
+		case DOT11_PRIV_WEP:
+			ext->alg = IW_ENCODE_ALG_WEP;
+			break;
+		}
+		wrqu->encoding.flags |= IW_ENCODE_ENABLED;
+	}
+
+out:
+	return ret;
+}
+
+
 static int
 prism54_reset(struct net_device *ndev, struct iw_request_info *info,
 	      __u32 * uwrq, char *extra)
@@ -1591,8 +2111,8 @@
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 
 static void
-prism54_wpa_ie_add(islpci_private *priv, u8 *bssid,
-		   u8 *wpa_ie, size_t wpa_ie_len)
+prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
+		       u8 *wpa_ie, size_t wpa_ie_len)
 {
 	struct list_head *ptr;
 	struct islpci_bss_wpa_ie *bss = NULL;
@@ -1658,7 +2178,7 @@
 }
 
 static size_t
-prism54_wpa_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
+prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
 {
 	struct list_head *ptr;
 	struct islpci_bss_wpa_ie *bss = NULL;
@@ -1683,14 +2203,14 @@
 }
 
 void
-prism54_wpa_ie_init(islpci_private *priv)
+prism54_wpa_bss_ie_init(islpci_private *priv)
 {
 	INIT_LIST_HEAD(&priv->bss_wpa_list);
 	sema_init(&priv->wpa_sem, 1);
 }
 
 void
-prism54_wpa_ie_clean(islpci_private *priv)
+prism54_wpa_bss_ie_clean(islpci_private *priv)
 {
 	struct list_head *ptr, *n;
 
@@ -1722,7 +2242,7 @@
 		}
 		if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
 		    memcmp(pos + 2, wpa_oid, 4) == 0) {
-			prism54_wpa_ie_add(priv, addr, pos, pos[1] + 2);
+			prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2);
 			return;
 		}
 		pos += 2 + pos[1];
@@ -1879,7 +2399,7 @@
 		send_formatted_event(priv, "Associate request (ex)", mlme, 1);
 
 		if (priv->iw_mode != IW_MODE_MASTER 
-				&& mlmeex->state != DOT11_STATE_AUTHING)
+				&& mlmeex->state != DOT11_STATE_ASSOCING)
 			break;
 		
 		confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC);
@@ -1893,7 +2413,7 @@
 		confirm->state = 0; /* not used */
 		confirm->code = 0;
 
-		wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
 		if (!wpa_ie_len) {
 			printk(KERN_DEBUG "No WPA IE found from "
@@ -1937,7 +2457,7 @@
 		confirm->state = 0; /* not used */
 		confirm->code = 0;
 
-		wpa_ie_len = prism54_wpa_ie_get(priv, mlmeex->address, wpa_ie);
+		wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
 
 		if (!wpa_ie_len) {
 			printk(KERN_DEBUG "No WPA IE found from "
@@ -2553,6 +3073,15 @@
 	(iw_handler) prism54_get_encode,	/* SIOCGIWENCODE */
 	(iw_handler) NULL,	/* SIOCSIWPOWER */
 	(iw_handler) NULL,	/* SIOCGIWPOWER */
+	NULL,			/* -- hole -- */
+	NULL,			/* -- hole -- */
+	(iw_handler) prism54_set_genie,	/* SIOCSIWGENIE */
+	(iw_handler) prism54_get_genie,	/* SIOCGIWGENIE */
+	(iw_handler) prism54_set_auth,	/* SIOCSIWAUTH */
+	(iw_handler) prism54_get_auth,	/* SIOCGIWAUTH */
+	(iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */
+	(iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */
+	NULL,			/* SIOCSIWPMKSA */
 };
 
 /* The low order bit identify a SET (0) or a GET (1) ioctl.  */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h
index 46d5cde..65f33ac 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.h
+++ b/drivers/net/wireless/prism54/isl_ioctl.h
@@ -27,7 +27,7 @@
 
 #include <net/iw_handler.h>	/* New driver API */
 
-#define SUPPORTED_WIRELESS_EXT                  16
+#define SUPPORTED_WIRELESS_EXT                  19
 
 void prism54_mib_init(islpci_private *);
 
@@ -39,8 +39,8 @@
 
 void prism54_process_trap(void *);
 
-void prism54_wpa_ie_init(islpci_private *priv);
-void prism54_wpa_ie_clean(islpci_private *priv);
+void prism54_wpa_bss_ie_init(islpci_private *priv);
+void prism54_wpa_bss_ie_clean(islpci_private *priv);
 
 int prism54_set_mac_address(struct net_device *, void *);
 
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 5ddf295..ab3c5a2 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -715,7 +715,7 @@
 	}
 
 	prism54_acl_init(&priv->acl);
-	prism54_wpa_ie_init(priv);
+	prism54_wpa_bss_ie_init(priv);
 	if (mgt_init(priv)) 
 		goto out_free;
 
@@ -774,7 +774,7 @@
 
 	/* Free the acces control list and the WPA list */
 	prism54_acl_clean(&priv->acl);
-	prism54_wpa_ie_clean(priv);
+	prism54_wpa_bss_ie_clean(priv);
 	mgt_clean(priv);
 
 	return 0;
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 0705316..5049f37 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -179,6 +179,8 @@
 	struct list_head bss_wpa_list;
 	int num_bss_wpa;
 	struct semaphore wpa_sem;
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
 
 	struct work_struct reset_task;
 	int reset_task_pending;
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 09fc17a..f692dcc 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -313,7 +313,7 @@
 
 	__bug_on_wrong_struct_sizes ();
 
-	return pci_module_init(&prism54_driver);
+	return pci_register_driver(&prism54_driver);
 }
 
 /* by the time prism54_module_exit() terminates, as a postcondition
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 61b83a5..8e112d1 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -52,8 +52,8 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
-#include <net/ieee80211.h>
 #include <linux/wireless.h>
+#include <net/iw_handler.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index 7f78b78..bcc7038 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -242,7 +242,7 @@
 	u_int save_cor;
 
 	/* Doing it if hardware is gone is guaranteed crash */
-	if (pcmcia_dev_present(link))
+	if (!pcmcia_dev_present(link))
 		return -ENODEV;
 
 	/* Save original COR value */
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index fd31885..ccaf28e 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -467,6 +467,7 @@
 		     struct net_device *dev)
 {
 	struct neighbour *neighbor_entry;
+	int ret = 0;
 
 	neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev);
 
@@ -474,10 +475,11 @@
 		neighbor_entry->used = jiffies;
 		if (neighbor_entry->nud_state & NUD_VALID) {
 			memcpy(haddr, neighbor_entry->ha, dev->addr_len);
-			return 1;
+			ret = 1;
 		}
+		neigh_release(neighbor_entry);
 	}
-	return 0;
+	return ret;
 }
 
 static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr,
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index 662ecc8..c52e9bcf 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -1820,6 +1820,8 @@
 	    zd->dev->name);
 
 	usb_set_intfdata(interface, zd);
+	zd1201_enable(zd);	/* zd1201 likes to startup enabled, */
+	zd1201_disable(zd);	/* interfering with all the wifis in range */
 	return 0;
 
 err_net:
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 500314f..6603ad5 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,6 +3,7 @@
 zd1211rw-objs := zd_chip.o zd_ieee80211.o \
 		zd_mac.o zd_netdev.o \
 		zd_rf_al2230.o zd_rf_rf2959.o \
+		zd_rf_al7230b.o \
 		zd_rf.o zd_usb.o zd_util.o
 
 ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index efc9c4b..7c4e32c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -42,12 +42,11 @@
 
 void zd_chip_clear(struct zd_chip *chip)
 {
-	mutex_lock(&chip->mutex);
+	ZD_ASSERT(!mutex_is_locked(&chip->mutex));
 	zd_usb_clear(&chip->usb);
 	zd_rf_clear(&chip->rf);
-	mutex_unlock(&chip->mutex);
 	mutex_destroy(&chip->mutex);
-	memset(chip, 0, sizeof(*chip));
+	ZD_MEMCLEAR(chip, sizeof(*chip));
 }
 
 static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size)
@@ -68,10 +67,11 @@
 	i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i);
 	i += scnprintf(buffer+i, size-i, " ");
 	i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i);
-	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type,
+	i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c", chip->pa_type,
 		chip->patch_cck_gain ? 'g' : '-',
 		chip->patch_cr157 ? '7' : '-',
-		chip->patch_6m_band_edge ? '6' : '-');
+		chip->patch_6m_band_edge ? '6' : '-',
+		chip->new_phy_layout ? 'N' : '-');
 	return i;
 }
 
@@ -330,13 +330,14 @@
 	chip->patch_cck_gain = (value >> 8) & 0x1;
 	chip->patch_cr157 = (value >> 13) & 0x1;
 	chip->patch_6m_band_edge = (value >> 21) & 0x1;
+	chip->new_phy_layout = (value >> 31) & 0x1;
 
 	dev_dbg_f(zd_chip_dev(chip),
 		"RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-		"patch 6M %d\n",
+		"patch 6M %d new PHY %d\n",
 		zd_rf_name(*rf_type), *rf_type,
 		chip->pa_type, chip->patch_cck_gain,
-		chip->patch_cr157, chip->patch_6m_band_edge);
+		chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
 	return 0;
 error:
 	*rf_type = 0;
@@ -344,6 +345,7 @@
 	chip->patch_cck_gain = 0;
 	chip->patch_cr157 = 0;
 	chip->patch_6m_band_edge = 0;
+	chip->new_phy_layout = 0;
 	return r;
 }
 
@@ -717,7 +719,7 @@
 		{ CR21,  0x0e }, { CR22,  0x23 }, { CR23,  0x90 },
 		{ CR24,  0x14 }, { CR25,  0x40 }, { CR26,  0x10 },
 		{ CR27,  0x10 }, { CR28,  0x7f }, { CR29,  0x80 },
-		{ CR30,  0x49 }, /* jointly decoder, no ASIC */
+		{ CR30,  0x4b }, /* ASIC/FWT, no jointly decoder */
 		{ CR31,  0x60 }, { CR32,  0x43 }, { CR33,  0x08 },
 		{ CR34,  0x06 }, { CR35,  0x0a }, { CR36,  0x00 },
 		{ CR37,  0x00 }, { CR38,  0x38 }, { CR39,  0x0c },
@@ -797,7 +799,7 @@
 		{ CR_ADDA_MBIAS_WARMTIME,	0x30000808 },
 		{ CR_ZD1211_RETRY_MAX,		0x2 },
 		{ CR_SNIFFER_ON,		0 },
-		{ CR_RX_FILTER,			AP_RX_FILTER },
+		{ CR_RX_FILTER,			STA_RX_FILTER },
 		{ CR_GROUP_HASH_P1,		0x00 },
 		{ CR_GROUP_HASH_P2,		0x80000000 },
 		{ CR_REG1,			0xa4 },
@@ -807,7 +809,6 @@
 		{ CR_ACK_TIMEOUT_EXT,		0x80 },
 		{ CR_ADDA_PWR_DWN,		0x00 },
 		{ CR_ACK_TIME_80211,		0x100 },
-		{ CR_IFS_VALUE,			0x547c032 },
 		{ CR_RX_PE_DELAY,		0x70 },
 		{ CR_PS_CTRL,			0x10000000 },
 		{ CR_RTS_CTS_RATE,		0x02030203 },
@@ -844,7 +845,7 @@
 		{ CR_ZD1211B_AIFS_CTL2,		0x008C003C },
 		{ CR_ZD1211B_TXOP,		0x01800824 },
 		{ CR_SNIFFER_ON,		0 },
-		{ CR_RX_FILTER,			AP_RX_FILTER },
+		{ CR_RX_FILTER,			STA_RX_FILTER },
 		{ CR_GROUP_HASH_P1,		0x00 },
 		{ CR_GROUP_HASH_P2,		0x80000000 },
 		{ CR_REG1,			0xa4 },
@@ -854,11 +855,10 @@
 		{ CR_ACK_TIMEOUT_EXT,		0x80 },
 		{ CR_ADDA_PWR_DWN,		0x00 },
 		{ CR_ACK_TIME_80211,		0x100 },
-		{ CR_IFS_VALUE,			0x547c032 },
 		{ CR_RX_PE_DELAY,		0x70 },
 		{ CR_PS_CTRL,			0x10000000 },
 		{ CR_RTS_CTS_RATE,		0x02030203 },
-		{ CR_RX_THRESHOLD,		0x000c0640 },
+		{ CR_RX_THRESHOLD,		0x000c0eff, },
 		{ CR_AFTER_PNP,			0x1 },
 		{ CR_WEP_PROTECT,		0x114 },
 	};
@@ -970,10 +970,15 @@
 	r = hw_init_hmac(chip);
 	if (r)
 		return r;
-	r = set_beacon_interval(chip, 100);
+
+	/* Although the vendor driver defaults to a different value during
+	 * init, it overwrites the IFS value with the following every time
+	 * the channel changes. We should aim to be more intelligent... */
+	r = zd_iowrite32_locked(chip, IFS_VALUE_DEFAULT, CR_IFS_VALUE);
 	if (r)
 		return r;
-	return 0;
+
+	return set_beacon_interval(chip, 100);
 }
 
 #ifdef DEBUG
@@ -1430,9 +1435,43 @@
 			break;
 	}
 
+	switch (rate) {
+	case ZD_OFDM_RATE_6M:
+	case ZD_OFDM_RATE_9M:
+		i += 3;
+		break;
+	case ZD_OFDM_RATE_12M:
+	case ZD_OFDM_RATE_18M:
+		i += 5;
+		break;
+	case ZD_OFDM_RATE_24M:
+	case ZD_OFDM_RATE_36M:
+		i += 9;
+		break;
+	case ZD_OFDM_RATE_48M:
+	case ZD_OFDM_RATE_54M:
+		i += 15;
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	return i;
 }
 
+static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size)
+{
+	int r;
+
+	r = ofdm_qual_db(status_quality, rate, size);
+	ZD_ASSERT(r >= 0);
+	if (r < 0)
+		r = 0;
+
+	r = (r * 100)/29;
+	return r <= 100 ? r : 100;
+}
+
 static unsigned int log10times100(unsigned int x)
 {
 	static const u8 log10[] = {
@@ -1476,31 +1515,28 @@
 	return r;
 }
 
-static int rx_qual_db(const void *rx_frame, unsigned int size,
-	              const struct rx_status *status)
+static int cck_qual_percent(u8 status_quality)
 {
-	return (status->frame_status&ZD_RX_OFDM) ?
-		ofdm_qual_db(status->signal_quality_ofdm,
-			     zd_ofdm_plcp_header_rate(rx_frame),
-			     size) :
-		cck_snr_db(status->signal_quality_cck);
+	int r;
+
+	r = cck_snr_db(status_quality);
+	r = (100*r)/17;
+	return r <= 100 ? r : 100;
 }
 
 u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
 	              const struct rx_status *status)
 {
-	int r = rx_qual_db(rx_frame, size, status);
-	if (r < 0)
-		r = 0;
-	r = (r * 100) / 14;
-	if (r > 100)
-		r = 100;
-	return r;
+	return (status->frame_status&ZD_RX_OFDM) ?
+		ofdm_qual_percent(status->signal_quality_ofdm,
+			          zd_ofdm_plcp_header_rate(rx_frame),
+			          size) :
+		cck_qual_percent(status->signal_quality_cck);
 }
 
 u8 zd_rx_strength_percent(u8 rssi)
 {
-	int r = (rssi*100) / 30;
+	int r = (rssi*100) / 41;
 	if (r > 100)
 		r = 100;
 	return (u8) r;
@@ -1613,3 +1649,34 @@
 
 	return 0;
 }
+
+/*
+ * We can optionally program the RF directly through CR regs, if supported by
+ * the hardware. This is much faster than the older method.
+ */
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value)
+{
+	struct zd_ioreq16 ioreqs[] = {
+		{ CR244, (value >> 16) & 0xff },
+		{ CR243, (value >>  8) & 0xff },
+		{ CR242,  value        & 0xff },
+	};
+	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+	                  const u32 *values, unsigned int count)
+{
+	int r;
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		r = zd_rfwrite_cr_locked(chip, values[i]);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 8051210..4b12508 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -461,14 +461,27 @@
 
 #define CR_RX_FILTER			CTL_REG(0x068c)
 #define RX_FILTER_ASSOC_RESPONSE	0x0002
+#define RX_FILTER_REASSOC_RESPONSE	0x0008
 #define RX_FILTER_PROBE_RESPONSE	0x0020
 #define RX_FILTER_BEACON		0x0100
+#define RX_FILTER_DISASSOC		0x0400
 #define RX_FILTER_AUTH			0x0800
-/* Sniff modus sets filter to 0xfffff */
+#define AP_RX_FILTER			0x0400feff
+#define STA_RX_FILTER			0x0000ffff
+
+/* Monitor mode sets filter to 0xfffff */
 
 #define CR_ACK_TIMEOUT_EXT		CTL_REG(0x0690)
 #define CR_BCN_FIFO_SEMAPHORE		CTL_REG(0x0694)
+
 #define CR_IFS_VALUE			CTL_REG(0x0698)
+#define IFS_VALUE_DIFS_SH		0
+#define IFS_VALUE_EIFS_SH		12
+#define IFS_VALUE_SIFS_SH		24
+#define IFS_VALUE_DEFAULT		((  50 << IFS_VALUE_DIFS_SH) | \
+					 (1148 << IFS_VALUE_EIFS_SH) | \
+					 (  10 << IFS_VALUE_SIFS_SH))
+
 #define CR_RX_TIME_OUT			CTL_REG(0x069C)
 #define CR_TOTAL_RX_FRM			CTL_REG(0x06A0)
 #define CR_CRC32_CNT			CTL_REG(0x06A4)
@@ -546,9 +559,6 @@
 #define CR_ZD1211B_TXOP			CTL_REG(0x0b20)
 #define CR_ZD1211B_RETRY_MAX		CTL_REG(0x0b28)
 
-#define AP_RX_FILTER			0x0400feff
-#define STA_RX_FILTER			0x0000ffff
-
 #define CWIN_SIZE			0x007f043f
 
 
@@ -628,6 +638,7 @@
 	LOAD_CODE_SIZE			= 0xe, /* words */
 	LOAD_VECT_SIZE			= 0x10000 - 0xfff7, /* words */
 	EEPROM_REGS_OFFSET		= LOAD_CODE_SIZE + LOAD_VECT_SIZE,
+	EEPROM_REGS_SIZE		= 0x7e, /* words */
 	E2P_BASE_OFFSET			= EEPROM_START_OFFSET +
 		                          EEPROM_REGS_OFFSET,
 };
@@ -653,7 +664,7 @@
 	/* SetPointOFDM in the vendor driver */
 	u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
 	u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-	   is_zd1211b:1;
+	   new_phy_layout:1, is_zd1211b:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -737,8 +748,12 @@
 	return zd_usb_rfwrite(&chip->usb, value, bits);
 }
 
+int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value);
+
 int zd_rfwritev_locked(struct zd_chip *chip,
 	               const u32* values, unsigned int count, u8 bits);
+int zd_rfwritev_cr_locked(struct zd_chip *chip,
+	                  const u32* values, unsigned int count);
 
 /* Locking functions for reading and writing registers.
  * The different parameters are intentional.
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 4659068..a13ec72 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -45,4 +45,10 @@
 #  define ZD_ASSERT(x) do { } while (0)
 #endif
 
+#ifdef DEBUG
+#  define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size))
+#else
+#  define ZD_MEMCLEAR(pointer, size) do { } while (0)
+#endif
+
 #endif /* _ZD_DEF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
index 3632989..f63245b 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
@@ -64,7 +64,7 @@
 	u8 service;
 	__le16 length;
 	__le16 crc16;
-} __attribute__((packed));
+};
 
 static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header)
 {
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 3bdc54d..1989f1c 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -108,7 +108,9 @@
 	if (r)
 		goto disable_int;
 
-	r = zd_set_encryption_type(chip, NO_WEP);
+	/* We must inform the device that we are doing encryption/decryption in
+	 * software at the moment. */
+	r = zd_set_encryption_type(chip, ENC_SNIFFER);
 	if (r)
 		goto disable_int;
 
@@ -125,21 +127,17 @@
 
 void zd_mac_clear(struct zd_mac *mac)
 {
-	/* Aquire the lock. */
-	spin_lock(&mac->lock);
-	spin_unlock(&mac->lock);
 	zd_chip_clear(&mac->chip);
-	memset(mac, 0, sizeof(*mac));
+	ZD_ASSERT(!spin_is_locked(&mac->lock));
+	ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
 }
 
 static int reset_mode(struct zd_mac *mac)
 {
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 	struct zd_ioreq32 ioreqs[3] = {
-		{ CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE|
-			        RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE },
+		{ CR_RX_FILTER, STA_RX_FILTER },
 		{ CR_SNIFFER_ON, 0U },
-		{ CR_ENCRYPTION_TYPE, NO_WEP },
 	};
 
 	if (ieee->iw_mode == IW_MODE_MONITOR) {
@@ -713,9 +711,9 @@
 struct zd_rt_hdr {
 	struct ieee80211_radiotap_header rt_hdr;
 	u8  rt_flags;
+	u8  rt_rate;
 	u16 rt_channel;
 	u16 rt_chbitmask;
-	u16 rt_rate;
 };
 
 static void fill_rt_header(void *buffer, struct zd_mac *mac,
@@ -735,14 +733,14 @@
 	if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256))
 		hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP;
 
+	hdr->rt_rate = stats->rate / 5;
+
 	/* FIXME: 802.11a */
 	hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz(
 		                             _zd_chip_get_channel(&mac->chip)));
 	hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ |
 		((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) ==
 		ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK));
-
-	hdr->rt_rate = stats->rate / 5;
 }
 
 /* Returns 1 if the data packet is for us and 0 otherwise. */
@@ -816,13 +814,25 @@
 	return -EINVAL;
 }
 
-static void update_qual_rssi(struct zd_mac *mac, u8 qual_percent, u8 rssi)
+static void update_qual_rssi(struct zd_mac *mac,
+			     const u8 *buffer, unsigned int length,
+			     u8 qual_percent, u8 rssi_percent)
 {
 	unsigned long flags;
+	struct ieee80211_hdr_3addr *hdr;
+	int i;
+
+	hdr = (struct ieee80211_hdr_3addr *)buffer;
+	if (length < offsetof(struct ieee80211_hdr_3addr, addr3))
+		return;
+	if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0)
+		return;
 
 	spin_lock_irqsave(&mac->lock, flags);
-	mac->qual_average = (7 * mac->qual_average + qual_percent) / 8;
-	mac->rssi_average = (7 * mac->rssi_average + rssi) / 8;
+	i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE;
+	mac->qual_buffer[i] = qual_percent;
+	mac->rssi_buffer[i] = rssi_percent;
+	mac->stats_count++;
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
 
@@ -853,7 +863,6 @@
 	if (stats->rate)
 		stats->mask |= IEEE80211_STATMASK_RATE;
 
-	update_qual_rssi(mac, stats->signal, stats->rssi);
 	return 0;
 }
 
@@ -877,6 +886,8 @@
 		  sizeof(struct rx_status);
 	buffer += ZD_PLCP_HEADER_SIZE;
 
+	update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi);
+
 	r = filter_rx(ieee, buffer, length, &stats);
 	if (r <= 0)
 		return r;
@@ -981,17 +992,31 @@
 {
 	struct zd_mac *mac = zd_netdev_mac(ndev);
 	struct iw_statistics *iw_stats = &mac->iw_stats;
+	unsigned int i, count, qual_total, rssi_total;
 
 	memset(iw_stats, 0, sizeof(struct iw_statistics));
 	/* We are not setting the status, because ieee->state is not updated
 	 * at all and this driver doesn't track authentication state.
 	 */
 	spin_lock_irq(&mac->lock);
-	iw_stats->qual.qual = mac->qual_average;
-	iw_stats->qual.level = mac->rssi_average;
-	iw_stats->qual.updated = IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED|
-		                 IW_QUAL_NOISE_INVALID;
+	count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ?
+		mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE;
+	qual_total = rssi_total = 0;
+	for (i = 0; i < count; i++) {
+		qual_total += mac->qual_buffer[i];
+		rssi_total += mac->rssi_buffer[i];
+	}
 	spin_unlock_irq(&mac->lock);
+	iw_stats->qual.updated = IW_QUAL_NOISE_INVALID;
+	if (count > 0) {
+		iw_stats->qual.qual = qual_total / count;
+		iw_stats->qual.level = rssi_total / count;
+		iw_stats->qual.updated |=
+			IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED;
+	} else {
+		iw_stats->qual.updated |=
+			IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID;
+	}
 	/* TODO: update counter */
 	return iw_stats;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 71e382c..29b51fd 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -1,4 +1,4 @@
-/* zd_mac.c
+/* zd_mac.h
  *
  * 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
@@ -82,18 +82,18 @@
 struct rx_length_info {
 	__le16 length[3];
 	__le16 tag;
-} __attribute__((packed));
+};
 
 #define RX_LENGTH_INFO_TAG		0x697e
 
 struct rx_status {
+	u8 signal_quality_cck;
 	/* rssi */
 	u8 signal_strength;
-	u8 signal_quality_cck;
 	u8 signal_quality_ofdm;
 	u8 decryption_type;
 	u8 frame_status;
-} __attribute__((packed));
+};
 
 /* rx_status field decryption_type */
 #define ZD_RX_NO_WEP	0
@@ -120,14 +120,17 @@
 	MAC_FIXED_CHANNEL = 0x01,
 };
 
+#define ZD_MAC_STATS_BUFFER_SIZE 16
+
 struct zd_mac {
-	struct net_device *netdev;
 	struct zd_chip chip;
 	spinlock_t lock;
+	struct net_device *netdev;
 	/* Unlocked reading possible */
 	struct iw_statistics iw_stats;
-	u8 qual_average;
-	u8 rssi_average;
+	unsigned int stats_count;
+	u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
+	u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
 	u8 regdomain;
 	u8 default_regdomain;
 	u8 requested_channel;
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
index 9df232c..440ef24 100644
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ b/drivers/net/wireless/zd1211rw/zd_netdev.c
@@ -72,10 +72,18 @@
 	               struct iw_request_info *info,
 		       union iwreq_data *req, char *extra)
 {
-	/* FIXME: check whether 802.11a will also supported, add also
-	 *        zd1211B, if we support it.
-	 */
-	strlcpy(req->name, "802.11g zd1211", IFNAMSIZ);
+	/* FIXME: check whether 802.11a will also supported */
+	strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
+	return 0;
+}
+
+static int iw_get_nick(struct net_device *netdev,
+	               struct iw_request_info *info,
+		       union iwreq_data *req, char *extra)
+{
+	strcpy(extra, "zd1211");
+	req->data.length = strlen(extra) + 1;
+	req->data.flags = 1;
 	return 0;
 }
 
@@ -181,6 +189,7 @@
 
 static const iw_handler zd_standard_iw_handlers[] = {
 	WX(SIOCGIWNAME)		= iw_get_name,
+	WX(SIOCGIWNICKN)	= iw_get_nick,
 	WX(SIOCSIWFREQ)		= iw_set_freq,
 	WX(SIOCGIWFREQ)		= iw_get_freq,
 	WX(SIOCSIWMODE)		= iw_set_mode,
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index d3770d2..f50cff3 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -56,7 +56,7 @@
 
 void zd_rf_clear(struct zd_rf *rf)
 {
-	memset(rf, 0, sizeof(*rf));
+	ZD_MEMCLEAR(rf, sizeof(*rf));
 }
 
 int zd_rf_init_hw(struct zd_rf *rf, u8 type)
@@ -76,6 +76,11 @@
 		if (r)
 			return r;
 		break;
+	case AL7230B_RF:
+		r = zd_rf_init_al7230b(rf);
+		if (r)
+			return r;
+		break;
 	default:
 		dev_err(zd_chip_dev(chip),
 			"RF %s %#x is not supported\n", zd_rf_name(type), type);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index ea30f69..676b373 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -78,5 +78,6 @@
 
 int zd_rf_init_rf2959(struct zd_rf *rf);
 int zd_rf_init_al2230(struct zd_rf *rf);
+int zd_rf_init_al7230b(struct zd_rf *rf);
 
 #endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 0948b25..25323a1 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -21,7 +21,7 @@
 #include "zd_usb.h"
 #include "zd_chip.h"
 
-static const u32 al2230_table[][3] = {
+static const u32 zd1211_al2230_table[][3] = {
 	RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, },
 	RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, },
 	RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, },
@@ -38,6 +38,53 @@
 	RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, },
 };
 
+static const u32 zd1211b_al2230_table[][3] = {
+	RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, },
+	RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, },
+	RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, },
+};
+
+static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = {
+	{ CR240, 0x57 }, { CR9,   0xe0 },
+};
+
+static int zd1211b_al2230_finalize_rf(struct zd_chip *chip)
+{
+	int r;
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR80,  0x30 }, { CR81,  0x30 }, { CR79,  0x58 },
+		{ CR12,  0xf0 }, { CR77,  0x1b }, { CR78,  0x58 },
+		{ CR203, 0x06 },
+		{ },
+
+		{ CR240, 0x80 },
+	};
+
+	r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+	if (r)
+		return r;
+
+	/* related to antenna selection? */
+	if (chip->new_phy_layout) {
+		r = zd_iowrite16_locked(chip, 0xe1, CR9);
+		if (r)
+			return r;
+	}
+
+	return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
 static int zd1211_al2230_init_hw(struct zd_rf *rf)
 {
 	int r;
@@ -139,7 +186,7 @@
 		{ CR47,  0x1e },
 
 		/* ZD1211B 05.06.10 */
-		{ CR48,  0x00 }, { CR49,  0x00 }, { CR51,  0x01 },
+		{ CR48,  0x06 }, { CR49,  0xf9 }, { CR51,  0x01 },
 		{ CR52,  0x80 }, { CR53,  0x7e }, { CR65,  0x00 },
 		{ CR66,  0x00 }, { CR67,  0x00 }, { CR68,  0x00 },
 		{ CR69,  0x28 },
@@ -172,79 +219,78 @@
 		{ CR137, 0x50 }, /* 5614 */
 		{ CR138, 0xa8 },
 		{ CR144, 0xac }, /* 5621 */
-		{ CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 },
+		{ CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 },
 	};
 
 	static const u32 rv1[] = {
-		/* channel 1 */
-		0x03f790,
-		0x033331,
-		0x00000d,
+		0x8cccd0,
+		0x481dc0,
+		0xcfff00,
+		0x25a000,
 
-		0x0b3331,
-		0x03b812,
-		0x00fff3,
-		0x0005a4,
-		0x0f4dc5, /* fix freq shift 0x044dc5 */
-		0x0805b6,
-		0x0146c7,
-		0x000688,
-		0x0403b9, /* External control TX power (CR31) */
-		0x00dbba,
-		0x00099b,
-		0x0bdffc,
-		0x00000d,
-		0x00580f,
+		/* To improve AL2230 yield, improve phase noise, 4713 */
+		0x25a000,
+		0xa3b2f0,
+
+		0x6da010, /* Reg6 update for MP versio */
+		0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */
+		0x116000,
+		0x9dc020, /* External control TX power (CR31) */
+		0x5ddb00, /* RegA update for MP version */
+		0xd99000, /* RegB update for MP version */
+		0x3ffbd0, /* RegC update for MP version */
+		0xb00000, /* RegD update for MP version */
+
+		/* improve phase noise and remove phase calibration,4713 */
+		0xf01a00,
 	};
 
 	static const struct zd_ioreq16 ioreqs2[] = {
-		{ CR47,  0x1e }, { CR_RFCFG, 0x03 },
+		{ CR251, 0x2f }, /* shdnb(PLL_ON)=0 */
+		{ CR251, 0x7f }, /* shdnb(PLL_ON)=1 */
 	};
 
 	static const u32 rv2[] = {
-		0x00880f,
-		0x00080f,
+		/* To improve AL2230 yield, 4713 */
+		0xf01b00,
+		0xf01e00,
+		0xf01a00,
 	};
 
 	static const struct zd_ioreq16 ioreqs3[] = {
-		{ CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f },
+		/* related to 6M band edge patching, happens unconditionally */
+		{ CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
 	};
 
-	static const u32 rv3[] = {
-		0x00d80f,
-		0x00780f,
-		0x00580f,
-	};
-
-	static const struct zd_ioreq16 ioreqs4[] = {
-		{ CR138, 0x28 }, { CR203, 0x06 },
-	};
-
+	r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+		ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+	if (r)
+		return r;
 	r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1));
 	if (r)
 		return r;
-	r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS);
+	r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3);
+	if (r)
+		return r;
+	r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1));
 	if (r)
 		return r;
 	r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2));
 	if (r)
 		return r;
-	r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS);
+	r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2));
 	if (r)
 		return r;
 	r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3));
 	if (r)
 		return r;
-	r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS);
-	if (r)
-		return r;
-	return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4));
+	return zd1211b_al2230_finalize_rf(chip);
 }
 
-static int al2230_set_channel(struct zd_rf *rf, u8 channel)
+static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel)
 {
 	int r;
-	const u32 *rv = al2230_table[channel-1];
+	const u32 *rv = zd1211_al2230_table[channel-1];
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 	static const struct zd_ioreq16 ioreqs[] = {
 		{ CR138, 0x28 },
@@ -257,6 +303,24 @@
 	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
+static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel)
+{
+	int r;
+	const u32 *rv = zd1211b_al2230_table[channel-1];
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1,
+		ARRAY_SIZE(zd1211b_ioreqs_shared_1));
+	if (r)
+		return r;
+
+	r = zd_rfwritev_cr_locked(chip, rv, 3);
+	if (r)
+		return r;
+
+	return zd1211b_al2230_finalize_rf(chip);
+}
+
 static int zd1211_al2230_switch_radio_on(struct zd_rf *rf)
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
@@ -294,13 +358,14 @@
 {
 	struct zd_chip *chip = zd_rf_to_chip(rf);
 
-	rf->set_channel = al2230_set_channel;
 	rf->switch_radio_off = al2230_switch_radio_off;
 	if (chip->is_zd1211b) {
 		rf->init_hw = zd1211b_al2230_init_hw;
+		rf->set_channel = zd1211b_al2230_set_channel;
 		rf->switch_radio_on = zd1211b_al2230_switch_radio_on;
 	} else {
 		rf->init_hw = zd1211_al2230_init_hw;
+		rf->set_channel = zd1211_al2230_set_channel;
 		rf->switch_radio_on = zd1211_al2230_switch_radio_on;
 	}
 	rf->patch_6m_band_edge = 1;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
new file mode 100644
index 0000000..a289f95
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -0,0 +1,274 @@
+/* zd_rf_al7230b.c: Functions for the AL7230B RF controller
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+static const u32 chan_rv[][2] = {
+	RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 },
+	RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 },
+	RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 },
+	RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 },
+	RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 },
+	RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 },
+	RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 },
+	RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 },
+	RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 },
+	RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 },
+	RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 },
+	RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 },
+	RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 },
+	RF_CHANNEL(14) = { 0x03ec00, 0x866660 },
+};
+
+static const u32 std_rv[] = {
+	0x4ff821,
+	0xc5fbfc,
+	0x21ebfe,
+	0xafd401, /* freq shift 0xaad401 */
+	0x6cf56a,
+	0xe04073,
+	0x193d76,
+	0x9dd844,
+	0x500007,
+	0xd8c010,
+};
+
+static int al7230b_init_hw(struct zd_rf *rf)
+{
+	int i, r;
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	/* All of these writes are identical to AL2230 unless otherwise
+	 * specified */
+	static const struct zd_ioreq16 ioreqs_1[] = {
+		/* This one is 7230-specific, and happens before the rest */
+		{ CR240,  0x57 },
+		{ },
+
+		{ CR15,   0x20 }, { CR23,   0x40 }, { CR24,  0x20 },
+		{ CR26,   0x11 }, { CR28,   0x3e }, { CR29,  0x00 },
+		{ CR44,   0x33 },
+		/* This value is different for 7230 (was: 0x2a) */
+		{ CR106,  0x22 },
+		{ CR107,  0x1a }, { CR109,  0x09 }, { CR110,  0x27 },
+		{ CR111,  0x2b }, { CR112,  0x2b }, { CR119,  0x0a },
+		/* This happened further down in AL2230,
+		 * and the value changed (was: 0xe0) */
+		{ CR122,  0xfc },
+		{ CR10,   0x89 },
+		/* for newest (3rd cut) AL2300 */
+		{ CR17,   0x28 },
+		{ CR26,   0x93 }, { CR34,   0x30 },
+		/* for newest (3rd cut) AL2300 */
+		{ CR35,   0x3e },
+		{ CR41,   0x24 }, { CR44,   0x32 },
+		/* for newest (3rd cut) AL2300 */
+		{ CR46,   0x96 },
+		{ CR47,   0x1e }, { CR79,   0x58 }, { CR80,  0x30 },
+		{ CR81,   0x30 }, { CR87,   0x0a }, { CR89,  0x04 },
+		{ CR92,   0x0a }, { CR99,   0x28 },
+		/* This value is different for 7230 (was: 0x00) */
+		{ CR100,  0x02 },
+		{ CR101,  0x13 }, { CR102,  0x27 },
+		/* This value is different for 7230 (was: 0x24) */
+		{ CR106,  0x22 },
+		/* This value is different for 7230 (was: 0x2a) */
+		{ CR107,  0x3f },
+		{ CR109,  0x09 },
+		/* This value is different for 7230 (was: 0x13) */
+		{ CR110,  0x1f },
+		{ CR111,  0x1f }, { CR112,  0x1f }, { CR113, 0x27 },
+		{ CR114,  0x27 },
+		/* for newest (3rd cut) AL2300 */
+		{ CR115,  0x24 },
+		/* This value is different for 7230 (was: 0x24) */
+		{ CR116,  0x3f },
+		/* This value is different for 7230 (was: 0xf4) */
+		{ CR117,  0xfa },
+		{ CR118,  0xfc }, { CR119,  0x10 }, { CR120, 0x4f },
+		{ CR121,  0x77 }, { CR137,  0x88 },
+		/* This one is 7230-specific */
+		{ CR138,  0xa8 },
+		/* This value is different for 7230 (was: 0xff) */
+		{ CR252,  0x34 },
+		/* This value is different for 7230 (was: 0xff) */
+		{ CR253,  0x34 },
+
+		/* PLL_OFF */
+		{ CR251, 0x2f },
+	};
+
+	static const struct zd_ioreq16 ioreqs_2[] = {
+		/* PLL_ON */
+		{ CR251, 0x3f },
+		{ CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+		{ CR38, 0x38 }, { CR136, 0xdf },
+	};
+
+	r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+	if (r)
+		return r;
+
+	r = zd_rfwrite_cr_locked(chip, 0x09ec04);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0x8cccc8);
+	if (r)
+		return r;
+
+	for (i = 0; i < ARRAY_SIZE(std_rv); i++) {
+		r = zd_rfwrite_cr_locked(chip, std_rv[i]);
+		if (r)
+			return r;
+	}
+
+	r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0xbfffff);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0x700000);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+	if (r)
+		return r;
+
+	r = zd_rfwrite_cr_locked(chip, 0xf15d59);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0xf15d5c);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+	if (r)
+		return r;
+
+	r = zd_iowrite16_locked(chip, 0x06, CR203);
+	if (r)
+		return r;
+	r = zd_iowrite16_locked(chip, 0x80, CR240);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+static int al7230b_set_channel(struct zd_rf *rf, u8 channel)
+{
+	int i, r;
+	const u32 *rv = chan_rv[channel-1];
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	struct zd_ioreq16 ioreqs_1[] = {
+		{ CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 },
+		{ CR38,  0x38 }, { CR136, 0xdf },
+	};
+
+	struct zd_ioreq16 ioreqs_2[] = {
+		/* PLL_ON */
+		{ CR251, 0x3f },
+		{ CR203, 0x06 }, { CR240, 0x08 },
+	};
+
+	r = zd_iowrite16_locked(chip, 0x57, CR240);
+	if (r)
+		return r;
+
+	/* PLL_OFF */
+	r = zd_iowrite16_locked(chip, 0x2f, CR251);
+	if (r)
+		return r;
+
+	for (i = 0; i < ARRAY_SIZE(std_rv); i++) {
+		r = zd_rfwrite_cr_locked(chip, std_rv[i]);
+		if (r)
+			return r;
+	}
+
+	r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+	if (r)
+		return r;
+	r = zd_rfwrite_cr_locked(chip, 0xf15d58);
+	if (r)
+		return r;
+
+	r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1));
+	if (r)
+		return r;
+
+	for (i = 0; i < 2; i++) {
+		r = zd_rfwrite_cr_locked(chip, rv[i]);
+		if (r)
+			return r;
+	}
+
+	r = zd_rfwrite_cr_locked(chip, 0x3c9000);
+	if (r)
+		return r;
+
+	return zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2));
+}
+
+static int al7230b_switch_radio_on(struct zd_rf *rf)
+{
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x00 },
+		{ CR251, 0x3f },
+	};
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int al7230b_switch_radio_off(struct zd_rf *rf)
+{
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+	static const struct zd_ioreq16 ioreqs[] = {
+		{ CR11,  0x04 },
+		{ CR251, 0x2f },
+	};
+
+	return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+int zd_rf_init_al7230b(struct zd_rf *rf)
+{
+	struct zd_chip *chip = zd_rf_to_chip(rf);
+
+	if (chip->is_zd1211b) {
+		dev_err(zd_chip_dev(chip), "AL7230B is currently not "
+			"supported for ZD1211B devices\n");
+		return -ENODEV;
+	}
+
+	rf->init_hw = al7230b_init_hw;
+	rf->set_channel = al7230b_set_channel;
+	rf->switch_radio_on = al7230b_switch_radio_on;
+	rf->switch_radio_off = al7230b_switch_radio_off;
+	rf->patch_6m_band_edge = 1;
+	return 0;
+}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 72f9052..31027e5 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -16,6 +16,7 @@
  */
 
 #include <asm/unaligned.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/firmware.h>
@@ -39,9 +40,19 @@
 	{ USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
 	{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
 	{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B },
+	{ USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B },
+	/* "Driverless" devices that need ejecting */
+	{ USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
 	{}
 };
 
@@ -263,6 +274,39 @@
 	return buffer;
 }
 
+static int handle_version_mismatch(struct usb_device *udev, u8 device_type,
+	const struct firmware *ub_fw)
+{
+	const struct firmware *ur_fw = NULL;
+	int offset;
+	int r = 0;
+	char fw_name[128];
+
+	r = request_fw_file(&ur_fw,
+		get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"),
+		&udev->dev);
+	if (r)
+		goto error;
+
+	r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START_OFFSET,
+		REBOOT);
+	if (r)
+		goto error;
+
+	offset = ((EEPROM_REGS_OFFSET + EEPROM_REGS_SIZE) * sizeof(u16));
+	r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset,
+		E2P_BASE_OFFSET + EEPROM_REGS_SIZE, REBOOT);
+
+	/* At this point, the vendor driver downloads the whole firmware
+	 * image, hacks around with version IDs, and uploads it again,
+	 * completely overwriting the boot code. We do not do this here as
+	 * it is not required on any tested devices, and it is suspected to
+	 * cause problems. */
+error:
+	release_firmware(ur_fw);
+	return r;
+}
+
 static int upload_firmware(struct usb_device *udev, u8 device_type)
 {
 	int r;
@@ -282,15 +326,17 @@
 
 	fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET);
 
-	/* FIXME: do we have any reason to perform the kludge that the vendor
-	 * driver does when there is a version mismatch? (their driver uploads
-	 * different firmwares and stuff)
-	 */
 	if (fw_bcdDevice != bcdDevice) {
 		dev_info(&udev->dev,
-			"firmware device id %#06x and actual device id "
-			"%#06x differ, continuing anyway\n",
-			fw_bcdDevice, bcdDevice);
+			"firmware version %#06x and device bootcode version "
+			"%#06x differ\n", fw_bcdDevice, bcdDevice);
+		if (bcdDevice <= 0x4313)
+			dev_warn(&udev->dev, "device has old bootcode, please "
+				"report success or failure\n");
+
+		r = handle_version_mismatch(udev, device_type, ub_fw);
+		if (r)
+			goto error;
 	} else {
 		dev_dbg_f(&udev->dev,
 			"firmware device id %#06x is equal to the "
@@ -323,7 +369,6 @@
 {
 	struct zd_usb_interrupt *intr = &usb->intr;
 
-	ZD_ASSERT(in_interrupt());
 	spin_lock(&intr->lock);
 	intr->read_regs_enabled = 0;
 	spin_unlock(&intr->lock);
@@ -545,11 +590,11 @@
 	 * be padded. Unaligned access might also happen if the length_info
 	 * structure is not present.
 	 */
-	if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) {
+	if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG))
+	{
 		unsigned int l, k, n;
 		for (i = 0, l = 0;; i++) {
-			k = le16_to_cpu(get_unaligned(
-				&length_info->length[i]));
+			k = le16_to_cpu(get_unaligned(&length_info->length[i]));
 			n = l+k;
 			if (n > length)
 				return;
@@ -621,7 +666,7 @@
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
-struct urb *alloc_urb(struct zd_usb *usb)
+static struct urb *alloc_urb(struct zd_usb *usb)
 {
 	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct urb *urb;
@@ -645,7 +690,7 @@
 	return urb;
 }
 
-void free_urb(struct urb *urb)
+static void free_urb(struct urb *urb)
 {
 	if (!urb)
 		return;
@@ -865,7 +910,7 @@
 {
 	usb_set_intfdata(usb->intf, NULL);
 	usb_put_intf(usb->intf);
-	memset(usb, 0, sizeof(*usb));
+	ZD_MEMCLEAR(usb, sizeof(*usb));
 	/* FIXME: usb_interrupt, usb_tx, usb_rx? */
 }
 
@@ -911,6 +956,55 @@
 #define print_id(udev) do { } while (0)
 #endif
 
+static int eject_installer(struct usb_interface *intf)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_host_interface *iface_desc = &intf->altsetting[0];
+	struct usb_endpoint_descriptor *endpoint;
+	unsigned char *cmd;
+	u8 bulk_out_ep;
+	int r;
+
+	/* Find bulk out endpoint */
+	endpoint = &iface_desc->endpoint[1].desc;
+	if ((endpoint->bEndpointAddress & USB_TYPE_MASK) == USB_DIR_OUT &&
+	    (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+	    USB_ENDPOINT_XFER_BULK) {
+		bulk_out_ep = endpoint->bEndpointAddress;
+	} else {
+		dev_err(&udev->dev,
+			"zd1211rw: Could not find bulk out endpoint\n");
+		return -ENODEV;
+	}
+
+	cmd = kzalloc(31, GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENODEV;
+
+	/* USB bulk command block */
+	cmd[0] = 0x55;	/* bulk command signature */
+	cmd[1] = 0x53;	/* bulk command signature */
+	cmd[2] = 0x42;	/* bulk command signature */
+	cmd[3] = 0x43;	/* bulk command signature */
+	cmd[14] = 6;	/* command length */
+
+	cmd[15] = 0x1b;	/* SCSI command: START STOP UNIT */
+	cmd[19] = 0x2;	/* eject disc */
+
+	dev_info(&udev->dev, "Ejecting virtual installer media...\n");
+	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
+		cmd, 31, NULL, 2000);
+	kfree(cmd);
+	if (r)
+		return r;
+
+	/* At this point, the device disconnects and reconnects with the real
+	 * ID numbers. */
+
+	usb_set_intfdata(intf, NULL);
+	return 0;
+}
+
 static int probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	int r;
@@ -919,6 +1013,9 @@
 
 	print_id(udev);
 
+	if (id->driver_info & DEVICE_INSTALLER)
+		return eject_installer(intf);
+
 	switch (udev->speed) {
 	case USB_SPEED_LOW:
 	case USB_SPEED_FULL:
@@ -984,6 +1081,11 @@
 	struct zd_mac *mac = zd_netdev_mac(netdev);
 	struct zd_usb *usb = &mac->chip.usb;
 
+	/* Either something really bad happened, or we're just dealing with
+	 * a DEVICE_INSTALLER. */
+	if (netdev == NULL)
+		return;
+
 	dev_dbg_f(zd_usb_dev(usb), "\n");
 
 	zd_netdev_disconnect(netdev);
@@ -999,7 +1101,6 @@
 	 */
 	usb_reset_device(interface_to_usbdev(intf));
 
-	/* If somebody still waits on this lock now, this is an error. */
 	zd_netdev_free(netdev);
 	dev_dbg(&intf->dev, "disconnected\n");
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index d642028..ded39de 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -30,6 +30,7 @@
 enum devicetype {
 	DEVICE_ZD1211  = 0,
 	DEVICE_ZD1211B = 1,
+	DEVICE_INSTALLER = 2,
 };
 
 enum endpoints {
@@ -73,17 +74,17 @@
 struct usb_req_read_regs {
 	__le16 id;
 	__le16 addr[0];
-} __attribute__((packed));
+};
 
 struct reg_data {
 	__le16 addr;
 	__le16 value;
-} __attribute__((packed));
+};
 
 struct usb_req_write_regs {
 	__le16 id;
 	struct reg_data reg_writes[0];
-} __attribute__((packed));
+};
 
 enum {
 	RF_IF_LE = 0x02,
@@ -100,7 +101,7 @@
 	/* RF2595: 24 */
 	__le16 bit_values[0];
 	/* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */
-} __attribute__((packed));
+};
 
 /* USB interrupt */
 
@@ -117,12 +118,12 @@
 struct usb_int_header {
 	u8 type;	/* must always be 1 */
 	u8 id;
-} __attribute__((packed));
+};
 
 struct usb_int_regs {
 	struct usb_int_header hdr;
 	struct reg_data regs[0];
-} __attribute__((packed));
+};
 
 struct usb_int_retry_fail {
 	struct usb_int_header hdr;
@@ -130,7 +131,7 @@
 	u8 _dummy;
 	u8 addr[ETH_ALEN];
 	u8 ibss_wakeup_dest;
-} __attribute__((packed));
+};
 
 struct read_regs_int {
 	struct completion completion;
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 8459a182..8746cc7 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -24,8 +24,8 @@
 */
 
 #define DRV_NAME	"yellowfin"
-#define DRV_VERSION	"2.0"
-#define DRV_RELDATE	"Jun 27, 2006"
+#define DRV_VERSION	"2.1"
+#define DRV_RELDATE	"Sep 11, 2006"
 
 #define PFX DRV_NAME ": "
 
@@ -1307,8 +1307,6 @@
 	/* Stop the Rx process to change any value. */
 	iowrite16(cfg_value & ~0x1000, ioaddr + Cnfg);
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
-		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		iowrite16(0x000F, ioaddr + AddrMode);
 	} else if ((dev->mc_count > 64)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to filter well, or accept all multicasts. */
@@ -1434,7 +1432,7 @@
 #ifdef MODULE
 	printk(version);
 #endif
-	return pci_module_init (&yellowfin_driver);
+	return pci_register_driver(&yellowfin_driver);
 }
 
 
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 3fae77f..8a60f39 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -76,7 +76,7 @@
 
 config HOTPLUG_PCI_ACPI
 	tristate "ACPI PCI Hotplug driver"
-	depends on ACPI_DOCK && HOTPLUG_PCI
+	depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI)
 	help
 	  Say Y here if you have a system that supports PCI Hotplug using
 	  ACPI.
@@ -153,13 +153,6 @@
 
 	  When in doubt, say N.
 
-config HOTPLUG_PCI_SHPC_PHPRM_LEGACY
-	bool "For AMD SHPC only: Use $HRT for resource/configuration"
-	depends on HOTPLUG_PCI_SHPC && !ACPI 
-	help
-	  Say Y here for AMD SHPC. You have to select this option if you are 
-	  using this driver on platform with AMD SHPC.
-
 config HOTPLUG_PCI_RPA
 	tristate "RPA PCI Hotplug driver"
 	depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 34de569..e2fef60 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -27,8 +27,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <gregkh@us.ibm.com>,
- *		    <t-kochi@bq.jp.nec.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ef95d12..ae67a8f 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -26,7 +26,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Send feedback to <t-kochi@bq.jp.nec.com>
+ * Send feedback to <kristen.c.accardi@intel.com>
  *
  */
 
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 02be74c..4afcaff 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -254,8 +254,8 @@
 
 int cpci_configure_slot(struct slot* slot)
 {
-	unsigned char busnr;
-	struct pci_bus *child;
+	struct pci_bus *parent;
+	int fn;
 
 	dbg("%s - enter", __FUNCTION__);
 
@@ -276,23 +276,53 @@
 		 */
 		n = pci_scan_slot(slot->bus, slot->devfn);
 		dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
-		if (n > 0)
-			pci_bus_add_devices(slot->bus);
 		slot->dev = pci_get_slot(slot->bus, slot->devfn);
 		if (slot->dev == NULL) {
 			err("Could not find PCI device for slot %02x", slot->number);
-			return 1;
+			return -ENODEV;
 		}
 	}
+	parent = slot->dev->bus;
 
-	if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-		pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr);
-		child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr);
-		pci_do_scan_bus(child);
-		pci_bus_size_bridges(child);
+	for (fn = 0; fn < 8; fn++) {
+		struct pci_dev *dev;
+
+		dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
+		if (!dev)
+			continue;
+		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+			/* Find an unused bus number for the new bridge */
+			struct pci_bus *child;
+			unsigned char busnr, start = parent->secondary;
+			unsigned char end = parent->subordinate;
+
+			for (busnr = start; busnr <= end; busnr++) {
+				if (!pci_find_bus(pci_domain_nr(parent),
+						  busnr))
+					break;
+			}
+			if (busnr >= end) {
+				err("No free bus for hot-added bridge\n");
+				pci_dev_put(dev);
+				continue;
+			}
+			child = pci_add_new_bus(parent, dev, busnr);
+			if (!child) {
+				err("Cannot add new bus for %s\n",
+				    pci_name(dev));
+				pci_dev_put(dev);
+				continue;
+			}
+			child->subordinate = pci_do_scan_bus(child);
+			pci_bus_size_bridges(child);
+		}
+		pci_dev_put(dev);
 	}
 
-	pci_bus_assign_resources(slot->dev->bus);
+	pci_bus_assign_resources(parent);
+	pci_bus_add_devices(parent);
+	pci_enable_bridges(parent);
 
 	dbg("%s - exit", __FUNCTION__);
 	return 0;
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index ce89f58..eaea9d3 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -279,6 +279,11 @@
 
 
 #ifdef CONFIG_ACPI
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+#include <linux/pci-acpi.h>
+
 #define pciehp_get_hp_hw_control_from_firmware(dev) \
 	pciehp_acpi_get_hp_hw_control_from_firmware(dev)
 static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 0d8fb6e..6ab3b6c 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -38,10 +38,6 @@
 
 #include "../pci.h"
 #include "pciehp.h"
-#include <acpi/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/actypes.h>
-#include <linux/pci-acpi.h>
 #ifdef DEBUG
 #define DBG_K_TRACE_ENTRY      ((unsigned int)0x00000001)	/* On function entry */
 #define DBG_K_TRACE_EXIT       ((unsigned int)0x00000002)	/* On function exit */
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 10e1a90..474e9cd 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -139,9 +139,8 @@
 /**
  * pci_match_device - Tell if a PCI device structure has a matching
  *                    PCI device id structure
- * @ids: array of PCI device id structures to search in
- * @dev: the PCI device structure to match against
  * @drv: the PCI driver to match against
+ * @dev: the PCI device structure to match against
  *
  * Used by a driver to check whether a PCI device present in the
  * system is in its list of supported devices.  Returns the matching
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 50bfc1b..478d0d2 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -30,23 +30,6 @@
 /* global data */
 static const char device_name[] = "pcieport-driver";
 
-static int pcie_portdrv_save_config(struct pci_dev *dev)
-{
-	return pci_save_state(dev);
-}
-
-static int pcie_portdrv_restore_config(struct pci_dev *dev)
-{
-	int retval;
-
-	pci_restore_state(dev);
-	retval = pci_enable_device(dev);
-	if (retval)
-		return retval;
-	pci_set_master(dev);
-	return 0;
-}
-
 /*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
@@ -73,8 +56,10 @@
 		"%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", 
 		__FUNCTION__, dev->device, dev->vendor);
 	}
-	if (pcie_port_device_register(dev)) 
+	if (pcie_port_device_register(dev)) {
+		pci_disable_device(dev);
 		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -86,6 +71,23 @@
 }
 
 #ifdef CONFIG_PM
+static int pcie_portdrv_save_config(struct pci_dev *dev)
+{
+	return pci_save_state(dev);
+}
+
+static int pcie_portdrv_restore_config(struct pci_dev *dev)
+{
+	int retval;
+
+	pci_restore_state(dev);
+	retval = pci_enable_device(dev);
+	if (retval)
+		return retval;
+	pci_set_master(dev);
+	return 0;
+}
+
 static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
 {
 	int ret = pcie_port_device_suspend(dev, state);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e3c78c3..17e709e 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -438,6 +438,7 @@
 	pci_read_config_dword(dev, 0x48, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
 
 /*
@@ -666,6 +667,7 @@
 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_8235_USB_2, 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);
@@ -990,6 +992,11 @@
 			case 0x8070: /* P4G8X Deluxe */
 				asus_hides_smbus = 1;
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH)
+			switch (dev->subsystem_device) {
+			case 0x80c9: /* PU-DLS */
+				asus_hides_smbus = 1;
+			}
 		if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
 			switch (dev->subsystem_device) {
 			case 0x1751: /* M2N notebook */
@@ -1058,6 +1065,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_E7501_MCH,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
@@ -1081,10 +1089,10 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_0,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ICH6_1,	asus_hides_smbus_lpc );
 
 static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
 {
@@ -1511,6 +1519,63 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
 
+static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
+{
+	u16 command;
+	u32 bar;
+	u8 __iomem *csr;
+	u8 cmd_hi;
+
+	switch (dev->device) {
+	/* PCI IDs taken from drivers/net/e100.c */
+	case 0x1029:
+	case 0x1030 ... 0x1034:
+	case 0x1038 ... 0x103E:
+	case 0x1050 ... 0x1057:
+	case 0x1059:
+	case 0x1064 ... 0x106B:
+	case 0x1091 ... 0x1095:
+	case 0x1209:
+	case 0x1229:
+	case 0x2449:
+	case 0x2459:
+	case 0x245D:
+	case 0x27DC:
+		break;
+	default:
+		return;
+	}
+
+	/*
+	 * Some firmware hands off the e100 with interrupts enabled,
+	 * which can cause a flood of interrupts if packets are
+	 * received before the driver attaches to the device.  So
+	 * disable all e100 interrupts here.  The driver will
+	 * re-enable them when it's ready.
+	 */
+	pci_read_config_word(dev, PCI_COMMAND, &command);
+	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar);
+
+	if (!(command & PCI_COMMAND_MEMORY) || !bar)
+		return;
+
+	csr = ioremap(bar, 8);
+	if (!csr) {
+		printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
+			pci_name(dev));
+		return;
+	}
+
+	cmd_hi = readb(csr + 3);
+	if (cmd_hi == 0) {
+		printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts "
+			"enabled, disabling\n", pci_name(dev));
+		writeb(1, csr + 3);
+	}
+
+	iounmap(csr);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt);
 
 static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
 {
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 622b3f8..d529462 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -41,7 +41,7 @@
  * in the global list of PCI buses.  If the bus is found, a pointer to its
  * data structure is returned.  If no bus is found, %NULL is returned.
  */
-struct pci_bus * __devinit pci_find_bus(int domain, int busnr)
+struct pci_bus * pci_find_bus(int domain, int busnr)
 {
 	struct pci_bus *bus = NULL;
 	struct pci_bus *tmp_bus;
@@ -61,7 +61,7 @@
  * @from: Previous PCI bus found, or %NULL for new search.
  *
  * Iterates through the list of known PCI busses.  A new search is
- * initiated by passing %NULL to the @from argument.  Otherwise if
+ * initiated by passing %NULL as the @from argument.  Otherwise if
  * @from is not %NULL, searches continue from next device on the
  * global list.
  */
@@ -148,13 +148,14 @@
  * @from: Previous PCI device found in search, or %NULL for new search.
  *
  * Iterates through the list of known PCI devices.  If a PCI device is
- * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
- * device structure is returned.  Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL to the @from argument.
- * Otherwise if @from is not %NULL, searches continue from next device on the global list.
+ * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
+ * pointer to its device structure is returned.  Otherwise, %NULL is returned.
+ * A new search is initiated by passing %NULL as the @from argument.
+ * Otherwise if @from is not %NULL, searches continue from next device
+ * on the global list.
  *
- * NOTE: Do not use this function anymore, use pci_get_subsys() instead, as
- * the pci device returned by this function can disappear at any moment in
+ * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
+ * the PCI device returned by this function can disappear at any moment in
  * time.
  */
 static struct pci_dev * pci_find_subsys(unsigned int vendor,
@@ -191,14 +192,15 @@
  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
  * @from: Previous PCI device found in search, or %NULL for new search.
  *
- * Iterates through the list of known PCI devices.  If a PCI device is
- * found with a matching @vendor and @device, a pointer to its device structure is
+ * Iterates through the list of known PCI devices.  If a PCI device is found
+ * with a matching @vendor and @device, a pointer to its device structure is
  * returned.  Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL to the @from argument.
- * Otherwise if @from is not %NULL, searches continue from next device on the global list.
+ * A new search is initiated by passing %NULL as the @from argument.
+ * Otherwise if @from is not %NULL, searches continue from next device
+ * on the global list.
  * 
- * NOTE: Do not use this function anymore, use pci_get_device() instead, as
- * the pci device returned by this function can disappear at any moment in
+ * NOTE: Do not use this function any more; use pci_get_device() instead, as
+ * the PCI device returned by this function can disappear at any moment in
  * time.
  */
 struct pci_dev *
@@ -215,11 +217,11 @@
  * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
  * @from: Previous PCI device found in search, or %NULL for new search.
  *
- * Iterates through the list of known PCI devices.  If a PCI device is
- * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
+ * Iterates through the list of known PCI devices.  If a PCI device is found
+ * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
  * device structure is returned, and the reference count to the device is
  * incremented.  Otherwise, %NULL is returned.  A new search is initiated by
- * passing %NULL to the @from argument.  Otherwise if @from is not %NULL,
+ * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
  * searches continue from next device on the global list.
  * The reference count for @from is always decremented if it is not %NULL.
  */
@@ -262,7 +264,7 @@
  * found with a matching @vendor and @device, the reference count to the
  * device is incremented and a pointer to its device structure is returned.
  * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
- * to the @from argument.  Otherwise if @from is not %NULL, searches continue
+ * as the @from argument.  Otherwise if @from is not %NULL, searches continue
  * from next device on the global list.  The reference count for @from is
  * always decremented if it is not %NULL.
  */
@@ -279,11 +281,13 @@
  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
  * @from: Previous PCI device found in search, or %NULL for new search.
  *
- * Iterates through the list of known PCI devices in the reverse order of pci_find_device().
+ * Iterates through the list of known PCI devices in the reverse order of
+ * pci_find_device().
  * If a PCI device is found with a matching @vendor and @device, a pointer to
  * its device structure is returned.  Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL to the @from argument.
- * Otherwise if @from is not %NULL, searches continue from previous device on the global list.
+ * A new search is initiated by passing %NULL as the @from argument.
+ * Otherwise if @from is not %NULL, searches continue from previous device
+ * on the global list.
  */
 struct pci_dev *
 pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from)
@@ -317,7 +321,7 @@
  * found with a matching @class, the reference count to the device is
  * incremented and a pointer to its device structure is returned.
  * Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL to the @from argument.
+ * A new search is initiated by passing %NULL as the @from argument.
  * Otherwise if @from is not %NULL, searches continue from next device
  * on the global list.  The reference count for @from is always decremented
  * if it is not %NULL.
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 738b1ef..9ad18e6 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -601,12 +601,8 @@
 	    ret = CS_BAD_ARGS;
 	else {
 	    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function);
-	    if (p_dev == NULL)
-		    ret = CS_BAD_ARGS;
-	    else {
-		    ret = pccard_get_configuration_info(s, p_dev, &buf->config);
-		    pcmcia_put_dev(p_dev);
-	    }
+	    ret = pccard_get_configuration_info(s, p_dev, &buf->config);
+	    pcmcia_put_dev(p_dev);
 	}
 	break;
     case DS_GET_FIRST_TUPLE:
@@ -636,12 +632,8 @@
 		    ret = CS_BAD_ARGS;
 	    else {
 		    struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function);
-		    if (p_dev == NULL)
-			    ret = CS_BAD_ARGS;
-		    else {
-			    ret = pccard_get_status(s, p_dev, &buf->status);
-			    pcmcia_put_dev(p_dev);
-		    }
+		    ret = pccard_get_status(s, p_dev, &buf->status);
+		    pcmcia_put_dev(p_dev);
 	    }
 	    break;
     case DS_VALIDATE_CIS:
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 7bf25b8..c832339 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -245,10 +245,17 @@
 		return CS_SUCCESS;
 	}
 
-	/* !!! This is a hack !!! */
-	memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
-	config->Attributes |= CONF_VALID_CLIENT;
-	config->CardValues = c->CardValues;
+	config->Attributes = c->Attributes | CONF_VALID_CLIENT;
+	config->Vcc = s->socket.Vcc;
+	config->Vpp1 = config->Vpp2 = s->socket.Vpp;
+	config->IntType = c->IntType;
+	config->ConfigBase = c->ConfigBase;
+	config->Status = c->Status;
+	config->Pin = c->Pin;
+	config->Copy = c->Copy;
+	config->Option = c->Option;
+	config->ExtStatus = c->ExtStatus;
+	config->Present = config->CardValues = c->CardValues;
 	config->IRQAttributes = c->irq.Attributes;
 	config->AssignedIRQ = s->irq.AssignedIRQ;
 	config->BasePort1 = c->io.BasePort1;
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 3163e3d..9d8b415 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -265,8 +265,8 @@
 				pnp_printf(buffer," disabled\n");
 			else
 				pnp_printf(buffer," 0x%llx-0x%llx\n",
-						pnp_port_start(dev, i),
-						pnp_port_end(dev, i));
+					(unsigned long long)pnp_port_start(dev, i),
+					(unsigned long long)pnp_port_end(dev, i));
 		}
 	}
 	for (i = 0; i < PNP_MAX_MEM; i++) {
@@ -276,8 +276,8 @@
 				pnp_printf(buffer," disabled\n");
 			else
 				pnp_printf(buffer," 0x%llx-0x%llx\n",
-						pnp_mem_start(dev, i),
-						pnp_mem_end(dev, i));
+					(unsigned long long)pnp_mem_start(dev, i),
+					(unsigned long long)pnp_mem_end(dev, i));
 		}
 	}
 	for (i = 0; i < PNP_MAX_IRQ; i++) {
@@ -287,7 +287,7 @@
 				pnp_printf(buffer," disabled\n");
 			else
 				pnp_printf(buffer," %lld\n",
-						pnp_irq(dev, i));
+					(unsigned long long)pnp_irq(dev, i));
 		}
 	}
 	for (i = 0; i < PNP_MAX_DMA; i++) {
@@ -297,7 +297,7 @@
 				pnp_printf(buffer," disabled\n");
 			else
 				pnp_printf(buffer," %lld\n",
-						pnp_dma(dev, i));
+					(unsigned long long)pnp_dma(dev, i));
 		}
 	}
 	ret = (buffer->curr - buf);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 2122688..dc79b0a 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -173,6 +173,9 @@
 		return;
 	}
 
+	if (p->producer_consumer == ACPI_PRODUCER)
+		return;
+
 	if (p->resource_type == ACPI_MEMORY_RANGE)
 		pnpacpi_parse_allocated_memresource(res_table,
 				p->minimum, p->address_length);
@@ -252,9 +255,14 @@
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
+		if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER)
+			return AE_OK;
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER)
+			return AE_OK;
+
 		for (i = 0; i < res->data.extended_irq.interrupt_count; i++) {
 			pnpacpi_parse_allocated_irqresource(res_table,
 				res->data.extended_irq.interrupts[i],
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index b154b3f..551f58e 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -346,7 +346,7 @@
 	dev->flags = node->flags;
 	if (!(dev->flags & PNPBIOS_NO_CONFIG))
 		dev->capabilities |= PNP_CONFIGURABLE;
-	if (!(dev->flags & PNPBIOS_NO_DISABLE))
+	if (!(dev->flags & PNPBIOS_NO_DISABLE) && pnpbios_is_dynamic(dev))
 		dev->capabilities |= PNP_DISABLE;
 	dev->capabilities |= PNP_READ;
 	if (pnpbios_is_dynamic(dev))
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index d6d1bff..2c7de79 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -69,12 +69,12 @@
 
 	pr_debug("%s: aie=%d\n", __FUNCTION__, to);
 
-	tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+	tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
 
 	if (to)
 		tmp |= S3C2410_RTCALM_ALMEN;
 
-	writeb(tmp, S3C2410_RTCALM);
+	writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
 }
 
 static void s3c_rtc_setpie(int to)
@@ -84,12 +84,12 @@
 	pr_debug("%s: pie=%d\n", __FUNCTION__, to);
 
 	spin_lock_irq(&s3c_rtc_pie_lock);
-	tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
+	tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
 
 	if (to)
 		tmp |= S3C2410_TICNT_ENABLE;
 
-	writeb(tmp, S3C2410_TICNT);
+	writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
 	spin_unlock_irq(&s3c_rtc_pie_lock);
 }
 
@@ -98,13 +98,13 @@
 	unsigned int tmp;
 
 	spin_lock_irq(&s3c_rtc_pie_lock);
-	tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
+	tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
 
 	s3c_rtc_freq = freq;
 
 	tmp |= (128 / freq)-1;
 
-	writeb(tmp, S3C2410_TICNT);
+	writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
 	spin_unlock_irq(&s3c_rtc_pie_lock);
 }
 
@@ -113,14 +113,15 @@
 static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
 {
 	unsigned int have_retried = 0;
+	void __iomem *base = s3c_rtc_base;
 
  retry_get_time:
-	rtc_tm->tm_min  = readb(S3C2410_RTCMIN);
-	rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
-	rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
-	rtc_tm->tm_mon  = readb(S3C2410_RTCMON);
-	rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
-	rtc_tm->tm_sec  = readb(S3C2410_RTCSEC);
+	rtc_tm->tm_min  = readb(base + S3C2410_RTCMIN);
+	rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
+	rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
+	rtc_tm->tm_mon  = readb(base + S3C2410_RTCMON);
+	rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
+	rtc_tm->tm_sec  = readb(base + S3C2410_RTCSEC);
 
 	/* the only way to work out wether the system was mid-update
 	 * when we read it is to check the second counter, and if it
@@ -151,17 +152,26 @@
 
 static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
 {
-	/* the rtc gets round the y2k problem by just not supporting it */
+	void __iomem *base = s3c_rtc_base;
+	int year = tm->tm_year - 100;
 
-	if (tm->tm_year < 100)
+	pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+		 tm->tm_year, tm->tm_mon, tm->tm_mday,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	/* we get around y2k by simply not supporting it */
+
+	if (year < 0 || year >= 100) {
+		dev_err(dev, "rtc only supports 100 years\n");
 		return -EINVAL;
+	}
 
-	writeb(BIN2BCD(tm->tm_sec),  S3C2410_RTCSEC);
-	writeb(BIN2BCD(tm->tm_min),  S3C2410_RTCMIN);
-	writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
-	writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
-	writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
-	writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
+	writeb(BIN2BCD(tm->tm_sec),  base + S3C2410_RTCSEC);
+	writeb(BIN2BCD(tm->tm_min),  base + S3C2410_RTCMIN);
+	writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR);
+	writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE);
+	writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON);
+	writeb(BIN2BCD(year), base + S3C2410_RTCYEAR);
 
 	return 0;
 }
@@ -169,16 +179,17 @@
 static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct rtc_time *alm_tm = &alrm->time;
+	void __iomem *base = s3c_rtc_base;
 	unsigned int alm_en;
 
-	alm_tm->tm_sec  = readb(S3C2410_ALMSEC);
-	alm_tm->tm_min  = readb(S3C2410_ALMMIN);
-	alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
-	alm_tm->tm_mon  = readb(S3C2410_ALMMON);
-	alm_tm->tm_mday = readb(S3C2410_ALMDATE);
-	alm_tm->tm_year = readb(S3C2410_ALMYEAR);
+	alm_tm->tm_sec  = readb(base + S3C2410_ALMSEC);
+	alm_tm->tm_min  = readb(base + S3C2410_ALMMIN);
+	alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
+	alm_tm->tm_mon  = readb(base + S3C2410_ALMMON);
+	alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
+	alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
 
-	alm_en = readb(S3C2410_RTCALM);
+	alm_en = readb(base + S3C2410_RTCALM);
 
 	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
 		 alm_en,
@@ -226,6 +237,7 @@
 static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct rtc_time *tm = &alrm->time;
+	void __iomem *base = s3c_rtc_base;
 	unsigned int alrm_en;
 
 	pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
@@ -234,32 +246,32 @@
 		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
 
 
-	alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
-	writeb(0x00, S3C2410_RTCALM);
+	alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
+	writeb(0x00, base + S3C2410_RTCALM);
 
 	if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
 		alrm_en |= S3C2410_RTCALM_SECEN;
-		writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
+		writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC);
 	}
 
 	if (tm->tm_min < 60 && tm->tm_min >= 0) {
 		alrm_en |= S3C2410_RTCALM_MINEN;
-		writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
+		writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN);
 	}
 
 	if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
 		alrm_en |= S3C2410_RTCALM_HOUREN;
-		writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
+		writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR);
 	}
 
 	pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
 
-	writeb(alrm_en, S3C2410_RTCALM);
+	writeb(alrm_en, base + S3C2410_RTCALM);
 
 	if (0) {
-		alrm_en = readb(S3C2410_RTCALM);
+		alrm_en = readb(base + S3C2410_RTCALM);
 		alrm_en &= ~S3C2410_RTCALM_ALMEN;
-		writeb(alrm_en, S3C2410_RTCALM);
+		writeb(alrm_en, base + S3C2410_RTCALM);
 		disable_irq_wake(s3c_rtc_alarmno);
 	}
 
@@ -319,8 +331,8 @@
 
 static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	unsigned int rtcalm = readb(S3C2410_RTCALM);
-	unsigned int ticnt = readb (S3C2410_TICNT);
+	unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
+	unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
 
 	seq_printf(seq, "alarm_IRQ\t: %s\n",
 		   (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
@@ -387,39 +399,40 @@
 
 static void s3c_rtc_enable(struct platform_device *pdev, int en)
 {
+	void __iomem *base = s3c_rtc_base;
 	unsigned int tmp;
 
 	if (s3c_rtc_base == NULL)
 		return;
 
 	if (!en) {
-		tmp = readb(S3C2410_RTCCON);
-		writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
+		tmp = readb(base + S3C2410_RTCCON);
+		writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON);
 
-		tmp = readb(S3C2410_TICNT);
-		writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
+		tmp = readb(base + S3C2410_TICNT);
+		writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT);
 	} else {
 		/* re-enable the device, and check it is ok */
 
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
+		if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
 			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
 
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
+			tmp = readb(base + S3C2410_RTCCON);
+			writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON);
 		}
 
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
+		if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
 			dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
 
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
+			tmp = readb(base + S3C2410_RTCCON);
+			writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON);
 		}
 
-		if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
+		if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
 			dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
 
-			tmp = readb(S3C2410_RTCCON);
-			writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
+			tmp = readb(base + S3C2410_RTCCON);
+			writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON);
 		}
 	}
 }
@@ -475,8 +488,8 @@
 	}
 
 	s3c_rtc_mem = request_mem_region(res->start,
-					     res->end-res->start+1,
-					     pdev->name);
+					 res->end-res->start+1,
+					 pdev->name);
 
 	if (s3c_rtc_mem == NULL) {
 		dev_err(&pdev->dev, "failed to reserve memory region\n");
@@ -495,7 +508,8 @@
 
 	s3c_rtc_enable(pdev, 1);
 
- 	pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
+ 	pr_debug("s3c2410_rtc: RTCCON=%02x\n",
+		 readb(s3c_rtc_base + S3C2410_RTCCON));
 
 	s3c_rtc_setfreq(s3c_rtc_freq);
 
@@ -543,7 +557,7 @@
 
 	/* save TICNT for anyone using periodic interrupts */
 
-	ticnt_save = readb(S3C2410_TICNT);
+	ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
 
 	/* calculate time delta for suspend */
 
@@ -567,7 +581,7 @@
 	rtc_tm_to_time(&tm, &time.tv_sec);
 	restore_time_delta(&s3c_rtc_delta, &time);
 
-	writeb(ticnt_save, S3C2410_TICNT);
+	writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
 	return 0;
 }
 #else
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 4bf03fb..25c1ef6 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -52,7 +52,7 @@
 static void dasd_free_queue(struct dasd_device * device);
 static void dasd_flush_request_queue(struct dasd_device *);
 static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
-static void dasd_flush_ccw_queue(struct dasd_device *, int);
+static int dasd_flush_ccw_queue(struct dasd_device *, int);
 static void dasd_tasklet(struct dasd_device *);
 static void do_kick_device(void *data);
 
@@ -60,6 +60,7 @@
  * SECTION: Operations on the device structure.
  */
 static wait_queue_head_t dasd_init_waitq;
+static wait_queue_head_t dasd_flush_wq;
 
 /*
  * Allocate memory for a new device structure.
@@ -121,7 +122,7 @@
 /*
  * Make a new device known to the system.
  */
-static inline int
+static int
 dasd_state_new_to_known(struct dasd_device *device)
 {
 	int rc;
@@ -145,7 +146,7 @@
 /*
  * Let the system forget about a device.
  */
-static inline void
+static int
 dasd_state_known_to_new(struct dasd_device * device)
 {
 	/* Disable extended error reporting for this device. */
@@ -163,12 +164,13 @@
 
 	/* Give up reference we took in dasd_state_new_to_known. */
 	dasd_put_device(device);
+	return 0;
 }
 
 /*
  * Request the irq line for the device.
  */
-static inline int
+static int
 dasd_state_known_to_basic(struct dasd_device * device)
 {
 	int rc;
@@ -192,17 +194,23 @@
 /*
  * Release the irq line for the device. Terminate any running i/o.
  */
-static inline void
+static int
 dasd_state_basic_to_known(struct dasd_device * device)
 {
+	int rc;
+
 	dasd_gendisk_free(device);
-	dasd_flush_ccw_queue(device, 1);
+	rc = dasd_flush_ccw_queue(device, 1);
+	if (rc)
+		return rc;
+
 	DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device);
 	if (device->debug_area != NULL) {
 		debug_unregister(device->debug_area);
 		device->debug_area = NULL;
 	}
 	device->state = DASD_STATE_KNOWN;
+	return 0;
 }
 
 /*
@@ -219,7 +227,7 @@
  * In case the analysis returns an error, the device setup is stopped
  * (a fake disk was already added to allow formatting).
  */
-static inline int
+static int
 dasd_state_basic_to_ready(struct dasd_device * device)
 {
 	int rc;
@@ -247,25 +255,31 @@
  * Forget format information. Check if the target level is basic
  * and if it is create fake disk for formatting.
  */
-static inline void
+static int
 dasd_state_ready_to_basic(struct dasd_device * device)
 {
-	dasd_flush_ccw_queue(device, 0);
+	int rc;
+
+	rc = dasd_flush_ccw_queue(device, 0);
+	if (rc)
+		return rc;
 	dasd_destroy_partitions(device);
 	dasd_flush_request_queue(device);
 	device->blocks = 0;
 	device->bp_block = 0;
 	device->s2b_shift = 0;
 	device->state = DASD_STATE_BASIC;
+	return 0;
 }
 
 /*
  * Back to basic.
  */
-static inline void
+static int
 dasd_state_unfmt_to_basic(struct dasd_device * device)
 {
 	device->state = DASD_STATE_BASIC;
+	return 0;
 }
 
 /*
@@ -273,7 +287,7 @@
  * the requeueing of requests from the linux request queue to the
  * ccw queue.
  */
-static inline int
+static int
 dasd_state_ready_to_online(struct dasd_device * device)
 {
 	device->state = DASD_STATE_ONLINE;
@@ -284,16 +298,17 @@
 /*
  * Stop the requeueing of requests again.
  */
-static inline void
+static int
 dasd_state_online_to_ready(struct dasd_device * device)
 {
 	device->state = DASD_STATE_READY;
+	return 0;
 }
 
 /*
  * Device startup state changes.
  */
-static inline int
+static int
 dasd_increase_state(struct dasd_device *device)
 {
 	int rc;
@@ -329,30 +344,37 @@
 /*
  * Device shutdown state changes.
  */
-static inline int
+static int
 dasd_decrease_state(struct dasd_device *device)
 {
+	int rc;
+
+	rc = 0;
 	if (device->state == DASD_STATE_ONLINE &&
 	    device->target <= DASD_STATE_READY)
-		dasd_state_online_to_ready(device);
+		rc = dasd_state_online_to_ready(device);
 
-	if (device->state == DASD_STATE_READY &&
+	if (!rc &&
+	    device->state == DASD_STATE_READY &&
 	    device->target <= DASD_STATE_BASIC)
-		dasd_state_ready_to_basic(device);
+		rc = dasd_state_ready_to_basic(device);
 
-	if (device->state == DASD_STATE_UNFMT &&
+	if (!rc &&
+	    device->state == DASD_STATE_UNFMT &&
 	    device->target <= DASD_STATE_BASIC)
-		dasd_state_unfmt_to_basic(device);
+		rc = dasd_state_unfmt_to_basic(device);
 
-	if (device->state == DASD_STATE_BASIC &&
+	if (!rc &&
+	    device->state == DASD_STATE_BASIC &&
 	    device->target <= DASD_STATE_KNOWN)
-		dasd_state_basic_to_known(device);
+		rc = dasd_state_basic_to_known(device);
 
-	if (device->state == DASD_STATE_KNOWN &&
+	if (!rc &&
+	    device->state == DASD_STATE_KNOWN &&
 	    device->target <= DASD_STATE_NEW)
-		dasd_state_known_to_new(device);
+		rc = dasd_state_known_to_new(device);
 
-	return 0;
+	return rc;
 }
 
 /*
@@ -701,6 +723,7 @@
 			cqr->retries--;
 			cqr->status = DASD_CQR_CLEAR;
 			cqr->stopclk = get_clock();
+			cqr->starttime = 0;
 			DBF_DEV_EVENT(DBF_DEBUG, device,
 				      "terminate cqr %p successful",
 				      cqr);
@@ -978,6 +1001,7 @@
 	    irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
 		cqr->status = DASD_CQR_QUEUED;
 		dasd_clear_timer(device);
+		wake_up(&dasd_flush_wq);
 		dasd_schedule_bh(device);
 		return;
 	}
@@ -1241,6 +1265,10 @@
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
 	if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) {
 		if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) {
+			DEV_MESSAGE(KERN_ERR, device,
+				    "internal error - timeout (%is) expired "
+				    "for cqr %p (%i retries left)",
+				    (cqr->expires/HZ), cqr, cqr->retries);
 			if (device->discipline->term_IO(cqr) != 0)
 				/* Hmpf, try again in 1/10 sec */
 				dasd_set_timer(device, 10);
@@ -1285,46 +1313,100 @@
 		dasd_set_timer(device, 50);
 }
 
+static inline int
+_wait_for_clear(struct dasd_ccw_req *cqr)
+{
+	return (cqr->status == DASD_CQR_QUEUED);
+}
+
 /*
- * Remove requests from the ccw queue.
+ * Remove all requests from the ccw queue (all = '1') or only block device
+ * requests in case all = '0'.
+ * Take care of the erp-chain (chained via cqr->refers) and remove either
+ * the whole erp-chain or none of the erp-requests.
+ * If a request is currently running, term_IO is called and the request
+ * is re-queued. Prior to removing the terminated request we need to wait
+ * for the clear-interrupt.
+ * In case termination is not possible we stop processing and just finishing
+ * the already moved requests.
  */
-static void
+static int
 dasd_flush_ccw_queue(struct dasd_device * device, int all)
 {
+	struct dasd_ccw_req *cqr, *orig, *n;
+	int rc, i;
+
 	struct list_head flush_queue;
-	struct list_head *l, *n;
-	struct dasd_ccw_req *cqr;
 
 	INIT_LIST_HEAD(&flush_queue);
 	spin_lock_irq(get_ccwdev_lock(device->cdev));
-	list_for_each_safe(l, n, &device->ccw_queue) {
-		cqr = list_entry(l, struct dasd_ccw_req, list);
+	rc = 0;
+restart:
+	list_for_each_entry_safe(cqr, n, &device->ccw_queue, list) {
+		/* get original request of erp request-chain */
+		for (orig = cqr; orig->refers != NULL; orig = orig->refers);
+
 		/* Flush all request or only block device requests? */
-		if (all == 0 && cqr->callback == dasd_end_request_cb)
+		if (all == 0 && cqr->callback != dasd_end_request_cb &&
+		    orig->callback != dasd_end_request_cb) {
 			continue;
-		if (cqr->status == DASD_CQR_IN_IO)
-			device->discipline->term_IO(cqr);
-		if (cqr->status != DASD_CQR_DONE ||
-		    cqr->status != DASD_CQR_FAILED) {
-			cqr->status = DASD_CQR_FAILED;
+		}
+		/* Check status and move request to flush_queue */
+		switch (cqr->status) {
+		case DASD_CQR_IN_IO:
+			rc = device->discipline->term_IO(cqr);
+			if (rc) {
+				/* unable to terminate requeust */
+				DEV_MESSAGE(KERN_ERR, device,
+					    "dasd flush ccw_queue is unable "
+					    " to terminate request %p",
+					    cqr);
+				/* stop flush processing */
+				goto finished;
+			}
+			break;
+		case DASD_CQR_QUEUED:
+		case DASD_CQR_ERROR:
+			/* set request to FAILED */
 			cqr->stopclk = get_clock();
+			cqr->status = DASD_CQR_FAILED;
+			break;
+		default: /* do not touch the others */
+			break;
+		}
+		/* Rechain request (including erp chain) */
+		for (i = 0; cqr != NULL; cqr = cqr->refers, i++) {
+			cqr->endclk = get_clock();
+			list_move_tail(&cqr->list, &flush_queue);
+		}
+		if (i > 1)
+			/* moved more than one request - need to restart */
+			goto restart;
+	}
+
+finished:
+	spin_unlock_irq(get_ccwdev_lock(device->cdev));
+	/* Now call the callback function of flushed requests */
+restart_cb:
+	list_for_each_entry_safe(cqr, n, &flush_queue, list) {
+		if (cqr->status == DASD_CQR_CLEAR) {
+			/* wait for clear interrupt! */
+			wait_event(dasd_flush_wq, _wait_for_clear(cqr));
+			cqr->status = DASD_CQR_FAILED;
 		}
 		/* Process finished ERP request. */
 		if (cqr->refers) {
 			__dasd_process_erp(device, cqr);
-			continue;
+			/* restart list_for_xx loop since dasd_process_erp
+			 * might remove multiple elements */
+			goto restart_cb;
 		}
-		/* Rechain request on device request queue */
+		/* call the callback function */
 		cqr->endclk = get_clock();
-		list_move_tail(&cqr->list, &flush_queue);
-	}
-	spin_unlock_irq(get_ccwdev_lock(device->cdev));
-	/* Now call the callback function of flushed requests */
-	list_for_each_safe(l, n, &flush_queue) {
-		cqr = list_entry(l, struct dasd_ccw_req, list);
 		if (cqr->callback != NULL)
 			(cqr->callback)(cqr, cqr->callback_data);
 	}
+	return rc;
 }
 
 /*
@@ -1510,10 +1592,8 @@
 			if (device->discipline->term_IO) {
 				cqr->retries = -1;
 				device->discipline->term_IO(cqr);
-				/*nished =
-				 * wait (non-interruptible) for final status
-				 * because signal ist still pending
-				 */
+				/* wait (non-interruptible) for final status
+				 * because signal ist still pending */
 				spin_unlock_irq(get_ccwdev_lock(device->cdev));
 				wait_event(wait_q, _wait_for_wakeup(cqr));
 				spin_lock_irq(get_ccwdev_lock(device->cdev));
@@ -1546,19 +1626,11 @@
 _dasd_term_running_cqr(struct dasd_device *device)
 {
 	struct dasd_ccw_req *cqr;
-	int rc;
 
 	if (list_empty(&device->ccw_queue))
 		return 0;
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list);
-	rc = device->discipline->term_IO(cqr);
-	if (rc == 0) {
-		/* termination successful */
-		cqr->status = DASD_CQR_QUEUED;
-		cqr->startclk = cqr->stopclk = 0;
-		cqr->starttime = 0;
-	}
-	return rc;
+	return device->discipline->term_IO(cqr);
 }
 
 int
@@ -1726,12 +1798,9 @@
 		return;
 
 	spin_lock_irq(&device->request_queue_lock);
-	while (!list_empty(&device->request_queue->queue_head)) {
-		req = elv_next_request(device->request_queue);
-		if (req == NULL)
-			break;
-		dasd_end_request(req, 0);
+	while ((req = elv_next_request(device->request_queue))) {
 		blkdev_dequeue_request(req);
+		dasd_end_request(req, 0);
 	}
 	spin_unlock_irq(&device->request_queue_lock);
 }
@@ -2091,6 +2160,7 @@
 	int rc;
 
 	init_waitqueue_head(&dasd_init_waitq);
+	init_waitqueue_head(&dasd_flush_wq);
 
 	/* register 'common' DASD debug area, used for all DBF_XXX calls */
 	dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long));
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 7f6fdac..9af02c7 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -48,18 +48,20 @@
 };
 
 /*
- * dasd_servermap is used to store the server_id of all storage servers
- * accessed by DASD device driver.
+ * dasd_server_ssid_map contains a globally unique storage server subsystem ID.
+ * dasd_server_ssid_list contains the list of all subsystem IDs accessed by
+ * the DASD device driver.
  */
-struct dasd_servermap {
+struct dasd_server_ssid_map {
 	struct list_head list;
-	struct server_id {
+	struct system_id {
 		char vendor[4];
 		char serial[15];
+		__u16 ssid;
 	} sid;
 };
 
-static struct list_head dasd_serverlist;
+static struct list_head dasd_server_ssid_list;
 
 /*
  * Parameter parsing functions for dasd= parameter. The syntax is:
@@ -89,7 +91,7 @@
 module_param_array(dasd, charp, NULL, 0);
 
 /*
- * Single spinlock to protect devmap structures and lists.
+ * Single spinlock to protect devmap and servermap structures and lists.
  */
 static DEFINE_SPINLOCK(dasd_devmap_lock);
 
@@ -264,8 +266,9 @@
 		if (dasd_page_cache)
 			return residual_str;
 		dasd_page_cache =
-			kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0,
-					  SLAB_CACHE_DMA, NULL, NULL );
+			kmem_cache_create("dasd_page_cache", PAGE_SIZE,
+					  PAGE_SIZE, SLAB_CACHE_DMA,
+					  NULL, NULL );
 		if (!dasd_page_cache)
 			MESSAGE(KERN_WARNING, "%s", "Failed to create slab, "
 				"fixed buffer mode disabled.");
@@ -859,39 +862,6 @@
 };
 
 /*
- * Check if the related storage server is already contained in the
- * dasd_serverlist. If server is not contained, create new entry.
- * Return 0 if server was already in serverlist,
- *	  1 if the server was added successfully
- *	 <0 in case of error.
- */
-static int
-dasd_add_server(struct dasd_uid *uid)
-{
-	struct dasd_servermap *new, *tmp;
-
-	/* check if server is already contained */
-	list_for_each_entry(tmp, &dasd_serverlist, list)
-	  // normale cmp?
-		if (strncmp(tmp->sid.vendor, uid->vendor,
-			    sizeof(tmp->sid.vendor)) == 0
-		    && strncmp(tmp->sid.serial, uid->serial,
-			       sizeof(tmp->sid.serial)) == 0)
-			return 0;
-
-	new = (struct dasd_servermap *)
-		kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL);
-	if (!new)
-		return -ENOMEM;
-
-	strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor));
-	strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial));
-	list_add(&new->list, &dasd_serverlist);
-	return 1;
-}
-
-
-/*
  * Return copy of the device unique identifier.
  */
 int
@@ -910,6 +880,9 @@
 
 /*
  * Register the given device unique identifier into devmap struct.
+ * In addition check if the related storage server subsystem ID is already
+ * contained in the dasd_server_ssid_list. If subsystem ID is not contained,
+ * create new entry.
  * Return 0 if server was already in serverlist,
  *	  1 if the server was added successful
  *	 <0 in case of error.
@@ -918,16 +891,39 @@
 dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid)
 {
 	struct dasd_devmap *devmap;
-	int rc;
+	struct dasd_server_ssid_map *srv, *tmp;
 
 	devmap = dasd_find_busid(cdev->dev.bus_id);
 	if (IS_ERR(devmap))
 		return PTR_ERR(devmap);
+
+	/* generate entry for server_ssid_map */
+	srv = (struct dasd_server_ssid_map *)
+		kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL);
+	if (!srv)
+		return -ENOMEM;
+	strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1);
+	strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1);
+	srv->sid.ssid = uid->ssid;
+
+	/* server is already contained ? */
 	spin_lock(&dasd_devmap_lock);
 	devmap->uid = *uid;
-	rc = dasd_add_server(uid);
+	list_for_each_entry(tmp, &dasd_server_ssid_list, list) {
+		if (!memcmp(&srv->sid, &tmp->sid,
+			    sizeof(struct system_id))) {
+			kfree(srv);
+			srv = NULL;
+			break;
+		}
+	}
+
+	/* add servermap to serverlist */
+	if (srv)
+		list_add(&srv->list, &dasd_server_ssid_list);
 	spin_unlock(&dasd_devmap_lock);
-	return rc;
+
+	return (srv ? 1 : 0);
 }
 EXPORT_SYMBOL_GPL(dasd_set_uid);
 
@@ -995,7 +991,7 @@
 		INIT_LIST_HEAD(&dasd_hashlists[i]);
 
 	/* Initialize servermap structure. */
-	INIT_LIST_HEAD(&dasd_serverlist);
+	INIT_LIST_HEAD(&dasd_server_ssid_list);
 	return 0;
 }
 
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 39c2281..b7a7fac 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -468,11 +468,11 @@
 		return -ENODEV;
 
 	memset(uid, 0, sizeof(struct dasd_uid));
-	strncpy(uid->vendor, confdata->ned1.HDA_manufacturer,
-		sizeof(uid->vendor) - 1);
+	memcpy(uid->vendor, confdata->ned1.HDA_manufacturer,
+	       sizeof(uid->vendor) - 1);
 	EBCASC(uid->vendor, sizeof(uid->vendor) - 1);
-	strncpy(uid->serial, confdata->ned1.HDA_location,
-		sizeof(uid->serial) - 1);
+	memcpy(uid->serial, confdata->ned1.HDA_location,
+	       sizeof(uid->serial) - 1);
 	EBCASC(uid->serial, sizeof(uid->serial) - 1);
 	uid->ssid = confdata->neq.subsystemID;
 	if (confdata->ned2.sneq.flags == 0x40) {
@@ -607,7 +607,7 @@
  * Valide storage server of current device.
  */
 static int
-dasd_eckd_validate_server(struct dasd_device *device)
+dasd_eckd_validate_server(struct dasd_device *device, struct dasd_uid *uid)
 {
 	int rc;
 
@@ -616,11 +616,11 @@
 		return 0;
 
 	rc = dasd_eckd_psf_ssc(device);
-	if (rc)
-		/* may be requested feature is not available on server,
-		 * therefore just report error and go ahead */
-		DEV_MESSAGE(KERN_INFO, device,
-			    "Perform Subsystem Function returned rc=%d", rc);
+	/* may be requested feature is not available on server,
+	 * therefore just report error and go ahead */
+	DEV_MESSAGE(KERN_INFO, device,
+		    "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d",
+		    uid->vendor, uid->serial, uid->ssid, rc);
 	/* RE-Read Configuration Data */
 	return dasd_eckd_read_conf(device);
 }
@@ -666,7 +666,7 @@
 		return rc;
 	rc = dasd_set_uid(device->cdev, &uid);
 	if (rc == 1)	/* new server found */
-		rc = dasd_eckd_validate_server(device);
+		rc = dasd_eckd_validate_server(device, &uid);
 	if (rc)
 		return rc;
 
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 4c272b7..d163632 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -83,10 +83,12 @@
 void
 dasd_gendisk_free(struct dasd_device *device)
 {
-	del_gendisk(device->gdp);
-	device->gdp->queue = NULL;
-	put_disk(device->gdp);
-	device->gdp = NULL;
+	if (device->gdp) {
+		del_gendisk(device->gdp);
+		device->gdp->queue = NULL;
+		put_disk(device->gdp);
+		device->gdp = NULL;
+	}
 }
 
 /*
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
index 1140302..ca7d51f 100644
--- a/drivers/s390/block/xpram.c
+++ b/drivers/s390/block/xpram.c
@@ -48,15 +48,6 @@
 #define PRINT_ERR(x...)		printk(KERN_ERR XPRAM_NAME " error:" x)
 
 
-static struct sysdev_class xpram_sysclass = {
-	set_kset_name("xpram"),
-};
-
-static struct sys_device xpram_sys_device = {
-	.id	= 0,
-	.cls	= &xpram_sysclass,
-}; 
-
 typedef struct {
 	unsigned int	size;		/* size of xpram segment in pages */
 	unsigned int	offset;		/* start page of xpram segment */
@@ -451,8 +442,6 @@
 	}
 	unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 	blk_cleanup_queue(xpram_queue);
-	sysdev_unregister(&xpram_sys_device);
-	sysdev_class_unregister(&xpram_sysclass);
 }
 
 static int __init xpram_init(void)
@@ -470,19 +459,7 @@
 	rc = xpram_setup_sizes(xpram_pages);
 	if (rc)
 		return rc;
-	rc = sysdev_class_register(&xpram_sysclass);
-	if (rc)
-		return rc;
-
-	rc = sysdev_register(&xpram_sys_device);
-	if (rc) {
-		sysdev_class_unregister(&xpram_sysclass);
-		return rc;
-	}
-	rc = xpram_setup_blkdev();
-	if (rc)
-		sysdev_unregister(&xpram_sys_device);
-	return rc;
+	return xpram_setup_blkdev();
 }
 
 module_init(xpram_init);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 643b6d0..56b8761 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -76,7 +76,7 @@
 				device,
 				"%s", tcd->device_name
 			);
-	rc = PTR_ERR(tcd->class_device);
+	rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0;
 	if (rc)
 		goto fail_with_cdev;
 	rc = sysfs_create_link(
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index f26a2ee..38954f5 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -152,7 +152,6 @@
 	struct ccwgroup_device *gdev;
 	int i;
 	int rc;
-	int del_drvdata;
 
 	if (argc > 256) /* disallow dumb users */
 		return -EINVAL;
@@ -163,7 +162,6 @@
 
 	atomic_set(&gdev->onoff, 0);
 
-	del_drvdata = 0;
 	for (i = 0; i < argc; i++) {
 		gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
 
@@ -180,18 +178,14 @@
 			rc = -EINVAL;
 			goto free_dev;
 		}
-	}
-	for (i = 0; i < argc; i++)
 		gdev->cdev[i]->dev.driver_data = gdev;
-	del_drvdata = 1;
+	}
 
 	gdev->creator_id = creator_id;
 	gdev->count = argc;
-	gdev->dev = (struct device ) {
-		.bus = &ccwgroup_bus_type,
-		.parent = root,
-		.release = ccwgroup_release,
-	};
+	gdev->dev.bus = &ccwgroup_bus_type;
+	gdev->dev.parent = root;
+	gdev->dev.release = ccwgroup_release;
 
 	snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
 			gdev->cdev[0]->dev.bus_id);
@@ -226,9 +220,9 @@
 free_dev:
 	for (i = 0; i < argc; i++)
 		if (gdev->cdev[i]) {
-			put_device(&gdev->cdev[i]->dev);
-			if (del_drvdata)
+			if (gdev->cdev[i]->dev.driver_data == gdev)
 				gdev->cdev[i]->dev.driver_data = NULL;
+			put_device(&gdev->cdev[i]->dev);
 		}
 	kfree(gdev);
 	return rc;
@@ -395,10 +389,8 @@
 ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
 {
 	/* register our new driver with the core */
-	cdriver->driver = (struct device_driver) {
-		.bus = &ccwgroup_bus_type,
-		.name = cdriver->name,
-	};
+	cdriver->driver.bus = &ccwgroup_bus_type;
+	cdriver->driver.name = cdriver->name;
 
 	return driver_register(&cdriver->driver);
 }
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 61ce3f1..c28444a 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -238,8 +238,6 @@
 	/* Check for single path devices. */
 	if (sch->schib.pmcw.pim == 0x80)
 		goto out_unreg;
-	if (sch->vpm == mask)
-		goto out_unreg;
 
 	if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
 	    (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
@@ -258,6 +256,8 @@
 	/* trigger path verification. */
 	if (sch->driver && sch->driver->verify)
 		sch->driver->verify(&sch->dev);
+	else if (sch->vpm == mask)
+		goto out_unreg;
 out_unlock:
 	spin_unlock_irq(&sch->lock);
 	return 0;
@@ -1391,10 +1391,8 @@
 	/* fill in status, etc. */
 	chp->id = chpid;
 	chp->state = 1;
-	chp->dev = (struct device) {
-		.parent  = &css[0]->device,
-		.release = chp_release,
-	};
+	chp->dev.parent = &css[0]->device;
+	chp->dev.release = chp_release;
 	snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid);
 
 	/* Obtain channel path description and fill it in. */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 585fa04..646da56 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -556,12 +556,11 @@
 			 struct ccw_device *sibling)
 {
 	struct device *dev;
-	struct match_data data = {
-		.devno   = devno,
-		.ssid    = ssid,
-		.sibling = sibling,
-	};
+	struct match_data data;
 
+	data.devno = devno;
+	data.ssid = ssid;
+	data.sibling = sibling;
 	dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno);
 
 	return dev ? to_ccwdev(dev) : NULL;
@@ -835,10 +834,8 @@
 		return -ENOMEM;
 	}
 	atomic_set(&cdev->private->onoff, 0);
-	cdev->dev = (struct device) {
-		.parent = &sch->dev,
-		.release = ccw_device_release,
-	};
+	cdev->dev.parent = &sch->dev;
+	cdev->dev.release = ccw_device_release;
 	INIT_LIST_HEAD(&cdev->private->kick_work.entry);
 	/* Do first half of device_register. */
 	device_initialize(&cdev->dev);
@@ -977,9 +974,7 @@
 	int rc;
 
 	/* Initialize the ccw_device structure. */
-	cdev->dev = (struct device) {
-		.parent = &sch->dev,
-	};
+	cdev->dev.parent= &sch->dev;
 	rc = io_subchannel_recog(cdev, sch);
 	if (rc)
 		return rc;
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index ac6e0c7..35e162b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -152,7 +152,8 @@
 		if (cdev->private->iretry) {
 			cdev->private->iretry--;
 			ret = cio_halt(sch);
-			return (ret == 0) ? -EBUSY : ret;
+			if (ret != -EBUSY)
+				return (ret == 0) ? -EBUSY : ret;
 		}
 		/* halt io unsuccessful. */
 		cdev->private->iretry = 255;	/* 255 clear retries. */
@@ -266,12 +267,10 @@
 			notify = 1;
 		}
 		/* fill out sense information */
-		cdev->id = (struct ccw_device_id) {
-			.cu_type   = cdev->private->senseid.cu_type,
-			.cu_model  = cdev->private->senseid.cu_model,
-			.dev_type  = cdev->private->senseid.dev_type,
-			.dev_model = cdev->private->senseid.dev_model,
-		};
+		cdev->id.cu_type   = cdev->private->senseid.cu_type;
+		cdev->id.cu_model  = cdev->private->senseid.cu_model;
+		cdev->id.dev_type  = cdev->private->senseid.dev_type;
+		cdev->id.dev_model = cdev->private->senseid.dev_model;
 		if (notify) {
 			cdev->private->state = DEV_STATE_OFFLINE;
 			if (same_dev) {
@@ -565,12 +564,10 @@
 		/* Deliver fake irb to device driver, if needed. */
 		if (cdev->private->flags.fake_irb) {
 			memset(&cdev->private->irb, 0, sizeof(struct irb));
-			cdev->private->irb.scsw = (struct scsw) {
-				.cc = 1,
-				.fctl = SCSW_FCTL_START_FUNC,
-				.actl = SCSW_ACTL_START_PEND,
-				.stctl = SCSW_STCTL_STATUS_PEND,
-			};
+			cdev->private->irb.scsw.cc = 1;
+			cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC;
+			cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND;
+			cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND;
 			cdev->private->flags.fake_irb = 0;
 			if (cdev->handler)
 				cdev->handler(cdev, cdev->private->intparm,
@@ -771,6 +768,7 @@
 	stsch(sch->schid, &sch->schib);
 
 	if (sch->schib.scsw.actl != 0 ||
+	    (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) ||
 	    (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
 		/*
 		 * No final status yet or final status not yet delivered
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index a601242..9e3de0bd 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -263,6 +263,9 @@
 	/* Abuse intparm for error reporting. */
 	if (IS_ERR(irb))
 		cdev->private->intparm = -EIO;
+	else if (irb->scsw.cc == 1)
+		/* Retry for deferred condition code. */
+		cdev->private->intparm = -EAGAIN;
 	else if ((irb->scsw.dstat !=
 		  (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) ||
 		 (irb->scsw.cstat != 0)) {
diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 32610fd..1693a10 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -24,6 +24,21 @@
 #include "ioasm.h"
 
 /*
+ * Helper function called from interrupt context to decide whether an
+ * operation should be tried again.
+ */
+static int __ccw_device_should_retry(struct scsw *scsw)
+{
+	/* CC is only valid if start function bit is set. */
+	if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1)
+		return 1;
+	/* No more activity. For sense and set PGID we stubbornly try again. */
+	if (!scsw->actl)
+		return 1;
+	return 0;
+}
+
+/*
  * Start Sense Path Group ID helper function. Used in ccw_device_recog
  * and ccw_device_sense_pgid.
  */
@@ -155,10 +170,10 @@
 	int ret;
 
 	irb = (struct irb *) __LC_IRB;
-	/* Retry sense pgid for cc=1. */
+
 	if (irb->scsw.stctl ==
 	    (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-		if (irb->scsw.cc == 1) {
+		if (__ccw_device_should_retry(&irb->scsw)) {
 			ret = __ccw_device_sense_pgid_start(cdev);
 			if (ret && ret != -EBUSY)
 				ccw_device_sense_pgid_done(cdev, ret);
@@ -391,10 +406,10 @@
 	int ret;
 
 	irb = (struct irb *) __LC_IRB;
-	/* Retry set pgid for cc=1. */
+
 	if (irb->scsw.stctl ==
 	    (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-		if (irb->scsw.cc == 1)
+		if (__ccw_device_should_retry(&irb->scsw))
 			__ccw_device_verify_start(cdev);
 		return;
 	}
@@ -494,10 +509,10 @@
 	int ret;
 
 	irb = (struct irb *) __LC_IRB;
-	/* Retry set pgid for cc=1. */
+
 	if (irb->scsw.stctl ==
 	    (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-		if (irb->scsw.cc == 1)
+		if (__ccw_device_should_retry(&irb->scsw))
 			__ccw_device_disband_start(cdev);
 		return;
 	}
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 5fff1f9..e1327b8 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -8510,9 +8510,9 @@
 qeth_ipv6_init(void)
 {
 	qeth_old_arp_constructor = arp_tbl.constructor;
-	write_lock(&arp_tbl.lock);
+	write_lock_bh(&arp_tbl.lock);
 	arp_tbl.constructor = qeth_arp_constructor;
-	write_unlock(&arp_tbl.lock);
+	write_unlock_bh(&arp_tbl.lock);
 
 	arp_direct_ops = (struct neigh_ops*)
 		kmalloc(sizeof(struct neigh_ops), GFP_KERNEL);
@@ -8528,9 +8528,9 @@
 static void
 qeth_ipv6_uninit(void)
 {
-	write_lock(&arp_tbl.lock);
+	write_lock_bh(&arp_tbl.lock);
 	arp_tbl.constructor = qeth_old_arp_constructor;
-	write_unlock(&arp_tbl.lock);
+	write_unlock_bh(&arp_tbl.lock);
 	kfree(arp_direct_ops);
 }
 #endif /* CONFIG_QETH_IPV6 */
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 9cd789b..adc9d8f 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -112,6 +112,105 @@
 		printk("\n");
 }
 
+
+/****************************************************************/
+/****** Functions to handle the request ID hash table    ********/
+/****************************************************************/
+
+#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_FSF
+
+static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
+{
+	int i;
+
+	adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
+				    GFP_KERNEL);
+
+	if (!adapter->req_list)
+		return -ENOMEM;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		INIT_LIST_HEAD(&adapter->req_list[i]);
+
+	return 0;
+}
+
+static void zfcp_reqlist_free(struct zfcp_adapter *adapter)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++) {
+		if (list_empty(&adapter->req_list[i]))
+			continue;
+
+		list_for_each_entry_safe(request, tmp,
+					 &adapter->req_list[i], list)
+			list_del(&request->list);
+	}
+
+	kfree(adapter->req_list);
+}
+
+void zfcp_reqlist_add(struct zfcp_adapter *adapter,
+		      struct zfcp_fsf_req *fsf_req)
+{
+	unsigned int i;
+
+	i = fsf_req->req_id % REQUEST_LIST_SIZE;
+	list_add_tail(&fsf_req->list, &adapter->req_list[i]);
+}
+
+void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i, counter;
+	u64 dbg_tmp[2];
+
+	i = req_id % REQUEST_LIST_SIZE;
+	BUG_ON(list_empty(&adapter->req_list[i]));
+
+	counter = 0;
+	list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) {
+		if (request->req_id == req_id) {
+			dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
+			dbg_tmp[1] = (u64) counter;
+			debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+			list_del(&request->list);
+			break;
+		}
+		counter++;
+	}
+}
+
+struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
+					   unsigned long req_id)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i;
+
+	i = req_id % REQUEST_LIST_SIZE;
+
+	list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
+		if (request->req_id == req_id)
+			return request;
+
+	return NULL;
+}
+
+int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
+{
+	unsigned int i;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		if (!list_empty(&adapter->req_list[i]))
+			return 0;
+
+	return 1;
+}
+
+#undef ZFCP_LOG_AREA
+
 /****************************************************************/
 /************** Uncategorised Functions *************************/
 /****************************************************************/
@@ -961,8 +1060,12 @@
 	INIT_LIST_HEAD(&adapter->port_remove_lh);
 
 	/* initialize list of fsf requests */
-	spin_lock_init(&adapter->fsf_req_list_lock);
-	INIT_LIST_HEAD(&adapter->fsf_req_list_head);
+	spin_lock_init(&adapter->req_list_lock);
+	retval = zfcp_reqlist_init(adapter);
+	if (retval) {
+		ZFCP_LOG_INFO("request list initialization failed\n");
+		goto failed_low_mem_buffers;
+	}
 
 	/* initialize debug locks */
 
@@ -1041,8 +1144,6 @@
  *		!0 - struct zfcp_adapter  data structure could not be removed
  *			(e.g. still used)
  * locks:	adapter list write lock is assumed to be held by caller
- *              adapter->fsf_req_list_lock is taken and released within this 
- *              function and must not be held on entry
  */
 void
 zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
@@ -1054,14 +1155,14 @@
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	/* sanity check: no pending FSF requests */
-	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	retval = !list_empty(&adapter->fsf_req_list_head);
-	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-	if (retval) {
+	spin_lock_irqsave(&adapter->req_list_lock, flags);
+	retval = zfcp_reqlist_isempty(adapter);
+	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+	if (!retval) {
 		ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
 				"%i requests outstanding\n",
 				zfcp_get_busid_by_adapter(adapter), adapter,
-				atomic_read(&adapter->fsf_reqs_active));
+				atomic_read(&adapter->reqs_active));
 		retval = -EBUSY;
 		goto out;
 	}
@@ -1087,6 +1188,7 @@
 	zfcp_free_low_mem_buffers(adapter);
 	/* free memory of adapter data structure and queues */
 	zfcp_qdio_free_queues(adapter);
+	zfcp_reqlist_free(adapter);
 	kfree(adapter->fc_stats);
 	kfree(adapter->stats_reset_data);
 	ZFCP_LOG_TRACE("freeing adapter structure\n");
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 57d8e4b..fdabade 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -164,6 +164,11 @@
 	retval = zfcp_adapter_scsi_register(adapter);
 	if (retval)
 		goto out_scsi_register;
+
+	/* initialize request counter */
+	BUG_ON(!zfcp_reqlist_isempty(adapter));
+	adapter->req_no = 0;
+
 	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
 				       ZFCP_SET);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 2df512a..94d1b74d 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -52,7 +52,7 @@
 /********************* GENERAL DEFINES *********************************/
 
 /* zfcp version number, it consists of major, minor, and patch-level number */
-#define ZFCP_VERSION		"4.7.0"
+#define ZFCP_VERSION		"4.8.0"
 
 /**
  * zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -80,7 +80,7 @@
 #define REQUEST_LIST_SIZE 128
 
 /********************* SCSI SPECIFIC DEFINES *********************************/
-#define ZFCP_SCSI_ER_TIMEOUT                    (100*HZ)
+#define ZFCP_SCSI_ER_TIMEOUT                    (10*HZ)
 
 /********************* CIO/QDIO SPECIFIC DEFINES *****************************/
 
@@ -886,11 +886,11 @@
 	struct list_head        port_remove_lh;    /* head of ports to be
 						      removed */
 	u32			ports;	           /* number of remote ports */
-        struct timer_list       scsi_er_timer;     /* SCSI err recovery watch */
-	struct list_head	fsf_req_list_head; /* head of FSF req list */
-	spinlock_t		fsf_req_list_lock; /* lock for ops on list of
-						      FSF requests */
-        atomic_t       		fsf_reqs_active;   /* # active FSF reqs */
+	struct timer_list	scsi_er_timer;     /* SCSI err recovery watch */
+	atomic_t		reqs_active;	   /* # active FSF reqs */
+	unsigned long		req_no;		   /* unique FSF req number */
+	struct list_head	*req_list;	   /* list of pending reqs */
+	spinlock_t		req_list_lock;	   /* request list lock */
 	struct zfcp_qdio_queue	request_queue;	   /* request queue */
 	u32			fsf_req_seq_no;	   /* FSF cmnd seq number */
 	wait_queue_head_t	request_wq;	   /* can be used to wait for
@@ -986,6 +986,7 @@
 /* FSF request */
 struct zfcp_fsf_req {
 	struct list_head       list;	       /* list of FSF requests */
+	unsigned long	       req_id;	       /* unique request ID */
 	struct zfcp_adapter    *adapter;       /* adapter request belongs to */
 	u8		       sbal_number;    /* nr of SBALs free for use */
 	u8		       sbal_first;     /* first SBAL for this request */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 8ec8da0..7f60b6f 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -64,8 +64,8 @@
 static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int);
 static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *);
-static int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);
-static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);
+static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *);
+static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *);
 static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *);
@@ -93,10 +93,9 @@
 static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *);
 static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *);
 
-static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
-static int zfcp_erp_action_dismiss_port(struct zfcp_port *);
-static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
-static int zfcp_erp_action_dismiss(struct zfcp_erp_action *);
+static void zfcp_erp_action_dismiss_port(struct zfcp_port *);
+static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *);
+static void zfcp_erp_action_dismiss(struct zfcp_erp_action *);
 
 static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *,
 				   struct zfcp_port *, struct zfcp_unit *);
@@ -135,29 +134,39 @@
 	zfcp_erp_adapter_reopen(adapter, 0);
 }
 
-/*
- * function:	zfcp_fsf_scsi_er_timeout_handler
+/**
+ * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks
  *
- * purpose:     This function needs to be called whenever a SCSI error recovery
- *              action (abort/reset) does not return.
- *              Re-opening the adapter means that the command can be returned
- *              by zfcp (it is guarranteed that it does not return via the
- *              adapter anymore). The buffer can then be used again.
- *    
- * returns:     sod all
+ * This function needs to be called whenever a SCSI error recovery
+ * action (abort/reset) does not return.  Re-opening the adapter means
+ * that the abort/reset command can be returned by zfcp. It won't complete
+ * via the adapter anymore (because qdio queues are closed). If ERP is
+ * already running on this adapter it will be stopped.
  */
-void
-zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
+void zfcp_fsf_scsi_er_timeout_handler(unsigned long data)
 {
 	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
+	unsigned long flags;
 
 	ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. "
 			"Restarting all operations on the adapter %s\n",
 			zfcp_get_busid_by_adapter(adapter));
 	debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout");
-	zfcp_erp_adapter_reopen(adapter, 0);
 
-	return;
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
+			     &adapter->status)) {
+		zfcp_erp_modify_adapter_status(adapter,
+		       ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
+		       ZFCP_CLEAR);
+		zfcp_erp_action_dismiss_adapter(adapter);
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+		/* dismiss all pending requests including requests for ERP */
+		zfcp_fsf_req_dismiss_all(adapter);
+		adapter->fsf_req_seq_no = 0;
+	} else
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+	zfcp_erp_adapter_reopen(adapter, 0);
 }
 
 /*
@@ -670,17 +679,10 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	disable I/O,
- *		return any open requests and clean them up,
- *		aim: no pending and incoming I/O
- *
- * returns:
+/**
+ * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests
  */
-static void
-zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
+static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask)
 {
 	debug_text_event(adapter->erp_dbf, 6, "a_bl");
 	zfcp_erp_modify_adapter_status(adapter,
@@ -688,15 +690,10 @@
 				       clear_mask, ZFCP_CLEAR);
 }
 
-/*
- * function:	
- *
- * purpose:	enable I/O
- *
- * returns:
+/**
+ * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests
  */
-static void
-zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
+static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
 {
 	debug_text_event(adapter->erp_dbf, 6, "a_ubl");
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
@@ -848,18 +845,16 @@
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	if (erp_action->fsf_req) {
-		/* take lock to ensure that request is not being deleted meanwhile */
-		spin_lock(&adapter->fsf_req_list_lock);
-		/* check whether fsf req does still exist */
-		list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
-		    if (fsf_req == erp_action->fsf_req)
-			break;
-		if (fsf_req && (fsf_req->erp_action == erp_action)) {
+		/* take lock to ensure that request is not deleted meanwhile */
+		spin_lock(&adapter->req_list_lock);
+		if ((!zfcp_reqlist_ismember(adapter,
+					    erp_action->fsf_req->req_id)) &&
+		    (fsf_req->erp_action == erp_action)) {
 			/* fsf_req still exists */
 			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
 			debug_event(adapter->erp_dbf, 3, &fsf_req,
 				    sizeof (unsigned long));
-			/* dismiss fsf_req of timed out or dismissed erp_action */
+			/* dismiss fsf_req of timed out/dismissed erp_action */
 			if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
 						  ZFCP_STATUS_ERP_TIMEDOUT)) {
 				debug_text_event(adapter->erp_dbf, 3,
@@ -892,30 +887,22 @@
 			 */
 			erp_action->fsf_req = NULL;
 		}
-		spin_unlock(&adapter->fsf_req_list_lock);
+		spin_unlock(&adapter->req_list_lock);
 	} else
 		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
 
 	return retval;
 }
 
-/*
- * purpose:	generic handler for asynchronous events related to erp_action events
- *		(normal completion, time-out, dismissing, retry after
- *		low memory condition)
+/**
+ * zfcp_erp_async_handler_nolock - complete erp_action
  *
- * note:	deletion of timer is not required (e.g. in case of a time-out),
- *		but a second try does no harm,
- *		we leave it in here to allow for greater simplification
- *
- * returns:	0 - there was an action to handle
- *		!0 - otherwise
+ * Used for normal completion, time-out, dismissal and failure after
+ * low memory condition.
  */
-static int
-zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
-			      unsigned long set_mask)
+static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action,
+					  unsigned long set_mask)
 {
-	int retval;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
@@ -926,43 +913,26 @@
 			del_timer(&erp_action->timer);
 		erp_action->status |= set_mask;
 		zfcp_erp_action_ready(erp_action);
-		retval = 0;
 	} else {
 		/* action is ready or gone - nothing to do */
 		debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone");
 		debug_event(adapter->erp_dbf, 3, &erp_action->action,
 			    sizeof (int));
-		retval = 1;
 	}
-
-	return retval;
 }
 
-/*
- * purpose:	generic handler for asynchronous events related to erp_action
- *               events	(normal completion, time-out, dismissing, retry after
- *		low memory condition)
- *
- * note:	deletion of timer is not required (e.g. in case of a time-out),
- *		but a second try does no harm,
- *		we leave it in here to allow for greater simplification
- *
- * returns:	0 - there was an action to handle
- *		!0 - otherwise
+/**
+ * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking
  */
-int
-zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
-		       unsigned long set_mask)
+void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action,
+			    unsigned long set_mask)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 	unsigned long flags;
-	int retval;
 
 	write_lock_irqsave(&adapter->erp_lock, flags);
-	retval = zfcp_erp_async_handler_nolock(erp_action, set_mask);
+	zfcp_erp_async_handler_nolock(erp_action, set_mask);
 	write_unlock_irqrestore(&adapter->erp_lock, flags);
-
-	return retval;
 }
 
 /*
@@ -999,17 +969,15 @@
 	zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT);
 }
 
-/*
- * purpose:	is called for an erp_action which needs to be ended
- *		though not being done,
- *		this is usually required if an higher is generated,
- *		action gets an appropriate flag and will be processed
- *		accordingly
+/**
+ * zfcp_erp_action_dismiss - dismiss an erp_action
  *
- * locks:	erp_lock held (thus we need to call another handler variant)
+ * adapter->erp_lock must be held
+ * 
+ * Dismissal of an erp_action is usually required if an erp_action of
+ * higher priority is generated.
  */
-static int
-zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
+static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action)
 {
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
@@ -1017,8 +985,6 @@
 	debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int));
 
 	zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED);
-
-	return 0;
 }
 
 int
@@ -2074,18 +2040,12 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_qdio_cleanup
- *
- * purpose:	cleans up QDIO operation for the specified adapter
- *
- * returns:	0 - successful cleanup
- *		!0 - failed cleanup
+/**
+ * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter
  */
-int
+static void
 zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action)
 {
-	int retval = ZFCP_ERP_SUCCEEDED;
 	int first_used;
 	int used_count;
 	struct zfcp_adapter *adapter = erp_action->adapter;
@@ -2094,15 +2054,13 @@
 		ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO "
 			       "queues on adapter %s\n",
 			       zfcp_get_busid_by_adapter(adapter));
-		retval = ZFCP_ERP_FAILED;
-		goto out;
+		return;
 	}
 
 	/*
 	 * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that
 	 * do_QDIO won't be called while qdio_shutdown is in progress.
 	 */
-
 	write_lock_irq(&adapter->request_queue.queue_lock);
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
 	write_unlock_irq(&adapter->request_queue.queue_lock);
@@ -2134,8 +2092,6 @@
 	adapter->request_queue.free_index = 0;
 	atomic_set(&adapter->request_queue.free_count, 0);
 	adapter->request_queue.distance_from_int = 0;
- out:
-	return retval;
 }
 
 static int
@@ -2258,11 +2214,11 @@
 			      "%s)\n", zfcp_get_busid_by_adapter(adapter));
 		ret = ZFCP_ERP_FAILED;
 	}
-	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) {
-		ZFCP_LOG_INFO("error: exchange port data failed (adapter "
+
+	/* don't treat as error for the sake of compatibility */
+	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status))
+		ZFCP_LOG_INFO("warning: exchange port data failed (adapter "
 			      "%s\n", zfcp_get_busid_by_adapter(adapter));
-		ret = ZFCP_ERP_FAILED;
-	}
 
 	return ret;
 }
@@ -2292,18 +2248,12 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_cleanup
- *
- * purpose:	cleanup FSF operation for specified adapter
- *
- * returns:	0 - FSF operation successfully cleaned up
- *		!0 - failed to cleanup FSF operation for this adapter
+/**
+ * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter
  */
-static int
+static void
 zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action)
 {
-	int retval = ZFCP_ERP_SUCCEEDED;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	/*
@@ -2317,8 +2267,6 @@
 	/* all ports and units are closed */
 	zfcp_erp_modify_adapter_status(adapter,
 				       ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
-
-	return retval;
 }
 
 /*
@@ -3293,10 +3241,8 @@
 }
 
 
-static int
-zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
+void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 {
-	int retval = 0;
 	struct zfcp_port *port;
 
 	debug_text_event(adapter->erp_dbf, 5, "a_actab");
@@ -3305,14 +3251,10 @@
 	else
 		list_for_each_entry(port, &adapter->port_list_head, list)
 		    zfcp_erp_action_dismiss_port(port);
-
-	return retval;
 }
 
-static int
-zfcp_erp_action_dismiss_port(struct zfcp_port *port)
+static void zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 {
-	int retval = 0;
 	struct zfcp_unit *unit;
 	struct zfcp_adapter *adapter = port->adapter;
 
@@ -3323,22 +3265,16 @@
 	else
 		list_for_each_entry(unit, &port->unit_list_head, list)
 		    zfcp_erp_action_dismiss_unit(unit);
-
-	return retval;
 }
 
-static int
-zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
+static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
 {
-	int retval = 0;
 	struct zfcp_adapter *adapter = unit->port->adapter;
 
 	debug_text_event(adapter->erp_dbf, 5, "u_actab");
 	debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t));
 	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
 		zfcp_erp_action_dismiss(&unit->erp_action);
-
-	return retval;
 }
 
 static inline void
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index d023660..146d7a2 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -63,7 +63,6 @@
 extern void zfcp_qdio_free_queues(struct zfcp_adapter *);
 extern int  zfcp_qdio_determine_pci(struct zfcp_qdio_queue *,
 				    struct zfcp_fsf_req *);
-extern int  zfcp_qdio_reqid_check(struct zfcp_adapter *, void *);
 
 extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
 	(struct zfcp_fsf_req *, int, int);
@@ -140,6 +139,7 @@
 extern int  zfcp_erp_adapter_reopen(struct zfcp_adapter *, int);
 extern int  zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int);
 extern void zfcp_erp_adapter_failed(struct zfcp_adapter *);
+extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *);
 
 extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int);
 extern int  zfcp_erp_port_reopen(struct zfcp_port *, int);
@@ -156,7 +156,7 @@
 extern int  zfcp_erp_thread_setup(struct zfcp_adapter *);
 extern int  zfcp_erp_thread_kill(struct zfcp_adapter *);
 extern int  zfcp_erp_wait(struct zfcp_adapter *);
-extern int  zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
+extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
 
 extern int  zfcp_test_link(struct zfcp_port *);
 
@@ -190,5 +190,10 @@
 				      struct zfcp_fsf_req *);
 extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
 					 struct scsi_cmnd *);
+extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
+extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long);
+extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *,
+						  unsigned long);
+extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
 
 #endif	/* ZFCP_EXT_H */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 31db2b0..ff2eacf 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -49,7 +49,6 @@
 static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
 	struct fsf_link_down_info *);
 static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
-static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
 
 /* association between FSF command and FSF QTCB type */
 static u32 fsf_qtcb_type[] = {
@@ -146,49 +145,50 @@
 		kfree(fsf_req);
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- *
- * note: qdio queues shall be down (no ongoing inbound processing)
+/**
+ * zfcp_fsf_req_dismiss - dismiss a single fsf request
  */
-int
-zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter,
+				 struct zfcp_fsf_req *fsf_req,
+				 unsigned int counter)
 {
-	struct zfcp_fsf_req *fsf_req, *tmp;
-	unsigned long flags;
-	LIST_HEAD(remove_queue);
+	u64 dbg_tmp[2];
 
-	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	list_splice_init(&adapter->fsf_req_list_head, &remove_queue);
-	atomic_set(&adapter->fsf_reqs_active, 0);
-	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-
-	list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) {
-		list_del(&fsf_req->list);
-		zfcp_fsf_req_dismiss(fsf_req);
-	}
-
-	return 0;
-}
-
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
-static void
-zfcp_fsf_req_dismiss(struct zfcp_fsf_req *fsf_req)
-{
+	dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
+	dbg_tmp[1] = (u64) counter;
+	debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+	list_del(&fsf_req->list);
 	fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
 	zfcp_fsf_req_complete(fsf_req);
 }
 
+/**
+ * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
+ */
+int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned long flags;
+	unsigned int i, counter;
+
+	spin_lock_irqsave(&adapter->req_list_lock, flags);
+	atomic_set(&adapter->reqs_active, 0);
+	for (i=0; i<REQUEST_LIST_SIZE; i++) {
+		if (list_empty(&adapter->req_list[i]))
+			continue;
+
+		counter = 0;
+		list_for_each_entry_safe(request, tmp,
+					 &adapter->req_list[i], list) {
+			zfcp_fsf_req_dismiss(adapter, request, counter);
+			counter++;
+		}
+	}
+	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+	return 0;
+}
+
 /*
  * function:    zfcp_fsf_req_complete
  *
@@ -4592,12 +4592,14 @@
 zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
 {
 	if (likely(fsf_req->qtcb != NULL)) {
-		fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no;
-		fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req;
+		fsf_req->qtcb->prefix.req_seq_no =
+			fsf_req->adapter->fsf_req_seq_no;
+		fsf_req->qtcb->prefix.req_id = fsf_req->req_id;
 		fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
-		fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command];
+		fsf_req->qtcb->prefix.qtcb_type =
+			fsf_qtcb_type[fsf_req->fsf_command];
 		fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
-		fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req;
+		fsf_req->qtcb->header.req_handle = fsf_req->req_id;
 		fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command;
 	}
 }
@@ -4654,6 +4656,7 @@
 {
 	volatile struct qdio_buffer_element *sbale;
 	struct zfcp_fsf_req *fsf_req = NULL;
+	unsigned long flags;
 	int ret = 0;
 	struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
 
@@ -4668,6 +4671,12 @@
 
 	fsf_req->adapter = adapter;
 	fsf_req->fsf_command = fsf_cmd;
+	INIT_LIST_HEAD(&fsf_req->list);
+	
+	/* unique request id */
+	spin_lock_irqsave(&adapter->req_list_lock, flags);
+	fsf_req->req_id = adapter->req_no++;
+	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
         zfcp_fsf_req_qtcb_init(fsf_req);
 
@@ -4707,7 +4716,7 @@
 	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
 	/* setup common SBALE fields */
-	sbale[0].addr = fsf_req;
+	sbale[0].addr = (void *) fsf_req->req_id;
 	sbale[0].flags |= SBAL_FLAGS0_COMMAND;
 	if (likely(fsf_req->qtcb != NULL)) {
 		sbale[1].addr = (void *) fsf_req->qtcb;
@@ -4747,7 +4756,7 @@
 	volatile struct qdio_buffer_element *sbale;
 	int inc_seq_no;
 	int new_distance_from_int;
-	unsigned long flags;
+	u64 dbg_tmp[2];
 	int retval = 0;
 
 	adapter = fsf_req->adapter;
@@ -4761,10 +4770,10 @@
 	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr,
 		      sbale[1].length);
 
-	/* put allocated FSF request at list tail */
-	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
-	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+	/* put allocated FSF request into hash table */
+	spin_lock(&adapter->req_list_lock);
+	zfcp_reqlist_add(adapter, fsf_req);
+	spin_unlock(&adapter->req_list_lock);
 
 	inc_seq_no = (fsf_req->qtcb != NULL);
 
@@ -4803,6 +4812,10 @@
 			 QDIO_FLAG_SYNC_OUTPUT,
 			 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
 
+	dbg_tmp[0] = (unsigned long) sbale[0].addr;
+	dbg_tmp[1] = (u64) retval;
+	debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+
 	if (unlikely(retval)) {
 		/* Queues are down..... */
 		retval = -EIO;
@@ -4812,22 +4825,17 @@
 		 */
 		if (timer)
 			del_timer(timer);
-		spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-		list_del(&fsf_req->list);
-		spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-		/*
-		 * adjust the number of free SBALs in request queue as well as
-		 * position of first one
-		 */
+		spin_lock(&adapter->req_list_lock);
+		zfcp_reqlist_remove(adapter, fsf_req->req_id);
+		spin_unlock(&adapter->req_list_lock);
+		/* undo changes in request queue made for this request */
 		zfcp_qdio_zero_sbals(req_queue->buffer,
 				     fsf_req->sbal_first, fsf_req->sbal_number);
 		atomic_add(fsf_req->sbal_number, &req_queue->free_count);
-		req_queue->free_index -= fsf_req->sbal_number;	 /* increase */
+		req_queue->free_index -= fsf_req->sbal_number;
 		req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
 		req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
-		ZFCP_LOG_DEBUG
-			("error: do_QDIO failed. Buffers could not be enqueued "
-			 "to request queue.\n");
+		zfcp_erp_adapter_reopen(adapter, 0);
 	} else {
 		req_queue->distance_from_int = new_distance_from_int;
 		/*
@@ -4843,7 +4851,7 @@
 			adapter->fsf_req_seq_no++;
 
 		/* count FSF requests pending */
-		atomic_inc(&adapter->fsf_reqs_active);
+		atomic_inc(&adapter->reqs_active);
 	}
 	return retval;
 }
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 49ea5ad..dbd9f48 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -282,6 +282,37 @@
 	return;
 }
 
+/**
+ * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status
+ */
+static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, 
+				 unsigned long req_id)
+{
+	struct zfcp_fsf_req *fsf_req;
+	unsigned long flags;
+
+	debug_long_event(adapter->erp_dbf, 4, req_id);
+
+	spin_lock_irqsave(&adapter->req_list_lock, flags);
+	fsf_req = zfcp_reqlist_ismember(adapter, req_id);
+
+	if (!fsf_req) {
+		spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+		ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id);
+		zfcp_erp_adapter_reopen(adapter, 0);
+		return -EINVAL;
+	}
+
+	zfcp_reqlist_remove(adapter, req_id);
+	atomic_dec(&adapter->reqs_active);
+	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+
+	/* finish the FSF request */
+	zfcp_fsf_req_complete(fsf_req);
+
+	return 0;
+}
+
 /*
  * function:   	zfcp_qdio_response_handler
  *
@@ -344,7 +375,7 @@
 			/* look for QDIO request identifiers in SB */
 			buffere = &buffer->element[buffere_index];
 			retval = zfcp_qdio_reqid_check(adapter,
-						       (void *) buffere->addr);
+					(unsigned long) buffere->addr);
 
 			if (retval) {
 				ZFCP_LOG_NORMAL("bug: unexpected inbound "
@@ -415,52 +446,6 @@
 	return;
 }
 
-/*
- * function:	zfcp_qdio_reqid_check
- *
- * purpose:	checks for valid reqids or unsolicited status
- *
- * returns:	0 - valid request id or unsolicited status
- *		!0 - otherwise
- */
-int
-zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
-{
-	struct zfcp_fsf_req *fsf_req;
-	unsigned long flags;
-
-	/* invalid (per convention used in this driver) */
-	if (unlikely(!sbale_addr)) {
-		ZFCP_LOG_NORMAL("bug: invalid reqid\n");
-		return -EINVAL;
-	}
-
-	/* valid request id and thus (hopefully :) valid fsf_req address */
-	fsf_req = (struct zfcp_fsf_req *) sbale_addr;
-
-	/* serialize with zfcp_fsf_req_dismiss_all */
-	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	if (list_empty(&adapter->fsf_req_list_head)) {
-		spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-		return 0;
-	}
-	list_del(&fsf_req->list);
-	atomic_dec(&adapter->fsf_reqs_active);
-	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-
-	if (unlikely(adapter != fsf_req->adapter)) {
-		ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
-				"fsf_req->adapter=%p, adapter=%p)\n",
-				fsf_req, fsf_req->adapter, adapter);
-		return -EINVAL;
-	}
-
-	/* finish the FSF request */
-	zfcp_fsf_req_complete(fsf_req);
-
-	return 0;
-}
-
 /**
  * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue
  * @queue: queue from which SBALE should be returned
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 671f4a6..1bb5508 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -30,7 +30,6 @@
 				  void (*done) (struct scsi_cmnd *));
 static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *);
-static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *);
 static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *);
 static int zfcp_task_management_function(struct zfcp_unit *, u8,
 					 struct scsi_cmnd *);
@@ -46,30 +45,22 @@
 	.scsi_host_template = {
 		.name			= ZFCP_NAME,
 		.proc_name		= "zfcp",
-		.proc_info		= NULL,
-		.detect			= NULL,
 		.slave_alloc		= zfcp_scsi_slave_alloc,
 		.slave_configure	= zfcp_scsi_slave_configure,
 		.slave_destroy		= zfcp_scsi_slave_destroy,
 		.queuecommand		= zfcp_scsi_queuecommand,
 		.eh_abort_handler	= zfcp_scsi_eh_abort_handler,
 		.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
-		.eh_bus_reset_handler	= zfcp_scsi_eh_bus_reset_handler,
+		.eh_bus_reset_handler	= zfcp_scsi_eh_host_reset_handler,
 		.eh_host_reset_handler	= zfcp_scsi_eh_host_reset_handler,
 		.can_queue		= 4096,
 		.this_id		= -1,
-		/*
-		 * FIXME:
-		 * one less? can zfcp_create_sbale cope with it?
-		 */
 		.sg_tablesize		= ZFCP_MAX_SBALES_PER_REQ,
 		.cmd_per_lun		= 1,
-		.unchecked_isa_dma	= 0,
 		.use_clustering		= 1,
 		.sdev_attrs		= zfcp_sysfs_sdev_attrs,
 	},
 	.driver_version = ZFCP_VERSION,
-	/* rest initialised with zeros */
 };
 
 /* Find start of Response Information in FCP response unit*/
@@ -176,8 +167,14 @@
 	return retval;
 }
 
-static void
-zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
+/**
+ * zfcp_scsi_slave_destroy - called when scsi device is removed
+ *
+ * Remove reference to associated scsi device for an zfcp_unit.
+ * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs
+ * or a scan for this device might have failed.
+ */
+static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
 {
 	struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
 
@@ -185,6 +182,7 @@
 		atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
 		sdpnt->hostdata = NULL;
 		unit->device = NULL;
+		zfcp_erp_unit_failed(unit);
 		zfcp_unit_put(unit);
 	} else {
 		ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at "
@@ -549,35 +547,38 @@
 }
 
 /**
- * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter)
+ * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
+ *
+ * If ERP is already running it will be stopped.
  */
-int
-zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
+int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
-	struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
+	struct zfcp_unit *unit;
+	struct zfcp_adapter *adapter;
+	unsigned long flags;
 
-	ZFCP_LOG_NORMAL("bus reset because of problems with "
+	unit = (struct zfcp_unit*) scpnt->device->hostdata;
+	adapter = unit->port->adapter;
+
+	ZFCP_LOG_NORMAL("host/bus reset because of problems with "
 			"unit 0x%016Lx\n", unit->fcp_lun);
-	zfcp_erp_adapter_reopen(adapter, 0);
-	zfcp_erp_wait(adapter);
 
-	return SUCCESS;
-}
-
-/**
- * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter)
- */
-int
-zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
-{
-	struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;
-	struct zfcp_adapter *adapter = unit->port->adapter;
-
-	ZFCP_LOG_NORMAL("host reset because of problems with "
-			"unit 0x%016Lx\n", unit->fcp_lun);
-	zfcp_erp_adapter_reopen(adapter, 0);
-	zfcp_erp_wait(adapter);
+	write_lock_irqsave(&adapter->erp_lock, flags);
+	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING,
+			     &adapter->status)) {
+		zfcp_erp_modify_adapter_status(adapter,
+		       ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN,
+		       ZFCP_CLEAR);
+		zfcp_erp_action_dismiss_adapter(adapter);
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+		zfcp_fsf_req_dismiss_all(adapter);
+		adapter->fsf_req_seq_no = 0;
+		zfcp_erp_adapter_reopen(adapter, 0);
+	} else {
+		write_unlock_irqrestore(&adapter->erp_lock, flags);
+		zfcp_erp_adapter_reopen(adapter, 0);
+		zfcp_erp_wait(adapter);
+	}
 
 	return SUCCESS;
 }
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 77e7202a..904c25f 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -940,14 +940,8 @@
 		return;
 
 	/* ignore interim PIO setup fis interrupts */
-	if (ata_tag_valid(ap->active_tag)) {
-		struct ata_queued_cmd *qc =
-			ata_qc_from_tag(ap, ap->active_tag);
-
-		if (qc && qc->tf.protocol == ATA_PROT_PIO &&
-		    (status & PORT_IRQ_PIOS_FIS))
-			return;
-	}
+	if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) 
+		return;
 
 	if (ata_ratelimit())
 		ata_port_printk(ap, KERN_INFO, "spurious interrupt "
diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
index 8c91fda..b98c5c1 100644
--- a/drivers/scsi/aic7xxx/aicasm/Makefile
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile
@@ -14,6 +14,8 @@
 clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG)
 # Override default kernel CFLAGS.  This is a userland app.
 AICASM_CFLAGS:= -I/usr/include -I.
+LEX= flex
+YACC= bison
 YFLAGS= -d
 
 NOMAN=	noman
diff --git a/drivers/scsi/arm/Kconfig b/drivers/scsi/arm/Kconfig
index 06d7601..d006a8c 100644
--- a/drivers/scsi/arm/Kconfig
+++ b/drivers/scsi/arm/Kconfig
@@ -69,6 +69,7 @@
 config SCSI_CUMANA_1
 	tristate "CumanaSCSI I support (EXPERIMENTAL)"
 	depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This enables support for the Cumana SCSI I card. If you have an
 	  Acorn system with one of these, say Y. If unsure, say N.
@@ -76,6 +77,7 @@
 config SCSI_ECOSCSI
 	tristate "EcoScsi support (EXPERIMENTAL)"
 	depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This enables support for the EcoSCSI card -- a small card that sits
 	  in the Econet socket. If you have an Acorn system with one of these,
@@ -84,6 +86,7 @@
 config SCSI_OAK1
 	tristate "Oak SCSI support (EXPERIMENTAL)"
 	depends on ARCH_ACORN && EXPERIMENTAL && SCSI
+	select SCSI_SPI_ATTRS
 	help
 	  This enables support for the Oak SCSI card. If you have an Acorn
 	  system with one of these, say Y. If unsure, say N.
diff --git a/drivers/scsi/arm/scsi.h b/drivers/scsi/arm/scsi.h
index 6dd544a..8c2600f 100644
--- a/drivers/scsi/arm/scsi.h
+++ b/drivers/scsi/arm/scsi.h
@@ -74,7 +74,7 @@
 		unsigned long len = 0;
 		int buf;
 
-		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
+		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
 		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
 		SCpnt->SCp.ptr = (char *)
 			 (page_address(SCpnt->SCp.buffer->page) +
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 19745a3..a9bb3cb 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -123,7 +123,8 @@
 	ich6_sata		= 4,
 	ich6_sata_ahci		= 5,
 	ich6m_sata_ahci		= 6,
-	ich8_sata_ahci		= 7,
+	ich7m_sata_ahci		= 7,
+	ich8_sata_ahci		= 8,
 
 	/* constants for mapping table */
 	P0			= 0,  /* port 0 */
@@ -188,7 +189,7 @@
 	/* 82801GB/GR/GH (ICH7, identical to ICH6) */
 	{ 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	/* 2801GBM/GHM (ICH7M, identical to ICH6M) */
-	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci },
+	{ 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7m_sata_ahci },
 	/* Enterprise Southbridge 2 (where's the datasheet?) */
 	{ 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci },
 	/* SATA Controller 1 IDE (ICH8, no datasheet yet) */
@@ -336,6 +337,24 @@
 	},
 };
 
+static const struct piix_map_db ich7m_map_db = {
+	.mask = 0x3,
+	.port_enable = 0x5,
+	.present_shift = 4,
+
+	/* Map 01b isn't specified in the doc but some notebooks use
+	 * it anyway.  ATM, the only case spotted carries subsystem ID
+	 * 1025:0107.  This is the only difference from ich6m.
+	 */
+	.map = {
+		/* PM   PS   SM   SS       MAP */
+		{  P0,  P2,  RV,  RV }, /* 00b */
+		{ IDE, IDE,  P1,  P3 }, /* 01b */
+		{  P0,  P2, IDE, IDE }, /* 10b */
+		{  RV,  RV,  RV,  RV },
+	},
+};
+
 static const struct piix_map_db ich8_map_db = {
 	.mask = 0x3,
 	.port_enable = 0x3,
@@ -355,6 +374,7 @@
 	[ich6_sata]		= &ich6_map_db,
 	[ich6_sata_ahci]	= &ich6_map_db,
 	[ich6m_sata_ahci]	= &ich6m_map_db,
+	[ich7m_sata_ahci]	= &ich7m_map_db,
 	[ich8_sata_ahci]	= &ich8_map_db,
 };
 
@@ -390,7 +410,8 @@
 	/* ich5_sata */
 	{
 		.sht		= &piix_sht,
-		.host_flags	= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+		.host_flags	= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR |
+				  PIIX_FLAG_IGNORE_PCS,
 		.pio_mask	= 0x1f,	/* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f,	/* udma0-6 */
@@ -443,6 +464,18 @@
 		.port_ops	= &piix_sata_ops,
 	},
 
+	/* ich7m_sata_ahci */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA |
+				  PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR |
+				  PIIX_FLAG_AHCI,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+
 	/* ich8_sata_ahci */
 	{
 		.sht		= &piix_sht,
@@ -467,6 +500,11 @@
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+static int force_pcs = 0;
+module_param(force_pcs, int, 0444);
+MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around "
+		 "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)");
+
 /**
  *	piix_pata_cbl_detect - Probe host controller cable detect info
  *	@ap: Port for which cable detect info is desired
@@ -531,27 +569,25 @@
 }
 
 /**
- *	piix_sata_prereset - prereset for SATA host controller
+ *	piix_sata_present_mask - determine present mask for SATA host controller
  *	@ap: Target port
  *
- *	Reads and configures SATA PCI device's PCI config register
- *	Port Configuration and Status (PCS) to determine port and
- *	device availability.  Return -ENODEV to skip reset if no
- *	device is present.
+ *	Reads SATA PCI device's PCI config register Port Configuration
+ *	and Status (PCS) to determine port and device availability.
  *
  *	LOCKING:
  *	None (inherited from caller).
  *
  *	RETURNS:
- *	0 if device is present, -ENODEV otherwise.
+ *	determined present_mask
  */
-static int piix_sata_prereset(struct ata_port *ap)
+static unsigned int piix_sata_present_mask(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 	struct piix_host_priv *hpriv = ap->host_set->private_data;
 	const unsigned int *map = hpriv->map;
 	int base = 2 * ap->hard_port_no;
-	unsigned int present = 0;
+	unsigned int present_mask = 0;
 	int port, i;
 	u16 pcs;
 
@@ -564,24 +600,52 @@
 			continue;
 		if ((ap->flags & PIIX_FLAG_IGNORE_PCS) ||
 		    (pcs & 1 << (hpriv->map_db->present_shift + port)))
-			present = 1;
+			present_mask |= 1 << i;
 	}
 
 	DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
 		ap->id, pcs, present_mask);
 
-	if (!present) {
-		ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
-		ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
-		return 0;
+	return present_mask;
+}
+
+/**
+ *	piix_sata_softreset - reset SATA host port via ATA SRST
+ *	@ap: port to reset
+ *	@classes: resulting classes of attached devices
+ *
+ *	Reset SATA host port via ATA SRST.  On controllers with
+ *	reliable PCS present bits, the bits are used to determine
+ *	device presence.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise.
+ */
+static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes)
+{
+	unsigned int present_mask;
+	int i, rc;
+
+	present_mask = piix_sata_present_mask(ap);
+
+	rc = ata_std_softreset(ap, classes);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		if (!(present_mask & (1 << i)))
+			classes[i] = ATA_DEV_NONE;
 	}
 
-	return ata_std_prereset(ap);
+	return 0;
 }
 
 static void piix_sata_error_handler(struct ata_port *ap)
 {
-	ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
+	ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL,
 			   ata_std_postreset);
 }
 
@@ -785,6 +849,7 @@
 }
 
 static void __devinit piix_init_pcs(struct pci_dev *pdev,
+				    struct ata_port_info *pinfo,
 				    const struct piix_map_db *map_db)
 {
 	u16 pcs, new_pcs;
@@ -798,6 +863,18 @@
 		pci_write_config_word(pdev, ICH5_PCS, new_pcs);
 		msleep(150);
 	}
+
+	if (force_pcs == 1) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "force ignoring PCS (0x%x)\n", new_pcs);
+		pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS;
+		pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS;
+	} else if (force_pcs == 2) {
+		dev_printk(KERN_INFO, &pdev->dev,
+			   "force honoring PCS (0x%x)\n", new_pcs);
+		pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
+		pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS;
+	}
 }
 
 static void __devinit piix_init_sata_map(struct pci_dev *pdev,
@@ -828,6 +905,7 @@
 		case IDE:
 			WARN_ON((i & 1) || map[i + 1] != IDE);
 			pinfo[i / 2] = piix_port_info[ich5_pata];
+			pinfo[i / 2].private_data = hpriv;
 			i++;
 			printk(" IDE IDE");
 			break;
@@ -905,7 +983,8 @@
 	if (host_flags & ATA_FLAG_SATA) {
 		piix_init_sata_map(pdev, port_info,
 				   piix_map_db_table[ent->driver_data]);
-		piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]);
+		piix_init_pcs(pdev, port_info,
+			      piix_map_db_table[ent->driver_data]);
 	}
 
 	/* On ICH5, some BIOSen disable the interrupt using the
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 98bd227..5630868 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1146,7 +1146,7 @@
 static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
 {
 	if (sun4_esp_physaddr) {
-		memset(&sun4_esp_dev, 0, sizeof(esp_dev));
+		memset(&sun4_esp_dev, 0, sizeof(sun4_esp_dev));
 		sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
 		sun4_esp_dev.irqs[0] = 4;
 		sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
@@ -1162,6 +1162,7 @@
 
 static int __devexit esp_sun4_remove(void)
 {
+	struct of_device *dev = &sun4_esp_dev.ofdev;
 	struct esp *esp = dev_get_drvdata(&dev->dev);
 
 	return esp_remove_common(esp);
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index ab2f8b2..bcb3444f 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -45,10 +45,6 @@
 static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
 static const char driver_ver[] = "v1.0 (060426)";
 
-static DEFINE_SPINLOCK(hptiop_hba_list_lock);
-static LIST_HEAD(hptiop_hba_list);
-static int hptiop_cdev_major = -1;
-
 static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag);
 static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag);
 static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
@@ -577,7 +573,7 @@
 	if (atomic_xchg(&hba->resetting, 1) == 0) {
 		atomic_inc(&hba->reset_count);
 		writel(IOPMU_INBOUND_MSG0_RESET,
-				&hba->iop->outbound_msgaddr0);
+				&hba->iop->inbound_msgaddr0);
 		hptiop_pci_posting_flush(hba->iop);
 	}
 
@@ -620,532 +616,11 @@
 	return queue_depth;
 }
 
-struct hptiop_getinfo {
-	char __user *buffer;
-	loff_t buflength;
-	loff_t bufoffset;
-	loff_t buffillen;
-	loff_t filpos;
-};
-
-static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo,
-					char *data, int datalen)
-{
-	if (pinfo->filpos < pinfo->bufoffset) {
-		if (pinfo->filpos + datalen <= pinfo->bufoffset) {
-			pinfo->filpos += datalen;
-			return;
-		} else {
-			data += (pinfo->bufoffset - pinfo->filpos);
-			datalen  -= (pinfo->bufoffset - pinfo->filpos);
-			pinfo->filpos = pinfo->bufoffset;
-		}
-	}
-
-	pinfo->filpos += datalen;
-	if (pinfo->buffillen == pinfo->buflength)
-		return;
-
-	if (pinfo->buflength - pinfo->buffillen < datalen)
-		datalen = pinfo->buflength - pinfo->buffillen;
-
-	if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen))
-		return;
-
-	pinfo->buffillen += datalen;
-}
-
-static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...)
-{
-	va_list args;
-	char buf[128];
-	int len;
-
-	va_start(args, fmt);
-	len = vsnprintf(buf, sizeof(buf), fmt, args);
-	va_end(args);
-	hptiop_copy_mem_info(pinfo, buf, len);
-	return len;
-}
-
-static void hptiop_ioctl_done(struct hpt_ioctl_k *arg)
-{
-	arg->done = NULL;
-	wake_up(&arg->hba->ioctl_wq);
-}
-
-static void hptiop_do_ioctl(struct hpt_ioctl_k *arg)
-{
-	struct hptiop_hba *hba = arg->hba;
-	u32 val;
-	struct hpt_iop_request_ioctl_command __iomem *req;
-	int ioctl_retry = 0;
-
-	dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no);
-
-	/*
-	 * check (in + out) buff size from application.
-	 * outbuf must be dword aligned.
-	 */
-	if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size >
-			hba->max_request_size
-				- sizeof(struct hpt_iop_request_header)
-				- 4 * sizeof(u32)) {
-		dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n",
-				hba->host->host_no,
-				arg->inbuf_size, arg->outbuf_size);
-		arg->result = HPT_IOCTL_RESULT_FAILED;
-		return;
-	}
-
-retry:
-	spin_lock_irq(hba->host->host_lock);
-
-	val = readl(&hba->iop->inbound_queue);
-	if (val == IOPMU_QUEUE_EMPTY) {
-		spin_unlock_irq(hba->host->host_lock);
-		dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no);
-		arg->result = -1;
-		return;
-	}
-
-	req = (struct hpt_iop_request_ioctl_command __iomem *)
-			((unsigned long)hba->iop + val);
-
-	writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code),
-			&req->ioctl_code);
-	writel(arg->inbuf_size, &req->inbuf_size);
-	writel(arg->outbuf_size, &req->outbuf_size);
-
-	/*
-	 * use the buffer on the IOP local memory first, then copy it
-	 * back to host.
-	 * the caller's request buffer shoudl be little-endian.
-	 */
-	if (arg->inbuf_size)
-		memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size);
-
-	/* correct the controller ID for IOP */
-	if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO ||
-		arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 ||
-		arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO)
-		&& arg->inbuf_size >= sizeof(u32))
-		writel(0, req->buf);
-
-	writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type);
-	writel(0, &req->header.flags);
-	writel(offsetof(struct hpt_iop_request_ioctl_command, buf)
-			+ arg->inbuf_size, &req->header.size);
-	writel((u32)(unsigned long)arg, &req->header.context);
-	writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0,
-			&req->header.context_hi32);
-	writel(IOP_RESULT_PENDING, &req->header.result);
-
-	arg->result = HPT_IOCTL_RESULT_FAILED;
-	arg->done = hptiop_ioctl_done;
-
-	writel(val, &hba->iop->inbound_queue);
-	hptiop_pci_posting_flush(hba->iop);
-
-	spin_unlock_irq(hba->host->host_lock);
-
-	wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ);
-
-	if (arg->done != NULL) {
-		hptiop_reset_hba(hba);
-		if (ioctl_retry++ < 3)
-			goto retry;
-	}
-
-	dprintk("hpt_iop_ioctl %x result %d\n",
-			arg->ioctl_code, arg->result);
-}
-
-static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf,
-			u32 insize, void *outbuf, u32 outsize)
-{
-	struct hpt_ioctl_k arg;
-	arg.hba = hba;
-	arg.ioctl_code = code;
-	arg.inbuf = inbuf;
-	arg.outbuf = outbuf;
-	arg.inbuf_size = insize;
-	arg.outbuf_size = outsize;
-	arg.bytes_returned = NULL;
-	hptiop_do_ioctl(&arg);
-	return arg.result;
-}
-
-static inline int hpt_id_valid(__le32 id)
-{
-	return id != 0 && id != cpu_to_le32(0xffffffff);
-}
-
-static int hptiop_get_controller_info(struct hptiop_hba *hba,
-					struct hpt_controller_info *pinfo)
-{
-	int id = 0;
-
-	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO,
-		&id, sizeof(int), pinfo, sizeof(*pinfo));
-}
-
-
-static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus,
-					struct hpt_channel_info *pinfo)
-{
-	u32 ids[2];
-
-	ids[0] = 0;
-	ids[1] = bus;
-	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO,
-				ids, sizeof(ids), pinfo, sizeof(*pinfo));
-
-}
-
-static int hptiop_get_logical_devices(struct hptiop_hba *hba,
-					__le32 *pids, int maxcount)
-{
-	int i;
-	u32 count = maxcount - 1;
-
-	if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES,
-			&count, sizeof(u32),
-			pids, sizeof(u32) * maxcount))
-		return -1;
-
-	maxcount = le32_to_cpu(pids[0]);
-	for (i = 0; i < maxcount; i++)
-		pids[i] = pids[i+1];
-
-	return maxcount;
-}
-
-static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id,
-				struct hpt_logical_device_info_v3 *pinfo)
-{
-	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3,
-				&id, sizeof(u32),
-				pinfo, sizeof(*pinfo));
-}
-
-static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo)
-{
-	static char s[64];
-	u32 flags = le32_to_cpu(devinfo->u.array.flags);
-	u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress);
-	u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress);
-
-	if (flags & ARRAY_FLAG_DISABLED)
-		return "Disabled";
-	else if (flags & ARRAY_FLAG_TRANSFORMING)
-		sprintf(s, "Expanding/Migrating %d.%d%%%s%s",
-			trans_prog / 100,
-			trans_prog % 100,
-			(flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))?
-					", Critical" : "",
-			((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
-			 !(flags & ARRAY_FLAG_REBUILDING) &&
-			 !(flags & ARRAY_FLAG_INITIALIZING))?
-					", Unintialized" : "");
-	else if ((flags & ARRAY_FLAG_BROKEN) &&
-				devinfo->u.array.array_type != AT_RAID6)
-		return "Critical";
-	else if (flags & ARRAY_FLAG_REBUILDING)
-		sprintf(s,
-			(flags & ARRAY_FLAG_NEEDINITIALIZING)?
-				"%sBackground initializing %d.%d%%" :
-					"%sRebuilding %d.%d%%",
-			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
-			reb_prog / 100,
-			reb_prog % 100);
-	else if (flags & ARRAY_FLAG_VERIFYING)
-		sprintf(s, "%sVerifying %d.%d%%",
-			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
-			reb_prog / 100,
-			reb_prog % 100);
-	else if (flags & ARRAY_FLAG_INITIALIZING)
-		sprintf(s, "%sForground initializing %d.%d%%",
-			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
-			reb_prog / 100,
-			reb_prog % 100);
-	else if (flags & ARRAY_FLAG_NEEDTRANSFORM)
-		sprintf(s,"%s%s%s", "Need Expanding/Migrating",
-			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
-			((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
-			 !(flags & ARRAY_FLAG_REBUILDING) &&
-			 !(flags & ARRAY_FLAG_INITIALIZING))?
-				", Unintialized" : "");
-	else if (flags & ARRAY_FLAG_NEEDINITIALIZING &&
-		!(flags & ARRAY_FLAG_REBUILDING) &&
-		!(flags & ARRAY_FLAG_INITIALIZING))
-		sprintf(s,"%sUninitialized",
-			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "");
-	else if ((flags & ARRAY_FLAG_NEEDBUILDING) ||
-			(flags & ARRAY_FLAG_BROKEN))
-		return "Critical";
-	else
-		return "Normal";
-	return s;
-}
-
-static void hptiop_dump_devinfo(struct hptiop_hba *hba,
-			struct hptiop_getinfo *pinfo, __le32 id, int indent)
-{
-	struct hpt_logical_device_info_v3 devinfo;
-	int i;
-	u64 capacity;
-
-	for (i = 0; i < indent; i++)
-		hptiop_copy_info(pinfo, "\t");
-
-	if (hptiop_get_device_info_v3(hba, id, &devinfo)) {
-		hptiop_copy_info(pinfo, "unknown\n");
-		return;
-	}
-
-	switch (devinfo.type) {
-
-	case LDT_DEVICE: {
-		struct hd_driveid *driveid;
-		u32 flags = le32_to_cpu(devinfo.u.device.flags);
-
-		driveid = (struct hd_driveid *)devinfo.u.device.ident;
-		/* model[] is 40 chars long, but we just want 20 chars here */
-		driveid->model[20] = 0;
-
-		if (indent)
-			if (flags & DEVICE_FLAG_DISABLED)
-				hptiop_copy_info(pinfo,"Missing\n");
-			else
-				hptiop_copy_info(pinfo, "CH%d %s\n",
-					devinfo.u.device.path_id + 1,
-					driveid->model);
-		else {
-			capacity = le64_to_cpu(devinfo.capacity) * 512;
-			do_div(capacity, 1000000);
-			hptiop_copy_info(pinfo,
-				"CH%d %s, %lluMB, %s %s%s%s%s\n",
-				devinfo.u.device.path_id + 1,
-				driveid->model,
-				capacity,
-				(flags & DEVICE_FLAG_DISABLED)?
-					"Disabled" : "Normal",
-				devinfo.u.device.read_ahead_enabled?
-						"[RA]" : "",
-				devinfo.u.device.write_cache_enabled?
-						"[WC]" : "",
-				devinfo.u.device.TCQ_enabled?
-						"[TCQ]" : "",
-				devinfo.u.device.NCQ_enabled?
-						"[NCQ]" : ""
-			);
-		}
-		break;
-	}
-
-	case LDT_ARRAY:
-		if (devinfo.target_id != INVALID_TARGET_ID)
-			hptiop_copy_info(pinfo, "[DISK %d_%d] ",
-					devinfo.vbus_id, devinfo.target_id);
-
-		capacity = le64_to_cpu(devinfo.capacity) * 512;
-		do_div(capacity, 1000000);
-		hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n",
-			devinfo.u.array.name,
-			devinfo.u.array.array_type==AT_RAID0? "RAID0" :
-				devinfo.u.array.array_type==AT_RAID1? "RAID1" :
-				devinfo.u.array.array_type==AT_RAID5? "RAID5" :
-				devinfo.u.array.array_type==AT_RAID6? "RAID6" :
-				devinfo.u.array.array_type==AT_JBOD? "JBOD" :
-					"unknown",
-			capacity,
-			get_array_status(&devinfo));
-		for (i = 0; i < devinfo.u.array.ndisk; i++) {
-			if (hpt_id_valid(devinfo.u.array.members[i])) {
-				if (cpu_to_le16(1<<i) &
-					devinfo.u.array.critical_members)
-					hptiop_copy_info(pinfo, "\t*");
-				hptiop_dump_devinfo(hba, pinfo,
-					devinfo.u.array.members[i], indent+1);
-			}
-			else
-				hptiop_copy_info(pinfo, "\tMissing\n");
-		}
-		if (id == devinfo.u.array.transform_source) {
-			hptiop_copy_info(pinfo, "\tExpanding/Migrating to:\n");
-			hptiop_dump_devinfo(hba, pinfo,
-				devinfo.u.array.transform_target, indent+1);
-		}
-		break;
-	}
-}
-
 static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
 }
 
-static ssize_t hptiop_cdev_read(struct file *filp, char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	struct hptiop_hba *hba = filp->private_data;
-	struct hptiop_getinfo info;
-	int i, j, ndev;
-	struct hpt_controller_info con_info;
-	struct hpt_channel_info chan_info;
-	__le32 ids[32];
-
-	info.buffer     = buf;
-	info.buflength  = count;
-	info.bufoffset  = ppos ? *ppos : 0;
-	info.filpos     = 0;
-	info.buffillen  = 0;
-
-	if (hptiop_get_controller_info(hba, &con_info))
-		return -EIO;
-
-	for (i = 0; i < con_info.num_buses; i++) {
-		if (hptiop_get_channel_info(hba, i, &chan_info) == 0) {
-			if (hpt_id_valid(chan_info.devices[0]))
-				hptiop_dump_devinfo(hba, &info,
-						chan_info.devices[0], 0);
-			if (hpt_id_valid(chan_info.devices[1]))
-				hptiop_dump_devinfo(hba, &info,
-						chan_info.devices[1], 0);
-		}
-	}
-
-	ndev = hptiop_get_logical_devices(hba, ids,
-					sizeof(ids) / sizeof(ids[0]));
-
-	/*
-	 * if hptiop_get_logical_devices fails, ndev==-1 and it just
-	 * output nothing here
-	 */
-	for (j = 0; j < ndev; j++)
-		hptiop_dump_devinfo(hba, &info, ids[j], 0);
-
-	if (ppos)
-		*ppos += info.buffillen;
-
-	return info.buffillen;
-}
-
-static int hptiop_cdev_ioctl(struct inode *inode,  struct file *file,
-					unsigned int cmd, unsigned long arg)
-{
-	struct hptiop_hba *hba = file->private_data;
-	struct hpt_ioctl_u ioctl_u;
-	struct hpt_ioctl_k ioctl_k;
-	u32 bytes_returned;
-	int err = -EINVAL;
-
-	if (copy_from_user(&ioctl_u,
-		(void __user *)arg, sizeof(struct hpt_ioctl_u)))
-		return -EINVAL;
-
-	if (ioctl_u.magic != HPT_IOCTL_MAGIC)
-		return -EINVAL;
-
-	ioctl_k.ioctl_code = ioctl_u.ioctl_code;
-	ioctl_k.inbuf = NULL;
-	ioctl_k.inbuf_size = ioctl_u.inbuf_size;
-	ioctl_k.outbuf = NULL;
-	ioctl_k.outbuf_size = ioctl_u.outbuf_size;
-	ioctl_k.hba = hba;
-	ioctl_k.bytes_returned = &bytes_returned;
-
-	/* verify user buffer */
-	if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ,
-			ioctl_u.inbuf, ioctl_k.inbuf_size)) ||
-		(ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE,
-			ioctl_u.outbuf, ioctl_k.outbuf_size)) ||
-		(ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE,
-			ioctl_u.bytes_returned, sizeof(u32))) ||
-		ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) {
-
-		dprintk("scsi%d: got bad user address\n", hba->host->host_no);
-		return -EINVAL;
-	}
-
-	/* map buffer to kernel. */
-	if (ioctl_k.inbuf_size) {
-		ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL);
-		if (!ioctl_k.inbuf) {
-			dprintk("scsi%d: fail to alloc inbuf\n",
-					hba->host->host_no);
-			err = -ENOMEM;
-			goto err_exit;
-		}
-
-		if (copy_from_user(ioctl_k.inbuf,
-				ioctl_u.inbuf, ioctl_k.inbuf_size)) {
-			goto err_exit;
-		}
-	}
-
-	if (ioctl_k.outbuf_size) {
-		ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL);
-		if (!ioctl_k.outbuf) {
-			dprintk("scsi%d: fail to alloc outbuf\n",
-					hba->host->host_no);
-			err = -ENOMEM;
-			goto err_exit;
-		}
-	}
-
-	hptiop_do_ioctl(&ioctl_k);
-
-	if (ioctl_k.result == HPT_IOCTL_RESULT_OK) {
-		if (ioctl_k.outbuf_size &&
-			copy_to_user(ioctl_u.outbuf,
-				ioctl_k.outbuf, ioctl_k.outbuf_size))
-			goto err_exit;
-
-		if (ioctl_u.bytes_returned &&
-			copy_to_user(ioctl_u.bytes_returned,
-				&bytes_returned, sizeof(u32)))
-			goto err_exit;
-
-		err = 0;
-	}
-
-err_exit:
-	kfree(ioctl_k.inbuf);
-	kfree(ioctl_k.outbuf);
-
-	return err;
-}
-
-static int hptiop_cdev_open(struct inode *inode, struct file *file)
-{
-	struct hptiop_hba *hba;
-	unsigned i = 0, minor = iminor(inode);
-	int ret = -ENODEV;
-
-	spin_lock(&hptiop_hba_list_lock);
-	list_for_each_entry(hba, &hptiop_hba_list, link) {
-		if (i == minor) {
-			file->private_data = hba;
-			ret = 0;
-			goto out;
-		}
-		i++;
-	}
-
-out:
-	spin_unlock(&hptiop_hba_list_lock);
-	return ret;
-}
-
-static struct file_operations hptiop_cdev_fops = {
-	.owner = THIS_MODULE,
-	.read  = hptiop_cdev_read,
-	.ioctl = hptiop_cdev_ioctl,
-	.open  = hptiop_cdev_open,
-};
-
 static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
 {
 	struct Scsi_Host *host = class_to_shost(class_dev);
@@ -1296,19 +771,13 @@
 		goto unmap_pci_bar;
 	}
 
-	if (scsi_add_host(host, &pcidev->dev)) {
-		printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
-					hba->host->host_no);
-		goto unmap_pci_bar;
-	}
-
 	pci_set_drvdata(pcidev, host);
 
 	if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED,
 					driver_name, hba)) {
 		printk(KERN_ERR "scsi%d: request irq %d failed\n",
 					hba->host->host_no, pcidev->irq);
-		goto remove_scsi_host;
+		goto unmap_pci_bar;
 	}
 
 	/* Allocate request mem */
@@ -1355,9 +824,12 @@
 	if (hptiop_initialize_iop(hba))
 		goto free_request_mem;
 
-	spin_lock(&hptiop_hba_list_lock);
-	list_add_tail(&hba->link, &hptiop_hba_list);
-	spin_unlock(&hptiop_hba_list_lock);
+	if (scsi_add_host(host, &pcidev->dev)) {
+		printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
+					hba->host->host_no);
+		goto free_request_mem;
+	}
+
 
 	scsi_scan_host(host);
 
@@ -1372,9 +844,6 @@
 free_request_irq:
 	free_irq(hba->pcidev->irq, hba);
 
-remove_scsi_host:
-	scsi_remove_host(host);
-
 unmap_pci_bar:
 	iounmap(hba->iop);
 
@@ -1422,10 +891,6 @@
 
 	scsi_remove_host(host);
 
-	spin_lock(&hptiop_hba_list_lock);
-	list_del_init(&hba->link);
-	spin_unlock(&hptiop_hba_list_lock);
-
 	hptiop_shutdown(pcidev);
 
 	free_irq(hba->pcidev->irq, hba);
@@ -1462,27 +927,12 @@
 
 static int __init hptiop_module_init(void)
 {
-	int error;
-
 	printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver);
-
-	error = pci_register_driver(&hptiop_pci_driver);
-	if (error < 0)
-		return error;
-
-	hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops);
-	if (hptiop_cdev_major < 0) {
-		printk(KERN_WARNING "unable to register hptiop device.\n");
-		return hptiop_cdev_major;
-	}
-
-	return 0;
+	return pci_register_driver(&hptiop_pci_driver);
 }
 
 static void __exit hptiop_module_exit(void)
 {
-	dprintk("hptiop_module_exit\n");
-	unregister_chrdev(hptiop_cdev_major, "hptiop");
 	pci_unregister_driver(&hptiop_pci_driver);
 }
 
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f7b5d73..94d1de5 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -517,7 +517,7 @@
 		/* No more interrupts */
 		if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
 			printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-		local_irq_enable();
+		local_irq_enable_in_hardirq();
 		if (status.b.check)
 			rq->errors++;
 		idescsi_end_request (drive, 1, 0);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 848fb2a..058f094 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -43,13 +43,10 @@
 
 #include "iscsi_tcp.h"
 
-#define ISCSI_TCP_VERSION "1.0-595"
-
 MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
 	      "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(ISCSI_TCP_VERSION);
 /* #define DEBUG_TCP */
 #define DEBUG_ASSERT
 
@@ -185,11 +182,19 @@
  * must be called with session lock
  */
 static void
-__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_r2t_info *r2t;
 	struct scsi_cmnd *sc;
 
+	/* flush ctask's r2t queues */
+	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+			    sizeof(void*));
+		debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n");
+	}
+
 	sc = ctask->sc;
 	if (unlikely(!sc))
 		return;
@@ -374,6 +379,7 @@
 		spin_unlock(&session->lock);
 		return 0;
 	}
+
 	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
 	BUG_ON(!rc);
 
@@ -399,7 +405,7 @@
 	tcp_ctask->exp_r2tsn = r2tsn + 1;
 	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
 	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
+	list_move_tail(&ctask->running, &conn->xmitqueue);
 
 	scsi_queue_work(session->host, &conn->xmitwork);
 	conn->r2t_pdus_cnt++;
@@ -477,6 +483,8 @@
 	case ISCSI_OP_SCSI_DATA_IN:
 		tcp_conn->in.ctask = session->cmds[itt];
 		rc = iscsi_data_rsp(conn, tcp_conn->in.ctask);
+		if (rc)
+			return rc;
 		/* fall through */
 	case ISCSI_OP_SCSI_CMD_RSP:
 		tcp_conn->in.ctask = session->cmds[itt];
@@ -484,7 +492,7 @@
 			goto copy_hdr;
 
 		spin_lock(&session->lock);
-		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
+		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
 		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
 		spin_unlock(&session->lock);
 		break;
@@ -500,13 +508,28 @@
 		break;
 	case ISCSI_OP_LOGIN_RSP:
 	case ISCSI_OP_TEXT_RSP:
-	case ISCSI_OP_LOGOUT_RSP:
-	case ISCSI_OP_NOOP_IN:
 	case ISCSI_OP_REJECT:
 	case ISCSI_OP_ASYNC_EVENT:
+		/*
+		 * It is possible that we could get a PDU with a buffer larger
+		 * than 8K, but there are no targets that currently do this.
+		 * For now we fail until we find a vendor that needs it
+		 */
+		if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH <
+		    tcp_conn->in.datalen) {
+			printk(KERN_ERR "iscsi_tcp: received buffer of len %u "
+			      "but conn buffer is only %u (opcode %0x)\n",
+			      tcp_conn->in.datalen,
+			      DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode);
+			rc = ISCSI_ERR_PROTO;
+			break;
+		}
+
 		if (tcp_conn->in.datalen)
 			goto copy_hdr;
 	/* fall through */
+	case ISCSI_OP_LOGOUT_RSP:
+	case ISCSI_OP_NOOP_IN:
 	case ISCSI_OP_SCSI_TMFUNC_RSP:
 		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
 		break;
@@ -523,7 +546,7 @@
 	 * skbs to complete the command then we have to copy the header
 	 * for later use
 	 */
-	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <
+	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <=
 	   (tcp_conn->in.datalen + tcp_conn->in.padding +
 	    (conn->datadgst_en ? 4 : 0))) {
 		debug_tcp("Copying header for later use. in.copy %d in.datalen"
@@ -614,9 +637,9 @@
  *	byte counters.
  **/
 static inline int
-iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
+iscsi_tcp_copy(struct iscsi_conn *conn)
 {
-	void *buf = tcp_conn->data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	int buf_size = tcp_conn->in.datalen;
 	int buf_left = buf_size - tcp_conn->data_copied;
 	int size = min(tcp_conn->in.copy, buf_left);
@@ -627,7 +650,7 @@
 	BUG_ON(size <= 0);
 
 	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
-			   (char*)buf + tcp_conn->data_copied, size);
+			   (char*)conn->data + tcp_conn->data_copied, size);
 	BUG_ON(rc);
 
 	tcp_conn->in.offset += size;
@@ -745,10 +768,11 @@
 done:
 	/* check for non-exceptional status */
 	if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
-		debug_scsi("done [sc %lx res %d itt 0x%x]\n",
-			   (long)sc, sc->result, ctask->itt);
+		debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n",
+			   (long)sc, sc->result, ctask->itt,
+			   tcp_conn->in.hdr->flags);
 		spin_lock(&conn->session->lock);
-		__iscsi_ctask_cleanup(conn, ctask);
+		iscsi_tcp_cleanup_ctask(conn, ctask);
 		__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
 		spin_unlock(&conn->session->lock);
 	}
@@ -769,26 +793,25 @@
 		break;
 	case ISCSI_OP_SCSI_CMD_RSP:
 		spin_lock(&conn->session->lock);
-		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
+		iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
 		spin_unlock(&conn->session->lock);
 	case ISCSI_OP_TEXT_RSP:
 	case ISCSI_OP_LOGIN_RSP:
-	case ISCSI_OP_NOOP_IN:
 	case ISCSI_OP_ASYNC_EVENT:
 	case ISCSI_OP_REJECT:
 		/*
 		 * Collect data segment to the connection's data
 		 * placeholder
 		 */
-		if (iscsi_tcp_copy(tcp_conn)) {
+		if (iscsi_tcp_copy(conn)) {
 			rc = -EAGAIN;
 			goto exit;
 		}
 
-		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data,
+		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data,
 					tcp_conn->in.datalen);
 		if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP)
-			iscsi_recv_digest_update(tcp_conn, tcp_conn->data,
+			iscsi_recv_digest_update(tcp_conn, conn->data,
 			  			tcp_conn->in.datalen);
 		break;
 	default:
@@ -843,7 +866,7 @@
 		       if (rc == -EAGAIN)
 				goto nomore;
 		       else {
-				iscsi_conn_failure(conn, rc);
+				iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 				return 0;
 		       }
 		}
@@ -897,7 +920,7 @@
 		if (rc) {
 			if (rc == -EAGAIN)
 				goto again;
-			iscsi_conn_failure(conn, rc);
+			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 			return 0;
 		}
 		tcp_conn->in.copy -= tcp_conn->in.padding;
@@ -1028,9 +1051,8 @@
 }
 
 static void
-iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
+iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn)
 {
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct sock *sk = tcp_conn->sock->sk;
 
 	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
@@ -1308,7 +1330,7 @@
 				    ctask->imm_count -
 				    ctask->unsol_count;
 
-		debug_scsi("cmd [itt %x total %d imm %d imm_data %d "
+		debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d "
 			   "r2t_data %d]\n",
 			   ctask->itt, ctask->total_length, ctask->imm_count,
 			   ctask->unsol_count, tcp_ctask->r2t_data_count);
@@ -1636,7 +1658,7 @@
 	}
 solicit_again:
 	/*
-	 * send Data-Out whitnin this R2T sequence.
+	 * send Data-Out within this R2T sequence.
 	 */
 	if (!r2t->data_count)
 		goto data_out_done;
@@ -1731,7 +1753,7 @@
 	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct iscsi_data_task *dtask = tcp_ctask->dtask;
-	int sent, rc;
+	int sent = 0, rc;
 
 	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
 	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
@@ -1900,27 +1922,32 @@
 	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 	/* initial operational parameters */
 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
-	tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
-
-	/* allocate initial PDU receive place holder */
-	if (tcp_conn->data_size <= PAGE_SIZE)
-		tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL);
-	else
-		tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL,
-					get_order(tcp_conn->data_size));
-	if (!tcp_conn->data)
-		goto max_recv_dlenght_alloc_fail;
 
 	return cls_conn;
 
-max_recv_dlenght_alloc_fail:
-	kfree(tcp_conn);
 tcp_conn_alloc_fail:
 	iscsi_conn_teardown(cls_conn);
 	return NULL;
 }
 
 static void
+iscsi_tcp_release_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+	if (!tcp_conn->sock)
+		return;
+
+	sock_hold(tcp_conn->sock->sk);
+	iscsi_conn_restore_callbacks(tcp_conn);
+	sock_put(tcp_conn->sock->sk);
+
+	sock_release(tcp_conn->sock);
+	tcp_conn->sock = NULL;
+	conn->recv_lock = NULL;
+}
+
+static void
 iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
@@ -1930,6 +1957,7 @@
 	if (conn->hdrdgst_en || conn->datadgst_en)
 		digest = 1;
 
+	iscsi_tcp_release_conn(conn);
 	iscsi_conn_teardown(cls_conn);
 
 	/* now free tcp_conn */
@@ -1944,15 +1972,18 @@
 			crypto_free_tfm(tcp_conn->data_rx_tfm);
 	}
 
-	/* free conn->data, size = MaxRecvDataSegmentLength */
-	if (tcp_conn->data_size <= PAGE_SIZE)
-		kfree(tcp_conn->data);
-	else
-		free_pages((unsigned long)tcp_conn->data,
-			   get_order(tcp_conn->data_size));
 	kfree(tcp_conn);
 }
 
+static void
+iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	iscsi_conn_stop(cls_conn, flag);
+	iscsi_tcp_release_conn(conn);
+}
+
 static int
 iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
@@ -2001,52 +2032,6 @@
 	return 0;
 }
 
-static void
-iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
-	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-	struct iscsi_r2t_info *r2t;
-
-	/* flush ctask's r2t queues */
-	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
-		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
-			    sizeof(void*));
-
-	__iscsi_ctask_cleanup(conn, ctask);
-}
-
-static void
-iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-	struct sock *sk;
-
-	if (!tcp_conn->sock)
-		return;
-
-	sk = tcp_conn->sock->sk;
-	write_lock_bh(&sk->sk_callback_lock);
-	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
-	write_unlock_bh(&sk->sk_callback_lock);
-}
-
-static void
-iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
-{
-	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
-
-	if (!tcp_conn->sock)
-		return;
-
-	sock_hold(tcp_conn->sock->sk);
-	iscsi_conn_restore_callbacks(conn);
-	sock_put(tcp_conn->sock->sk);
-
-	sock_release(tcp_conn->sock);
-	tcp_conn->sock = NULL;
-	conn->recv_lock = NULL;
-}
-
 /* called with host lock */
 static void
 iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
@@ -2057,6 +2042,7 @@
 	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
 			   sizeof(struct iscsi_hdr));
 	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
+	tcp_mtask->sent = 0;
 
 	if (mtask->data_count)
 		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
@@ -2138,39 +2124,6 @@
 	int value;
 
 	switch(param) {
-	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
-		char *saveptr = tcp_conn->data;
-		gfp_t flags = GFP_KERNEL;
-
-		sscanf(buf, "%d", &value);
-		if (tcp_conn->data_size >= value) {
-			iscsi_set_param(cls_conn, param, buf, buflen);
-			break;
-		}
-
-		spin_lock_bh(&session->lock);
-		if (conn->stop_stage == STOP_CONN_RECOVER)
-			flags = GFP_ATOMIC;
-		spin_unlock_bh(&session->lock);
-
-		if (value <= PAGE_SIZE)
-			tcp_conn->data = kmalloc(value, flags);
-		else
-			tcp_conn->data = (void*)__get_free_pages(flags,
-							     get_order(value));
-		if (tcp_conn->data == NULL) {
-			tcp_conn->data = saveptr;
-			return -ENOMEM;
-		}
-		if (tcp_conn->data_size <= PAGE_SIZE)
-			kfree(saveptr);
-		else
-			free_pages((unsigned long)saveptr,
-				   get_order(tcp_conn->data_size));
-		iscsi_set_param(cls_conn, param, buf, buflen);
-		tcp_conn->data_size = value;
-		break;
-		}
 	case ISCSI_PARAM_HDRDGST_EN:
 		iscsi_set_param(cls_conn, param, buf, buflen);
 		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
@@ -2361,8 +2314,7 @@
 }
 
 static struct scsi_host_template iscsi_sht = {
-	.name			= "iSCSI Initiator over TCP/IP, v"
-				  ISCSI_TCP_VERSION,
+	.name			= "iSCSI Initiator over TCP/IP",
 	.queuecommand           = iscsi_queuecommand,
 	.change_queue_depth	= iscsi_change_queue_depth,
 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
@@ -2414,10 +2366,7 @@
 	.get_conn_param		= iscsi_tcp_conn_get_param,
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn		= iscsi_conn_start,
-	.stop_conn		= iscsi_conn_stop,
-	/* these are called as part of conn recovery */
-	.suspend_conn_recv	= iscsi_tcp_suspend_conn_rx,
-	.terminate_conn		= iscsi_tcp_terminate_conn,
+	.stop_conn		= iscsi_tcp_conn_stop,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
 	.get_stats		= iscsi_conn_get_stats,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 8083028..6a4ee70 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -78,8 +78,6 @@
 	char			hdrext[4*sizeof(__u16) +
 				    sizeof(__u32)];
 	int			data_copied;
-	char			*data;		/* data placeholder */
-	int			data_size;	/* actual recv_dlength */
 	int			stop_stage;	/* conn_stop() flag: *
 						 * stop to recover,  *
 						 * stop to terminate */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 386e5f2..73dd6c8 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -2746,7 +2746,7 @@
 		if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
 			return rc;
 
-		scontrol = (scontrol & 0x0f0) | 0x302;
+		scontrol = (scontrol & 0x0f0) | 0x304;
 
 		if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
 			return rc;
@@ -5185,28 +5185,6 @@
 		iounmap(host_set->mmio_base);
 }
 
-
-/**
- *	ata_host_remove - Unregister SCSI host structure with upper layers
- *	@ap: Port to unregister
- *	@do_unregister: 1 if we fully unregister, 0 to just stop the port
- *
- *	LOCKING:
- *	Inherited from caller.
- */
-
-static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
-{
-	struct Scsi_Host *sh = ap->host;
-
-	DPRINTK("ENTER\n");
-
-	if (do_unregister)
-		scsi_remove_host(sh);
-
-	ap->ops->port_stop(ap);
-}
-
 /**
  *	ata_dev_init - Initialize an ata_device structure
  *	@dev: Device structure to initialize
@@ -5532,8 +5510,11 @@
 
 err_out:
 	for (i = 0; i < count; i++) {
-		ata_host_remove(host_set->ports[i], 1);
-		scsi_host_put(host_set->ports[i]->host);
+		struct ata_port *ap = host_set->ports[i];
+		if (ap) {
+			ap->ops->port_stop(ap);
+			scsi_host_put(ap->host);
+		}
 	}
 err_free_ret:
 	kfree(host_set);
@@ -5558,7 +5539,7 @@
 	int i;
 
 	if (!ap->ops->error_handler)
-		return;
+		goto skip_eh;
 
 	/* tell EH we're leaving & flush EH */
 	spin_lock_irqsave(ap->lock, flags);
@@ -5594,6 +5575,7 @@
 	cancel_delayed_work(&ap->hotplug_task);
 	flush_workqueue(ata_aux_wq);
 
+ skip_eh:
 	/* remove the associated SCSI host */
 	scsi_remove_host(ap->host);
 }
@@ -5662,7 +5644,7 @@
 	DPRINTK("ENTER\n");
 
 	ap->ops->port_disable(ap);
-	ata_host_remove(ap, 0);
+	ap->ops->port_stop(ap);
 
 	DPRINTK("EXIT\n");
 	return 1;
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 4b6aa30..29f5934 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -764,12 +764,27 @@
 			       unsigned int action)
 {
 	unsigned long flags;
+	struct ata_eh_info *ehi = &ap->eh_info;
+	struct ata_eh_context *ehc = &ap->eh_context;
 
 	spin_lock_irqsave(ap->lock, flags);
 
-	ata_eh_clear_action(dev, &ap->eh_info, action);
+	/* Reset is represented by combination of actions and EHI
+	 * flags.  Suck in all related bits before clearing eh_info to
+	 * avoid losing requested action.
+	 */
+	if (action & ATA_EH_RESET_MASK) {
+		ehc->i.action |= ehi->action & ATA_EH_RESET_MASK;
+		ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK;
 
-	if (!(ap->eh_context.i.flags & ATA_EHI_QUIET))
+		/* make sure all reset actions are cleared & clear EHI flags */
+		action |= ATA_EH_RESET_MASK;
+		ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+	}
+
+	ata_eh_clear_action(dev, ehi, action);
+
+	if (!(ehc->i.flags & ATA_EHI_QUIET))
 		ap->pflags |= ATA_PFLAG_RECOVERED;
 
 	spin_unlock_irqrestore(ap->lock, flags);
@@ -790,6 +805,12 @@
 static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
 			unsigned int action)
 {
+	/* if reset is complete, clear all reset actions & reset modifier */
+	if (action & ATA_EH_RESET_MASK) {
+		action |= ATA_EH_RESET_MASK;
+		ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK;
+	}
+
 	ata_eh_clear_action(dev, &ap->eh_context.i, action);
 }
 
@@ -1276,8 +1297,6 @@
 static void ata_eh_autopsy(struct ata_port *ap)
 {
 	struct ata_eh_context *ehc = &ap->eh_context;
-	unsigned int action = ehc->i.action;
-	struct ata_device *failed_dev = NULL;
 	unsigned int all_err_mask = 0;
 	int tag, is_io = 0;
 	u32 serror;
@@ -1294,7 +1313,7 @@
 		ehc->i.serror |= serror;
 		ata_eh_analyze_serror(ap);
 	} else if (rc != -EOPNOTSUPP)
-		action |= ATA_EH_HARDRESET;
+		ehc->i.action |= ATA_EH_HARDRESET;
 
 	/* analyze NCQ failure */
 	ata_eh_analyze_ncq_error(ap);
@@ -1315,7 +1334,7 @@
 		qc->err_mask |= ehc->i.err_mask;
 
 		/* analyze TF */
-		action |= ata_eh_analyze_tf(qc, &qc->result_tf);
+		ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf);
 
 		/* DEV errors are probably spurious in case of ATA_BUS error */
 		if (qc->err_mask & AC_ERR_ATA_BUS)
@@ -1329,11 +1348,11 @@
 		/* SENSE_VALID trumps dev/unknown error and revalidation */
 		if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
 			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
-			action &= ~ATA_EH_REVALIDATE;
+			ehc->i.action &= ~ATA_EH_REVALIDATE;
 		}
 
 		/* accumulate error info */
-		failed_dev = qc->dev;
+		ehc->i.dev = qc->dev;
 		all_err_mask |= qc->err_mask;
 		if (qc->flags & ATA_QCFLAG_IO)
 			is_io = 1;
@@ -1342,25 +1361,22 @@
 	/* enforce default EH actions */
 	if (ap->pflags & ATA_PFLAG_FROZEN ||
 	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
-		action |= ATA_EH_SOFTRESET;
+		ehc->i.action |= ATA_EH_SOFTRESET;
 	else if (all_err_mask)
-		action |= ATA_EH_REVALIDATE;
+		ehc->i.action |= ATA_EH_REVALIDATE;
 
 	/* if we have offending qcs and the associated failed device */
-	if (failed_dev) {
+	if (ehc->i.dev) {
 		/* speed down */
-		action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
+		ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
+						   all_err_mask);
 
 		/* perform per-dev EH action only on the offending device */
-		ehc->i.dev_action[failed_dev->devno] |=
-			action & ATA_EH_PERDEV_MASK;
-		action &= ~ATA_EH_PERDEV_MASK;
+		ehc->i.dev_action[ehc->i.dev->devno] |=
+			ehc->i.action & ATA_EH_PERDEV_MASK;
+		ehc->i.action &= ~ATA_EH_PERDEV_MASK;
 	}
 
-	/* record autopsy result */
-	ehc->i.dev = failed_dev;
-	ehc->i.action |= action;
-
 	DPRINTK("EXIT\n");
 }
 
@@ -1483,6 +1499,9 @@
 	ata_reset_fn_t reset;
 	int i, did_followup_srst, rc;
 
+	/* about to reset */
+	ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
+
 	/* Determine which reset to use and record in ehc->i.action.
 	 * prereset() may examine and modify it.
 	 */
@@ -1531,8 +1550,7 @@
 		ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
 				reset == softreset ? "soft" : "hard");
 
-	/* reset */
-	ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
+	/* mark that this EH session started with reset */
 	ehc->i.flags |= ATA_EHI_DID_RESET;
 
 	rc = ata_do_reset(ap, reset, classes);
@@ -1595,7 +1613,7 @@
 			postreset(ap, classes);
 
 		/* reset successful, schedule revalidation */
-		ata_eh_done(ap, NULL, ATA_EH_RESET_MASK);
+		ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
 		ehc->i.action |= ATA_EH_REVALIDATE;
 	}
 
@@ -1848,15 +1866,16 @@
 	for (i = 0; i < ata_port_max_devices(ap); i++) {
 		struct ata_device *dev = &ap->device[i];
 
-		if (ata_dev_absent(dev) || ata_dev_ready(dev))
+		if (!(dev->flags & ATA_DFLAG_SUSPENDED))
 			break;
 	}
 
 	if (i == ata_port_max_devices(ap))
 		return 1;
 
-	/* always thaw frozen port and recover failed devices */
-	if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap))
+	/* thaw frozen port, resume link and recover failed devices */
+	if ((ap->pflags & ATA_PFLAG_FROZEN) ||
+	    (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap))
 		return 0;
 
 	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 7ced41e..e92c31d 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -2353,6 +2353,19 @@
 			ata_gen_ata_desc_sense(qc);
 		}
 
+		/* SCSI EH automatically locks door if sdev->locked is
+		 * set.  Sometimes door lock request continues to
+		 * fail, for example, when no media is present.  This
+		 * creates a loop - SCSI EH issues door lock which
+		 * fails and gets invoked again to acquire sense data
+		 * for the failed command.
+		 *
+		 * If door lock fails, always clear sdev->locked to
+		 * avoid this infinite loop.
+		 */
+		if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL)
+			qc->dev->sdev->locked = 0;
+
 		qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
 		qc->scsidone(cmd);
 		ata_qc_free(qc);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 7e6e031..5884cd2 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -189,6 +189,7 @@
 {
 	struct scsi_cmnd *sc = ctask->sc;
 
+	ctask->state = ISCSI_TASK_COMPLETED;
 	ctask->sc = NULL;
 	list_del_init(&ctask->running);
 	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
@@ -275,6 +276,25 @@
 	return rc;
 }
 
+static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
+{
+	struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
+
+	conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+	conn->tmfrsp_pdus_cnt++;
+
+	if (conn->tmabort_state != TMABORT_INITIAL)
+		return;
+
+	if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
+		conn->tmabort_state = TMABORT_SUCCESS;
+	else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
+		conn->tmabort_state = TMABORT_NOT_FOUND;
+	else
+		conn->tmabort_state = TMABORT_FAILED;
+	wake_up(&conn->ehwait);
+}
+
 /**
  * __iscsi_complete_pdu - complete pdu
  * @conn: iscsi conn
@@ -340,6 +360,10 @@
 
 		switch(opcode) {
 		case ISCSI_OP_LOGOUT_RSP:
+			if (datalen) {
+				rc = ISCSI_ERR_PROTO;
+				break;
+			}
 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
 			/* fall through */
 		case ISCSI_OP_LOGIN_RSP:
@@ -348,7 +372,8 @@
 			 * login related PDU's exp_statsn is handled in
 			 * userspace
 			 */
-			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+				rc = ISCSI_ERR_CONN_FAILED;
 			list_del(&mtask->running);
 			if (conn->login_mtask != mtask)
 				__kfifo_put(session->mgmtpool.queue,
@@ -360,25 +385,17 @@
 				break;
 			}
 
-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
-			conn->tmfrsp_pdus_cnt++;
-			if (conn->tmabort_state == TMABORT_INITIAL) {
-				conn->tmabort_state =
-					((struct iscsi_tm_rsp *)hdr)->
-					response == ISCSI_TMF_RSP_COMPLETE ?
-						TMABORT_SUCCESS:TMABORT_FAILED;
-				/* unblock eh_abort() */
-				wake_up(&conn->ehwait);
-			}
+			iscsi_tmf_rsp(conn, hdr);
 			break;
 		case ISCSI_OP_NOOP_IN:
-			if (hdr->ttt != ISCSI_RESERVED_TAG) {
+			if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) {
 				rc = ISCSI_ERR_PROTO;
 				break;
 			}
 			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
 
-			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+			if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
+				rc = ISCSI_ERR_CONN_FAILED;
 			list_del(&mtask->running);
 			if (conn->login_mtask != mtask)
 				__kfifo_put(session->mgmtpool.queue,
@@ -391,14 +408,21 @@
 	} else if (itt == ISCSI_RESERVED_TAG) {
 		switch(opcode) {
 		case ISCSI_OP_NOOP_IN:
-			if (!datalen) {
-				rc = iscsi_check_assign_cmdsn(session,
-						 (struct iscsi_nopin*)hdr);
-				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
-					rc = iscsi_recv_pdu(conn->cls_conn,
-							    hdr, NULL, 0);
-			} else
+			if (datalen) {
 				rc = ISCSI_ERR_PROTO;
+				break;
+			}
+
+			rc = iscsi_check_assign_cmdsn(session,
+						 (struct iscsi_nopin*)hdr);
+			if (rc)
+				break;
+
+			if (hdr->ttt == ISCSI_RESERVED_TAG)
+				break;
+
+			if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0))
+				rc = ISCSI_ERR_CONN_FAILED;
 			break;
 		case ISCSI_OP_REJECT:
 			/* we need sth like iscsi_reject_rsp()*/
@@ -568,20 +592,24 @@
 	}
 
 	/* process command queue */
-	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
-			   sizeof(void*))) {
+	spin_lock_bh(&conn->session->lock);
+	while (!list_empty(&conn->xmitqueue)) {
 		/*
 		 * iscsi tcp may readd the task to the xmitqueue to send
 		 * write data
 		 */
-		spin_lock_bh(&conn->session->lock);
-		if (list_empty(&conn->ctask->running))
-			list_add_tail(&conn->ctask->running, &conn->run_list);
+		conn->ctask = list_entry(conn->xmitqueue.next,
+					 struct iscsi_cmd_task, running);
+		conn->ctask->state = ISCSI_TASK_RUNNING;
+		list_move_tail(conn->xmitqueue.next, &conn->run_list);
 		spin_unlock_bh(&conn->session->lock);
+
 		rc = tt->xmit_cmd_task(conn, conn->ctask);
 		if (rc)
 			goto again;
+		spin_lock_bh(&conn->session->lock);
 	}
+	spin_unlock_bh(&conn->session->lock);
 	/* done with this ctask */
 	conn->ctask = NULL;
 
@@ -691,6 +719,7 @@
 	sc->SCp.phase = session->age;
 	sc->SCp.ptr = (char *)ctask;
 
+	ctask->state = ISCSI_TASK_PENDING;
 	ctask->mtask = NULL;
 	ctask->conn = conn;
 	ctask->sc = sc;
@@ -700,7 +729,7 @@
 
 	session->tt->init_cmd_task(ctask);
 
-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
+	list_add_tail(&ctask->running, &conn->xmitqueue);
 	debug_scsi(
 	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
 		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
@@ -977,31 +1006,27 @@
 /*
  * xmit mutex and session lock must be held
  */
-#define iscsi_remove_task(tasktype)					\
-static struct iscsi_##tasktype *					\
-iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt)		\
-{									\
-	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);		\
-	struct iscsi_##tasktype *task;					\
-									\
-	debug_scsi("searching %d tasks\n", nr_tasks);			\
-									\
-	for (i = 0; i < nr_tasks; i++) {				\
-		__kfifo_get(fifo, (void*)&task, sizeof(void*));		\
-		debug_scsi("check task %u\n", task->itt);		\
-									\
-		if (task->itt == itt) {					\
-			debug_scsi("matched task\n");			\
-			return task;					\
-		}							\
-									\
-		__kfifo_put(fifo, (void*)&task, sizeof(void*));		\
-	}								\
-	return NULL;							\
-}
+static struct iscsi_mgmt_task *
+iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt)
+{
+	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);
+	struct iscsi_mgmt_task *task;
 
-iscsi_remove_task(mgmt_task);
-iscsi_remove_task(cmd_task);
+	debug_scsi("searching %d tasks\n", nr_tasks);
+
+	for (i = 0; i < nr_tasks; i++) {
+		__kfifo_get(fifo, (void*)&task, sizeof(void*));
+		debug_scsi("check task %u\n", task->itt);
+
+		if (task->itt == itt) {
+			debug_scsi("matched task\n");
+			return task;
+		}
+
+		__kfifo_put(fifo, (void*)&task, sizeof(void*));
+	}
+	return NULL;
+}
 
 static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
 {
@@ -1027,12 +1052,13 @@
 {
 	struct scsi_cmnd *sc;
 
-	conn->session->tt->cleanup_cmd_task(conn, ctask);
-	iscsi_ctask_mtask_cleanup(ctask);
-
 	sc = ctask->sc;
 	if (!sc)
 		return;
+
+	conn->session->tt->cleanup_cmd_task(conn, ctask);
+	iscsi_ctask_mtask_cleanup(ctask);
+
 	sc->result = err;
 	sc->resid = sc->request_bufflen;
 	iscsi_complete_command(conn->session, ctask);
@@ -1043,7 +1069,6 @@
 	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
 	struct iscsi_conn *conn = ctask->conn;
 	struct iscsi_session *session = conn->session;
-	struct iscsi_cmd_task *pending_ctask;
 	int rc;
 
 	conn->eh_abort_cnt++;
@@ -1061,8 +1086,11 @@
 		goto failed;
 
 	/* ctask completed before time out */
-	if (!ctask->sc)
-		goto success;
+	if (!ctask->sc) {
+		spin_unlock_bh(&session->lock);
+		debug_scsi("sc completed while abort in progress\n");
+		goto success_rel_mutex;
+	}
 
 	/* what should we do here ? */
 	if (conn->ctask == ctask) {
@@ -1071,17 +1099,8 @@
 		goto failed;
 	}
 
-	/* check for the easy pending cmd abort */
-	pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt);
-	if (pending_ctask) {
-		/* iscsi_tcp queues write transfers on the xmitqueue */
-		if (list_empty(&pending_ctask->running)) {
-			debug_scsi("found pending task\n");
-			goto success;
-		} else
-			__kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
-				    sizeof(void*));
-	}
+	if (ctask->state == ISCSI_TASK_PENDING)
+		goto success_cleanup;
 
 	conn->tmabort_state = TMABORT_INITIAL;
 
@@ -1089,25 +1108,31 @@
 	rc = iscsi_exec_abort_task(sc, ctask);
 	spin_lock_bh(&session->lock);
 
-	iscsi_ctask_mtask_cleanup(ctask);
 	if (rc || sc->SCp.phase != session->age ||
 	    session->state != ISCSI_STATE_LOGGED_IN)
 		goto failed;
+	iscsi_ctask_mtask_cleanup(ctask);
 
-	/* ctask completed before tmf abort response */
-	if (!ctask->sc) {
-		debug_scsi("sc completed while abort in progress\n");
-		goto success;
-	}
-
-	if (conn->tmabort_state != TMABORT_SUCCESS) {
+	switch (conn->tmabort_state) {
+	case TMABORT_SUCCESS:
+		goto success_cleanup;
+	case TMABORT_NOT_FOUND:
+		if (!ctask->sc) {
+			/* ctask completed before tmf abort response */
+			spin_unlock_bh(&session->lock);
+			debug_scsi("sc completed while abort in progress\n");
+			goto success_rel_mutex;
+		}
+		/* fall through */
+	default:
+		/* timedout or failed */
 		spin_unlock_bh(&session->lock);
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 		spin_lock_bh(&session->lock);
 		goto failed;
 	}
 
-success:
+success_cleanup:
 	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
 	spin_unlock_bh(&session->lock);
 
@@ -1121,6 +1146,7 @@
 	spin_unlock(&session->lock);
 	write_unlock_bh(conn->recv_lock);
 
+success_rel_mutex:
 	mutex_unlock(&conn->xmitmutex);
 	return SUCCESS;
 
@@ -1263,6 +1289,7 @@
 		if (cmd_task_size)
 			ctask->dd_data = &ctask[1];
 		ctask->itt = cmd_i;
+		INIT_LIST_HEAD(&ctask->running);
 	}
 
 	spin_lock_init(&session->lock);
@@ -1282,6 +1309,7 @@
 		if (mgmt_task_size)
 			mtask->dd_data = &mtask[1];
 		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
+		INIT_LIST_HEAD(&mtask->running);
 	}
 
 	if (scsi_add_host(shost, NULL))
@@ -1322,15 +1350,18 @@
 {
 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
 	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+	struct module *owner = cls_session->transport->owner;
 
 	scsi_remove_host(shost);
 
 	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
 	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
 
+	kfree(session->targetname);
+
 	iscsi_destroy_session(cls_session);
 	scsi_host_put(shost);
-	module_put(cls_session->transport->owner);
+	module_put(owner);
 }
 EXPORT_SYMBOL_GPL(iscsi_session_teardown);
 
@@ -1361,12 +1392,7 @@
 	conn->tmabort_state = TMABORT_INITIAL;
 	INIT_LIST_HEAD(&conn->run_list);
 	INIT_LIST_HEAD(&conn->mgmt_run_list);
-
-	/* initialize general xmit PDU commands queue */
-	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
-					GFP_KERNEL, NULL);
-	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
-		goto xmitqueue_alloc_fail;
+	INIT_LIST_HEAD(&conn->xmitqueue);
 
 	/* initialize general immediate & non-immediate PDU commands queue */
 	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
@@ -1394,7 +1420,7 @@
 	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
 	if (!data)
 		goto login_mtask_data_alloc_fail;
-	conn->login_mtask->data = data;
+	conn->login_mtask->data = conn->data = data;
 
 	init_timer(&conn->tmabort_timer);
 	mutex_init(&conn->xmitmutex);
@@ -1410,8 +1436,6 @@
 mgmtqueue_alloc_fail:
 	kfifo_free(conn->immqueue);
 immqueue_alloc_fail:
-	kfifo_free(conn->xmitqueue);
-xmitqueue_alloc_fail:
 	iscsi_destroy_conn(cls_conn);
 	return NULL;
 }
@@ -1432,12 +1456,6 @@
 
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 	mutex_lock(&conn->xmitmutex);
-	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
-		if (session->tt->suspend_conn_recv)
-			session->tt->suspend_conn_recv(conn);
-
-		session->tt->terminate_conn(conn);
-	}
 
 	spin_lock_bh(&session->lock);
 	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
@@ -1474,7 +1492,8 @@
 	}
 
 	spin_lock_bh(&session->lock);
-	kfree(conn->login_mtask->data);
+	kfree(conn->data);
+	kfree(conn->persistent_address);
 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
 		    sizeof(void*));
 	list_del(&conn->item);
@@ -1489,7 +1508,6 @@
 		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
 	spin_unlock_bh(&session->lock);
 
-	kfifo_free(conn->xmitqueue);
 	kfifo_free(conn->immqueue);
 	kfifo_free(conn->mgmtqueue);
 
@@ -1572,7 +1590,7 @@
 	struct iscsi_cmd_task *ctask, *tmp;
 
 	/* flush pending */
-	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
+	list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) {
 		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
 			   ctask->itt);
 		fail_command(conn, ctask, DID_BUS_BUSY << 16);
@@ -1615,8 +1633,9 @@
 	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
 	spin_unlock_bh(&session->lock);
 
-	if (session->tt->suspend_conn_recv)
-		session->tt->suspend_conn_recv(conn);
+	write_lock_bh(conn->recv_lock);
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+	write_unlock_bh(conn->recv_lock);
 
 	mutex_lock(&conn->xmitmutex);
 	/*
@@ -1635,7 +1654,6 @@
 		}
 	}
 
-	session->tt->terminate_conn(conn);
 	/*
 	 * flush queues.
 	 */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 5c68cdd..d384c16 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -222,7 +222,7 @@
 	pmboxq->mb.mbxCommand = MBX_DOWN_LINK;
 	pmboxq->mb.mbxOwner = OWN_HOST;
 
-	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2);
 
 	if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) {
 		memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t));
@@ -884,7 +884,7 @@
 		    phba->sysfs_mbox.mbox   == NULL ) {
 			sysfs_mbox_idle(phba);
 			spin_unlock_irq(host->host_lock);
-			return -EINVAL;
+			return -EAGAIN;
 		}
 	}
 
@@ -1000,14 +1000,15 @@
 			spin_unlock_irq(phba->host->host_lock);
 			rc = lpfc_sli_issue_mbox_wait (phba,
 						       phba->sysfs_mbox.mbox,
-						       phba->fc_ratov * 2);
+				lpfc_mbox_tmo_val(phba,
+				    phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ);
 			spin_lock_irq(phba->host->host_lock);
 		}
 
 		if (rc != MBX_SUCCESS) {
 			sysfs_mbox_idle(phba);
 			spin_unlock_irq(host->host_lock);
-			return -ENODEV;
+			return  (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
 		}
 		phba->sysfs_mbox.state = SMBOX_READING;
 	}
@@ -1016,7 +1017,7 @@
 		printk(KERN_WARNING  "mbox_read: Bad State\n");
 		sysfs_mbox_idle(phba);
 		spin_unlock_irq(host->host_lock);
-		return -EINVAL;
+		return -EAGAIN;
 	}
 
 	memcpy(buf, (uint8_t *) & phba->sysfs_mbox.mbox->mb + off, count);
@@ -1210,8 +1211,10 @@
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
 	struct lpfc_sli *psli = &phba->sli;
 	struct fc_host_statistics *hs = &phba->link_stats;
+	struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
 	LPFC_MBOXQ_t *pmboxq;
 	MAILBOX_t *pmb;
+	unsigned long seconds;
 	int rc = 0;
 
 	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -1272,22 +1275,103 @@
 	hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
 	hs->error_frames = pmb->un.varRdLnk.crcCnt;
 
+	hs->link_failure_count -= lso->link_failure_count;
+	hs->loss_of_sync_count -= lso->loss_of_sync_count;
+	hs->loss_of_signal_count -= lso->loss_of_signal_count;
+	hs->prim_seq_protocol_err_count -= lso->prim_seq_protocol_err_count;
+	hs->invalid_tx_word_count -= lso->invalid_tx_word_count;
+	hs->invalid_crc_count -= lso->invalid_crc_count;
+	hs->error_frames -= lso->error_frames;
+
 	if (phba->fc_topology == TOPOLOGY_LOOP) {
 		hs->lip_count = (phba->fc_eventTag >> 1);
+		hs->lip_count -= lso->link_events;
 		hs->nos_count = -1;
 	} else {
 		hs->lip_count = -1;
 		hs->nos_count = (phba->fc_eventTag >> 1);
+		hs->nos_count -= lso->link_events;
 	}
 
 	hs->dumped_frames = -1;
 
-/* FIX ME */
-	/*hs->SecondsSinceLastReset = (jiffies - lpfc_loadtime) / HZ;*/
+	seconds = get_seconds();
+	if (seconds < psli->stats_start)
+		hs->seconds_since_last_reset = seconds +
+				((unsigned long)-1 - psli->stats_start);
+	else
+		hs->seconds_since_last_reset = seconds - psli->stats_start;
 
 	return hs;
 }
 
+static void
+lpfc_reset_stats(struct Scsi_Host *shost)
+{
+	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
+	struct lpfc_sli *psli = &phba->sli;
+	struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets;
+	LPFC_MBOXQ_t *pmboxq;
+	MAILBOX_t *pmb;
+	int rc = 0;
+
+	pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+	if (!pmboxq)
+		return;
+	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
+
+	pmb = &pmboxq->mb;
+	pmb->mbxCommand = MBX_READ_STATUS;
+	pmb->mbxOwner = OWN_HOST;
+	pmb->un.varWords[0] = 0x1; /* reset request */
+	pmboxq->context1 = NULL;
+
+	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+		(!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+	else
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+
+	if (rc != MBX_SUCCESS) {
+		if (rc == MBX_TIMEOUT)
+			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		else
+			mempool_free(pmboxq, phba->mbox_mem_pool);
+		return;
+	}
+
+	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
+	pmb->mbxCommand = MBX_READ_LNK_STAT;
+	pmb->mbxOwner = OWN_HOST;
+	pmboxq->context1 = NULL;
+
+	if ((phba->fc_flag & FC_OFFLINE_MODE) ||
+	    (!(psli->sli_flag & LPFC_SLI2_ACTIVE)))
+		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
+	else
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+
+	if (rc != MBX_SUCCESS) {
+		if (rc == MBX_TIMEOUT)
+			pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+		else
+			mempool_free( pmboxq, phba->mbox_mem_pool);
+		return;
+	}
+
+	lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
+	lso->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt;
+	lso->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt;
+	lso->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt;
+	lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord;
+	lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
+	lso->error_frames = pmb->un.varRdLnk.crcCnt;
+	lso->link_events = (phba->fc_eventTag >> 1);
+
+	psli->stats_start = get_seconds();
+
+	return;
+}
 
 /*
  * The LPFC driver treats linkdown handling as target loss events so there
@@ -1431,8 +1515,7 @@
 	 */
 
 	.get_fc_host_stats = lpfc_get_stats,
-
-	/* the LPFC driver doesn't support resetting stats yet */
+	.reset_fc_host_stats = lpfc_reset_stats,
 
 	.dd_fcrport_size = sizeof(struct lpfc_rport_data),
 	.show_rport_maxframe_size = 1,
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 517e9e4..2a17646 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -127,6 +127,7 @@
 void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *);
 LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *);
+int lpfc_mbox_tmo_val(struct lpfc_hba *, int);
 
 int lpfc_mem_alloc(struct lpfc_hba *);
 void lpfc_mem_free(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index b65ee57..bbb7310 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -131,6 +131,7 @@
 	}
 
 ct_unsol_event_exit_piocbq:
+	list_del(&head);
 	if (pmbuf) {
 		list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) {
 			lpfc_mbuf_free(phba, matp->virt, matp->phys);
@@ -481,7 +482,7 @@
 		if (CTrsp->CommandResponse.bits.CmdRsp ==
 		    be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
 			lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-					"%d:0239 NameServer Rsp "
+					"%d:0208 NameServer Rsp "
 					"Data: x%x\n",
 					phba->brd_no,
 					phba->fc_flag);
@@ -588,13 +589,9 @@
 
 	lpfc_decode_firmware_rev(phba, fwrev, 0);
 
-	if (phba->Port[0]) {
-		sprintf(symbp, "Emulex %s Port %s FV%s DV%s", phba->ModelName,
-			phba->Port, fwrev, lpfc_release_version);
-	} else {
-		sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
-			fwrev, lpfc_release_version);
-	}
+	sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName,
+		fwrev, lpfc_release_version);
+	return;
 }
 
 /*
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index b89f6cb..3567de61 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1848,9 +1848,12 @@
 lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
 		  struct lpfc_iocbq * rspiocb)
 {
+	IOCB_t *irsp;
 	struct lpfc_nodelist *ndlp;
 	LPFC_MBOXQ_t *mbox = NULL;
 
+	irsp = &rspiocb->iocb;
+
 	ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
 	if (cmdiocb->context_un.mbox)
 		mbox = cmdiocb->context_un.mbox;
@@ -1893,9 +1896,15 @@
 			mempool_free( mbox, phba->mbox_mem_pool);
 		} else {
 			mempool_free( mbox, phba->mbox_mem_pool);
-			if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
-				lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
-				ndlp = NULL;
+			/* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
+			if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+			      ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
+			       (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
+			       (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
+				if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
+					lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
+					ndlp = NULL;
+				}
 			}
 		}
 	}
@@ -2839,7 +2848,7 @@
 
 	/* Xmit ELS RPS ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0128 Xmit ELS RPS ACC response tag x%x "
+			"%d:0118 Xmit ELS RPS ACC response tag x%x "
 			"Data: x%x x%x x%x x%x x%x\n",
 			phba->brd_no,
 			elsiocb->iocb.ulpIoTag,
@@ -2948,7 +2957,7 @@
 
 	/* Xmit ELS RPL ACC response tag <ulpIoTag> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"%d:0128 Xmit ELS RPL ACC response tag x%x "
+			"%d:0120 Xmit ELS RPL ACC response tag x%x "
 			"Data: x%x x%x x%x x%x x%x\n",
 			phba->brd_no,
 			elsiocb->iocb.ulpIoTag,
@@ -3109,7 +3118,7 @@
 	struct lpfc_nodelist *ndlp, *next_ndlp;
 
 	/* FAN received */
-	lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:265 FAN received\n",
+	lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
 								phba->brd_no);
 
 	icmd = &cmdiocb->iocb;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 4d6cf99..b2f1552 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1557,6 +1557,8 @@
 			mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
 		}
 	}
+
+	spin_lock_irq(phba->host->host_lock);
 	list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
 		if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
 		   (ndlp == (struct lpfc_nodelist *) mb->context2)) {
@@ -1569,6 +1571,7 @@
 			mempool_free(mb, phba->mbox_mem_pool);
 		}
 	}
+	spin_unlock_irq(phba->host->host_lock);
 
 	lpfc_els_abort(phba,ndlp,0);
 	spin_lock_irq(phba->host->host_lock);
@@ -1782,7 +1785,7 @@
 				/* LOG change to REGLOGIN */
 				/* FIND node DID reglogin */
 				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-						"%d:0931 FIND node DID reglogin"
+						"%d:0901 FIND node DID reglogin"
 						" Data: x%p x%x x%x x%x\n",
 						phba->brd_no,
 						ndlp, ndlp->nlp_DID,
@@ -1805,7 +1808,7 @@
 				/* LOG change to PRLI */
 				/* FIND node DID prli */
 				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-						"%d:0931 FIND node DID prli "
+						"%d:0902 FIND node DID prli "
 						"Data: x%p x%x x%x x%x\n",
 						phba->brd_no,
 						ndlp, ndlp->nlp_DID,
@@ -1828,7 +1831,7 @@
 				/* LOG change to NPR */
 				/* FIND node DID npr */
 				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-						"%d:0931 FIND node DID npr "
+						"%d:0903 FIND node DID npr "
 						"Data: x%p x%x x%x x%x\n",
 						phba->brd_no,
 						ndlp, ndlp->nlp_DID,
@@ -1851,7 +1854,7 @@
 				/* LOG change to UNUSED */
 				/* FIND node DID unused */
 				lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
-						"%d:0931 FIND node DID unused "
+						"%d:0905 FIND node DID unused "
 						"Data: x%p x%x x%x x%x\n",
 						phba->brd_no,
 						ndlp, ndlp->nlp_DID,
@@ -2335,7 +2338,7 @@
 		initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (!initlinkmbox) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-					"%d:0226 Device Discovery "
+					"%d:0206 Device Discovery "
 					"completion error\n",
 					phba->brd_no);
 			phba->hba_state = LPFC_HBA_ERROR;
@@ -2365,7 +2368,7 @@
 		if (!clearlambox) {
 			clrlaerr = 1;
 			lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-					"%d:0226 Device Discovery "
+					"%d:0207 Device Discovery "
 					"completion error\n",
 					phba->brd_no);
 			phba->hba_state = LPFC_HBA_ERROR;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index ef47b82..f6948ff 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1379,6 +1379,7 @@
 	/* stop all timers associated with this hba */
 	lpfc_stop_timer(phba);
 	phba->work_hba_events = 0;
+	phba->work_ha = 0;
 
 	lpfc_printf_log(phba,
 		       KERN_WARNING,
@@ -1616,7 +1617,11 @@
 		goto out_free_iocbq;
 	}
 
-	/* We can rely on a queue depth attribute only after SLI HBA setup */
+	/*
+	 * Set initial can_queue value since 0 is no longer supported and
+	 * scsi_add_host will fail. This will be adjusted later based on the
+	 * max xri value determined in hba setup.
+	 */
 	host->can_queue = phba->cfg_hba_queue_depth - 10;
 
 	/* Tell the midlayer we support 16 byte commands */
@@ -1656,6 +1661,12 @@
 		goto out_free_irq;
 	}
 
+	/*
+	 * hba setup may have changed the hba_queue_depth so we need to adjust
+	 * the value of can_queue.
+	 */
+	host->can_queue = phba->cfg_hba_queue_depth - 10;
+
 	lpfc_discovery_wait(phba);
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index e42f22a..4d016c2 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -651,3 +651,19 @@
 
 	return mbq;
 }
+
+int
+lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
+{
+	switch (cmd) {
+	case MBX_WRITE_NV:	/* 0x03 */
+	case MBX_UPDATE_CFG:	/* 0x1B */
+	case MBX_DOWN_LOAD:	/* 0x1C */
+	case MBX_DEL_LD_ENTRY:	/* 0x1D */
+	case MBX_LOAD_AREA:	/* 0x81 */
+	case MBX_FLASH_WR_ULA:  /* 0x98 */
+	case MBX_LOAD_EXP_ROM:	/* 0x9C */
+		return LPFC_MBOX_TMO_FLASH_CMD;
+	}
+	return LPFC_MBOX_TMO;
+}
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index bd0b0e2..20449a8 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -179,7 +179,7 @@
 
 	/* Abort outstanding I/O on NPort <nlp_DID> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-			"%d:0201 Abort outstanding I/O on NPort x%x "
+			"%d:0205 Abort outstanding I/O on NPort x%x "
 			"Data: x%x x%x x%x\n",
 			phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
 			ndlp->nlp_state, ndlp->nlp_rpi);
@@ -393,6 +393,20 @@
 	mbox->context2  = ndlp;
 	ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
 
+	/*
+	 * If there is an outstanding PLOGI issued, abort it before
+	 * sending ACC rsp for received PLOGI. If pending plogi
+	 * is not canceled here, the plogi will be rejected by
+	 * remote port and will be retried. On a configuration with
+	 * single discovery thread, this will cause a huge delay in
+	 * discovery. Also this will cause multiple state machines
+	 * running in parallel for this node.
+	 */
+	if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
+		/* software abort outstanding PLOGI */
+		lpfc_els_abort(phba, ndlp, 1);
+	}
+
 	lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
 	return 1;
 
@@ -1601,7 +1615,13 @@
 
 	lpfc_rcv_padisc(phba, ndlp, cmdiocb);
 
-	if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+	/*
+	 * Do not start discovery if discovery is about to start
+	 * or discovery in progress for this node. Starting discovery
+	 * here will affect the counting of discovery threads.
+	 */
+	if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) &&
+		(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
 		if (ndlp->nlp_flag & NLP_NPR_ADISC) {
 			ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
 			ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index a760a44..a8816a8 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -21,6 +21,7 @@
 
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -841,6 +842,21 @@
 	return 0;
 }
 
+static void
+lpfc_block_error_handler(struct scsi_cmnd *cmnd)
+{
+	struct Scsi_Host *shost = cmnd->device->host;
+	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+
+	spin_lock_irq(shost->host_lock);
+	while (rport->port_state == FC_PORTSTATE_BLOCKED) {
+		spin_unlock_irq(shost->host_lock);
+		msleep(1000);
+		spin_lock_irq(shost->host_lock);
+	}
+	spin_unlock_irq(shost->host_lock);
+	return;
+}
 
 static int
 lpfc_abort_handler(struct scsi_cmnd *cmnd)
@@ -855,6 +871,7 @@
 	unsigned int loop_count = 0;
 	int ret = SUCCESS;
 
+	lpfc_block_error_handler(cmnd);
 	spin_lock_irq(shost->host_lock);
 
 	lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
@@ -957,6 +974,7 @@
 	int ret = FAILED;
 	int cnt, loopcnt;
 
+	lpfc_block_error_handler(cmnd);
 	spin_lock_irq(shost->host_lock);
 	/*
 	 * If target is not in a MAPPED state, delay the reset until
@@ -1073,6 +1091,7 @@
 	int cnt, loopcnt;
 	struct lpfc_scsi_buf * lpfc_cmd;
 
+	lpfc_block_error_handler(cmnd);
 	spin_lock_irq(shost->host_lock);
 
 	lpfc_cmd = lpfc_get_scsi_buf(phba);
@@ -1104,7 +1123,7 @@
 					  ndlp->rport->dd_data);
 		if (ret != SUCCESS) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
-				"%d:0713 Bus Reset on target %d failed\n",
+				"%d:0700 Bus Reset on target %d failed\n",
 				phba->brd_no, i);
 			err_count++;
 		}
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 350a625..70f4d5a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -320,7 +320,8 @@
 			kfree(old_arr);
 			return iotag;
 		}
-	}
+	} else
+		spin_unlock_irq(phba->host->host_lock);
 
 	lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
 			"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
@@ -969,9 +970,11 @@
 			 * resources need to be recovered.
 			 */
 			if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
-				printk(KERN_INFO "%s: IOCB cmd 0x%x processed."
-				       " Skipping completion\n", __FUNCTION__,
-				       irsp->ulpCommand);
+				lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+						"%d:0314 IOCB cmd 0x%x"
+						" processed. Skipping"
+						" completion", phba->brd_no,
+						irsp->ulpCommand);
 				break;
 			}
 
@@ -1104,7 +1107,7 @@
 		if (unlikely(irsp->ulpStatus)) {
 			/* Rsp ring <ringno> error: IOCB */
 			lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
-				"%d:0326 Rsp Ring %d error: IOCB Data: "
+				"%d:0336 Rsp Ring %d error: IOCB Data: "
 				"x%x x%x x%x x%x x%x x%x x%x x%x\n",
 				phba->brd_no, pring->ringno,
 				irsp->un.ulpWord[0], irsp->un.ulpWord[1],
@@ -1122,9 +1125,11 @@
 			 * resources need to be recovered.
 			 */
 			if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
-				printk(KERN_INFO "%s: IOCB cmd 0x%x processed. "
-				       "Skipping completion\n", __FUNCTION__,
-				       irsp->ulpCommand);
+				lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+						"%d:0333 IOCB cmd 0x%x"
+						" processed. Skipping"
+						" completion\n", phba->brd_no,
+						irsp->ulpCommand);
 				break;
 			}
 
@@ -1155,7 +1160,7 @@
 			} else {
 				/* Unknown IOCB command */
 				lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-					"%d:0321 Unknown IOCB command "
+					"%d:0334 Unknown IOCB command "
 					"Data: x%x, x%x x%x x%x x%x\n",
 					phba->brd_no, type, irsp->ulpCommand,
 					irsp->ulpStatus, irsp->ulpIoTag,
@@ -1238,7 +1243,7 @@
 		lpfc_printf_log(phba,
 				KERN_ERR,
 				LOG_SLI,
-				"%d:0312 Ring %d handler: portRspPut %d "
+				"%d:0303 Ring %d handler: portRspPut %d "
 				"is bigger then rsp ring %d\n",
 				phba->brd_no,
 				pring->ringno, portRspPut, portRspMax);
@@ -1383,7 +1388,7 @@
 					lpfc_printf_log(phba,
 						KERN_ERR,
 						LOG_SLI,
-						"%d:0321 Unknown IOCB command "
+						"%d:0335 Unknown IOCB command "
 						"Data: x%x x%x x%x x%x\n",
 						phba->brd_no,
 						irsp->ulpCommand,
@@ -1399,11 +1404,11 @@
 								 next_iocb,
 								 &saveq->list,
 								 list) {
+						list_del(&rspiocbp->list);
 						lpfc_sli_release_iocbq(phba,
 								     rspiocbp);
 					}
 				}
-
 				lpfc_sli_release_iocbq(phba, saveq);
 			}
 		}
@@ -1711,15 +1716,13 @@
 	phba->fc_myDID = 0;
 	phba->fc_prevDID = 0;
 
-	psli->sli_flag = 0;
-
 	/* Turn off parity checking and serr during the physical reset */
 	pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
 	pci_write_config_word(phba->pcidev, PCI_COMMAND,
 			      (cfg_value &
 			       ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
 
-	psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+	psli->sli_flag &= ~(LPFC_SLI2_ACTIVE | LPFC_PROCESS_LA);
 	/* Now toggle INITFF bit in the Host Control Register */
 	writel(HC_INITFF, phba->HCregaddr);
 	mdelay(1);
@@ -1760,7 +1763,7 @@
 
 	/* Restart HBA */
 	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-			"%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no,
+			"%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
 			phba->hba_state, psli->sli_flag);
 
 	word0 = 0;
@@ -1792,6 +1795,9 @@
 
 	spin_unlock_irq(phba->host->host_lock);
 
+	memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
+	psli->stats_start = get_seconds();
+
 	if (skip_post)
 		mdelay(100);
 	else
@@ -1902,6 +1908,9 @@
 	}
 
 	while (resetcount < 2 && !done) {
+		spin_lock_irq(phba->host->host_lock);
+		phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
+		spin_unlock_irq(phba->host->host_lock);
 		phba->hba_state = LPFC_STATE_UNKNOWN;
 		lpfc_sli_brdrestart(phba);
 		msleep(2500);
@@ -1909,6 +1918,9 @@
 		if (rc)
 			break;
 
+		spin_lock_irq(phba->host->host_lock);
+		phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+		spin_unlock_irq(phba->host->host_lock);
 		resetcount++;
 
 	/* Call pre CONFIG_PORT mailbox command initialization.  A value of 0
@@ -2194,7 +2206,8 @@
 			return (MBX_NOT_FINISHED);
 		}
 		/* timeout active mbox command */
-		mod_timer(&psli->mbox_tmo, jiffies + HZ * LPFC_MBOX_TMO);
+		mod_timer(&psli->mbox_tmo, (jiffies +
+			       (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
 	}
 
 	/* Mailbox cmd <cmd> issue */
@@ -2254,7 +2267,6 @@
 		break;
 
 	case MBX_POLL:
-		i = 0;
 		psli->mbox_active = NULL;
 		if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
 			/* First read mbox status word */
@@ -2268,11 +2280,14 @@
 		/* Read the HBA Host Attention Register */
 		ha_copy = readl(phba->HAregaddr);
 
+		i = lpfc_mbox_tmo_val(phba, mb->mbxCommand);
+		i *= 1000; /* Convert to ms */
+
 		/* Wait for command to complete */
 		while (((word0 & OWN_CHIP) == OWN_CHIP) ||
 		       (!(ha_copy & HA_MBATT) &&
 			(phba->hba_state > LPFC_WARM_START))) {
-			if (i++ >= 100) {
+			if (i-- <= 0) {
 				psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
 				spin_unlock_irqrestore(phba->host->host_lock,
 						       drvr_flag);
@@ -2290,7 +2305,7 @@
 
 			/* Can be in interrupt context, do not sleep */
 			/* (or might be called with interrupts disabled) */
-			mdelay(i);
+			mdelay(1);
 
 			spin_lock_irqsave(phba->host->host_lock, drvr_flag);
 
@@ -3005,7 +3020,7 @@
 
 		if (timeleft == 0) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-					"%d:0329 IOCB wait timeout error - no "
+					"%d:0338 IOCB wait timeout error - no "
 					"wake response Data x%x\n",
 					phba->brd_no, timeout);
 			retval = IOCB_TIMEDOUT;
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index d8ef0d2..e26de6809 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -172,6 +172,18 @@
 	uint32_t mbox_busy;	 /* Mailbox cmd busy */
 };
 
+/* Structure to store link status values when port stats are reset */
+struct lpfc_lnk_stat {
+	uint32_t link_failure_count;
+	uint32_t loss_of_sync_count;
+	uint32_t loss_of_signal_count;
+	uint32_t prim_seq_protocol_err_count;
+	uint32_t invalid_tx_word_count;
+	uint32_t invalid_crc_count;
+	uint32_t error_frames;
+	uint32_t link_events;
+};
+
 /* Structure used to hold SLI information */
 struct lpfc_sli {
 	uint32_t num_rings;
@@ -201,6 +213,8 @@
 	struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */
 	size_t iocbq_lookup_len;           /* current lengs of the array */
 	uint16_t  last_iotag;              /* last allocated IOTAG */
+	unsigned long  stats_start;        /* in seconds */
+	struct lpfc_lnk_stat lnk_stat_offsets;
 };
 
 /* Given a pointer to the start of the ring, and the slot number of
@@ -211,3 +225,9 @@
 
 #define LPFC_MBOX_TMO           30	/* Sec tmo for outstanding mbox
 					   command */
+#define LPFC_MBOX_TMO_FLASH_CMD 300     /* Sec tmo for outstanding FLASH write
+					 * or erase cmds. This is especially
+					 * long because of the potential of
+					 * multiple flash erases that can be
+					 * spawned.
+					 */
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 10e89c6..c7091ea 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.7"
+#define LPFC_DRIVER_VERSION "8.1.9"
 
 #define LPFC_DRIVER_NAME "lpfc"
 
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index 4675343..8cd0bd1 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -37,6 +37,12 @@
 #define LSI_MAX_CHANNELS		16
 #define LSI_MAX_LOGICAL_DRIVES_64LD	(64+1)
 
+#define HBA_SIGNATURE_64_BIT		0x299
+#define PCI_CONF_AMISIG64		0xa4
+
+#define MEGA_SCSI_INQ_EVPD		1
+#define MEGA_INVALID_FIELD_IN_CDB	0x24
+
 
 /**
  * scb_t - scsi command control block
diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h
index bdaee14..b8aa342 100644
--- a/drivers/scsi/megaraid/megaraid_ioctl.h
+++ b/drivers/scsi/megaraid/megaraid_ioctl.h
@@ -132,6 +132,10 @@
 /* Driver Data: */
 	void __user *		user_data;
 	uint32_t		user_data_len;
+
+	/* 64bit alignment */
+	uint32_t                pad_for_64bit_align;
+
 	mraid_passthru_t	__user *user_pthru;
 
 	mraid_passthru_t	*pthru32;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 9271513..cd982c8 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.8 (Apr 11 2006)
+ * Version	: v2.20.4.9 (Jul 16 2006)
  *
  * Authors:
  * 	Atul Mukker		<Atul.Mukker@lsil.com>
@@ -720,6 +720,7 @@
 	struct pci_dev		*pdev;
 	mraid_device_t		*raid_dev;
 	int			i;
+	uint32_t		magic64;
 
 
 	adapter->ito	= MBOX_TIMEOUT;
@@ -863,12 +864,33 @@
 
 	// Set the DMA mask to 64-bit. All supported controllers as capable of
 	// DMA in this range
-	if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) {
+	pci_read_config_dword(adapter->pdev, PCI_CONF_AMISIG64, &magic64);
 
-		con_log(CL_ANN, (KERN_WARNING
-			"megaraid: could not set DMA mask for 64-bit.\n"));
+	if (((magic64 == HBA_SIGNATURE_64_BIT) &&
+		((adapter->pdev->subsystem_device !=
+		PCI_SUBSYS_ID_MEGARAID_SATA_150_6) ||
+		(adapter->pdev->subsystem_device !=
+		PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) ||
+		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
+		adapter->pdev->device == PCI_DEVICE_ID_VERDE) ||
+		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
+		adapter->pdev->device == PCI_DEVICE_ID_DOBSON) ||
+		(adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC &&
+		adapter->pdev->device == PCI_DEVICE_ID_LINDSAY) ||
+		(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
+		adapter->pdev->device == PCI_DEVICE_ID_PERC4_DI_EVERGLADES) ||
+		(adapter->pdev->vendor == PCI_VENDOR_ID_DELL &&
+		adapter->pdev->device == PCI_DEVICE_ID_PERC4E_DI_KOBUK)) {
+		if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK)) {
+			con_log(CL_ANN, (KERN_WARNING
+				"megaraid: DMA mask for 64-bit failed\n"));
 
-		goto out_free_sysfs_res;
+			if (pci_set_dma_mask (adapter->pdev, DMA_32BIT_MASK)) {
+				con_log(CL_ANN, (KERN_WARNING
+					"megaraid: 32-bit DMA mask failed\n"));
+				goto out_free_sysfs_res;
+			}
+		}
 	}
 
 	// setup tasklet for DPC
@@ -1622,6 +1644,14 @@
 				rdev->last_disp |= (1L << SCP2CHANNEL(scp));
 			}
 
+			if (scp->cmnd[1] & MEGA_SCSI_INQ_EVPD) {
+				scp->sense_buffer[0] = 0x70;
+				scp->sense_buffer[2] = ILLEGAL_REQUEST;
+				scp->sense_buffer[12] = MEGA_INVALID_FIELD_IN_CDB;
+				scp->result = CHECK_CONDITION << 1;
+				return NULL;
+			}
+
 			/* Fall through */
 
 		case READ_CAPACITY:
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 868fb0e..2b5a328 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.8"
-#define MEGARAID_EXT_VERSION	"(Release Date: Mon Apr 11 12:27:22 EST 2006)"
+#define MEGARAID_VERSION	"2.20.4.9"
+#define MEGARAID_EXT_VERSION	"(Release Date: Sun Jul 16 12:27:22 EST 2006)"
 
 
 /*
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index e8f534f..d85b9a8 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mm.c
- * Version	: v2.20.2.6 (Mar 7 2005)
+ * Version	: v2.20.2.7 (Jul 16 2006)
  *
  * Common management module
  */
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index 3d9e67d..c8762b2 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -27,9 +27,9 @@
 #include "megaraid_ioctl.h"
 
 
-#define LSI_COMMON_MOD_VERSION	"2.20.2.6"
+#define LSI_COMMON_MOD_VERSION	"2.20.2.7"
 #define LSI_COMMON_MOD_EXT_VERSION	\
-		"(Release Date: Mon Mar 7 00:01:03 EST 2005)"
+		"(Release Date: Sun Jul 16 00:01:03 EST 2006)"
 
 
 #define LSI_DBGLVL			dbglevel
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index d1f38c3..efc8fff 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -183,7 +183,8 @@
 	{
 		.sht		= &adma_ata_sht,
 		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
-				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO,
+				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
+				  ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
 		.udma_mask	= 0x1f, /* udma0-4 */
 		.port_ops	= &adma_ata_ops,
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 139ea0e..0930260 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -487,6 +487,7 @@
 #define MBA_IP_RCV_BUFFER_EMPTY 0x8026	/* IP receive buffer queue empty. */
 #define MBA_IP_HDR_DATA_SPLIT	0x8027	/* IP header/data splitting feature */
 					/* used. */
+#define MBA_TRACE_NOTIFICATION	0x8028	/* Trace/Diagnostic notification. */
 #define MBA_POINT_TO_POINT	0x8030	/* Point to point mode. */
 #define MBA_CMPLT_1_16BIT	0x8031	/* Completion 1 16bit IOSB. */
 #define MBA_CMPLT_2_16BIT	0x8032	/* Completion 2 16bit IOSB. */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 9758dba..8596491 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3063,6 +3063,7 @@
 int
 qla2x00_abort_isp(scsi_qla_host_t *ha)
 {
+	int rval;
 	unsigned long flags = 0;
 	uint16_t       cnt;
 	srb_t          *sp;
@@ -3119,6 +3120,16 @@
 
 			ha->isp_abort_cnt = 0;
 			clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
+
+			if (ha->eft) {
+				rval = qla2x00_trace_control(ha, TC_ENABLE,
+				    ha->eft_dma, EFT_NUM_BUFFERS);
+				if (rval) {
+					qla_printk(KERN_WARNING, ha,
+					    "Unable to reinitialize EFT "
+					    "(%d).\n", rval);
+				}
+			}
 		} else {	/* failed the ISP abort */
 			ha->flags.online = 1;
 			if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2b60a27..c5b3c61 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -471,6 +471,7 @@
 			mrk24->nport_handle = cpu_to_le16(loop_id);
 			mrk24->lun[1] = LSB(lun);
 			mrk24->lun[2] = MSB(lun);
+			host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
 		} else {
 			SET_TARGET_ID(ha, mrk->target, loop_id);
 			mrk->lun = cpu_to_le16(lun);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 795bf15..de06131 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -587,6 +587,11 @@
 		DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x "
 		    "%04x.\n", ha->host_no, mb[1], mb[2], mb[3]));
 		break;
+
+	case MBA_TRACE_NOTIFICATION:
+		DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
+		ha->host_no, mb[1], mb[2]));
+		break;
 	}
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index ec7ebb6..65cbe2f 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -744,7 +744,6 @@
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	srb_t *sp;
 	int ret;
 	unsigned int id, lun;
 	unsigned long serial;
@@ -755,8 +754,7 @@
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
 
-	sp = (srb_t *) CMD_SP(cmd);
-	if (!sp || !fcport)
+	if (!fcport)
 		return ret;
 
 	qla_printk(KERN_INFO, ha,
@@ -875,7 +873,6 @@
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	srb_t *sp;
 	int ret;
 	unsigned int id, lun;
 	unsigned long serial;
@@ -886,8 +883,7 @@
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
 
-	sp = (srb_t *) CMD_SP(cmd);
-	if (!sp || !fcport)
+	if (!fcport)
 		return ret;
 
 	qla_printk(KERN_INFO, ha,
@@ -936,7 +932,6 @@
 {
 	scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
-	srb_t *sp;
 	int ret;
 	unsigned int id, lun;
 	unsigned long serial;
@@ -947,8 +942,7 @@
 	lun = cmd->device->lun;
 	serial = cmd->serial_number;
 
-	sp = (srb_t *) CMD_SP(cmd);
-	if (!sp || !fcport)
+	if (!fcport)
 		return ret;
 
 	qla_printk(KERN_INFO, ha,
@@ -2244,9 +2238,6 @@
 
 			next_loopid = 0;
 			list_for_each_entry(fcport, &ha->fcports, list) {
-				if (fcport->port_type != FCT_TARGET)
-					continue;
-
 				/*
 				 * If the port is not ONLINE then try to login
 				 * to it if we haven't run out of retries.
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index d2d6834..9712590 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.05-k3"
+#define QLA2XXX_VERSION      "8.01.07-k1"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
-#define QLA_DRIVER_PATCH_VER	5
+#define QLA_DRIVER_PATCH_VER	7
 #define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 1053c7c..fa38a41 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1961,8 +1961,7 @@
 	timeout = jiffies + msecs_to_jiffies(200);
 	do {
 		sata_scr_read(ap, SCR_STATUS, &sstatus);
-		sstatus &= 0x3;
-		if ((sstatus == 3) || (sstatus == 0))
+		if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
 			break;
 
 		__msleep(1, can_sleep);
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 64631bd..4776f4e 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -269,8 +269,15 @@
 	{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20619 },
 
+/* TODO: remove all associated board_20771 code, as it completely
+ * duplicates board_2037x code, unless reason for separation can be
+ * divined.
+ */
+#if 0
 	{ PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20771 },
+#endif
+
 	{ }	/* terminate list */
 };
 
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 2e0f4a4..3f368c7 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -1106,7 +1106,6 @@
 
 	probe_ent->irq = pdev->irq;
 	probe_ent->irq_flags = IRQF_SHARED;
-	probe_ent->mmio_base = port_base;
 	probe_ent->private_data = hpriv;
 
 	hpriv->host_base = host_base;
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 03baec2..a3727af 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -74,8 +74,10 @@
 static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void vt6420_error_handler(struct ata_port *ap);
 
 static const struct pci_device_id svia_pci_tbl[] = {
+	{ 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
 	{ 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
 	{ 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
 
@@ -107,7 +109,38 @@
 	.bios_param		= ata_std_bios_param,
 };
 
-static const struct ata_port_operations svia_sata_ops = {
+static const struct ata_port_operations vt6420_sata_ops = {
+	.port_disable		= ata_port_disable,
+
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
+
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_pio_data_xfer,
+
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= vt6420_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+
+	.irq_handler		= ata_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= ata_host_stop,
+};
+
+static const struct ata_port_operations vt6421_sata_ops = {
 	.port_disable		= ata_port_disable,
 
 	.tf_load		= ata_tf_load,
@@ -141,13 +174,13 @@
 	.host_stop		= ata_host_stop,
 };
 
-static struct ata_port_info svia_port_info = {
+static struct ata_port_info vt6420_port_info = {
 	.sht		= &svia_sht,
 	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
 	.udma_mask	= 0x7f,
-	.port_ops	= &svia_sata_ops,
+	.port_ops	= &vt6420_sata_ops,
 };
 
 MODULE_AUTHOR("Jeff Garzik");
@@ -170,6 +203,81 @@
 	outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
 }
 
+/**
+ *	vt6420_prereset - prereset for vt6420
+ *	@ap: target ATA port
+ *
+ *	SCR registers on vt6420 are pieces of shit and may hang the
+ *	whole machine completely if accessed with the wrong timing.
+ *	To avoid such catastrophe, vt6420 doesn't provide generic SCR
+ *	access operations, but uses SStatus and SControl only during
+ *	boot probing in controlled way.
+ *
+ *	As the old (pre EH update) probing code is proven to work, we
+ *	strictly follow the access pattern.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise.
+ */
+static int vt6420_prereset(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	unsigned long timeout = jiffies + (HZ * 5);
+	u32 sstatus, scontrol;
+	int online;
+
+	/* don't do any SCR stuff if we're not loading */
+	if (!ATA_PFLAG_LOADING)
+		goto skip_scr;
+
+	/* Resume phy.  This is the old resume sequence from
+	 * __sata_phy_reset().
+	 */
+	svia_scr_write(ap, SCR_CONTROL, 0x300);
+	svia_scr_read(ap, SCR_CONTROL); /* flush */
+
+	/* wait for phy to become ready, if necessary */
+	do {
+		msleep(200);
+		if ((svia_scr_read(ap, SCR_STATUS) & 0xf) != 1)
+			break;
+	} while (time_before(jiffies, timeout));
+
+	/* open code sata_print_link_status() */
+	sstatus = svia_scr_read(ap, SCR_STATUS);
+	scontrol = svia_scr_read(ap, SCR_CONTROL);
+
+	online = (sstatus & 0xf) == 0x3;
+
+	ata_port_printk(ap, KERN_INFO,
+			"SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n",
+			online ? "up" : "down", sstatus, scontrol);
+
+	/* SStatus is read one more time */
+	svia_scr_read(ap, SCR_STATUS);
+
+	if (!online) {
+		/* tell EH to bail */
+		ehc->i.action &= ~ATA_EH_RESET_MASK;
+		return 0;
+	}
+
+ skip_scr:
+	/* wait for !BSY */
+	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	return 0;
+}
+
+static void vt6420_error_handler(struct ata_port *ap)
+{
+	return ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset,
+				  NULL, ata_std_postreset);
+}
+
 static const unsigned int svia_bar_sizes[] = {
 	8, 4, 8, 4, 16, 256
 };
@@ -210,7 +318,7 @@
 static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
 {
 	struct ata_probe_ent *probe_ent;
-	struct ata_port_info *ppi = &svia_port_info;
+	struct ata_port_info *ppi = &vt6420_port_info;
 
 	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
@@ -239,7 +347,7 @@
 
 	probe_ent->sht		= &svia_sht;
 	probe_ent->host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
-	probe_ent->port_ops	= &svia_sata_ops;
+	probe_ent->port_ops	= &vt6421_sata_ops;
 	probe_ent->n_ports	= N_PORTS;
 	probe_ent->irq		= pdev->irq;
 	probe_ent->irq_flags	= IRQF_SHARED;
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 6a5b731..a8ed5a2 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -460,7 +460,8 @@
  * Return value:
  *    SUCCESS or FAILED or NEEDS_RETRY
  **/
-static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense)
+static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
+			     int cmnd_size, int timeout, int copy_sense)
 {
 	struct scsi_device *sdev = scmd->device;
 	struct Scsi_Host *shost = sdev->host;
@@ -490,6 +491,9 @@
 	old_cmd_len = scmd->cmd_len;
 	old_use_sg = scmd->use_sg;
 
+	memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+	memcpy(scmd->cmnd, cmnd, cmnd_size);
+
 	if (copy_sense) {
 		int gfp_mask = GFP_ATOMIC;
 
@@ -610,8 +614,7 @@
 	static unsigned char generic_sense[6] =
 		{REQUEST_SENSE, 0, 0, 0, 252, 0};
 
-	memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense));
-	return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1);
+	return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1);
 }
 
 /**
@@ -736,10 +739,7 @@
 	int retry_cnt = 1, rtn;
 
 retry_tur:
-	memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
-
-
-	rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0);
+	rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
 		__FUNCTION__, scmd, rtn));
@@ -839,8 +839,8 @@
 	if (scmd->device->allow_restart) {
 		int rtn;
 
-		memcpy(scmd->cmnd, stu_command, sizeof(stu_command));
-		rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0);
+		rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
+					START_UNIT_TIMEOUT, 0);
 		if (rtn == SUCCESS)
 			return 0;
 	}
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index a89c411..32293f4 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -110,11 +110,8 @@
 				       sshdr.asc, sshdr.ascq);
 			break;
 		case NOT_READY:	/* This happens if there is no disc in drive */
-			if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) {
-				printk(KERN_INFO "Device not ready. Make sure"
-				       " there is a disc in the drive.\n");
+			if (sdev->removable)
 				break;
-			}
 		case UNIT_ATTENTION:
 			if (sdev->removable) {
 				sdev->changed = 1;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 7b9e8fa..2ecd141 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -34,6 +34,7 @@
 #define ISCSI_SESSION_ATTRS 11
 #define ISCSI_CONN_ATTRS 11
 #define ISCSI_HOST_ATTRS 0
+#define ISCSI_TRANSPORT_VERSION "1.1-646"
 
 struct iscsi_internal {
 	int daemon_pid;
@@ -634,13 +635,13 @@
 }
 
 static int
-iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb)
+iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp)
 {
 	unsigned long flags;
 	int rc;
 
 	skb_get(skb);
-	rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL);
+	rc = netlink_broadcast(nls, skb, 0, 1, gfp);
 	if (rc < 0) {
 		mempool_free(skb, zone->pool);
 		printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
@@ -749,7 +750,7 @@
 	ev->r.connerror.cid = conn->cid;
 	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
 
-	iscsi_broadcast_skb(conn->z_error, skb);
+	iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC);
 
 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
 		   error);
@@ -895,7 +896,7 @@
 	 * this will occur if the daemon is not up, so we just warn
 	 * the user and when the daemon is restarted it will handle it
 	 */
-	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
+	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
 	if (rc < 0)
 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
 			  "session destruction event. Check iscsi daemon\n");
@@ -958,7 +959,7 @@
 	 * this will occur if the daemon is not up, so we just warn
 	 * the user and when the daemon is restarted it will handle it
 	 */
-	rc = iscsi_broadcast_skb(conn->z_pdu, skb);
+	rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL);
 	if (rc < 0)
 		dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of "
 			  "session creation event. Check iscsi daemon\n");
@@ -1613,6 +1614,9 @@
 {
 	int err;
 
+	printk(KERN_INFO "Loading iSCSI transport class v%s.",
+		ISCSI_TRANSPORT_VERSION);
+
 	err = class_register(&iscsi_transport_class);
 	if (err)
 		return err;
@@ -1678,3 +1682,4 @@
 	      "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI Transport Interface");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 65eef338..34f9343e 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -18,8 +18,8 @@
  *
  */
 
-static int sg_version_num = 30533;	/* 2 digits for each component */
-#define SG_VERSION_STR "3.5.33"
+static int sg_version_num = 30534;	/* 2 digits for each component */
+#define SG_VERSION_STR "3.5.34"
 
 /*
  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
@@ -60,7 +60,7 @@
 
 #ifdef CONFIG_SCSI_PROC_FS
 #include <linux/proc_fs.h>
-static char *sg_version_date = "20050908";
+static char *sg_version_date = "20060818";
 
 static int sg_proc_init(void);
 static void sg_proc_cleanup(void);
@@ -1164,7 +1164,7 @@
 		len = vma->vm_end - sa;
 		len = (len < sg->length) ? len : sg->length;
 		if (offset < len) {
-			page = sg->page;
+			page = virt_to_page(page_address(sg->page) + offset);
 			get_page(page);	/* increment page count */
 			break;
 		}
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 8c50507..739d3ef 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -2084,7 +2084,7 @@
 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C860,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1510,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI<<8,  0xffff00, 0UL },
 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C896,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C895,
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index a1d322f..851e483 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -458,11 +458,11 @@
  * growing *huge*, we use this function to collapse some 70 entries
  * in the PCI table into one, for sanity's and compactness's sake.
  */
-static unsigned short timedia_single_port[] = {
+static const unsigned short timedia_single_port[] = {
 	0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0
 };
 
-static unsigned short timedia_dual_port[] = {
+static const unsigned short timedia_dual_port[] = {
 	0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
 	0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 
 	0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, 
@@ -470,35 +470,34 @@
 	0xD079, 0
 };
 
-static unsigned short timedia_quad_port[] = {
+static const unsigned short timedia_quad_port[] = {
 	0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 
 	0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 
 	0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
 	0xB157, 0
 };
 
-static unsigned short timedia_eight_port[] = {
+static const unsigned short timedia_eight_port[] = {
 	0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 
 	0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
 };
 
 static const struct timedia_struct {
 	int num;
-	unsigned short *ids;
+	const unsigned short *ids;
 } timedia_data[] = {
 	{ 1, timedia_single_port },
 	{ 2, timedia_dual_port },
 	{ 4, timedia_quad_port },
-	{ 8, timedia_eight_port },
-	{ 0, NULL }
+	{ 8, timedia_eight_port }
 };
 
 static int pci_timedia_init(struct pci_dev *dev)
 {
-	unsigned short *ids;
+	const unsigned short *ids;
 	int i, j;
 
-	for (i = 0; timedia_data[i].num; i++) {
+	for (i = 0; i < ARRAY_SIZE(timedia_data); i++) {
 		ids = timedia_data[i].ids;
 		for (j = 0; ids[j]; j++)
 			if (dev->subsystem_device == ids[j])
@@ -936,6 +935,7 @@
 	pbn_b1_8_1382400,
 
 	pbn_b2_1_115200,
+	pbn_b2_2_115200,
 	pbn_b2_8_115200,
 
 	pbn_b2_1_460800,
@@ -1243,6 +1243,12 @@
 		.base_baud	= 115200,
 		.uart_offset	= 8,
 	},
+	[pbn_b2_2_115200] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
 	[pbn_b2_8_115200] = {
 		.flags		= FL_BASE2,
 		.num_ports	= 8,
@@ -2340,6 +2346,13 @@
 		pbn_b0_1_115200 },
 
 	/*
+	 * IntaShield IS-200
+	 */
+	{	PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,	/* 135a.0811 */
+		pbn_b2_2_115200 },
+
+	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
 	 */
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 80ef7d4..372e47f 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2377,6 +2377,9 @@
 		return (port1->iobase == port2->iobase) &&
 		       (port1->hub6   == port2->hub6);
 	case UPIO_MEM:
+	case UPIO_MEM32:
+	case UPIO_AU:
+	case UPIO_TSI:
 		return (port1->mapbase == port2->mapbase);
 	}
 	return 0;
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index dc673e1..cfe20f7 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -886,6 +886,15 @@
 	unsigned long flags;
 	unsigned int baud, quot;
 
+	/*
+	 * The console framework calls us for each and every port
+	 * registered. Defer the console setup until the requested
+	 * port has been properly discovered. A bit of a hack,
+	 * though...
+	 */
+	if (up->port.type != PORT_SUNSAB)
+		return -1;
+
 	printk("Console: ttyS%d (SAB82532)\n",
 	       (sunsab_reg.minor - 64) + con->index);
 
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 47bc3d5..d34f336 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1146,6 +1146,9 @@
 	unsigned long flags;
 	int baud, brg;
 
+	if (up->port.type != PORT_SUNZILOG)
+		return -1;
+
 	printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
 	       (sunzilog_reg.minor - 64) + con->index, con->index);
 
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 2ee742d..0050431 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -24,7 +24,7 @@
 	default y if ARCH_S3C2410
 	default y if PXA27x
 	default y if ARCH_EP93XX
-	default y if ARCH_AT91RM9200
+	default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
 	# PPC:
 	default y if STB03xxx
 	default y if PPC_MPC52xx
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f7bdd94..218621b 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -517,19 +517,19 @@
 
 static struct usb_device *usbdev_lookup_minor(int minor)
 {
-	struct device *device;
-	struct usb_device *udev = NULL;
+	struct class_device *class_dev;
+	struct usb_device *dev = NULL;
 
 	down(&usb_device_class->sem);
-	list_for_each_entry(device, &usb_device_class->devices, node) {
-		if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
-			udev = device->platform_data;
+	list_for_each_entry(class_dev, &usb_device_class->children, node) {
+		if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+			dev = class_dev->class_data;
 			break;
 		}
 	}
 	up(&usb_device_class->sem);
 
-	return udev;
+	return dev;
 };
 
 /*
@@ -1580,16 +1580,16 @@
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
-	dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
-				MKDEV(USB_DEVICE_MAJOR, minor),
+	dev->class_dev = class_device_create(usb_device_class, NULL,
+				MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
 
-	dev->usbfs_dev->platform_data = dev;
+	dev->class_dev->class_data = dev;
 }
 
 static void usbdev_remove(struct usb_device *dev)
 {
-	device_unregister(dev->usbfs_dev);
+	class_device_unregister(dev->class_dev);
 }
 
 static int usbdev_notify(struct notifier_block *self, unsigned long action,
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index abee0f5..8de4f8c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -194,13 +194,14 @@
 		++temp;
 	else
 		temp = name;
-	intf->usb_dev = device_create(usb_class->class, &intf->dev,
-				      MKDEV(USB_MAJOR, minor), "%s", temp);
-	if (IS_ERR(intf->usb_dev)) {
+	intf->class_dev = class_device_create(usb_class->class, NULL,
+					      MKDEV(USB_MAJOR, minor),
+					      &intf->dev, "%s", temp);
+	if (IS_ERR(intf->class_dev)) {
 		spin_lock (&minor_lock);
 		usb_minors[intf->minor] = NULL;
 		spin_unlock (&minor_lock);
-		retval = PTR_ERR(intf->usb_dev);
+		retval = PTR_ERR(intf->class_dev);
 	}
 exit:
 	return retval;
@@ -241,8 +242,8 @@
 	spin_unlock (&minor_lock);
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
-	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
-	intf->usb_dev = NULL;
+	class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
+	intf->class_dev = NULL;
 	intf->minor = -1;
 	destroy_usb_class();
 }
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 363b2ad..1a32d96 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -207,7 +207,7 @@
 
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
-	depends on USB && EXPERIMENTAL
+	depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
 	select USB_GADGET_DUALSPEED
 	help
 	  This host controller driver emulates USB, looping all data transfer
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 1c459ff..cfebca0 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -57,19 +57,23 @@
 
 /*
  * This controller is simple and PIO-only.  It's used in many AT91-series
- * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU),
- * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions.
+ * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
+ * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
  *
  * This driver expects the board has been wired with two GPIOs suppporting
  * a VBUS sensing IRQ, and a D+ pullup.  (They may be omitted, but the
- * testing hasn't covered such cases.)  The pullup is most important; it
+ * testing hasn't covered such cases.)
+ *
+ * The pullup is most important (so it's integrated on sam926x parts).  It
  * provides software control over whether the host enumerates the device.
+ *
  * The VBUS sensing helps during enumeration, and allows both USB clocks
  * (and the transceiver) to stay gated off until they're necessary, saving
- * power.  During USB suspend, the 48 MHz clock is gated off.
+ * power.  During USB suspend, the 48 MHz clock is gated off in hardware;
+ * it may also be gated off by software during some Linux sleep states.
  */
 
-#define	DRIVER_VERSION	"8 March 2005"
+#define	DRIVER_VERSION	"3 May 2006"
 
 static const char driver_name [] = "at91_udc";
 static const char ep0name[] = "ep0";
@@ -316,9 +320,15 @@
  *
  * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
  * that shouldn't normally be changed.
+ *
+ * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
+ * implying a need to wait for one write to complete (test relevant bits)
+ * before starting the next write.  This shouldn't be an issue given how
+ * infrequently we write, except maybe for write-then-read idioms.
  */
 #define	SET_FX	(AT91_UDP_TXPKTRDY)
-#define	CLR_FX	(RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
+#define	CLR_FX	(RX_DATA_READY | AT91_UDP_RXSETUP \
+		| AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
 
 /* pull OUT packet data from the endpoint's fifo */
 static int read_fifo (struct at91_ep *ep, struct at91_request *req)
@@ -472,7 +482,8 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
+static int at91_ep_enable(struct usb_ep *_ep,
+				const struct usb_endpoint_descriptor *desc)
 {
 	struct at91_ep	*ep = container_of(_ep, struct at91_ep, ep);
 	struct at91_udc	*dev = ep->udc;
@@ -582,11 +593,12 @@
  * interesting for request or buffer allocation.
  */
 
-static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags)
+static struct usb_request *
+at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
 {
 	struct at91_request *req;
 
-	req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL);
+	req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
 	if (!req)
 		return NULL;
 
@@ -862,6 +874,7 @@
 	if (udc->gadget.speed == USB_SPEED_UNKNOWN)
 		driver = NULL;
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->suspended = 0;
 
 	for (i = 0; i < NUM_ENDPOINTS; i++) {
 		struct at91_ep *ep = &udc->ep[i];
@@ -889,8 +902,8 @@
 		return;
 	udc->clocked = 0;
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
-	clk_disable(udc->iclk);
 	clk_disable(udc->fclk);
+	clk_disable(udc->iclk);
 }
 
 /*
@@ -911,9 +924,6 @@
 		at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 		at91_set_gpio_value(udc->board.pullup_pin, 0);
 		clk_off(udc);
-
-		// REVISIT:  with transceiver disabled, will D- float
-		// so that a host would falsely detect a device?
 	}
 }
 
@@ -1290,7 +1300,8 @@
 			if (udc->wait_for_addr_ack) {
 				u32	tmp;
 
-				at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr);
+				at91_udp_write(AT91_UDP_FADDR,
+						AT91_UDP_FEN | udc->addr);
 				tmp = at91_udp_read(AT91_UDP_GLB_STAT);
 				tmp &= ~AT91_UDP_FADDEN;
 				if (udc->addr)
@@ -1361,9 +1372,10 @@
 	u32			rescans = 5;
 
 	while (rescans--) {
-		u32	status = at91_udp_read(AT91_UDP_ISR);
+		u32 status;
 
-		status &= at91_udp_read(AT91_UDP_IMR);
+		status = at91_udp_read(AT91_UDP_ISR)
+			& at91_udp_read(AT91_UDP_IMR);
 		if (!status)
 			break;
 
@@ -1379,18 +1391,17 @@
 			stop_activity(udc);
 
 			/* enable ep0 */
-			at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
+			at91_udp_write(AT91_UDP_CSR(0),
+					AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
 			udc->gadget.speed = USB_SPEED_FULL;
 			udc->suspended = 0;
 			at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
 
 			/*
 			 * NOTE:  this driver keeps clocks off unless the
-			 * USB host is present.  That saves power, and also
-			 * eliminates IRQs (reset, resume, suspend) that can
-			 * otherwise flood from the controller.  If your
-			 * board doesn't support VBUS detection, suspend and
-			 * resume irq logic may need more attention...
+			 * USB host is present.  That saves power, but for
+			 * boards that don't support VBUS detection, both
+			 * clocks need to be active most of the time.
 			 */
 
 		/* host initiated suspend (3+ms bus idle) */
@@ -1452,13 +1463,19 @@
 
 /*-------------------------------------------------------------------------*/
 
+static void nop_release(struct device *dev)
+{
+	/* nothing to free */
+}
+
 static struct at91_udc controller = {
 	.gadget = {
-		.ops = &at91_udc_ops,
-		.ep0 = &controller.ep[0].ep,
-		.name = driver_name,
-		.dev = {
-			.bus_id = "gadget"
+		.ops	= &at91_udc_ops,
+		.ep0	= &controller.ep[0].ep,
+		.name	= driver_name,
+		.dev	= {
+			.bus_id = "gadget",
+			.release = nop_release,
 		}
 	},
 	.ep[0] = {
@@ -1468,7 +1485,8 @@
 		},
 		.udc		= &controller,
 		.maxpacket	= 8,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(0)),
 		.int_mask	= 1 << 0,
 	},
 	.ep[1] = {
@@ -1479,7 +1497,8 @@
 		.udc		= &controller,
 		.is_pingpong	= 1,
 		.maxpacket	= 64,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(1)),
 		.int_mask	= 1 << 1,
 	},
 	.ep[2] = {
@@ -1490,7 +1509,8 @@
 		.udc		= &controller,
 		.is_pingpong	= 1,
 		.maxpacket	= 64,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(2)),
 		.int_mask	= 1 << 2,
 	},
 	.ep[3] = {
@@ -1501,7 +1521,8 @@
 		},
 		.udc		= &controller,
 		.maxpacket	= 8,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(3)),
 		.int_mask	= 1 << 3,
 	},
 	.ep[4] = {
@@ -1512,7 +1533,8 @@
 		.udc		= &controller,
 		.is_pingpong	= 1,
 		.maxpacket	= 256,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(4)),
 		.int_mask	= 1 << 4,
 	},
 	.ep[5] = {
@@ -1523,10 +1545,11 @@
 		.udc		= &controller,
 		.is_pingpong	= 1,
 		.maxpacket	= 256,
-		.creg		= (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)),
+		.creg		= (void __iomem *)(AT91_VA_BASE_UDP
+					+ AT91_UDP_CSR(5)),
 		.int_mask	= 1 << 5,
 	},
-	/* ep6 and ep7 are also reserved */
+	/* ep6 and ep7 are also reserved (custom silicon might use them) */
 };
 
 static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r)
@@ -1593,6 +1616,7 @@
 
 	local_irq_disable();
 	udc->enabled = 0;
+	at91_udp_write(AT91_UDP_IDR, ~0);
 	pullup(udc, 0);
 	local_irq_enable();
 
@@ -1624,6 +1648,16 @@
 		return -ENODEV;
 	}
 
+	if (pdev->num_resources != 2) {
+		DBG("invalid num_resources");
+		return -ENODEV;
+	}
+	if ((pdev->resource[0].flags != IORESOURCE_MEM)
+			|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
+		DBG("invalid resource type");
+		return -ENODEV;
+	}
+
 	if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) {
 		DBG("someone's using UDC memory\n");
 		return -EBUSY;
@@ -1649,19 +1683,26 @@
 	if (retval < 0)
 		goto fail0;
 
-	/* disable everything until there's a gadget driver and vbus */
-	pullup(udc, 0);
+	/* don't do anything until we have both gadget driver and VBUS */
+	clk_enable(udc->iclk);
+	at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+	at91_udp_write(AT91_UDP_IDR, 0xffffffff);
+	clk_disable(udc->iclk);
 
 	/* request UDC and maybe VBUS irqs */
-	if (request_irq(AT91_ID_UDP, at91_udc_irq, IRQF_DISABLED, driver_name, udc)) {
-		DBG("request irq %d failed\n", AT91_ID_UDP);
+	udc->udp_irq = platform_get_irq(pdev, 0);
+	if (request_irq(udc->udp_irq, at91_udc_irq,
+			IRQF_DISABLED, driver_name, udc)) {
+		DBG("request irq %d failed\n", udc->udp_irq);
 		retval = -EBUSY;
 		goto fail1;
 	}
 	if (udc->board.vbus_pin > 0) {
-		if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) {
-			DBG("request vbus irq %d failed\n", udc->board.vbus_pin);
-			free_irq(AT91_ID_UDP, udc);
+		if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
+				IRQF_DISABLED, driver_name, udc)) {
+			DBG("request vbus irq %d failed\n",
+					udc->board.vbus_pin);
+			free_irq(udc->udp_irq, udc);
 			retval = -EBUSY;
 			goto fail1;
 		}
@@ -1670,6 +1711,7 @@
 		udc->vbus = 1;
 	}
 	dev_set_drvdata(dev, udc);
+	device_init_wakeup(dev, 1);
 	create_debug_file(udc);
 
 	INFO("%s version %s\n", driver_name, DRIVER_VERSION);
@@ -1678,14 +1720,14 @@
 fail1:
 	device_unregister(&udc->gadget.dev);
 fail0:
-	release_mem_region(AT91_VA_BASE_UDP, SZ_16K);
+	release_mem_region(AT91_BASE_UDP, SZ_16K);
 	DBG("%s probe failed, %d\n", driver_name, retval);
 	return retval;
 }
 
-static int __devexit at91udc_remove(struct platform_device *dev)
+static int __devexit at91udc_remove(struct platform_device *pdev)
 {
-	struct at91_udc *udc = platform_get_drvdata(dev);
+	struct at91_udc *udc = platform_get_drvdata(pdev);
 
 	DBG("remove\n");
 
@@ -1694,10 +1736,11 @@
 	if (udc->driver != 0)
 		usb_gadget_unregister_driver(udc->driver);
 
+	device_init_wakeup(&pdev->dev, 0);
 	remove_debug_file(udc);
 	if (udc->board.vbus_pin > 0)
 		free_irq(udc->board.vbus_pin, udc);
-	free_irq(AT91_ID_UDP, udc);
+	free_irq(udc->udp_irq, udc);
 	device_unregister(&udc->gadget.dev);
 	release_mem_region(AT91_BASE_UDP, SZ_16K);
 
@@ -1708,31 +1751,36 @@
 }
 
 #ifdef CONFIG_PM
-static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg)
+static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
-	struct at91_udc *udc = platform_get_drvdata(dev);
+	struct at91_udc *udc = platform_get_drvdata(pdev);
+	int		wake = udc->driver && device_may_wakeup(&pdev->dev);
 
-	/*
-	 * The "safe" suspend transitions are opportunistic ... e.g. when
-	 * the USB link is suspended (48MHz clock autogated off), or when
-	 * it's disconnected (programmatically gated off, elsewhere).
-	 * Then we can suspend, and the chip can enter slow clock mode.
-	 *
-	 * The problem case is some component (user mode?) suspending this
-	 * device while it's active, with the 48 MHz clock in use.  There
-	 * are two basic approaches:  (a) veto suspend levels involving slow
-	 * clock mode, (b) disconnect, so 48 MHz will no longer be in use
-	 * and we can enter slow clock mode.  This uses (b) for now, since
-	 * it's simplest until AT91 PM exists and supports the other option.
+	/* Unless we can act normally to the host (letting it wake us up
+	 * whenever it has work for us) force disconnect.  Wakeup requires
+	 * PLLB for USB events (signaling for reset, wakeup, or incoming
+	 * tokens) and VBUS irqs (on systems which support them).
 	 */
-	if (udc->vbus && !udc->suspended)
+	if ((!udc->suspended && udc->addr)
+			|| !wake
+			|| at91_suspend_entering_slow_clock()) {
 		pullup(udc, 0);
+		disable_irq_wake(udc->udp_irq);
+	} else
+		enable_irq_wake(udc->udp_irq);
+
+	if (udc->board.vbus_pin > 0) {
+		if (wake)
+			enable_irq_wake(udc->board.vbus_pin);
+		else
+			disable_irq_wake(udc->board.vbus_pin);
+	}
 	return 0;
 }
 
-static int at91udc_resume(struct platform_device *dev)
+static int at91udc_resume(struct platform_device *pdev)
 {
-	struct at91_udc *udc = platform_get_drvdata(dev);
+	struct at91_udc *udc = platform_get_drvdata(pdev);
 
 	/* maybe reconnect to host; if so, clocks on */
 	pullup(udc, 1);
@@ -1748,7 +1796,7 @@
 	.remove		= __devexit_p(at91udc_remove),
 	.shutdown	= at91udc_shutdown,
 	.suspend	= at91udc_suspend,
-	.resume 	= at91udc_resume,
+	.resume		= at91udc_resume,
 	.driver		= {
 		.name	= (char *) driver_name,
 		.owner	= THIS_MODULE,
@@ -1767,6 +1815,6 @@
 }
 module_exit(udc_exit_module);
 
-MODULE_DESCRIPTION("AT91RM9200 udc driver");
+MODULE_DESCRIPTION("AT91 udc driver");
 MODULE_AUTHOR("Thomas Rathbone, David Brownell");
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 5a4799c..882af42 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -141,6 +141,7 @@
 	struct clk			*iclk, *fclk;
 	struct platform_device		*pdev;
 	struct proc_dir_entry		*pde;
+	int				udp_irq;
 };
 
 static inline struct at91_udc *to_udc(struct usb_gadget *g)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4be4719..7d1c22c 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -609,7 +609,8 @@
 	if (!dum->driver)
 		return -ESHUTDOWN;
 
-	spin_lock_irqsave (&dum->lock, flags);
+	local_irq_save (flags);
+	spin_lock (&dum->lock);
 	list_for_each_entry (req, &ep->queue, queue) {
 		if (&req->req == _req) {
 			list_del_init (&req->queue);
@@ -618,7 +619,7 @@
 			break;
 		}
 	}
-	spin_unlock_irqrestore (&dum->lock, flags);
+	spin_unlock (&dum->lock);
 
 	if (retval == 0) {
 		dev_dbg (udc_dev(dum),
@@ -626,6 +627,7 @@
 				req, _ep->name, _req->length, _req->buf);
 		_req->complete (_ep, _req);
 	}
+	local_irq_restore (flags);
 	return retval;
 }
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 4fe1bec..30299c6 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -117,6 +117,8 @@
 	struct usb_ep		*in_ep, *out_ep, *status_ep;
 	const struct usb_endpoint_descriptor
 				*in, *out, *status;
+
+	spinlock_t		req_lock;
 	struct list_head	tx_reqs, rx_reqs;
 
 	struct net_device	*net;
@@ -1066,21 +1068,31 @@
 	 */
 	if (dev->in) {
 		usb_ep_disable (dev->in_ep);
+		spin_lock(&dev->req_lock);
 		while (likely (!list_empty (&dev->tx_reqs))) {
 			req = container_of (dev->tx_reqs.next,
 						struct usb_request, list);
 			list_del (&req->list);
+
+			spin_unlock(&dev->req_lock);
 			usb_ep_free_request (dev->in_ep, req);
+			spin_lock(&dev->req_lock);
 		}
+		spin_unlock(&dev->req_lock);
 	}
 	if (dev->out) {
 		usb_ep_disable (dev->out_ep);
+		spin_lock(&dev->req_lock);
 		while (likely (!list_empty (&dev->rx_reqs))) {
 			req = container_of (dev->rx_reqs.next,
 						struct usb_request, list);
 			list_del (&req->list);
+
+			spin_unlock(&dev->req_lock);
 			usb_ep_free_request (dev->out_ep, req);
+			spin_lock(&dev->req_lock);
 		}
+		spin_unlock(&dev->req_lock);
 	}
 
 	if (dev->status) {
@@ -1659,9 +1671,9 @@
 	if (retval) {
 		DEBUG (dev, "rx submit --> %d\n", retval);
 		dev_kfree_skb_any (skb);
-		spin_lock (&dev->lock);
+		spin_lock(&dev->req_lock);
 		list_add (&req->list, &dev->rx_reqs);
-		spin_unlock (&dev->lock);
+		spin_unlock(&dev->req_lock);
 	}
 	return retval;
 }
@@ -1730,8 +1742,9 @@
 		dev_kfree_skb_any (skb);
 	if (!netif_running (dev->net)) {
 clean:
-		/* nobody reading rx_reqs, so no dev->lock */
+		spin_lock(&dev->req_lock);
 		list_add (&req->list, &dev->rx_reqs);
+		spin_unlock(&dev->req_lock);
 		req = NULL;
 	}
 	if (req)
@@ -1782,15 +1795,18 @@
 {
 	int status;
 
+	spin_lock(&dev->req_lock);
 	status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags);
 	if (status < 0)
 		goto fail;
 	status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags);
 	if (status < 0)
 		goto fail;
-	return 0;
+	goto done;
 fail:
 	DEBUG (dev, "can't alloc requests\n");
+done:
+	spin_unlock(&dev->req_lock);
 	return status;
 }
 
@@ -1800,21 +1816,21 @@
 	unsigned long		flags;
 
 	/* fill unused rxq slots with some skb */
-	spin_lock_irqsave (&dev->lock, flags);
+	spin_lock_irqsave(&dev->req_lock, flags);
 	while (!list_empty (&dev->rx_reqs)) {
 		req = container_of (dev->rx_reqs.next,
 				struct usb_request, list);
 		list_del_init (&req->list);
-		spin_unlock_irqrestore (&dev->lock, flags);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
 
 		if (rx_submit (dev, req, gfp_flags) < 0) {
 			defer_kevent (dev, WORK_RX_MEMORY);
 			return;
 		}
 
-		spin_lock_irqsave (&dev->lock, flags);
+		spin_lock_irqsave(&dev->req_lock, flags);
 	}
-	spin_unlock_irqrestore (&dev->lock, flags);
+	spin_unlock_irqrestore(&dev->req_lock, flags);
 }
 
 static void eth_work (void *_dev)
@@ -1848,9 +1864,9 @@
 	}
 	dev->stats.tx_packets++;
 
-	spin_lock (&dev->lock);
+	spin_lock(&dev->req_lock);
 	list_add (&req->list, &dev->tx_reqs);
-	spin_unlock (&dev->lock);
+	spin_unlock(&dev->req_lock);
 	dev_kfree_skb_any (skb);
 
 	atomic_dec (&dev->tx_qlen);
@@ -1896,12 +1912,12 @@
 		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
 	}
 
-	spin_lock_irqsave (&dev->lock, flags);
+	spin_lock_irqsave(&dev->req_lock, flags);
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
 	list_del (&req->list);
 	if (list_empty (&dev->tx_reqs))
 		netif_stop_queue (net);
-	spin_unlock_irqrestore (&dev->lock, flags);
+	spin_unlock_irqrestore(&dev->req_lock, flags);
 
 	/* no buffer copies needed, unless the network stack did it
 	 * or the hardware can't use skb buffers.
@@ -1955,11 +1971,11 @@
 drop:
 		dev->stats.tx_dropped++;
 		dev_kfree_skb_any (skb);
-		spin_lock_irqsave (&dev->lock, flags);
+		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty (&dev->tx_reqs))
 			netif_start_queue (net);
 		list_add (&req->list, &dev->tx_reqs);
-		spin_unlock_irqrestore (&dev->lock, flags);
+		spin_unlock_irqrestore(&dev->req_lock, flags);
 	}
 	return 0;
 }
@@ -2378,6 +2394,7 @@
 		return status;
 	dev = netdev_priv(net);
 	spin_lock_init (&dev->lock);
+	spin_lock_init (&dev->req_lock);
 	INIT_WORK (&dev->work, eth_work, dev);
 	INIT_LIST_HEAD (&dev->tx_reqs);
 	INIT_LIST_HEAD (&dev->rx_reqs);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 85b0b4a..d63177a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -892,7 +892,7 @@
 #define	PCI_DRIVER		ehci_pci_driver
 #endif
 
-#ifdef CONFIG_PPC_83xx
+#ifdef CONFIG_MPC834x
 #include "ehci-fsl.c"
 #define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index cdbafb7..85cc059 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -4,7 +4,7 @@
  *  Copyright (C) 2004 SAN People (Pty) Ltd.
  *  Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
  *
- * AT91RM9200 Bus Glue
+ * AT91 Bus Glue
  *
  * Based on fragments of 2.4 driver by Rick Bronson.
  * Based on ohci-omap.c
@@ -19,12 +19,13 @@
 #include <asm/hardware.h>
 #include <asm/arch/board.h>
 
-#ifndef CONFIG_ARCH_AT91RM9200
-#error "CONFIG_ARCH_AT91RM9200 must be defined."
+#ifndef CONFIG_ARCH_AT91
+#error "CONFIG_ARCH_AT91 must be defined."
 #endif
 
 /* interface and function clocks */
 static struct clk *iclk, *fclk;
+static int clocked;
 
 extern int usb_disabled(void);
 
@@ -35,13 +36,14 @@
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct ohci_regs __iomem *regs = hcd->regs;
 
-	dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n");
+	dev_dbg(&pdev->dev, "start\n");
 
 	/*
 	 * Start the USB clocks.
 	 */
 	clk_enable(iclk);
 	clk_enable(fclk);
+	clocked = 1;
 
 	/*
 	 * The USB host controller must remain in reset.
@@ -54,7 +56,7 @@
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct ohci_regs __iomem *regs = hcd->regs;
 
-	dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n");
+	dev_dbg(&pdev->dev, "stop\n");
 
 	/*
 	 * Put the USB host controller into reset.
@@ -66,6 +68,7 @@
 	 */
 	clk_disable(fclk);
 	clk_disable(iclk);
+	clocked = 0;
 }
 
 
@@ -78,14 +81,15 @@
 
 
 /**
- * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs
+ * usb_hcd_at91_probe - initialize AT91-based HCDs
  * Context: !in_interrupt()
  *
  * Allocates basic resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev)
+static int usb_hcd_at91_probe(const struct hc_driver *driver,
+			struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd = NULL;
@@ -95,12 +99,13 @@
 		return -ENODEV;
 	}
 
-	if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) {
+	if ((pdev->resource[0].flags != IORESOURCE_MEM)
+			|| (pdev->resource[1].flags != IORESOURCE_IRQ)) {
 		pr_debug("hcd probe: invalid resource type\n");
 		return -ENODEV;
 	}
 
-	hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200");
+	hcd = usb_create_hcd(driver, &pdev->dev, "at91");
 	if (!hcd)
 		return -ENOMEM;
 	hcd->rsrc_start = pdev->resource[0].start;
@@ -149,21 +154,23 @@
 /* may be called with controller, bus, and devices active */
 
 /**
- * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs
+ * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs
  * @dev: USB Host Controller being removed
  * Context: !in_interrupt()
  *
  * Reverses the effect of usb_hcd_at91_probe(), first invoking
  * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
+ * context, "rmmod" or something similar.
  *
  */
-static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev)
+static int usb_hcd_at91_remove(struct usb_hcd *hcd,
+				struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
 	at91_stop_hc(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	disable_irq_wake(hcd->irq);
 
 	clk_put(fclk);
 	clk_put(iclk);
@@ -178,19 +185,21 @@
 static int __devinit
 ohci_at91_start (struct usb_hcd *hcd)
 {
-//	struct at91_ohci_data	*board = hcd->self.controller->platform_data;
+	struct at91_usbh_data	*board = hcd->self.controller->platform_data;
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+	struct usb_device	*root = hcd->self.root_hub;
 	int			ret;
 
 	if ((ret = ohci_init(ohci)) < 0)
 		return ret;
 
+	root->maxchild = board->ports;
+
 	if ((ret = ohci_run(ohci)) < 0) {
 		err("can't start %s", hcd->self.bus_name);
 		ohci_stop(hcd);
 		return ret;
 	}
-//	hcd->self.root_hub->maxchild = board->ports;
 	return 0;
 }
 
@@ -198,7 +207,7 @@
 
 static const struct hc_driver ohci_at91_hc_driver = {
 	.description =		hcd_name,
-	.product_desc =		"AT91RM9200 OHCI",
+	.product_desc =		"AT91 OHCI",
 	.hcd_priv_size =	sizeof(struct ohci_hcd),
 
 	/*
@@ -240,33 +249,54 @@
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_at91_drv_probe(struct platform_device *dev)
+static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 {
-	return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev);
+	device_init_wakeup(&pdev->dev, 1);
+	return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
 
-static int ohci_hcd_at91_drv_remove(struct platform_device *dev)
+static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
 {
-	return usb_hcd_at91_remove(platform_get_drvdata(dev), dev);
+	device_init_wakeup(&pdev->dev, 0);
+	return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev);
 }
 
 #ifdef CONFIG_PM
 
-/* REVISIT suspend/resume look "too" simple here */
-
 static int
-ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg)
+ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
-	clk_disable(fclk);
-	clk_disable(iclk);
+	struct usb_hcd	*hcd = platform_get_drvdata(pdev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(hcd->irq);
+	else
+		disable_irq_wake(hcd->irq);
+
+	/*
+	 * The integrated transceivers seem unable to notice disconnect,
+	 * reconnect, or wakeup without the 48 MHz clock active.  so for
+	 * correctness, always discard connection state (using reset).
+	 *
+	 * REVISIT: some boards will be able to turn VBUS off...
+	 */
+	if (at91_suspend_entering_slow_clock()) {
+		ohci_usb_reset (ohci);
+		clk_disable(fclk);
+		clk_disable(iclk);
+		clocked = 0;
+	}
 
 	return 0;
 }
 
-static int ohci_hcd_at91_drv_resume(struct platform_device *dev)
+static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
 {
-	clk_enable(iclk);
-	clk_enable(fclk);
+	if (!clocked) {
+		clk_enable(iclk);
+		clk_enable(fclk);
+	}
 
 	return 0;
 }
@@ -275,7 +305,7 @@
 #define ohci_hcd_at91_drv_resume  NULL
 #endif
 
-MODULE_ALIAS("at91rm9200-ohci");
+MODULE_ALIAS("at91_ohci");
 
 static struct platform_driver ohci_hcd_at91_driver = {
 	.probe		= ohci_hcd_at91_drv_probe,
@@ -283,7 +313,7 @@
 	.suspend	= ohci_hcd_at91_drv_suspend,
 	.resume		= ohci_hcd_at91_drv_resume,
 	.driver		= {
-		.name	= "at91rm9200-ohci",
+		.name	= "at91_ohci",
 		.owner	= THIS_MODULE,
 	},
 };
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 822914e..f7a975d 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -110,7 +110,6 @@
 
 	printk(KERN_DEBUG __FILE__
 	": Clock to USB host has been enabled \n");
-#endif
 }
 
 static void au1xxx_stop_ohc(struct platform_device *dev)
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index afef5ac..94d8cf4 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -913,7 +913,7 @@
 #include "ohci-ppc-soc.c"
 #endif
 
-#ifdef CONFIG_ARCH_AT91RM9200
+#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
 #include "ohci-at91.c"
 #endif
 
@@ -927,6 +927,7 @@
       || defined (CONFIG_SOC_AU1X00) \
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
       || defined (CONFIG_ARCH_AT91RM9200) \
+      || defined (CONFIG_ARCH_AT91SAM9261) \
 	)
 #error "missing bus glue for ohci-hcd"
 #endif
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index c9d72ac..431e8f3 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -372,7 +372,7 @@
 		 * need to change any toggles in this URB */
 		td = list_entry(urbp->td_list.next, struct uhci_td, list);
 		if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) {
-			td = list_entry(urbp->td_list.next, struct uhci_td,
+			td = list_entry(urbp->td_list.prev, struct uhci_td,
 					list);
 			toggle = uhci_toggle(td_token(td)) ^ 1;
 
@@ -943,7 +943,9 @@
 			/* We received a short packet */
 			if (urb->transfer_flags & URB_SHORT_NOT_OK)
 				ret = -EREMOTEIO;
-			else if (ctrlstat & TD_CTRL_SPD)
+
+			/* Fixup needed only if this isn't the URB's last TD */
+			else if (&td->list != urbp->td_list.prev)
 				ret = 1;
 		}
 
@@ -1346,7 +1348,7 @@
 		}
 
 		uhci_giveback_urb(uhci, qh, urb, regs);
-		if (status < 0)
+		if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC)
 			break;
 	}
 
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 9e3f139..044faa0 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -597,9 +597,9 @@
 	if (dev) {
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
-		usb_free_urb(dev->urb);
 		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
+		usb_free_urb(dev->urb);
 		kfree(dev);
 	}
 	printk(KERN_INFO "input: appletouch disconnected\n");
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 05d2d60..3719fcb 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -111,14 +111,28 @@
 #define NAME_BUFSIZE      80    /* size of product name, path buffers */
 #define DATA_BUFSIZE      63    /* size of URB data buffers */
 
+/*
+ * Duplicate event filtering time.
+ * Sequential, identical KIND_FILTERED inputs with less than
+ * FILTER_TIME milliseconds between them are considered as repeat
+ * events. The hardware generates 5 events for the first keypress
+ * and we have to take this into account for an accurate repeat
+ * behaviour.
+ */
+#define FILTER_TIME	60 /* msec */
+
 static unsigned long channel_mask;
-module_param(channel_mask, ulong, 0444);
+module_param(channel_mask, ulong, 0644);
 MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
 
 static int debug;
-module_param(debug, int, 0444);
+module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
 
+static int repeat_filter = FILTER_TIME;
+module_param(repeat_filter, int, 0644);
+MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
+
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
 #undef err
 #define err(format, arg...) printk(KERN_ERR format , ## arg)
@@ -143,19 +157,6 @@
 static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
 static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
 
-/* Acceleration curve for directional control pad */
-static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
-
-/* Duplicate event filtering time.
- * Sequential, identical KIND_FILTERED inputs with less than
- * FILTER_TIME jiffies between them are considered as repeat
- * events. The hardware generates 5 events for the first keypress
- * and we have to take this into account for an accurate repeat
- * behaviour.
- * (HZ / 20) == 50 ms and works well for me.
- */
-#define FILTER_TIME (HZ / 20)
-
 struct ati_remote {
 	struct input_dev *idev;
 	struct usb_device *udev;
@@ -413,6 +414,43 @@
 }
 
 /*
+ *	ati_remote_compute_accel
+ *
+ * Implements acceleration curve for directional control pad
+ * If elapsed time since last event is > 1/4 second, user "stopped",
+ * so reset acceleration. Otherwise, user is probably holding the control
+ * pad down, so we increase acceleration, ramping up over two seconds to
+ * a maximum speed.
+ */
+static int ati_remote_compute_accel(struct ati_remote *ati_remote)
+{
+	static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
+	unsigned long now = jiffies;
+	int acc;
+
+	if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
+		acc = 1;
+		ati_remote->acc_jiffies = now;
+	}
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
+		acc = accel[0];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
+		acc = accel[1];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
+		acc = accel[2];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
+		acc = accel[3];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
+		acc = accel[4];
+	else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
+		acc = accel[5];
+	else
+		acc = accel[6];
+
+	return acc;
+}
+
+/*
  *	ati_remote_report_input
  */
 static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
@@ -465,9 +503,9 @@
 
 	if (ati_remote_tbl[index].kind == KIND_FILTERED) {
 		/* Filter duplicate events which happen "too close" together. */
-		if ((ati_remote->old_data[0] == data[1]) &&
-			(ati_remote->old_data[1] == data[2]) &&
-			time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
+		if (ati_remote->old_data[0] == data[1] &&
+		    ati_remote->old_data[1] == data[2] &&
+		    time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) {
 			ati_remote->repeat_count++;
 		} else {
 			ati_remote->repeat_count = 0;
@@ -477,75 +515,61 @@
 		ati_remote->old_data[1] = data[2];
 		ati_remote->old_jiffies = jiffies;
 
-		if ((ati_remote->repeat_count > 0)
-		    && (ati_remote->repeat_count < 5))
+		if (ati_remote->repeat_count > 0 &&
+		    ati_remote->repeat_count < 5)
 			return;
 
 
 		input_regs(dev, regs);
 		input_event(dev, ati_remote_tbl[index].type,
 			ati_remote_tbl[index].code, 1);
+		input_sync(dev);
 		input_event(dev, ati_remote_tbl[index].type,
 			ati_remote_tbl[index].code, 0);
 		input_sync(dev);
 
-		return;
-	}
+	} else {
 
-	/*
-	 * Other event kinds are from the directional control pad, and have an
-	 * acceleration factor applied to them.  Without this acceleration, the
-	 * control pad is mostly unusable.
-	 *
-	 * If elapsed time since last event is > 1/4 second, user "stopped",
-	 * so reset acceleration. Otherwise, user is probably holding the control
-	 * pad down, so we increase acceleration, ramping up over two seconds to
-	 * a maximum speed.  The acceleration curve is #defined above.
-	 */
-	if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
-		acc = 1;
-		ati_remote->acc_jiffies = jiffies;
-	}
-	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3)))  acc = accel[0];
-	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2)))  acc = accel[1];
-	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1)))  acc = accel[2];
-	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ))         acc = accel[3];
-	else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
-	else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1)))  acc = accel[5];
-	else acc = accel[6];
+		/*
+		 * Other event kinds are from the directional control pad, and have an
+		 * acceleration factor applied to them.  Without this acceleration, the
+		 * control pad is mostly unusable.
+		 */
+		acc = ati_remote_compute_accel(ati_remote);
 
-	input_regs(dev, regs);
-	switch (ati_remote_tbl[index].kind) {
-	case KIND_ACCEL:
-		input_event(dev, ati_remote_tbl[index].type,
-			ati_remote_tbl[index].code,
-			ati_remote_tbl[index].value * acc);
-		break;
-	case KIND_LU:
-		input_report_rel(dev, REL_X, -acc);
-		input_report_rel(dev, REL_Y, -acc);
-		break;
-	case KIND_RU:
-		input_report_rel(dev, REL_X, acc);
-		input_report_rel(dev, REL_Y, -acc);
-		break;
-	case KIND_LD:
-		input_report_rel(dev, REL_X, -acc);
-		input_report_rel(dev, REL_Y, acc);
-		break;
-	case KIND_RD:
-		input_report_rel(dev, REL_X, acc);
-		input_report_rel(dev, REL_Y, acc);
-		break;
-	default:
-		dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
-			ati_remote_tbl[index].kind);
-	}
-	input_sync(dev);
+		input_regs(dev, regs);
+		switch (ati_remote_tbl[index].kind) {
+		case KIND_ACCEL:
+			input_event(dev, ati_remote_tbl[index].type,
+				ati_remote_tbl[index].code,
+				ati_remote_tbl[index].value * acc);
+			break;
+		case KIND_LU:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_RU:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, -acc);
+			break;
+		case KIND_LD:
+			input_report_rel(dev, REL_X, -acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		case KIND_RD:
+			input_report_rel(dev, REL_X, acc);
+			input_report_rel(dev, REL_Y, acc);
+			break;
+		default:
+			dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
+				ati_remote_tbl[index].kind);
+		}
+		input_sync(dev);
 
-	ati_remote->old_jiffies = jiffies;
-	ati_remote->old_data[0] = data[1];
-	ati_remote->old_data[1] = data[2];
+		ati_remote->old_jiffies = jiffies;
+		ati_remote->old_data[0] = data[1];
+		ati_remote->old_data[1] = data[2];
+	}
 }
 
 /*
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 8ea9c91..a2c56b2 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1411,17 +1411,54 @@
 		warn("timeout initializing reports");
 }
 
+#define USB_VENDOR_ID_GTCO		0x078c
+#define USB_DEVICE_ID_GTCO_90		0x0090
+#define USB_DEVICE_ID_GTCO_100		0x0100
+#define USB_DEVICE_ID_GTCO_101		0x0101
+#define USB_DEVICE_ID_GTCO_103		0x0103
+#define USB_DEVICE_ID_GTCO_104		0x0104
+#define USB_DEVICE_ID_GTCO_105		0x0105
+#define USB_DEVICE_ID_GTCO_106		0x0106
+#define USB_DEVICE_ID_GTCO_107		0x0107
+#define USB_DEVICE_ID_GTCO_108		0x0108
+#define USB_DEVICE_ID_GTCO_200		0x0200
+#define USB_DEVICE_ID_GTCO_201		0x0201
+#define USB_DEVICE_ID_GTCO_202		0x0202
+#define USB_DEVICE_ID_GTCO_203		0x0203
+#define USB_DEVICE_ID_GTCO_204		0x0204
+#define USB_DEVICE_ID_GTCO_205		0x0205
+#define USB_DEVICE_ID_GTCO_206		0x0206
+#define USB_DEVICE_ID_GTCO_207		0x0207
+#define USB_DEVICE_ID_GTCO_300		0x0300
+#define USB_DEVICE_ID_GTCO_301		0x0301
+#define USB_DEVICE_ID_GTCO_302		0x0302
+#define USB_DEVICE_ID_GTCO_303		0x0303
+#define USB_DEVICE_ID_GTCO_304		0x0304
+#define USB_DEVICE_ID_GTCO_305		0x0305
+#define USB_DEVICE_ID_GTCO_306		0x0306
+#define USB_DEVICE_ID_GTCO_307		0x0307
+#define USB_DEVICE_ID_GTCO_308		0x0308
+#define USB_DEVICE_ID_GTCO_309		0x0309
+#define USB_DEVICE_ID_GTCO_400		0x0400
+#define USB_DEVICE_ID_GTCO_401		0x0401
+#define USB_DEVICE_ID_GTCO_402		0x0402
+#define USB_DEVICE_ID_GTCO_403		0x0403
+#define USB_DEVICE_ID_GTCO_404		0x0404
+#define USB_DEVICE_ID_GTCO_405		0x0405
+#define USB_DEVICE_ID_GTCO_500		0x0500
+#define USB_DEVICE_ID_GTCO_501		0x0501
+#define USB_DEVICE_ID_GTCO_502		0x0502
+#define USB_DEVICE_ID_GTCO_503		0x0503
+#define USB_DEVICE_ID_GTCO_504		0x0504
+#define USB_DEVICE_ID_GTCO_1000		0x1000
+#define USB_DEVICE_ID_GTCO_1001		0x1001
+#define USB_DEVICE_ID_GTCO_1002		0x1002
+#define USB_DEVICE_ID_GTCO_1003		0x1003
+#define USB_DEVICE_ID_GTCO_1004		0x1004
+#define USB_DEVICE_ID_GTCO_1005		0x1005
+#define USB_DEVICE_ID_GTCO_1006		0x1006
+
 #define USB_VENDOR_ID_WACOM		0x056a
-#define USB_DEVICE_ID_WACOM_PENPARTNER	0x0000
-#define USB_DEVICE_ID_WACOM_GRAPHIRE	0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS	0x0020
-#define USB_DEVICE_ID_WACOM_PL		0x0030
-#define USB_DEVICE_ID_WACOM_INTUOS2	0x0040
-#define USB_DEVICE_ID_WACOM_VOLITO	0x0060
-#define USB_DEVICE_ID_WACOM_PTU		0x0003
-#define USB_DEVICE_ID_WACOM_INTUOS3	0x00B0
-#define USB_DEVICE_ID_WACOM_CINTIQ	0x003F
-#define USB_DEVICE_ID_WACOM_DTF         0x00C0
 
 #define USB_VENDOR_ID_ACECAD		0x0460
 #define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
@@ -1588,6 +1625,51 @@
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE },
@@ -1617,49 +1699,6 @@
 	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
@@ -1778,6 +1817,10 @@
 	char *rdesc;
 	int n, len, insize = 0;
 
+        /* Ignore all Wacom devices */
+        if (dev->descriptor.idVendor == USB_VENDOR_ID_WACOM)
+                return NULL;
+
 	for (n = 0; hid_blacklist[n].idVendor; n++)
 		if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
 			(hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 028e1ad..7208839 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -607,7 +607,8 @@
 
 	}
 
-	if (usage->hat_min < usage->hat_max || usage->hat_dir) {
+	if (usage->type == EV_ABS &&
+	    (usage->hat_min < usage->hat_max || usage->hat_dir)) {
 		int i;
 		for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
 			input_set_abs_params(input, i, -1, 1, 0, 0);
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 70477f0..f6b839c 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -49,7 +49,7 @@
 	int open;
 	wait_queue_head_t wait;
 	struct hid_device *hid;
-	struct hiddev_list *list;
+	struct list_head list;
 };
 
 struct hiddev_list {
@@ -59,7 +59,7 @@
 	unsigned flags;
 	struct fasync_struct *fasync;
 	struct hiddev *hiddev;
-	struct hiddev_list *next;
+	struct list_head node;
 };
 
 static struct hiddev *hiddev_table[HIDDEV_MINORS];
@@ -73,12 +73,15 @@
 static struct hid_report *
 hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
 {
-	unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
+	unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
+	unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK;
 	struct hid_report_enum *report_enum;
+	struct hid_report *report;
 	struct list_head *list;
 
 	if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
-	    rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
+	    rinfo->report_type > HID_REPORT_TYPE_MAX)
+		return NULL;
 
 	report_enum = hid->report_enum +
 		(rinfo->report_type - HID_REPORT_TYPE_MIN);
@@ -88,21 +91,25 @@
 		break;
 
 	case HID_REPORT_ID_FIRST:
-		list = report_enum->report_list.next;
-		if (list == &report_enum->report_list)
+		if (list_empty(&report_enum->report_list))
 			return NULL;
-		rinfo->report_id = ((struct hid_report *) list)->id;
+
+		list = report_enum->report_list.next;
+		report = list_entry(list, struct hid_report, list);
+		rinfo->report_id = report->id;
 		break;
 
 	case HID_REPORT_ID_NEXT:
-		list = (struct list_head *)
-			report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK];
-		if (list == NULL)
+		report = report_enum->report_id_hash[rid];
+		if (!report)
 			return NULL;
-		list = list->next;
+
+		list = report->list.next;
 		if (list == &report_enum->report_list)
 			return NULL;
-		rinfo->report_id = ((struct hid_report *) list)->id;
+
+		report = list_entry(list, struct hid_report, list);
+		rinfo->report_id = report->id;
 		break;
 
 	default:
@@ -125,12 +132,13 @@
 	struct hid_field *field;
 
 	if (uref->report_type < HID_REPORT_TYPE_MIN ||
-	    uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
+	    uref->report_type > HID_REPORT_TYPE_MAX)
+		return NULL;
 
 	report_enum = hid->report_enum +
 		(uref->report_type - HID_REPORT_TYPE_MIN);
 
-	list_for_each_entry(report, &report_enum->report_list, list)
+	list_for_each_entry(report, &report_enum->report_list, list) {
 		for (i = 0; i < report->maxfield; i++) {
 			field = report->field[i];
 			for (j = 0; j < field->maxusage; j++) {
@@ -142,6 +150,7 @@
 				}
 			}
 		}
+	}
 
 	return NULL;
 }
@@ -150,9 +159,9 @@
 			      struct hiddev_usage_ref *uref)
 {
 	struct hiddev *hiddev = hid->hiddev;
-	struct hiddev_list *list = hiddev->list;
+	struct hiddev_list *list;
 
-	while (list) {
+	list_for_each_entry(list, &hiddev->list, node) {
 		if (uref->field_index != HID_FIELD_INDEX_NONE ||
 		    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
 			list->buffer[list->head] = *uref;
@@ -160,8 +169,6 @@
 				(HIDDEV_BUFFER_SIZE - 1);
 			kill_fasync(&list->fasync, SIGIO, POLL_IN);
 		}
-
-		list = list->next;
 	}
 
 	wake_up_interruptible(&hiddev->wait);
@@ -180,7 +187,7 @@
 	uref.report_type =
 	  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
 	  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
-	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
 	uref.report_id = field->report->id;
 	uref.field_index = field->index;
 	uref.usage_index = (usage - field->usage);
@@ -200,7 +207,7 @@
 	uref.report_type =
 	  (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
 	  ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
-	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
+	   ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0));
 	uref.report_id = report->id;
 	uref.field_index = HID_FIELD_INDEX_NONE;
 
@@ -213,7 +220,9 @@
 {
 	int retval;
 	struct hiddev_list *list = file->private_data;
+
 	retval = fasync_helper(fd, file, on, &list->fasync);
+
 	return retval < 0 ? retval : 0;
 }
 
@@ -224,14 +233,9 @@
 static int hiddev_release(struct inode * inode, struct file * file)
 {
 	struct hiddev_list *list = file->private_data;
-	struct hiddev_list **listptr;
 
-	listptr = &list->hiddev->list;
 	hiddev_fasync(-1, file, 0);
-
-	while (*listptr && (*listptr != list))
-		listptr = &((*listptr)->next);
-	*listptr = (*listptr)->next;
+	list_del(&list->node);
 
 	if (!--list->hiddev->open) {
 		if (list->hiddev->exist)
@@ -248,7 +252,8 @@
 /*
  * open file op
  */
-static int hiddev_open(struct inode * inode, struct file * file) {
+static int hiddev_open(struct inode *inode, struct file *file)
+{
 	struct hiddev_list *list;
 
 	int i = iminor(inode) - HIDDEV_MINOR_BASE;
@@ -260,9 +265,7 @@
 		return -ENOMEM;
 
 	list->hiddev = hiddev_table[i];
-	list->next = hiddev_table[i]->list;
-	hiddev_table[i]->list = list;
-
+	list_add_tail(&list->node, &hiddev_table[i]->list);
 	file->private_data = list;
 
 	if (!list->hiddev->open++)
@@ -362,6 +365,7 @@
 static unsigned int hiddev_poll(struct file *file, poll_table *wait)
 {
 	struct hiddev_list *list = file->private_data;
+
 	poll_wait(file, &list->hiddev->wait, wait);
 	if (list->head != list->tail)
 		return POLLIN | POLLRDNORM;
@@ -382,7 +386,7 @@
 	struct hiddev_collection_info cinfo;
 	struct hiddev_report_info rinfo;
 	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref_multi *uref_multi=NULL;
+	struct hiddev_usage_ref_multi *uref_multi = NULL;
 	struct hiddev_usage_ref *uref;
 	struct hiddev_devinfo dinfo;
 	struct hid_report *report;
@@ -764,15 +768,15 @@
 	}
 
 	init_waitqueue_head(&hiddev->wait);
-
-	hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
-
+	INIT_LIST_HEAD(&hiddev->list);
 	hiddev->hid = hid;
 	hiddev->exist = 1;
 
 	hid->minor = hid->intf->minor;
 	hid->hiddev = hiddev;
 
+	hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+
 	return 0;
 }
 
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 3b175aa..a338bf4 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -286,7 +286,7 @@
 static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
 {
 	*x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F);
-	*x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
+	*y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F);
 	*press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F);
 	*touch = ~pkt[7] & 0x20;
 
diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c
index e091d32..9c46746 100644
--- a/drivers/usb/misc/cypress_cy7c63.c
+++ b/drivers/usb/misc/cypress_cy7c63.c
@@ -12,8 +12,13 @@
 *	the single I/O ports of the device.
 *
 *	Supported vendors:	AK Modul-Bus Computer GmbH
-*	Supported devices:	CY7C63001A-PC (to be continued...)
-*	Supported functions:	Read/Write Ports (to be continued...)
+*				(Firmware "Port-Chip")
+*
+*	Supported devices:	CY7C63001A-PC
+*				CY7C63001C-PXC
+*				CY7C63001C-SXC
+*
+*	Supported functions:	Read/Write Ports
 *
 *
 *	This program is free software; you can redistribute it and/or
@@ -203,7 +208,7 @@
 	/* allocate memory for our device state and initialize it */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		dev_err(&dev->udev->dev, "Out of memory!\n");
+		dev_err(&interface->dev, "Out of memory!\n");
 		goto error;
 	}
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 738bd7c..e16582f 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3435,6 +3435,8 @@
 
 static struct usb_device_id sisusb_table [] = {
 	{ USB_DEVICE(0x0711, 0x0900) },
+	{ USB_DEVICE(0x0711, 0x0901) },
+	{ USB_DEVICE(0x0711, 0x0902) },
 	{ USB_DEVICE(0x182d, 0x021c) },
 	{ USB_DEVICE(0x182d, 0x0269) },
 	{ }
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 786e1db..983e104 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1242,11 +1242,12 @@
 static int ctrl_out (struct usbtest_dev *dev,
 		unsigned count, unsigned length, unsigned vary)
 {
-	unsigned		i, j, len, retval;
+	unsigned		i, j, len;
+	int			retval;
 	u8			*buf;
 	char			*what = "?";
 	struct usb_device	*udev;
-	
+
 	if (length < 1 || length > 0xffff || vary >= length)
 		return -EINVAL;
 
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index a54752c..0064380 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -131,6 +131,7 @@
 #define	VENDOR_COREGA		0x07aa
 #define	VENDOR_DLINK		0x2001
 #define	VENDOR_ELCON		0x0db7
+#define	VENDOR_ELECOM		0x056e
 #define	VENDOR_ELSA		0x05cc
 #define	VENDOR_GIGABYTE		0x1044
 #define	VENDOR_HAWKING		0x0e66
@@ -233,6 +234,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002,
 		DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA )
+PEGASUS_DEV( "ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM,  0x4010,
+		DEFAULT_GPIO_RESET  | PEGASUS_II )
 PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index e5e6e4f..a72685b 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -175,6 +175,8 @@
 static void rtl8150_disconnect(struct usb_interface *intf);
 static int rtl8150_probe(struct usb_interface *intf,
 			   const struct usb_device_id *id);
+static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message);
+static int rtl8150_resume(struct usb_interface *intf);
 
 static const char driver_name [] = "rtl8150";
 
@@ -183,6 +185,8 @@
 	.probe =	rtl8150_probe,
 	.disconnect =	rtl8150_disconnect,
 	.id_table =	rtl8150_table,
+	.suspend =	rtl8150_suspend,
+	.resume =	rtl8150_resume
 };
 
 /*
@@ -238,9 +242,11 @@
 	usb_fill_control_urb(dev->ctrl_urb, dev->udev,
 			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
 			 &dev->rx_creg, size, ctrl_callback, dev);
-	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
+	if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
+		if (ret == -ENODEV)
+			netif_device_detach(dev->netdev);
 		err("control request submission failed: %d", ret);
-	else
+	} else
 		set_bit(RX_REG_SET, &dev->flags);
 
 	return ret;
@@ -416,6 +422,7 @@
 	struct sk_buff *skb;
 	struct net_device *netdev;
 	u16 rx_stat;
+	int status;
 
 	dev = urb->context;
 	if (!dev)
@@ -465,7 +472,10 @@
 goon:
 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
+	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
+	if (status == -ENODEV)
+		netif_device_detach(dev->netdev);
+	else if (status) {
 		set_bit(RX_URB_FAIL, &dev->flags);
 		goto resched;
 	} else {
@@ -481,6 +491,7 @@
 {
 	rtl8150_t *dev;
 	struct sk_buff *skb;
+	int status;
 
 	dev = (rtl8150_t *)data;
 
@@ -499,10 +510,13 @@
 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
 try_again:
-	if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
+	status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
+	if (status == -ENODEV) {
+		netif_device_detach(dev->netdev);
+	} else if (status) {
 		set_bit(RX_URB_FAIL, &dev->flags);
 		goto tlsched;
-	 } else {
+	} else {
 		clear_bit(RX_URB_FAIL, &dev->flags);
 	}
 
@@ -574,12 +588,43 @@
 
 resubmit:
 	status = usb_submit_urb (urb, SLAB_ATOMIC);
-	if (status)
+	if (status == -ENODEV)
+		netif_device_detach(dev->netdev);
+	else if (status)
 		err ("can't resubmit intr, %s-%s/input0, status %d",
 				dev->udev->bus->bus_name,
 				dev->udev->devpath, status);
 }
 
+static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	rtl8150_t *dev = usb_get_intfdata(intf);
+
+	netif_device_detach(dev->netdev);
+
+	if (netif_running(dev->netdev)) {
+		usb_kill_urb(dev->rx_urb);
+		usb_kill_urb(dev->intr_urb);
+	}
+	return 0;
+}
+
+static int rtl8150_resume(struct usb_interface *intf)
+{
+	rtl8150_t *dev = usb_get_intfdata(intf);
+
+	netif_device_attach(dev->netdev);
+	if (netif_running(dev->netdev)) {
+		dev->rx_urb->status = 0;
+		dev->rx_urb->actual_length = 0;
+		read_bulk_callback(dev->rx_urb, NULL);
+
+		dev->intr_urb->status = 0;
+		dev->intr_urb->actual_length = 0;
+		intr_callback(dev->intr_urb, NULL);
+	}
+	return 0;
+}
 
 /*
 **
@@ -690,9 +735,14 @@
 	usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
 		      skb->data, count, write_bulk_callback, dev);
 	if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
-		warn("failed tx_urb %d\n", res);
-		dev->stats.tx_errors++;
-		netif_start_queue(netdev);
+		/* Can we get/handle EPIPE here? */
+		if (res == -ENODEV)
+			netif_device_detach(dev->netdev);
+		else {
+			warn("failed tx_urb %d\n", res);
+			dev->stats.tx_errors++;
+			netif_start_queue(netdev);
+		}
 	} else {
 		dev->stats.tx_packets++;
 		dev->stats.tx_bytes += skb->len;
@@ -729,16 +779,25 @@
 	
 	usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
 		      dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
-	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
+	if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
+		if (res == -ENODEV)
+			netif_device_detach(dev->netdev);
 		warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
+		return res;
+	}
 	usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
 		     dev->intr_buff, INTBUFSIZE, intr_callback,
 		     dev, dev->intr_interval);
-	if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
+	if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
+		if (res == -ENODEV)
+			netif_device_detach(dev->netdev);
 		warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
-	netif_start_queue(netdev);
+		usb_kill_urb(dev->rx_urb);
+		return res;
+	}
 	enable_net_traffic(dev);
 	set_carrier(netdev);
+	netif_start_queue(netdev);
 
 	return res;
 }
@@ -913,6 +972,7 @@
 	if (dev) {
 		set_bit(RTL8150_UNPLUG, &dev->flags);
 		tasklet_disable(&dev->tl);
+		tasklet_kill(&dev->tl);
 		unregister_netdev(dev->netdev);
 		unlink_all_urbs(dev);
 		free_all_urbs(dev);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index ac33bd4..f5b9438 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -62,15 +62,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called airprime.
 
-config USB_SERIAL_ANYDATA
-	tristate "USB AnyData CDMA Wireless Driver"
-	depends on USB_SERIAL
-	help
-	  Say Y here if you want to use a AnyData CDMA device.
-
-	  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
@@ -502,15 +493,18 @@
 	  module will be called keyspan_pda.
 
 config USB_SERIAL_OPTION
-	tristate "USB driver for GSM modems"
+	tristate "USB driver for GSM and CDMA modems"
 	depends on USB_SERIAL
 	help
-	  Say Y here if you have an "Option" GSM PCMCIA card
-	  (or an OEM version: branded Huawei, Audiovox, or Novatel).
+	  Say Y here if you have a GSM or CDMA modem that's connected to USB.
 
-	  These cards feature a built-in OHCI-USB adapter and an
-	  internally-connected GSM modem. The USB bus is not
-	  accessible externally.
+	  This driver also supports several PCMCIA cards which have a
+	  built-in OHCI-USB adapter and an internally-connected GSM modem.
+	  The USB bus on these cards is not accessible externally.
+
+	  Supported devices include (some of?) those made by:
+	  Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or
+	  Anydata.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called option.
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 35d4acc..8efed2c 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -12,7 +12,6 @@
 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
diff --git a/drivers/usb/serial/anydata.c b/drivers/usb/serial/anydata.c
deleted file mode 100644
index 01843ef..0000000
--- a/drivers/usb/serial/anydata.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * AnyData CDMA Serial USB driver
- *
- * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License version
- *	2 as published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-static struct usb_device_id id_table [] = {
-	{ USB_DEVICE(0x16d5, 0x6501) },	/* AirData CDMA device */
-	{ },
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-/* if overridden by the user, then use their value for the size of the
- * read and write urbs */
-static int buffer_size;
-static int debug;
-
-static struct usb_driver anydata_driver = {
-	.name =		"anydata",
-	.probe =	usb_serial_probe,
-	.disconnect =	usb_serial_disconnect,
-	.id_table =	id_table,
-	.no_dynamic_id = 	1,
-};
-
-static int anydata_open(struct usb_serial_port *port, struct file *filp)
-{
-	char *buffer;
-	int result = 0;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	if (buffer_size) {
-		/* override the default buffer sizes */
-		buffer = kmalloc(buffer_size, GFP_KERNEL);
-		if (!buffer) {
-			dev_err(&port->dev, "%s - out of memory.\n",
-				__FUNCTION__);
-			return -ENOMEM;
-		}
-		kfree (port->read_urb->transfer_buffer);
-		port->read_urb->transfer_buffer = buffer;
-		port->read_urb->transfer_buffer_length = buffer_size;
-
-		buffer = kmalloc(buffer_size, GFP_KERNEL);
-		if (!buffer) {
-			dev_err(&port->dev, "%s - out of memory.\n",
-				__FUNCTION__);
-			return -ENOMEM;
-		}
-		kfree (port->write_urb->transfer_buffer);
-		port->write_urb->transfer_buffer = buffer;
-		port->write_urb->transfer_buffer_length = buffer_size;
-		port->bulk_out_size = buffer_size;
-	}
-
-	/* Start reading from the device */
-	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
-			  usb_rcvbulkpipe(port->serial->dev,
-				  	  port->bulk_in_endpointAddress),
-			  port->read_urb->transfer_buffer,
-			  port->read_urb->transfer_buffer_length,
-			  usb_serial_generic_read_bulk_callback, port);
-	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-	if (result)
-		dev_err(&port->dev,
-			"%s - failed submitting read urb, error %d\n",
-			__FUNCTION__, result);
-
-	return result;
-}
-
-static struct usb_serial_driver anydata_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"anydata",
-	},
-	.id_table =		id_table,
-	.num_interrupt_in =	NUM_DONT_CARE,
-	.num_bulk_in =		NUM_DONT_CARE,
-	.num_bulk_out =		NUM_DONT_CARE,
-	.num_ports =		1,
-	.open =			anydata_open,
-};
-
-static int __init anydata_init(void)
-{
-	int retval;
-
-	retval = usb_serial_register(&anydata_device);
-	if (retval)
-		return retval;
-	retval = usb_register(&anydata_driver);
-	if (retval)
-		usb_serial_deregister(&anydata_device);
-	return retval;
-}
-
-static void __exit anydata_exit(void)
-{
-	usb_deregister(&anydata_driver);
-	usb_serial_deregister(&anydata_device);
-}
-
-module_init(anydata_init);
-module_exit(anydata_exit);
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-module_param(buffer_size, int, 0);
-MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers");
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b458aed..c6115aa 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -306,6 +306,8 @@
 
 
 static struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
@@ -337,6 +339,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) },
 	{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) },
@@ -503,6 +506,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) },
 	{ USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 04ef90f..7729999 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -32,6 +32,12 @@
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
 
 
+/* www.canusb.com Lawicel CANUSB device */
+#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
+/* AlphaMicro Components AMC-232USB01 device */
+#define FTDI_AMC232_PID 0xFF00 /* Product Id */
+
 /* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
 #define FTDI_ACTZWAVE_PID	0xF2D0
 
@@ -182,6 +188,10 @@
 /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
 #define FTDI_USB_UIRT_PID	0xF850	/* Product Id */
 
+/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */
+
+#define FTDI_TNC_X_PID		0xEBE0
+
 /*
  * ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
  * All of these devices use FTDI's vendor ID (0x0403).
@@ -457,6 +467,11 @@
 #define TESTO_VID			0x128D
 #define TESTO_USB_INTERFACE_PID		0x0001
 
+/*
+ * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com.
+ */
+#define FTDI_GAMMA_SCOUT_PID		0xD678	/* Gamma Scout online */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 59c5d99..9840bad 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -250,6 +250,9 @@
 	{ USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */
 	{ USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */
 	{ USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */
+	{ USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */
+	{ USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */
+	{ USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */
 	{ USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */
 	{ USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */
 	{ USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f0530c1..c856e6f 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -9,40 +9,14 @@
 
   Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
 
-  History:
-
-  2005-05-19  v0.1   Initial version, based on incomplete docs
-                     and analysis of misbehavior with the standard driver
-  2005-05-20  v0.2   Extended the input buffer to avoid losing
-                     random 64-byte chunks of data
-  2005-05-21  v0.3   implemented chars_in_buffer()
-                     turned on low_latency
-                     simplified the code somewhat
-  2005-05-24  v0.4   option_write() sometimes deadlocked under heavy load
-                     removed some dead code
-                     added sponsor notice
-                     coding style clean-up
-  2005-06-20  v0.4.1 add missing braces :-/
-                     killed end-of-line whitespace
-  2005-07-15  v0.4.2 rename WLAN product to FUSION, add FUSION2
-  2005-09-10  v0.4.3 added HUAWEI E600 card and Audiovox AirCard
-  2005-09-20  v0.4.4 increased recv buffer size: the card sometimes
-                     wants to send >2000 bytes.
-  2006-04-10  v0.5   fixed two array overrun errors :-/
-  2006-04-21  v0.5.1 added support for Sierra Wireless MC8755
-  2006-05-15  v0.6   re-enable multi-port support
-  2006-06-01  v0.6.1 add COBRA
-  2006-06-01  v0.6.2 add backwards-compatibility stuff
-  2006-06-01  v0.6.3 add Novatel Wireless
-  2006-06-01  v0.7   Option => GSM
-  2006-06-01  v0.7.1 add COBRA2
+  History: see the git log.
 
   Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
 
   This driver exists because the "normal" serial driver doesn't work too well
   with GSM modems. Issues:
   - data loss -- one single Receive URB is not nearly enough
-  - nonstandard flow (Option devices) and multiplex (Sierra) control
+  - nonstandard flow (Option devices) control
   - controlling the baud rate doesn't make sense
 
   This driver is named "option" because the most common device it's
@@ -96,8 +70,8 @@
 #define OPTION_VENDOR_ID                0x0AF0
 #define HUAWEI_VENDOR_ID                0x12D1
 #define AUDIOVOX_VENDOR_ID              0x0F3D
-#define SIERRAWIRELESS_VENDOR_ID        0x1199
 #define NOVATELWIRELESS_VENDOR_ID       0x1410
+#define ANYDATA_VENDOR_ID               0x16d5
 
 #define OPTION_PRODUCT_OLD              0x5000
 #define OPTION_PRODUCT_FUSION           0x6000
@@ -106,8 +80,8 @@
 #define OPTION_PRODUCT_COBRA2           0x6600
 #define HUAWEI_PRODUCT_E600             0x1001
 #define AUDIOVOX_PRODUCT_AIRCARD        0x0112
-#define SIERRAWIRELESS_PRODUCT_MC8755   0x6802
 #define NOVATELWIRELESS_PRODUCT_U740    0x1400
+#define ANYDATA_PRODUCT_ID              0x6501
 
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
@@ -117,8 +91,8 @@
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
-	{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
 	{ } /* Terminating entry */
 };
 
@@ -131,10 +105,7 @@
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
 	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
-	{ } /* Terminating entry */
-};
-static struct usb_device_id option_ids3[] = {
-	{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
+	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
 	{ } /* Terminating entry */
 };
 
@@ -151,37 +122,11 @@
 /* The card has three separate interfaces, which the serial driver
  * recognizes separately, thus num_port=1.
  */
-static struct usb_serial_driver option_3port_device = {
-	.driver = {
-		.owner =	THIS_MODULE,
-		.name =		"option",
-	},
-	.description       = "GSM modem (3-port)",
-	.id_table          = option_ids3,
-	.num_interrupt_in  = NUM_DONT_CARE,
-	.num_bulk_in       = NUM_DONT_CARE,
-	.num_bulk_out      = NUM_DONT_CARE,
-	.num_ports         = 3,
-	.open              = option_open,
-	.close             = option_close,
-	.write             = option_write,
-	.write_room        = option_write_room,
-	.chars_in_buffer   = option_chars_in_buffer,
-	.throttle          = option_rx_throttle,
-	.unthrottle        = option_rx_unthrottle,
-	.set_termios       = option_set_termios,
-	.break_ctl         = option_break_ctl,
-	.tiocmget          = option_tiocmget,
-	.tiocmset          = option_tiocmset,
-	.attach            = option_startup,
-	.shutdown          = option_shutdown,
-	.read_int_callback = option_instat_callback,
-};
 
 static struct usb_serial_driver option_1port_device = {
 	.driver = {
 		.owner =	THIS_MODULE,
-		.name =		"option",
+		.name =		"option1",
 	},
 	.description       = "GSM modem (1-port)",
 	.id_table          = option_ids1,
@@ -245,9 +190,6 @@
 	retval = usb_serial_register(&option_1port_device);
 	if (retval)
 		goto failed_1port_device_register;
-	retval = usb_serial_register(&option_3port_device);
-	if (retval)
-		goto failed_3port_device_register;
 	retval = usb_register(&option_driver);
 	if (retval)
 		goto failed_driver_register;
@@ -257,8 +199,6 @@
 	return 0;
 
 failed_driver_register:
-	usb_serial_deregister (&option_3port_device);
-failed_3port_device_register:
 	usb_serial_deregister (&option_1port_device);
 failed_1port_device_register:
 	return retval;
@@ -267,7 +207,6 @@
 static void __exit option_exit(void)
 {
 	usb_deregister (&option_driver);
-	usb_serial_deregister (&option_3port_device);
 	usb_serial_deregister (&option_1port_device);
 }
 
@@ -656,7 +595,6 @@
 
 	dbg("%s", __FUNCTION__);
 
-
 	for (i = 0; i < serial->num_ports; i++) {
 		port = serial->port[i];
 		portdata = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 259db31..65e4d04 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -79,8 +79,8 @@
 	{ USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) },
 	{ USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) },
 	{ USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
-	{ USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) },
 	{ USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
+	{ USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
 	{ }					/* Terminating entry */
 };
 
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
index d9c1e6e..55195e7 100644
--- a/drivers/usb/serial/pl2303.h
+++ b/drivers/usb/serial/pl2303.h
@@ -82,10 +82,10 @@
 #define SPEEDDRAGON_VENDOR_ID	0x0e55
 #define SPEEDDRAGON_PRODUCT_ID	0x110b
 
-/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */
-#define OTI_VENDOR_ID	0x0ea0
-#define OTI_PRODUCT_ID	0x6858
-
 /* DATAPILOT Universal-2 Phone Cable */
 #define DATAPILOT_U2_VENDOR_ID	0x0731
 #define DATAPILOT_U2_PRODUCT_ID	0x2003
+
+/* Belkin "F5U257" Serial Adapter */
+#define BELKIN_VENDOR_ID	0x050d
+#define BELKIN_PRODUCT_ID	0x0257
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index a5ca449..b130e17 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -145,6 +145,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Mario Rettig <mariorettig@web.de> */
+UNUSUAL_DEV(  0x0421, 0x042e, 0x0100, 0x0100,
+		"Nokia",
+		"Nokia 3250",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
 /* Reported by Sumedha Swamy <sumedhaswamy@gmail.com> and
  * Einar Th. Einarsson <einarthered@gmail.com> */
 UNUSUAL_DEV(  0x0421, 0x0444, 0x0100, 0x0100,
@@ -234,16 +241,6 @@
 		"Finecam S5",
 		US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY),
 
-/* Patch for Kyocera Finecam L3
- * Submitted by Michael Krauth <michael.krauth@web.de>
- * and Alessandro Fracchetti <al.fracchetti@tin.it>
- */
-UNUSUAL_DEV(  0x0482, 0x0105, 0x0100, 0x0100,
-		"Kyocera",
-		"Finecam L3",
-		US_SC_SCSI, US_PR_BULK, NULL,
-		US_FL_FIX_INQUIRY),
-
 /* Reported by Paul Stewart <stewart@wetlogic.net>
  * This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x04a4, 0x0004, 0x0001, 0x0001,
@@ -592,6 +589,13 @@
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_FIX_INQUIRY ),
 
+/* floppy reports multiple luns */
+UNUSUAL_DEV(  0x055d, 0x2020, 0x0000, 0x0210,
+               "SAMSUNG",
+               "SFD-321U [FW 0C]",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
+
 		
 UNUSUAL_DEV(  0x057b, 0x0000, 0x0000, 0x0299, 
 		"Y-E Data",
@@ -627,18 +631,6 @@
 		"Digital Camera EX-20 DSC",
 		US_SC_8070, US_PR_DEVICE, NULL, 0 ),
 
-/* The entry was here before I took over, and had US_SC_RBC. It turns
- * out that isn't needed. Additionally, Torsten Eriksson
- * <Torsten.Eriksson@bergianska.se> is able to use his device fine
- * without this entry at all - but I don't suspect that will be true
- * for all users (the protocol is likely needed), so is staying at
- * this time. - Phil Dibowitz <phil@ipom.com>
- */
-UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200, 
-		"LaCie",
-		"USB Hard Disk",
-		US_SC_DEVICE, US_PR_CB, NULL, 0 ),
-
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
  * Some versions of this device need the SubClass and Protocol overrides
  * while others don't.
@@ -1106,7 +1098,15 @@
                 "Optio S/S4",
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_FIX_INQUIRY ),
-		
+
+/* This is a virtual windows driver CD, which the zd1211rw driver automatically
+ * converts into a WLAN device. */
+UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
+                "ZyXEL",
+                "G-220F USB-WLAN Install",
+                US_SC_DEVICE, US_PR_DEVICE, NULL,
+                US_FL_IGNORE_DEVICE ),
+
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x0bf6, 0xa001, 0x0100, 0x0110,
 		"ATI",
@@ -1237,6 +1237,16 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64),
 
+/* David Kuehling <dvdkhlng@gmx.de>:
+ * for MP3-Player AVOX WSX-300ER (bought in Japan).  Reports lots of SCSI
+ * errors when trying to write.
+ */
+UNUSUAL_DEV(  0x0f19, 0x0105, 0x0100, 0x0100,
+		"C-MEX",
+		"A-VOX",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Reported by Michael Stattmann <michael@stattmann.com> */
 UNUSUAL_DEV(  0x0fce, 0xd008, 0x0000, 0x0000,
 		"Sony Ericsson",
@@ -1244,11 +1254,18 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_NO_WP_DETECT ),
 
+/* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
+UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
+		"Sony Ericsson",
+		"M600i",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
  */
-UNUSUAL_DEV(  0x1019, 0x0c55, 0x0000, 0x9999,
+UNUSUAL_DEV(  0x1019, 0x0c55, 0x0110, 0x0110,
 		"Desknote",
 		"UCR-61S2B",
 		US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 5ee19be..8d7bdcb 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -483,7 +483,7 @@
 }
 
 /* Get the unusual_devs entries and the string descriptors */
-static void get_device_info(struct us_data *us, const struct usb_device_id *id)
+static int get_device_info(struct us_data *us, const struct usb_device_id *id)
 {
 	struct usb_device *dev = us->pusb_dev;
 	struct usb_interface_descriptor *idesc =
@@ -500,6 +500,11 @@
 			unusual_dev->useTransport;
 	us->flags = USB_US_ORIG_FLAGS(id->driver_info);
 
+	if (us->flags & US_FL_IGNORE_DEVICE) {
+		printk(KERN_INFO USB_STORAGE "device ignored\n");
+		return -ENODEV;
+	}
+
 	/*
 	 * This flag is only needed when we're in high-speed, so let's
 	 * disable it if we're in full-speed
@@ -541,6 +546,8 @@
 				msgs[msg],
 				UTS_RELEASE);
 	}
+
+	return 0;
 }
 
 /* Get the transport settings */
@@ -969,7 +976,9 @@
 	 * of the match from the usb_device_id table, so we can find the
 	 * corresponding entry in the private table.
 	 */
-	get_device_info(us, id);
+	result = get_device_info(us, id);
+	if (result)
+		goto BadDevice;
 
 	/* Get the transport, protocol, and pipe settings */
 	result = get_transport(us);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6533b0f..702eb93 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -86,9 +86,11 @@
        default n
 
 config FB_BACKLIGHT
-       bool
-       depends on FB
-       default n
+	bool
+	depends on FB
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default n
 
 config FB_MODE_HELPERS
         bool "Enable Video Mode Handling Helpers"
@@ -420,7 +422,7 @@
 
 config FB_CONTROL
 	bool "Apple \"control\" display support"
-	depends on (FB = y) && PPC_PMAC
+	depends on (FB = y) && PPC_PMAC && PPC32
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -431,7 +433,7 @@
 
 config FB_PLATINUM
 	bool "Apple \"platinum\" display support"
-	depends on (FB = y) && PPC_PMAC
+	depends on (FB = y) && PPC_PMAC && PPC32
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -442,7 +444,7 @@
 
 config FB_VALKYRIE
 	bool "Apple \"valkyrie\" display support"
-	depends on (FB = y) && (MAC || PPC_PMAC)
+	depends on (FB = y) && (MAC || (PPC_PMAC && PPC32))
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -453,7 +455,7 @@
 
 config FB_CT65550
 	bool "Chips 65550 display support"
-	depends on (FB = y) && PPC
+	depends on (FB = y) && PPC32
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -552,7 +554,7 @@
 
 config FB_IMAC
 	bool "Intel-based Macintosh Framebuffer Support"
-	depends on (FB = y) && X86
+	depends on (FB = y) && X86 && EFI
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
@@ -721,10 +723,8 @@
 
 config FB_NVIDIA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_NVIDIA && PPC_PMAC
+	depends on FB_NVIDIA && PMAC_BACKLIGHT
 	select FB_BACKLIGHT
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -769,10 +769,8 @@
 
 config FB_RIVA_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RIVA && PPC_PMAC
+	depends on FB_RIVA && PMAC_BACKLIGHT
 	select FB_BACKLIGHT
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1025,10 +1023,8 @@
 
 config FB_RADEON_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_RADEON && PPC_PMAC
+	depends on FB_RADEON && PMAC_BACKLIGHT
 	select FB_BACKLIGHT
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1059,10 +1055,8 @@
 
 config FB_ATY128_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY128 && PPC_PMAC
+	depends on FB_ATY128 && PMAC_BACKLIGHT
 	select FB_BACKLIGHT
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1111,10 +1105,8 @@
 
 config FB_ATY_BACKLIGHT
 	bool "Support for backlight control"
-	depends on FB_ATY && PPC_PMAC
+	depends on FB_ATY && PMAC_BACKLIGHT
 	select FB_BACKLIGHT
-	select BACKLIGHT_LCD_SUPPORT
-	select BACKLIGHT_CLASS_DEVICE
 	default y
 	help
 	  Say Y here if you want to control the backlight of your display.
@@ -1620,7 +1612,7 @@
 	source "drivers/video/logo/Kconfig"
 endif
 
-if FB && SYSFS
+if SYSFS
 	source "drivers/video/backlight/Kconfig"
 endif
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 95563c9..481c6c9 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,6 +4,7 @@
 
 # Each configuration option enables a list of files.
 
+obj-y                             += fb_notify.o
 obj-$(CONFIG_FB)                  += fb.o
 fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
                                      modedb.o fbcvt.o
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index c64a717..276a215 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -455,7 +455,10 @@
 static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
 static void wait_for_idle(struct aty128fb_par *par);
 static u32 depth_to_dst(u32 depth);
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
 static void aty128_bl_set_power(struct fb_info *info, int power);
+#endif
 
 #define BIOS_IN8(v)  	(readb(bios + (v)))
 #define BIOS_IN16(v) 	(readb(bios + (v)) | \
@@ -1798,10 +1801,14 @@
 static void aty128_bl_set_power(struct fb_info *info, int power)
 {
 	mutex_lock(&info->bl_mutex);
-	up(&info->bl_dev->sem);
-	info->bl_dev->props->power = power;
-	__aty128_bl_update_status(info->bl_dev);
-	down(&info->bl_dev->sem);
+
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = power;
+		__aty128_bl_update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
+	}
+
 	mutex_unlock(&info->bl_mutex);
 }
 
@@ -1825,7 +1832,7 @@
 	bd = backlight_device_register(name, par, &aty128_bl_data);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
-		printk("aty128: Backlight registration failed\n");
+		printk(KERN_WARNING "aty128: Backlight registration failed\n");
 		goto error;
 	}
 
@@ -1836,11 +1843,11 @@
 		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
 	mutex_unlock(&info->bl_mutex);
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = aty128_bl_data.max_brightness;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	mutex_lock(&pmac_backlight_mutex);
@@ -1910,9 +1917,6 @@
 	u8 chip_rev;
 	u32 dac;
 
-	if (!par->vram_size)	/* may have already been probed */
-		par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
-
 	/* Get the chip revision */
 	chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
 
@@ -2025,9 +2029,6 @@
 
 	aty128_init_engine(par);
 
-	if (register_framebuffer(info) < 0)
-		return 0;
-
 	par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	par->pdev = pdev;
 	par->asleep = 0;
@@ -2037,6 +2038,9 @@
 	aty128_bl_init(par);
 #endif
 
+	if (register_framebuffer(info) < 0)
+		return 0;
+
 	printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
 	       info->node, info->fix.id, video_card);
 
@@ -2086,7 +2090,6 @@
 	par = info->par;
 
 	info->pseudo_palette = par->pseudo_palette;
-	info->fix = aty128fb_fix;
 
 	/* Virtualize mmio region */
 	info->fix.mmio_start = reg_addr;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 1507d19..19a71f0 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2200,10 +2200,14 @@
 static void aty_bl_set_power(struct fb_info *info, int power)
 {
 	mutex_lock(&info->bl_mutex);
-	up(&info->bl_dev->sem);
-	info->bl_dev->props->power = power;
-	__aty_bl_update_status(info->bl_dev);
-	down(&info->bl_dev->sem);
+
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = power;
+		__aty_bl_update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
+	}
+
 	mutex_unlock(&info->bl_mutex);
 }
 
@@ -2223,7 +2227,7 @@
 	bd = backlight_device_register(name, par, &aty_bl_data);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
-		printk("aty: Backlight registration failed\n");
+		printk(KERN_WARNING "aty: Backlight registration failed\n");
 		goto error;
 	}
 
@@ -2234,11 +2238,11 @@
 		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
 	mutex_unlock(&info->bl_mutex);
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = aty_bl_data.max_brightness;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	mutex_lock(&pmac_backlight_mutex);
@@ -2812,7 +2816,7 @@
 	if (par->lock_blank || par->asleep)
 		return 0;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
+#ifdef CONFIG_FB_ATY_BACKLIGHT
 	if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
 		aty_bl_set_power(info, FB_BLANK_POWERDOWN);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
@@ -2844,7 +2848,7 @@
 	}
 	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
-#ifdef CONFIG_PMAC_BACKLIGHT
+#ifdef CONFIG_FB_ATY_BACKLIGHT
 	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
 		aty_bl_set_power(info, FB_BLANK_UNBLANK);
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 1755ddd..585eb7b 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -195,11 +195,11 @@
 		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
 	mutex_unlock(&rinfo->info->bl_mutex);
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = radeon_bl_data.max_brightness;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 8d85fc5..8e3400d 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -266,6 +266,8 @@
 #ifdef CONFIG_MTRR
 static int nomtrr = 0;
 #endif
+static int force_sleep;
+static int ignore_devlist;
 
 /*
  * prototypes
@@ -2327,9 +2329,9 @@
 		/* -2 is special: means  ON on mobility chips and do not
 		 * change on others
 		 */
-		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep);
 	} else
-		radeonfb_pm_init(rinfo, default_dynclk);
+		radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep);
 
 	pci_set_drvdata(pdev, info);
 
@@ -2477,6 +2479,12 @@
 			force_measure_pll = 1;
 		} else if (!strncmp(this_opt, "ignore_edid", 11)) {
 			ignore_edid = 1;
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+	 	} else if (!strncmp(this_opt, "force_sleep", 11)) {
+			force_sleep = 1;
+		} else if (!strncmp(this_opt, "ignore_devlist", 14)) {
+			ignore_devlist = 1;
+#endif
 		} else
 			mode_option = this_opt;
 	}
@@ -2532,3 +2540,9 @@
 MODULE_PARM_DESC(panel_yres, "int: set panel yres");
 module_param(mode_option, charp, 0);
 MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+module_param(force_sleep, bool, 0);
+MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware");
+module_param(ignore_devlist, bool, 0);
+MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops");
+#endif
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
index c709176..f31e606 100644
--- a/drivers/video/aty/radeon_pm.c
+++ b/drivers/video/aty/radeon_pm.c
@@ -27,6 +27,99 @@
 
 #include "ati_ids.h"
 
+static void radeon_reinitialize_M10(struct radeonfb_info *rinfo);
+
+/*
+ * Workarounds for bugs in PC laptops:
+ * - enable D2 sleep in some IBM Thinkpads
+ * - special case for Samsung P35
+ *
+ * Whitelist by subsystem vendor/device because
+ * its the subsystem vendor's fault!
+ */
+
+#if defined(CONFIG_PM) && defined(CONFIG_X86)
+struct radeon_device_id {
+        const char *ident;                     /* (arbitrary) Name */
+        const unsigned short subsystem_vendor; /* Subsystem Vendor ID */
+        const unsigned short subsystem_device; /* Subsystem Device ID */
+	const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */
+	const reinit_function_ptr new_reinit_func;   /* changed reinit_func */
+};
+
+#define BUGFIX(model, sv, sd, pm, fn) { \
+	.ident = model, \
+	.subsystem_vendor = sv, \
+	.subsystem_device = sd, \
+	.pm_mode_modifier = pm, \
+	.new_reinit_func  = fn  \
+}
+
+static struct radeon_device_id radeon_workaround_list[] = {
+	BUGFIX("IBM Thinkpad R32",
+	       PCI_VENDOR_ID_IBM, 0x1905,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R40",
+	       PCI_VENDOR_ID_IBM, 0x0526,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R40",
+	       PCI_VENDOR_ID_IBM, 0x0527,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R50/R51/T40/T41",
+	       PCI_VENDOR_ID_IBM, 0x0531,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad R51/T40/T41/T42",
+	       PCI_VENDOR_ID_IBM, 0x0530,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T30",
+	       PCI_VENDOR_ID_IBM, 0x0517,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T40p",
+	       PCI_VENDOR_ID_IBM, 0x054d,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad T42",
+	       PCI_VENDOR_ID_IBM, 0x0550,
+	       radeon_pm_d2, NULL),
+	BUGFIX("IBM Thinkpad X31/X32",
+	       PCI_VENDOR_ID_IBM, 0x052f,
+	       radeon_pm_d2, NULL),
+	BUGFIX("Samsung P35",
+	       PCI_VENDOR_ID_SAMSUNG, 0xc00c,
+	       radeon_pm_off, radeon_reinitialize_M10),
+	{ .ident = NULL }
+};
+
+static int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+	struct radeon_device_id *id;
+
+	for (id = radeon_workaround_list; id->ident != NULL; id++ )
+		if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) &&
+		    (id->subsystem_device == rinfo->pdev->subsystem_device )) {
+
+			/* we found a device that requires workaround */
+			printk(KERN_DEBUG "radeonfb: %s detected"
+			       ", enabling workaround\n", id->ident);
+
+			rinfo->pm_mode |= id->pm_mode_modifier;
+
+			if (id->new_reinit_func != NULL)
+				rinfo->reinit_func = id->new_reinit_func;
+
+			return 1;
+		}
+	return 0;  /* not found */
+}
+
+#else  /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo)
+{
+        return 0;
+}
+#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */
+
+
+
 static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
 {
 	u32 tmp;
@@ -852,18 +945,26 @@
 	/* because both INPLL and OUTPLL take the same lock, that's why. */
 	tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND;
 	OUTPLL( pllMCLK_MISC, tmp);
-	
-	/* AGP PLL control */
-	if (rinfo->family <= CHIP_FAMILY_RV280) {
-		OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
 
-		OUTREG(BUS_CNTL1,
-		       (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
-		       | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));	// 440BX
-	} else {
-		OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
-		OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+	/* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset
+	 * and radeon chip dependent. Thus we only enable it on Mac for
+	 * now (until we get more info on how to compute the correct
+	 * value for various X86 bridges).
+	 */
+#ifdef CONFIG_PPC_PMAC
+	if (machine_is(powermac)) {
+		/* AGP PLL control */
+		if (rinfo->family <= CHIP_FAMILY_RV280) {
+			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) |  BUS_CNTL1__AGPCLK_VALID);
+			OUTREG(BUS_CNTL1,
+			       (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK)
+			       | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT));	// 440BX
+		} else {
+			OUTREG(BUS_CNTL1, INREG(BUS_CNTL1));
+			OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000);
+		}
 	}
+#endif
 
 	OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL)
 				  & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN));
@@ -2713,7 +2814,7 @@
 
 #endif /* CONFIG_PM */
 
-void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk)
+void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep)
 {
 	/* Find PM registers in config space if any*/
 	rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM);
@@ -2729,22 +2830,13 @@
 	}
 
 #if defined(CONFIG_PM)
+#if defined(CONFIG_PPC_PMAC)
 	/* Check if we can power manage on suspend/resume. We can do
 	 * D2 on M6, M7 and M9, and we can resume from D3 cold a few other
 	 * "Mac" cards, but that's all. We need more infos about what the
 	 * BIOS does tho. Right now, all this PM stuff is pmac-only for that
 	 * reason. --BenH
 	 */
-	/* Special case for Samsung P35 laptops
-	 */
-	if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) &&
-	    (rinfo->pdev->device == PCI_CHIP_RV350_NP) &&
-	    (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) &&
-	    (rinfo->pdev->subsystem_device == 0xc00c)) {
-		rinfo->reinit_func = radeon_reinitialize_M10;
-		rinfo->pm_mode |= radeon_pm_off;
-	}
-#if defined(CONFIG_PPC_PMAC)
 	if (machine_is(powermac) && rinfo->of_node) {
 		if (rinfo->is_mobility && rinfo->pm_reg &&
 		    rinfo->family <= CHIP_FAMILY_RV250)
@@ -2790,6 +2882,18 @@
 	}
 #endif /* defined(CONFIG_PPC_PMAC) */
 #endif /* defined(CONFIG_PM) */
+
+	if (ignore_devlist)
+		printk(KERN_DEBUG
+		       "radeonfb: skipping test for device workarounds\n");
+	else
+		radeon_apply_workarounds(rinfo);
+
+	if (force_sleep) {
+		printk(KERN_DEBUG
+		       "radeonfb: forcefully enabling D2 sleep mode\n");
+		rinfo->pm_mode |= radeon_pm_d2;
+	}
 }
 
 void radeonfb_pm_exit(struct radeonfb_info *rinfo)
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 38657b2..d5ff224 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -273,6 +273,8 @@
 	radeon_pm_off	= 0x00000002,	/* Can resume from D3 cold */
 };
 
+typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo);
+
 struct radeonfb_info {
 	struct fb_info		*info;
 
@@ -338,7 +340,7 @@
 	int			dynclk;
 	int			no_schedule;
 	enum radeon_pm_mode	pm_mode;
-	void			(*reinit_func)(struct radeonfb_info *rinfo);
+	reinit_function_ptr     reinit_func;
 
 	/* Lock on register access */
 	spinlock_t		reg_lock;
@@ -600,7 +602,7 @@
 /* PM Functions */
 extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int radeonfb_pci_resume(struct pci_dev *pdev);
-extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk);
+extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep);
 extern void radeonfb_pm_exit(struct radeonfb_info *rinfo);
 
 /* Monitor probe functions */
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index a92a91f..f25d5d6 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -156,7 +156,7 @@
 
 			info->fix.visual = FB_VISUAL_TRUECOLOR;
 			info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */
-	}
+		}
 	} else {
 		/* mono */
 		info->fix.visual = FB_VISUAL_MONO10;
@@ -164,20 +164,16 @@
 	}
 
 	info->screen_size = info->fix.line_length * info->var.yres_virtual;
+	info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \
+				>> LCD_CONTROL_SM_BIT) * 90;
 
 	/* Determine BPP mode and format */
-	fbdev->regs->lcd_control = fbdev->panel->control_base |
-			    ((info->var.rotate/90) << LCD_CONTROL_SM_BIT);
-
+	fbdev->regs->lcd_control = fbdev->panel->control_base;
+	fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
+	fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
+	fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
 	fbdev->regs->lcd_intenable = 0;
 	fbdev->regs->lcd_intstatus = 0;
-
-	fbdev->regs->lcd_horztiming = fbdev->panel->horztiming;
-
-	fbdev->regs->lcd_verttiming = fbdev->panel->verttiming;
-
-	fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base;
-
 	fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys);
 
 	if (panel_is_dual(fbdev->panel)) {
@@ -206,6 +202,8 @@
 
 	/* Resume controller */
 	fbdev->regs->lcd_control |= LCD_CONTROL_GO;
+	mdelay(10);
+	au1100fb_fb_blank(VESA_NO_BLANKING, info);
 
 	return 0;
 }
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 022f9d3..02f1529 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -10,7 +10,7 @@
 
 config BACKLIGHT_CLASS_DEVICE
         tristate "Lowlevel Backlight controls"
-	depends on BACKLIGHT_LCD_SUPPORT && FB
+	depends on BACKLIGHT_LCD_SUPPORT
 	default m
 	help
 	  This framework adds support for low-level control of the LCD
@@ -26,7 +26,7 @@
 
 config LCD_CLASS_DEVICE
         tristate "Lowlevel LCD controls"
-	depends on BACKLIGHT_LCD_SUPPORT && FB
+	depends on BACKLIGHT_LCD_SUPPORT
 	default m
 	help
 	  This framework adds support for low-level control of LCD.
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 52ed12b..eb4d03f 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -197,7 +197,7 @@
 __setup("mdacon=", mdacon_setup);
 #endif
 
-static int __init mda_detect(void)
+static int mda_detect(void)
 {
 	int count=0;
 	u16 *p, p_save;
@@ -282,7 +282,7 @@
 	return 1;
 }
 
-static void __init mda_initialize(void)
+static void mda_initialize(void)
 {
 	write_mda_b(97, 0x00);		/* horizontal total */
 	write_mda_b(80, 0x01);		/* horizontal displayed */
diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c
new file mode 100644
index 0000000..8c02038
--- /dev/null
+++ b/drivers/video/fb_notify.c
@@ -0,0 +1,46 @@
+/*
+ *  linux/drivers/video/fb_notify.c
+ *
+ *  Copyright (C) 2006 Antonino Daplas <adaplas@pol.net>
+ *
+ *	2001 - Documented with DocBook
+ *	- Brad Douglas <brad@neruo.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+#include <linux/fb.h>
+#include <linux/notifier.h>
+
+static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
+
+/**
+ *	fb_register_client - register a client notifier
+ *	@nb: notifier block to callback on events
+ */
+int fb_register_client(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_register_client);
+
+/**
+ *	fb_unregister_client - unregister a client notifier
+ *	@nb: notifier block to callback on events
+ */
+int fb_unregister_client(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
+}
+EXPORT_SYMBOL(fb_unregister_client);
+
+/**
+ * fb_notifier_call_chain - notify clients of fb_events
+ *
+ */
+int fb_notifier_call_chain(unsigned long val, void *v)
+{
+	return blocking_notifier_call_chain(&fb_notifier_list, val, v);
+}
+EXPORT_SYMBOL_GPL(fb_notifier_call_chain);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 4fc9df4..17961e3 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -52,7 +52,6 @@
 
 #define FBPIXMAPSIZE	(1024 * 8)
 
-static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb;
 
@@ -791,8 +790,7 @@
 
 		    event.info = info;
 		    event.data = &mode1;
-		    ret = blocking_notifier_call_chain(&fb_notifier_list,
-					      FB_EVENT_MODE_DELETE, &event);
+		    ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event);
 		}
 
 		if (!ret)
@@ -837,8 +835,7 @@
 
 				info->flags &= ~FBINFO_MISC_USEREVENT;
 				event.info = info;
-				blocking_notifier_call_chain(&fb_notifier_list,
-						evnt, &event);
+				fb_notifier_call_chain(evnt, &event);
 			}
 		}
 	}
@@ -861,8 +858,7 @@
 
 		event.info = info;
 		event.data = &blank;
-		blocking_notifier_call_chain(&fb_notifier_list,
-				FB_EVENT_BLANK, &event);
+		fb_notifier_call_chain(FB_EVENT_BLANK, &event);
 	}
 
  	return ret;
@@ -933,8 +929,7 @@
 		con2fb.framebuffer = -1;
 		event.info = info;
 		event.data = &con2fb;
-		blocking_notifier_call_chain(&fb_notifier_list,
-				    FB_EVENT_GET_CONSOLE_MAP, &event);
+		fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
 		return copy_to_user(argp, &con2fb,
 				    sizeof(con2fb)) ? -EFAULT : 0;
 	case FBIOPUT_CON2FBMAP:
@@ -952,9 +947,8 @@
 		    return -EINVAL;
 		event.info = info;
 		event.data = &con2fb;
-		return blocking_notifier_call_chain(&fb_notifier_list,
-					   FB_EVENT_SET_CONSOLE_MAP,
-					   &event);
+		return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
+					      &event);
 	case FBIOBLANK:
 		acquire_console_sem();
 		info->flags |= FBINFO_MISC_USEREVENT;
@@ -1330,8 +1324,7 @@
 	registered_fb[i] = fb_info;
 
 	event.info = fb_info;
-	blocking_notifier_call_chain(&fb_notifier_list,
-			    FB_EVENT_FB_REGISTERED, &event);
+	fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
 	return 0;
 }
 
@@ -1365,30 +1358,11 @@
 	fb_cleanup_class_device(fb_info);
 	class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	event.info = fb_info;
-	blocking_notifier_call_chain(&fb_notifier_list,
-				     FB_EVENT_FB_UNREGISTERED, &event);
+	fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
 	return 0;
 }
 
 /**
- *	fb_register_client - register a client notifier
- *	@nb: notifier block to callback on events
- */
-int fb_register_client(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&fb_notifier_list, nb);
-}
-
-/**
- *	fb_unregister_client - unregister a client notifier
- *	@nb: notifier block to callback on events
- */
-int fb_unregister_client(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
-}
-
-/**
  *	fb_set_suspend - low level driver signals suspend
  *	@info: framebuffer affected
  *	@state: 0 = resuming, !=0 = suspending
@@ -1403,13 +1377,11 @@
 
 	event.info = info;
 	if (state) {
-		blocking_notifier_call_chain(&fb_notifier_list,
-				FB_EVENT_SUSPEND, &event);
+		fb_notifier_call_chain(FB_EVENT_SUSPEND, &event);
 		info->state = FBINFO_STATE_SUSPENDED;
 	} else {
 		info->state = FBINFO_STATE_RUNNING;
-		blocking_notifier_call_chain(&fb_notifier_list,
-				FB_EVENT_RESUME, &event);
+		fb_notifier_call_chain(FB_EVENT_RESUME, &event);
 	}
 }
 
@@ -1480,9 +1452,7 @@
 
 	if (!list_empty(&info->modelist)) {
 		event.info = info;
-		err = blocking_notifier_call_chain(&fb_notifier_list,
-					   FB_EVENT_NEW_MODELIST,
-					   &event);
+		err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
 	}
 
 	return err;
@@ -1594,8 +1564,6 @@
 EXPORT_SYMBOL(fb_pan_display);
 EXPORT_SYMBOL(fb_get_buffer_offset);
 EXPORT_SYMBOL(fb_set_suspend);
-EXPORT_SYMBOL(fb_register_client);
-EXPORT_SYMBOL(fb_unregister_client);
 EXPORT_SYMBOL(fb_get_options);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
index ff233b8..18ea4a5 100644
--- a/drivers/video/imacfb.c
+++ b/drivers/video/imacfb.c
@@ -18,6 +18,8 @@
 #include <linux/screen_info.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/dmi.h>
+#include <linux/efi.h>
 
 #include <asm/io.h>
 
@@ -28,7 +30,7 @@
 	M_I20,
 	M_MINI,
 	M_MACBOOK,
-	M_NEW
+	M_UNKNOWN
 } MAC_TYPE;
 
 /* --------------------------------------------------------------------- */
@@ -52,10 +54,36 @@
 };
 
 static int inverse;
-static int model		= M_NEW;
+static int model		= M_UNKNOWN;
 static int manual_height;
 static int manual_width;
 
+static int set_system(struct dmi_system_id *id)
+{
+	printk(KERN_INFO "imacfb: %s detected - set system to %ld\n",
+		id->ident, (long)id->driver_data);
+
+	model = (long)id->driver_data;
+
+	return 0;
+}
+
+static struct dmi_system_id __initdata dmi_system_table[] = {
+	{ set_system, "iMac4,1", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
+	{ set_system, "MacBookPro1,1", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
+	{ set_system, "MacBook1,1", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
+	{ set_system, "Macmini1,1", {
+	  DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
+	  DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI},
+	{},
+};
+
 #define	DEFAULT_FB_MEM	1024*1024*16
 
 /* --------------------------------------------------------------------- */
@@ -149,7 +177,6 @@
 		screen_info.lfb_linelength = 1472 * 4;
 		screen_info.lfb_base = 0x80010000;
 		break;
-	case M_NEW:
 	case M_I20:
 		screen_info.lfb_width = 1680;
 		screen_info.lfb_height = 1050;
@@ -207,6 +234,10 @@
 		size_remap = size_total;
 	imacfb_fix.smem_len = size_remap;
 
+#ifndef __i386__
+	screen_info.imacpm_seg = 0;
+#endif
+
 	if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
 		printk(KERN_WARNING
 		       "imacfb: cannot reserve video memory at 0x%lx\n",
@@ -324,8 +355,16 @@
 	int ret;
 	char *option = NULL;
 
-	/* ignore error return of fb_get_options */
-	fb_get_options("imacfb", &option);
+	if (!efi_enabled)
+		return -ENODEV;
+	if (!dmi_check_system(dmi_system_table))
+		return -ENODEV;
+	if (model == M_UNKNOWN)
+		return -ENODEV;
+
+	if (fb_get_options("imacfb", &option))
+		return -ENODEV;
+
 	imacfb_setup(option);
 	ret = platform_driver_register(&imacfb_driver);
 
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 440272a..7c76e07 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -331,7 +331,15 @@
 					tmp |= M1064_XPIXCLKCTRL_PLL_UP;
 				}
 				matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp);
+#ifdef __powerpc__
+				/* This is necessary to avoid jitter on PowerPC
+				 * (OpenFirmware) systems, but apparently
+				 * introduces jitter, at least on a x86-64
+				 * using DVI.
+				 * A simple workaround is disable for non-PPC.
+				 */
 				matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0);
+#endif /* __powerpc__ */
 				matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl);
 
 				matroxfb_DAC_unlock_irqrestore(flags);
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index b45f577..5b75ae4 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -113,10 +113,14 @@
 void nvidia_bl_set_power(struct fb_info *info, int power)
 {
 	mutex_lock(&info->bl_mutex);
-	up(&info->bl_dev->sem);
-	info->bl_dev->props->power = power;
-	__nvidia_bl_update_status(info->bl_dev);
-	down(&info->bl_dev->sem);
+
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = power;
+		__nvidia_bl_update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
+	}
+
 	mutex_unlock(&info->bl_mutex);
 }
 
@@ -140,7 +144,7 @@
 	bd = backlight_device_register(name, par, &nvidia_bl_data);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
-		printk("nvidia: Backlight registration failed\n");
+		printk(KERN_WARNING "nvidia: Backlight registration failed\n");
 		goto error;
 	}
 
@@ -151,11 +155,11 @@
 		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
 	mutex_unlock(&info->bl_mutex);
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = nvidia_bl_data.max_brightness;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	mutex_lock(&pmac_backlight_mutex);
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 9f2066f..d4f8501 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -34,10 +34,6 @@
 #include "nv_proto.h"
 #include "nv_dma.h"
 
-#ifndef CONFIG_PCI		/* sanity check */
-#error This driver requires PCI support.
-#endif
-
 #undef CONFIG_FB_NVIDIA_DEBUG
 #ifdef CONFIG_FB_NVIDIA_DEBUG
 #define NVTRACE          printk
@@ -1303,20 +1299,19 @@
 
 	nvidia_save_vga(par, &par->SavedReg);
 
+	pci_set_drvdata(pd, info);
+	nvidia_bl_init(par);
 	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
 		goto err_out_iounmap_fb;
 	}
 
-	pci_set_drvdata(pd, info);
 
 	printk(KERN_INFO PFX
 	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
 	       info->fix.id,
 	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
 
-	nvidia_bl_init(par);
-
 	NVTRACE_LEAVE();
 	return 0;
 
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index ce5f303..0013311 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -62,8 +62,6 @@
      *  Interface used by the world
      */
 
-int offb_init(void);
-
 static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			  u_int transp, struct fb_info *info);
 static int offb_blank(int blank, struct fb_info *info);
@@ -72,11 +70,6 @@
 extern boot_infos_t *boot_infos;
 #endif
 
-static void offb_init_nodriver(struct device_node *);
-static void offb_init_fb(const char *name, const char *full_name,
-			 int width, int height, int depth, int pitch,
-			 unsigned long address, struct device_node *dp);
-
 static struct fb_ops offb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_setcolreg	= offb_setcolreg,
@@ -229,123 +222,17 @@
 	return 0;
 }
 
-    /*
-     *  Initialisation
-     */
 
-int __init offb_init(void)
+static void __iomem *offb_map_reg(struct device_node *np, int index,
+				  unsigned long offset, unsigned long size)
 {
-	struct device_node *dp = NULL, *boot_disp = NULL;
+	struct resource r;
 
-	if (fb_get_options("offb", NULL))
-		return -ENODEV;
-
-	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-		if (get_property(dp, "linux,opened", NULL) &&
-		    get_property(dp, "linux,boot-display", NULL)) {
-			boot_disp = dp;
-			offb_init_nodriver(dp);
-		}
-	}
-	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
-		if (get_property(dp, "linux,opened", NULL) &&
-		    dp != boot_disp)
-			offb_init_nodriver(dp);
-	}
-
-	return 0;
-}
-
-
-static void __init offb_init_nodriver(struct device_node *dp)
-{
-	unsigned int len;
-	int i, width = 640, height = 480, depth = 8, pitch = 640;
-	unsigned int flags, rsize, addr_prop = 0;
-	unsigned long max_size = 0;
-	u64 rstart, address = OF_BAD_ADDR;
-	u32 *pp, *addrp, *up;
-	u64 asize;
-
-	pp = (u32 *)get_property(dp, "linux,bootx-depth", &len);
-	if (pp == NULL)
-		pp = (u32 *)get_property(dp, "depth", &len);
-	if (pp && len == sizeof(u32))
-		depth = *pp;
-
-	pp = (u32 *)get_property(dp, "linux,bootx-width", &len);
-	if (pp == NULL)
-		pp = (u32 *)get_property(dp, "width", &len);
-	if (pp && len == sizeof(u32))
-		width = *pp;
-
-	pp = (u32 *)get_property(dp, "linux,bootx-height", &len);
-	if (pp == NULL)
-		pp = (u32 *)get_property(dp, "height", &len);
-	if (pp && len == sizeof(u32))
-		height = *pp;
-
-	pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len);
-	if (pp == NULL)
-		pp = (u32 *)get_property(dp, "linebytes", &len);
-	if (pp && len == sizeof(u32))
-		pitch = *pp;
-	else
-		pitch = width * ((depth + 7) / 8);
-
-	rsize = (unsigned long)pitch * (unsigned long)height;
-
-	/* Ok, now we try to figure out the address of the framebuffer.
-	 *
-	 * Unfortunately, Open Firmware doesn't provide a standard way to do
-	 * so. All we can do is a dodgy heuristic that happens to work in
-	 * practice. On most machines, the "address" property contains what
-	 * we need, though not on Matrox cards found in IBM machines. What I've
-	 * found that appears to give good results is to go through the PCI
-	 * ranges and pick one that is both big enough and if possible encloses
-	 * the "address" property. If none match, we pick the biggest
-	 */
-	up = (u32 *)get_property(dp, "linux,bootx-addr", &len);
-	if (up == NULL)
-		up = (u32 *)get_property(dp, "address", &len);
-	if (up && len == sizeof(u32))
-		addr_prop = *up;
-
-	for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
-		     != NULL; i++) {
-		int match_addrp = 0;
-
-		if (!(flags & IORESOURCE_MEM))
-			continue;
-		if (asize < rsize)
-			continue;
-		rstart = of_translate_address(dp, addrp);
-		if (rstart == OF_BAD_ADDR)
-			continue;
-		if (addr_prop && (rstart <= addr_prop) &&
-		    ((rstart + asize) >= (addr_prop + rsize)))
-			match_addrp = 1;
-		if (match_addrp) {
-			address = addr_prop;
-			break;
-		}
-		if (rsize > max_size) {
-			max_size = rsize;
-			address = OF_BAD_ADDR;
- 		}
-
-		if (address == OF_BAD_ADDR)
-			address = rstart;
-	}
-	if (address == OF_BAD_ADDR && addr_prop)
-		address = (u64)addr_prop;
-	if (address != OF_BAD_ADDR) {
-		/* kludge for valkyrie */
-		if (strcmp(dp->name, "valkyrie") == 0)
-			address += 0x1000;
-		offb_init_fb(dp->name, dp->full_name, width, height, depth,
-			     pitch, address, dp);
-	}
+	if (of_address_to_resource(np, index, &r))
+		return 0;
+	if ((r.start + offset + size) > r.end)
+		return 0;
+	return ioremap(r.start + offset, size);
 }
 
 static void __init offb_init_fb(const char *name, const char *full_name,
@@ -402,45 +289,39 @@
 
 	par->cmap_type = cmap_unknown;
 	if (depth == 8) {
-
 		/* Palette hacks disabled for now */
-#if 0
 		if (dp && !strncmp(name, "ATY,Rage128", 11)) {
-			unsigned long regbase = dp->addrs[2].address;
-			par->cmap_adr = ioremap(regbase, 0x1FFF);
-			par->cmap_type = cmap_r128;
+			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_r128;
 		} else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
 				  || !strncmp(name, "ATY,RageM3p12A", 14))) {
-			unsigned long regbase =
-			    dp->parent->addrs[2].address;
-			par->cmap_adr = ioremap(regbase, 0x1FFF);
-			par->cmap_type = cmap_M3A;
+			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_M3A;
 		} else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
-			unsigned long regbase =
-			    dp->parent->addrs[2].address;
-			par->cmap_adr = ioremap(regbase, 0x1FFF);
-			par->cmap_type = cmap_M3B;
+			par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_M3B;
 		} else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
-			unsigned long regbase = dp->addrs[1].address;
-			par->cmap_adr = ioremap(regbase, 0x1FFF);
-			par->cmap_type = cmap_radeon;
+			par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_radeon;
 		} else if (!strncmp(name, "ATY,", 4)) {
 			unsigned long base = address & 0xff000000UL;
 			par->cmap_adr =
 			    ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
 			par->cmap_data = par->cmap_adr + 1;
 			par->cmap_type = cmap_m64;
-		} else if (device_is_compatible(dp, "pci1014,b7")) {
-			unsigned long regbase = dp->addrs[0].address;
-			par->cmap_adr = ioremap(regbase + 0x6000, 0x1000);
-			par->cmap_type = cmap_gxt2000;
+		} else if (dp && device_is_compatible(dp, "pci1014,b7")) {
+			par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
+			if (par->cmap_adr)
+				par->cmap_type = cmap_gxt2000;
 		}
-#endif
-		fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
-		    : FB_VISUAL_STATIC_PSEUDOCOLOR;
+		fix->visual = (par->cmap_type != cmap_unknown) ?
+			FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR;
 	} else
-		fix->visual =	/* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR
-				   : */ FB_VISUAL_TRUECOLOR;
+		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	var->xoffset = var->yoffset = 0;
 	switch (depth) {
@@ -520,5 +401,139 @@
 	       info->node, full_name);
 }
 
+
+static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
+{
+	unsigned int len;
+	int i, width = 640, height = 480, depth = 8, pitch = 640;
+	unsigned int flags, rsize, addr_prop = 0;
+	unsigned long max_size = 0;
+	u64 rstart, address = OF_BAD_ADDR;
+	u32 *pp, *addrp, *up;
+	u64 asize;
+
+	pp = (u32 *)get_property(dp, "linux,bootx-depth", &len);
+	if (pp == NULL)
+		pp = (u32 *)get_property(dp, "depth", &len);
+	if (pp && len == sizeof(u32))
+		depth = *pp;
+
+	pp = (u32 *)get_property(dp, "linux,bootx-width", &len);
+	if (pp == NULL)
+		pp = (u32 *)get_property(dp, "width", &len);
+	if (pp && len == sizeof(u32))
+		width = *pp;
+
+	pp = (u32 *)get_property(dp, "linux,bootx-height", &len);
+	if (pp == NULL)
+		pp = (u32 *)get_property(dp, "height", &len);
+	if (pp && len == sizeof(u32))
+		height = *pp;
+
+	pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len);
+	if (pp == NULL)
+		pp = (u32 *)get_property(dp, "linebytes", &len);
+	if (pp && len == sizeof(u32))
+		pitch = *pp;
+	else
+		pitch = width * ((depth + 7) / 8);
+
+	rsize = (unsigned long)pitch * (unsigned long)height;
+
+	/* Ok, now we try to figure out the address of the framebuffer.
+	 *
+	 * Unfortunately, Open Firmware doesn't provide a standard way to do
+	 * so. All we can do is a dodgy heuristic that happens to work in
+	 * practice. On most machines, the "address" property contains what
+	 * we need, though not on Matrox cards found in IBM machines. What I've
+	 * found that appears to give good results is to go through the PCI
+	 * ranges and pick one that is both big enough and if possible encloses
+	 * the "address" property. If none match, we pick the biggest
+	 */
+	up = (u32 *)get_property(dp, "linux,bootx-addr", &len);
+	if (up == NULL)
+		up = (u32 *)get_property(dp, "address", &len);
+	if (up && len == sizeof(u32))
+		addr_prop = *up;
+
+	/* Hack for when BootX is passing us */
+	if (no_real_node)
+		goto skip_addr;
+
+	for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags))
+		     != NULL; i++) {
+		int match_addrp = 0;
+
+		if (!(flags & IORESOURCE_MEM))
+			continue;
+		if (asize < rsize)
+			continue;
+		rstart = of_translate_address(dp, addrp);
+		if (rstart == OF_BAD_ADDR)
+			continue;
+		if (addr_prop && (rstart <= addr_prop) &&
+		    ((rstart + asize) >= (addr_prop + rsize)))
+			match_addrp = 1;
+		if (match_addrp) {
+			address = addr_prop;
+			break;
+		}
+		if (rsize > max_size) {
+			max_size = rsize;
+			address = OF_BAD_ADDR;
+ 		}
+
+		if (address == OF_BAD_ADDR)
+			address = rstart;
+	}
+ skip_addr:
+	if (address == OF_BAD_ADDR && addr_prop)
+		address = (u64)addr_prop;
+	if (address != OF_BAD_ADDR) {
+		/* kludge for valkyrie */
+		if (strcmp(dp->name, "valkyrie") == 0)
+			address += 0x1000;
+		offb_init_fb(no_real_node ? "bootx" : dp->name,
+			     no_real_node ? "display" : dp->full_name,
+			     width, height, depth, pitch, address,
+			     no_real_node ? dp : NULL);
+	}
+}
+
+static int __init offb_init(void)
+{
+	struct device_node *dp = NULL, *boot_disp = NULL;
+
+	if (fb_get_options("offb", NULL))
+		return -ENODEV;
+
+	/* Check if we have a MacOS display without a node spec */
+	if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) {
+		/* The old code tried to work out which node was the MacOS
+		 * display based on the address. I'm dropping that since the
+		 * lack of a node spec only happens with old BootX versions
+		 * (users can update) and with this code, they'll still get
+		 * a display (just not the palette hacks).
+		 */
+		offb_init_nodriver(of_chosen, 1);
+	}
+
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    get_property(dp, "linux,boot-display", NULL)) {
+			boot_disp = dp;
+			offb_init_nodriver(dp, 0);
+		}
+	}
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    dp != boot_disp)
+			offb_init_nodriver(dp, 0);
+	}
+
+	return 0;
+}
+
+
 module_init(offb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 33dddba..8ddb47a 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -355,10 +355,14 @@
 static void riva_bl_set_power(struct fb_info *info, int power)
 {
 	mutex_lock(&info->bl_mutex);
-	up(&info->bl_dev->sem);
-	info->bl_dev->props->power = power;
-	__riva_bl_update_status(info->bl_dev);
-	down(&info->bl_dev->sem);
+
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = power;
+		__riva_bl_update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
+	}
+
 	mutex_unlock(&info->bl_mutex);
 }
 
@@ -382,7 +386,7 @@
 	bd = backlight_device_register(name, par, &riva_bl_data);
 	if (IS_ERR(bd)) {
 		info->bl_dev = NULL;
-		printk("riva: Backlight registration failed\n");
+		printk(KERN_WARNING "riva: Backlight registration failed\n");
 		goto error;
 	}
 
@@ -393,11 +397,11 @@
 		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
 	mutex_unlock(&info->bl_mutex);
 
-	up(&bd->sem);
+	down(&bd->sem);
 	bd->props->brightness = riva_bl_data.max_brightness;
 	bd->props->power = FB_BLANK_UNBLANK;
 	bd->props->update_status(bd);
-	down(&bd->sem);
+	up(&bd->sem);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	mutex_lock(&pmac_backlight_mutex);
@@ -2132,6 +2136,9 @@
 
 	fb_destroy_modedb(info->monspecs.modedb);
 	info->monspecs.modedb = NULL;
+
+	pci_set_drvdata(pd, info);
+	riva_bl_init(info->par);
 	ret = register_framebuffer(info);
 	if (ret < 0) {
 		printk(KERN_ERR PFX
@@ -2139,8 +2146,6 @@
 		goto err_iounmap_screen_base;
 	}
 
-	pci_set_drvdata(pd, info);
-
 	printk(KERN_INFO PFX
 		"PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
 		info->fix.id,
@@ -2148,8 +2153,6 @@
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
 
-	riva_bl_init(info->par);
-
 	NVTRACE_LEAVE();
 	return 0;
 
diff --git a/fs/9p/conv.c b/fs/9p/conv.c
index 1e89814..56d88c1 100644
--- a/fs/9p/conv.c
+++ b/fs/9p/conv.c
@@ -673,8 +673,10 @@
 	struct cbuf *bufp = &buffer;
 
 	size = 4 + 2 + strlen(name) + 4 + 1;	/* fid[4] name[s] perm[4] mode[1] */
-	if (extended && extension!=NULL)
-		size += 2 + strlen(extension);	/* extension[s] */
+	if (extended) {
+		size += 2 +			/* extension[s] */
+		    (extension == NULL ? 0 : strlen(extension));
+	}
 
 	fc = v9fs_create_common(bufp, size, TCREATE);
 	if (IS_ERR(fc))
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 2f580a1..eae50c9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -434,11 +434,11 @@
 	result = v9fs_t_remove(v9ses, fid, &fcall);
 	if (result < 0) {
 		PRINT_FCALL_ERROR("remove fails", fcall);
-	} else {
-		v9fs_put_idpool(fid, &v9ses->fidpool);
-		v9fs_fid_destroy(v9fid);
 	}
 
+	v9fs_put_idpool(fid, &v9ses->fidpool);
+	v9fs_fid_destroy(v9fid);
+
 	kfree(fcall);
 	return result;
 }
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index ba1c88a..8201101 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -308,7 +308,7 @@
 	if (adfs_checkmap(sb, dm))
 		return dm;
 
-	adfs_error(sb, NULL, "map corrupted");
+	adfs_error(sb, "map corrupted");
 
 error_free:
 	while (--zone >= 0)
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index fcaeead..50cfca5 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -512,7 +512,11 @@
 	wchar_t uni;
 	int unilen, utflen;
 	char *result;
-	int maxlen = in_len; /* The utf8->nls conversion can't make more chars */
+	/* The utf8->nls conversion won't make the final nls string bigger
+	 * than the utf one, but if the string is pure ascii they'll have the
+	 * same width and an extra char is needed to save the additional \0
+	 */
+	int maxlen = in_len + 1;
 
 	befs_debug(sb, "---> utf2nls()");
 
@@ -588,7 +592,10 @@
 	wchar_t uni;
 	int unilen, utflen;
 	char *result;
-	int maxlen = 3 * in_len;
+	/* There're nls characters that will translate to 3-chars-wide UTF-8
+	 * characters, a additional byte is needed to save the final \0
+	 * in special cases */
+	int maxlen = (3 * in_len) + 1;
 
 	befs_debug(sb, "---> nls2utf()\n");
 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 3753457..045f988 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -884,6 +884,61 @@
 }
 EXPORT_SYMBOL(bd_set_size);
 
+static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
+{
+	int ret = 0;
+	struct inode *bd_inode = bdev->bd_inode;
+	struct gendisk *disk = bdev->bd_disk;
+
+	mutex_lock_nested(&bdev->bd_mutex, subclass);
+	lock_kernel();
+	if (!--bdev->bd_openers) {
+		sync_blockdev(bdev);
+		kill_bdev(bdev);
+	}
+	if (bdev->bd_contains == bdev) {
+		if (disk->fops->release)
+			ret = disk->fops->release(bd_inode, NULL);
+	} else {
+		mutex_lock_nested(&bdev->bd_contains->bd_mutex,
+				  subclass + 1);
+		bdev->bd_contains->bd_part_count--;
+		mutex_unlock(&bdev->bd_contains->bd_mutex);
+	}
+	if (!bdev->bd_openers) {
+		struct module *owner = disk->fops->owner;
+
+		put_disk(disk);
+		module_put(owner);
+
+		if (bdev->bd_contains != bdev) {
+			kobject_put(&bdev->bd_part->kobj);
+			bdev->bd_part = NULL;
+		}
+		bdev->bd_disk = NULL;
+		bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
+		if (bdev != bdev->bd_contains)
+			__blkdev_put(bdev->bd_contains, subclass + 1);
+		bdev->bd_contains = NULL;
+	}
+	unlock_kernel();
+	mutex_unlock(&bdev->bd_mutex);
+	bdput(bdev);
+	return ret;
+}
+
+int blkdev_put(struct block_device *bdev)
+{
+	return __blkdev_put(bdev, BD_MUTEX_NORMAL);
+}
+EXPORT_SYMBOL(blkdev_put);
+
+int blkdev_put_partition(struct block_device *bdev)
+{
+	return __blkdev_put(bdev, BD_MUTEX_PARTITION);
+}
+EXPORT_SYMBOL(blkdev_put_partition);
+
 static int
 blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags);
 
@@ -980,7 +1035,7 @@
 	bdev->bd_disk = NULL;
 	bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
 	if (bdev != bdev->bd_contains)
-		blkdev_put(bdev->bd_contains);
+		__blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE);
 	bdev->bd_contains = NULL;
 	put_disk(disk);
 	module_put(owner);
@@ -1079,63 +1134,6 @@
 	return res;
 }
 
-static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
-{
-	int ret = 0;
-	struct inode *bd_inode = bdev->bd_inode;
-	struct gendisk *disk = bdev->bd_disk;
-
-	mutex_lock_nested(&bdev->bd_mutex, subclass);
-	lock_kernel();
-	if (!--bdev->bd_openers) {
-		sync_blockdev(bdev);
-		kill_bdev(bdev);
-	}
-	if (bdev->bd_contains == bdev) {
-		if (disk->fops->release)
-			ret = disk->fops->release(bd_inode, NULL);
-	} else {
-		mutex_lock_nested(&bdev->bd_contains->bd_mutex,
-				  subclass + 1);
-		bdev->bd_contains->bd_part_count--;
-		mutex_unlock(&bdev->bd_contains->bd_mutex);
-	}
-	if (!bdev->bd_openers) {
-		struct module *owner = disk->fops->owner;
-
-		put_disk(disk);
-		module_put(owner);
-
-		if (bdev->bd_contains != bdev) {
-			kobject_put(&bdev->bd_part->kobj);
-			bdev->bd_part = NULL;
-		}
-		bdev->bd_disk = NULL;
-		bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
-		if (bdev != bdev->bd_contains)
-			__blkdev_put(bdev->bd_contains, subclass + 1);
-		bdev->bd_contains = NULL;
-	}
-	unlock_kernel();
-	mutex_unlock(&bdev->bd_mutex);
-	bdput(bdev);
-	return ret;
-}
-
-int blkdev_put(struct block_device *bdev)
-{
-	return __blkdev_put(bdev, BD_MUTEX_NORMAL);
-}
-
-EXPORT_SYMBOL(blkdev_put);
-
-int blkdev_put_partition(struct block_device *bdev)
-{
-	return __blkdev_put(bdev, BD_MUTEX_PARTITION);
-}
-
-EXPORT_SYMBOL(blkdev_put_partition);
-
 static int blkdev_close(struct inode * inode, struct file * filp)
 {
 	struct block_device *bdev = I_BDEV(filp->f_mapping->host);
diff --git a/fs/buffer.c b/fs/buffer.c
index 3660dcb..71649ef 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -470,13 +470,18 @@
    pass does the actual I/O. */
 void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
 {
+	struct address_space *mapping = bdev->bd_inode->i_mapping;
+
+	if (mapping->nrpages == 0)
+		return;
+
 	invalidate_bh_lrus();
 	/*
 	 * FIXME: what about destroy_dirty_buffers?
 	 * We really want to use invalidate_inode_pages2() for
 	 * that, but not until that's cleaned up.
 	 */
-	invalidate_inode_pages(bdev->bd_inode->i_mapping);
+	invalidate_inode_pages(mapping);
 }
 
 /*
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a61d17e..0feb3bd 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
+Version 1.45
+------------
+Do not time out lockw calls when using posix extensions. Do not
+time out requests if server still responding reasonably fast
+on requests on other threads.  Improve POSIX locking emulation,
+(lock cancel now works, and unlock of merged range works even
+to Windows servers now).  Fix oops on mount to lanman servers
+(win9x, os/2 etc.) when null password.  Do not send listxattr
+(SMB to query all EAs) if nouser_xattr specified.
+
 Version 1.44
 ------------
 Rewritten sessionsetup support, including support for legacy SMB
diff --git a/fs/cifs/README b/fs/cifs/README
index 7986d0d..5f0e1bd 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -408,7 +408,7 @@
   user_xattr    Allow getting and setting user xattrs as OS/2 EAs (extended
 		attributes) to the server (default) e.g. via setfattr 
 		and getfattr utilities. 
-  nouser_xattr  Do not allow getfattr/setfattr to get/set xattrs 
+  nouser_xattr  Do not allow getfattr/setfattr to get/set/list xattrs 
   mapchars      Translate six of the seven reserved characters (not backslash)
 			*?<>|:
 		to the remap range (above 0xF000), which also
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a89efaf..4bc250b 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -277,7 +277,8 @@
 		return;
 
 	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
-	strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
+	if(ses->password)
+		strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
 
 	if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
 		if(extended_security & CIFSSEC_MAY_PLNTXT) {
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c28ede5..3cd7500 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -402,7 +402,6 @@
 };
 #endif
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 {
 	struct cifs_sb_info *cifs_sb;
@@ -422,7 +421,7 @@
 		tcon->tidStatus = CifsExiting;
 	up(&tcon->tconSem);
 
-	/* cancel_brl_requests(tcon); */
+	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
 	if(tcon->ses && tcon->ses->server)
 	{
@@ -438,7 +437,6 @@
 
 	return;
 }
-#endif	
 
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
@@ -457,9 +455,7 @@
    unless later we add lazy close of inodes or unless the kernel forgets to call
    us with the same number of releases (closes) as opens */
 	.show_options = cifs_show_options,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 	.umount_begin   = cifs_umount_begin,
-#endif
 	.remount_fs = cifs_remount,
 };
 
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 8f75c6f..39ee8ef 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.44"
+#define CIFS_VERSION   "1.45"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6d7cf5f..b24006c 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -3,6 +3,7 @@
  *
  *   Copyright (C) International Business Machines  Corp., 2002,2006
  *   Author(s): Steve French (sfrench@us.ibm.com)
+ *              Jeremy Allison (jra@samba.org)
  *
  *   This library is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU Lesser General Public License as published
@@ -158,7 +159,8 @@
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 
+	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
+	unsigned long lstrp; /* when we got last response from this server */
 };
 
 /*
@@ -266,14 +268,14 @@
 };
 
 /*
- * This info hangs off the cifsFileInfo structure.  This is used to track
- * byte stream locks on the file
+ * This info hangs off the cifsFileInfo structure, pointed to by llist.
+ * This is used to track byte stream locks on the file
  */
 struct cifsLockInfo {
-	struct cifsLockInfo *next;
-	int start;
-	int length;
-	int type;
+	struct list_head llist;	/* pointer to next cifsLockInfo */
+	__u64 offset;
+	__u64 length;
+	__u8 type;
 };
 
 /*
@@ -304,6 +306,8 @@
 	/* lock scope id (0 if none) */
 	struct file * pfile; /* needed for writepage */
 	struct inode * pInode; /* needed for oplock break */
+	struct semaphore lock_sem;
+	struct list_head llist; /* list of byte range locks we have. */
 	unsigned closePend:1;	/* file is marked to close */
 	unsigned invalidHandle:1;  /* file closed via session abend */
 	atomic_t wrtPending;   /* handle in use - defer close */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index a5ddc62..b35c55c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -50,6 +50,10 @@
 extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
 			struct kvec *, int /* nvec to send */, 
 			int * /* type of buf returned */ , const int long_op);
+extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *,
+				struct smb_hdr * /* input */ ,
+				struct smb_hdr * /* out */ ,
+				int * /* bytes returned */);
 extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
 extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
 extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 19678c5..075d8fb 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -477,7 +477,7 @@
 		/* BB get server time for time conversions and add
 		code to use it and timezone since this is not UTC */	
 
-		if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+		if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) {
 			memcpy(server->cryptKey, rsp->EncryptionKey,
 				CIFS_CRYPTO_KEY_SIZE);
 		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
@@ -1460,8 +1460,13 @@
 	pSMB->hdr.smb_buf_length += count;
 	pSMB->ByteCount = cpu_to_le16(count);
 
-	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+	if (waitFlag) {
+		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+			(struct smb_hdr *) pSMBr, &bytes_returned);
+	} else {
+		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+	}
 	cifs_stats_inc(&tcon->num_locks);
 	if (rc) {
 		cFYI(1, ("Send error in Lock = %d", rc));
@@ -1484,6 +1489,7 @@
 	char *data_offset;
 	struct cifs_posix_lock *parm_data;
 	int rc = 0;
+	int timeout = 0;
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count, count;
 
@@ -1503,7 +1509,6 @@
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
-	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
 	offset = param_offset + params;
@@ -1529,8 +1534,13 @@
 			(((char *) &pSMB->hdr.Protocol) + offset);
 
 	parm_data->lock_type = cpu_to_le16(lock_type);
-	if(waitFlag)
+	if(waitFlag) {
+		timeout = 3;  /* blocking operation, no timeout */
 		parm_data->lock_flags = cpu_to_le16(1);
+		pSMB->Timeout = cpu_to_le32(-1);
+	} else
+		pSMB->Timeout = 0;
+
 	parm_data->pid = cpu_to_le32(current->tgid);
 	parm_data->start = cpu_to_le64(pLockData->fl_start);
 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
@@ -1541,8 +1551,14 @@
 	pSMB->Reserved4 = 0;
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
-	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (waitFlag) {
+		rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB,
+			(struct smb_hdr *) pSMBr, &bytes_returned);
+	} else {
+		rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+	}
+
 	if (rc) {
 		cFYI(1, ("Send error in Posix Lock = %d", rc));
 	} else if (get_flag) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 876eb9e..5d394c7 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -182,6 +182,7 @@
 
 	while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
 	{
+		try_to_freeze();
 		if(server->protocolType == IPV6) {
 			rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
 		} else {
@@ -612,6 +613,10 @@
 #ifdef CONFIG_CIFS_STATS2
 				mid_entry->when_received = jiffies;
 #endif
+				/* so we do not time out requests to  server
+				which is still responding (since server could
+				be busy but not dead) */
+				server->lstrp = jiffies;
 				break;
 			}
 		}
@@ -1266,33 +1271,35 @@
 
 	read_lock(&GlobalSMBSeslock);
 	list_for_each(tmp, &GlobalTreeConnectionList) {
-		cFYI(1, ("Next tcon - "));
+		cFYI(1, ("Next tcon"));
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
 		if (tcon->ses) {
 			if (tcon->ses->server) {
 				cFYI(1,
-				     (" old ip addr: %x == new ip %x ?",
+				     ("old ip addr: %x == new ip %x ?",
 				      tcon->ses->server->addr.sockAddr.sin_addr.
 				      s_addr, new_target_ip_addr));
 				if (tcon->ses->server->addr.sockAddr.sin_addr.
 				    s_addr == new_target_ip_addr) {
-	/* BB lock tcon and server and tcp session and increment use count here? */
+	/* BB lock tcon, server and tcp session and increment use count here? */
 					/* found a match on the TCP session */
 					/* BB check if reconnection needed */
-					cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
+					cFYI(1,("IP match, old UNC: %s new: %s",
 					      tcon->treeName, uncName));
 					if (strncmp
 					    (tcon->treeName, uncName,
 					     MAX_TREE_SIZE) == 0) {
 						cFYI(1,
-						     ("Matched UNC, old user: %s == new: %s ?",
+						     ("and old usr: %s new: %s",
 						      tcon->treeName, uncName));
 						if (strncmp
 						    (tcon->ses->userName,
 						     userName,
 						     MAX_USERNAME_SIZE) == 0) {
 							read_unlock(&GlobalSMBSeslock);
-							return tcon;/* also matched user (smb session)*/
+							/* matched smb session
+							(user name */
+							return tcon;
 						}
 					}
 				}
@@ -1969,7 +1976,18 @@
 				}
 					
 				cFYI(1,("Negotiate caps 0x%x",(int)cap));
-
+#ifdef CONFIG_CIFS_DEBUG2
+				if(cap & CIFS_UNIX_FCNTL_CAP)
+					cFYI(1,("FCNTL cap"));
+				if(cap & CIFS_UNIX_EXTATTR_CAP)
+					cFYI(1,("EXTATTR cap"));
+				if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+					cFYI(1,("POSIX path cap"));
+				if(cap & CIFS_UNIX_XATTR_CAP)
+					cFYI(1,("XATTR cap"));
+				if(cap & CIFS_UNIX_POSIX_ACL_CAP)
+					cFYI(1,("POSIX ACL cap"));
+#endif /* CIFS_DEBUG2 */
 				if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
 					cFYI(1,("setting capabilities failed"));
 				}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index ba4cbe9..914239d5 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -267,6 +267,10 @@
 			pCifsFile->invalidHandle = FALSE;
 			pCifsFile->closePend     = FALSE;
 			init_MUTEX(&pCifsFile->fh_sem);
+			init_MUTEX(&pCifsFile->lock_sem);
+			INIT_LIST_HEAD(&pCifsFile->llist);
+			atomic_set(&pCifsFile->wrtPending,0);
+
 			/* set the following in open now 
 				pCifsFile->pfile = file; */
 			write_lock(&GlobalSMBSeslock);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 944d2b9..e9c5ba9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -5,6 +5,7 @@
  * 
  *   Copyright (C) International Business Machines  Corp., 2002,2003
  *   Author(s): Steve French (sfrench@us.ibm.com)
+ *              Jeremy Allison (jra@samba.org)
  *
  *   This library is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU Lesser General Public License as published
@@ -47,6 +48,8 @@
 	private_data->netfid = netfid;
 	private_data->pid = current->tgid;	
 	init_MUTEX(&private_data->fh_sem);
+	init_MUTEX(&private_data->lock_sem);
+	INIT_LIST_HEAD(&private_data->llist);
 	private_data->pfile = file; /* needed for writepage */
 	private_data->pInode = inode;
 	private_data->invalidHandle = FALSE;
@@ -473,6 +476,8 @@
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 	if (pSMBFile) {
+		struct cifsLockInfo *li, *tmp;
+
 		pSMBFile->closePend = TRUE;
 		if (pTcon) {
 			/* no sense reconnecting to close a file that is
@@ -496,6 +501,16 @@
 						  pSMBFile->netfid);
 			}
 		}
+
+		/* Delete any outstanding lock records.
+		   We'll lose them when the file is closed anyway. */
+		down(&pSMBFile->lock_sem);
+		list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
+			list_del(&li->llist);
+			kfree(li);
+		}
+		up(&pSMBFile->lock_sem);
+
 		write_lock(&GlobalSMBSeslock);
 		list_del(&pSMBFile->flist);
 		list_del(&pSMBFile->tlist);
@@ -570,6 +585,21 @@
 	return rc;
 }
 
+static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
+				__u64 offset, __u8 lockType)
+{
+	struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
+	if (li == NULL)
+		return -ENOMEM;
+	li->offset = offset;
+	li->length = len;
+	li->type = lockType;
+	down(&fid->lock_sem);
+	list_add(&li->llist, &fid->llist);
+	up(&fid->lock_sem);
+	return 0;
+}
+
 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 {
 	int rc, xid;
@@ -581,6 +611,7 @@
 	struct cifsTconInfo *pTcon;
 	__u16 netfid;
 	__u8 lockType = LOCKING_ANDX_LARGE_FILES;
+	int posix_locking;
 
 	length = 1 + pfLock->fl_end - pfLock->fl_start;
 	rc = -EACCES;
@@ -639,15 +670,14 @@
 	}
 	netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
 
+	posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+			(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
 
 	/* BB add code here to normalize offset and length to
 	account for negative length which we can not accept over the
 	wire */
 	if (IS_GETLK(cmd)) {
-		if(experimEnabled && 
-		   (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
-		   (CIFS_UNIX_FCNTL_CAP & 
-			le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+		if(posix_locking) {
 			int posix_lock_type;
 			if(lockType & LOCKING_ANDX_SHARED_LOCK)
 				posix_lock_type = CIFS_RDLCK;
@@ -683,10 +713,15 @@
 		FreeXid(xid);
 		return rc;
 	}
-	if (experimEnabled &&
-		(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
-		(CIFS_UNIX_FCNTL_CAP &
-			 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
+
+	if (!numLock && !numUnlock) {
+		/* if no lock or unlock then nothing
+		to do since we do not know what it is */
+		FreeXid(xid);
+		return -EOPNOTSUPP;
+	}
+
+	if (posix_locking) {
 		int posix_lock_type;
 		if(lockType & LOCKING_ANDX_SHARED_LOCK)
 			posix_lock_type = CIFS_RDLCK;
@@ -695,18 +730,46 @@
 		
 		if(numUnlock == 1)
 			posix_lock_type = CIFS_UNLCK;
-		else if(numLock == 0) {
-			/* if no lock or unlock then nothing
-			to do since we do not know what it is */
-			FreeXid(xid);
-			return -EOPNOTSUPP;
-		}
+
 		rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
 				      length, pfLock,
 				      posix_lock_type, wait_flag);
-	} else
-		rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
-				numUnlock, numLock, lockType, wait_flag);
+	} else {
+		struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
+
+		if (numLock) {
+			rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
+					0, numLock, lockType, wait_flag);
+
+			if (rc == 0) {
+				/* For Windows locks we must store them. */
+				rc = store_file_lock(fid, length,
+						pfLock->fl_start, lockType);
+			}
+		} else if (numUnlock) {
+			/* For each stored lock that this unlock overlaps
+			   completely, unlock it. */
+			int stored_rc = 0;
+			struct cifsLockInfo *li, *tmp;
+
+			down(&fid->lock_sem);
+			list_for_each_entry_safe(li, tmp, &fid->llist, llist) {
+				if (pfLock->fl_start <= li->offset &&
+						length >= li->length) {
+					stored_rc = CIFSSMBLock(xid, pTcon, netfid,
+							li->length, li->offset,
+							1, 0, li->type, FALSE);
+					if (stored_rc)
+						rc = stored_rc;
+
+					list_del(&li->llist);
+					kfree(li);
+				}
+			}
+		up(&fid->lock_sem);
+		}
+	}
+
 	if (pfLock->fl_flags & FL_POSIX)
 		posix_lock_file_wait(file, pfLock);
 	FreeXid(xid);
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index b66eff5..ce87550 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -72,6 +72,7 @@
 	{ERRinvlevel,-EOPNOTSUPP},
 	{ERRdirnotempty, -ENOTEMPTY},
 	{ERRnotlocked, -ENOLCK},
+	{ERRcancelviolation, -ENOLCK},
 	{ERRalreadyexists, -EEXIST},
 	{ERRmoredata, -EOVERFLOW},
 	{ERReasnotsupported,-EOPNOTSUPP},
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 03bbcb3..105761e 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -556,7 +556,7 @@
 		FIND_FILE_STANDARD_INFO * pFindData =
 			(FIND_FILE_STANDARD_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
-		len = le32_to_cpu(pFindData->FileNameLength);
+		len = pFindData->FileNameLength;
 	} else {
 		cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
 	}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 7202d53..d1705ab 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -372,7 +372,7 @@
 
 		/* no capabilities flags in old lanman negotiation */
 
-		pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; 
+		pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); 
 		/* BB calculate hash with password */
 		/* and copy into bcc */
 
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
index cd41c67..212c3c2 100644
--- a/fs/cifs/smberr.h
+++ b/fs/cifs/smberr.h
@@ -95,6 +95,7 @@
 #define ERRinvlevel		124
 #define ERRdirnotempty		145
 #define ERRnotlocked		158
+#define ERRcancelviolation	173
 #define ERRalreadyexists	183
 #define ERRbadpipe		230
 #define ERRpipebusy		231
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 17ba329..48d47b4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -3,7 +3,8 @@
  *
  *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
- *
+ *   Jeremy Allison (jra@samba.org) 2006.
+ *    
  *   This library is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU Lesser General Public License as published
  *   by the Free Software Foundation; either version 2.1 of the License, or
@@ -36,7 +37,7 @@
 extern kmem_cache_t *cifs_oplock_cachep;
 
 static struct mid_q_entry *
-AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
+AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
 {
 	struct mid_q_entry *temp;
 
@@ -203,6 +204,10 @@
 		rc = 0;
 	}
 
+	/* Don't want to modify the buffer as a
+	   side effect of this call. */
+	smb_buffer->smb_buf_length = smb_buf_length;
+
 	return rc;
 }
 
@@ -217,6 +222,7 @@
 	unsigned int len = iov[0].iov_len;
 	unsigned int total_len;
 	int first_vec = 0;
+	unsigned int smb_buf_length = smb_buffer->smb_buf_length;
 	
 	if(ssocket == NULL)
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
@@ -293,9 +299,123 @@
 	} else
 		rc = 0;
 
+	/* Don't want to modify the buffer as a
+	   side effect of this call. */
+	smb_buffer->smb_buf_length = smb_buf_length;
+
 	return rc;
 }
 
+static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
+{
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= 
+					cifs_max_pending){
+				spin_unlock(&GlobalMid_Lock);
+#ifdef CONFIG_CIFS_STATS2
+				atomic_inc(&ses->server->num_waiters);
+#endif
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < cifs_max_pending);
+#ifdef CONFIG_CIFS_STATS2
+				atomic_dec(&ses->server->num_waiters);
+#endif
+				spin_lock(&GlobalMid_Lock);
+			} else {
+				if(ses->server->tcpStatus == CifsExiting) {
+					spin_unlock(&GlobalMid_Lock);
+					return -ENOENT;
+				}
+
+				/* can not count locking commands against total since
+				   they are allowed to block on server */
+					
+				/* update # of requests on the wire to server */
+				if (long_op < 3)
+					atomic_inc(&ses->server->inFlight);
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
+			struct mid_q_entry **ppmidQ)
+{
+	if (ses->server->tcpStatus == CifsExiting) {
+		return -ENOENT;
+	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1,("tcp session dead - return to caller to retry"));
+		return -EAGAIN;
+	} else if (ses->status != CifsGood) {
+		/* check if SMB session is bad because we are setting it up */
+		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
+			(in_buf->Command != SMB_COM_NEGOTIATE)) {
+			return -EAGAIN;
+		} /* else ok - we are setting up session */
+	}
+	*ppmidQ = AllocMidQEntry(in_buf, ses);
+	if (*ppmidQ == NULL) {
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int wait_for_response(struct cifsSesInfo *ses, 
+			struct mid_q_entry *midQ,
+			unsigned long timeout,
+			unsigned long time_to_wait)
+{
+	unsigned long curr_timeout;
+
+	for (;;) {
+		curr_timeout = timeout + jiffies;
+		wait_event(ses->server->response_q,
+			(!(midQ->midState == MID_REQUEST_SUBMITTED)) || 
+			time_after(jiffies, curr_timeout) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
+
+		if (time_after(jiffies, curr_timeout) &&
+			(midQ->midState == MID_REQUEST_SUBMITTED) &&
+			((ses->server->tcpStatus == CifsGood) ||
+			 (ses->server->tcpStatus == CifsNew))) {
+
+			unsigned long lrt;
+
+			/* We timed out. Is the server still
+			   sending replies ? */
+			spin_lock(&GlobalMid_Lock);
+			lrt = ses->server->lstrp;
+			spin_unlock(&GlobalMid_Lock);
+
+			/* Calculate time_to_wait past last receive time.
+			 Although we prefer not to time out if the 
+			 server is still responding - we will time
+			 out if the server takes more than 15 (or 45 
+			 or 180) seconds to respond to this request
+			 and has not responded to any request from 
+			 other threads on the client within 10 seconds */
+			lrt += time_to_wait;
+			if (time_after(jiffies, lrt)) {
+				/* No replies for time_to_wait. */
+				cERROR(1,("server not responding"));
+				return -1;
+			}
+		} else {
+			return 0;
+		}
+	}
+}
+
 int
 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 
 	     struct kvec *iov, int n_vec, int * pRespBufType /* ret */, 
@@ -323,75 +443,27 @@
 	/* Ensure that we do not send more than 50 overlapping requests 
 	   to the same server. We may make this configurable later or
 	   use ses->maxReq */
-	if(long_op == -1) {
-		/* oplock breaks must not be held up */
-		atomic_inc(&ses->server->inFlight);
-	} else {
-		spin_lock(&GlobalMid_Lock); 
-		while(1) {        
-			if(atomic_read(&ses->server->inFlight) >= 
-					cifs_max_pending){
-				spin_unlock(&GlobalMid_Lock);
-#ifdef CONFIG_CIFS_STATS2
-				atomic_inc(&ses->server->num_waiters);
-#endif
-				wait_event(ses->server->request_q,
-					atomic_read(&ses->server->inFlight)
-					 < cifs_max_pending);
-#ifdef CONFIG_CIFS_STATS2
-				atomic_dec(&ses->server->num_waiters);
-#endif
-				spin_lock(&GlobalMid_Lock);
-			} else {
-				if(ses->server->tcpStatus == CifsExiting) {
-					spin_unlock(&GlobalMid_Lock);
-					cifs_small_buf_release(in_buf);
-					return -ENOENT;
-				}
 
-			/* can not count locking commands against total since
-			   they are allowed to block on server */
-					
-				if(long_op < 3) {
-				/* update # of requests on the wire to server */
-					atomic_inc(&ses->server->inFlight);
-				}
-				spin_unlock(&GlobalMid_Lock);
-				break;
-			}
-		}
+	rc = wait_for_free_request(ses, long_op);
+	if (rc) {
+		cifs_small_buf_release(in_buf);
+		return rc;
 	}
+
 	/* make sure that we sign in the same order that we send on this socket 
 	   and avoid races inside tcp sendmsg code that could cause corruption
 	   of smb data */
 
 	down(&ses->server->tcpSem); 
 
-	if (ses->server->tcpStatus == CifsExiting) {
-		rc = -ENOENT;
-		goto out_unlock2;
-	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
-		cFYI(1,("tcp session dead - return to caller to retry"));
-		rc = -EAGAIN;
-		goto out_unlock2;
-	} else if (ses->status != CifsGood) {
-		/* check if SMB session is bad because we are setting it up */
-		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
-			(in_buf->Command != SMB_COM_NEGOTIATE)) {
-			rc = -EAGAIN;
-			goto out_unlock2;
-		} /* else ok - we are setting up session */
-	}
-	midQ = AllocMidQEntry(in_buf, ses);
-	if (midQ == NULL) {
+	rc = allocate_mid(ses, in_buf, &midQ);
+	if (rc) {
 		up(&ses->server->tcpSem);
 		cifs_small_buf_release(in_buf);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return -ENOMEM;
+		/* Update # of requests on wire to server */
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+		return rc;
 	}
 
  	rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
@@ -406,32 +478,23 @@
 	atomic_dec(&ses->server->inSend);
 	midQ->when_sent = jiffies;
 #endif
-	if(rc < 0) {
-		DeleteMidQEntry(midQ);
-		up(&ses->server->tcpSem);
-		cifs_small_buf_release(in_buf);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return rc;
-	} else {
-		up(&ses->server->tcpSem);
-		cifs_small_buf_release(in_buf);
-	}
+
+	up(&ses->server->tcpSem);
+	cifs_small_buf_release(in_buf);
+
+	if(rc < 0)
+		goto out;
 
 	if (long_op == -1)
-		goto cifs_no_response_exit2;
+		goto out;
 	else if (long_op == 2) /* writes past end of file can take loong time */
 		timeout = 180 * HZ;
 	else if (long_op == 1)
 		timeout = 45 * HZ; /* should be greater than 
 			servers oplock break timeout (about 43 seconds) */
-	else if (long_op > 2) {
-		timeout = MAX_SCHEDULE_TIMEOUT;
-	} else
+	else
 		timeout = 15 * HZ;
+
 	/* wait for 15 seconds or until woken up due to response arriving or 
 	   due to last connection to this server being unmounted */
 	if (signal_pending(current)) {
@@ -441,19 +504,7 @@
 	}   
 
 	/* No user interrupts in wait - wreaks havoc with performance */
-	if(timeout != MAX_SCHEDULE_TIMEOUT) {
-		timeout += jiffies;
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
-	} else {
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
-	}
+	wait_for_response(ses, midQ, timeout, 10 * HZ);
 
 	spin_lock(&GlobalMid_Lock);
 	if (midQ->resp_buf) {
@@ -481,11 +532,9 @@
 		}
 		spin_unlock(&GlobalMid_Lock);
 		DeleteMidQEntry(midQ);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
+		/* Update # of requests on wire to server */
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
 		return rc;
 	}
   
@@ -536,24 +585,12 @@
 			cFYI(1,("Bad MID state?"));
 		}
 	}
-cifs_no_response_exit2:
+
+out:
+
 	DeleteMidQEntry(midQ);
-
-	if(long_op < 3) {
-		atomic_dec(&ses->server->inFlight); 
-		wake_up(&ses->server->request_q);
-	}
-
-	return rc;
-
-out_unlock2:
-	up(&ses->server->tcpSem);
-	cifs_small_buf_release(in_buf);
-	/* If not lock req, update # of requests on wire to server */
-	if(long_op < 3) {
-		atomic_dec(&ses->server->inFlight); 
-		wake_up(&ses->server->request_q);
-	}
+	atomic_dec(&ses->server->inFlight); 
+	wake_up(&ses->server->request_q);
 
 	return rc;
 }
@@ -583,85 +620,34 @@
 	/* Ensure that we do not send more than 50 overlapping requests 
 	   to the same server. We may make this configurable later or
 	   use ses->maxReq */
-	if(long_op == -1) {
-		/* oplock breaks must not be held up */
-		atomic_inc(&ses->server->inFlight);
-	} else {
-		spin_lock(&GlobalMid_Lock); 
-		while(1) {        
-			if(atomic_read(&ses->server->inFlight) >= 
-					cifs_max_pending){
-				spin_unlock(&GlobalMid_Lock);
-#ifdef CONFIG_CIFS_STATS2
-				atomic_inc(&ses->server->num_waiters);
-#endif
-				wait_event(ses->server->request_q,
-					atomic_read(&ses->server->inFlight)
-					 < cifs_max_pending);
-#ifdef CONFIG_CIFS_STATS2
-				atomic_dec(&ses->server->num_waiters);
-#endif
-				spin_lock(&GlobalMid_Lock);
-			} else {
-				if(ses->server->tcpStatus == CifsExiting) {
-					spin_unlock(&GlobalMid_Lock);
-					return -ENOENT;
-				}
 
-			/* can not count locking commands against total since
-			   they are allowed to block on server */
-					
-				if(long_op < 3) {
-				/* update # of requests on the wire to server */
-					atomic_inc(&ses->server->inFlight);
-				}
-				spin_unlock(&GlobalMid_Lock);
-				break;
-			}
-		}
-	}
+	rc = wait_for_free_request(ses, long_op);
+	if (rc)
+		return rc;
+
 	/* make sure that we sign in the same order that we send on this socket 
 	   and avoid races inside tcp sendmsg code that could cause corruption
 	   of smb data */
 
 	down(&ses->server->tcpSem); 
 
-	if (ses->server->tcpStatus == CifsExiting) {
-		rc = -ENOENT;
-		goto out_unlock;
-	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
-		cFYI(1,("tcp session dead - return to caller to retry"));
-		rc = -EAGAIN;
-		goto out_unlock;
-	} else if (ses->status != CifsGood) {
-		/* check if SMB session is bad because we are setting it up */
-		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
-			(in_buf->Command != SMB_COM_NEGOTIATE)) {
-			rc = -EAGAIN;
-			goto out_unlock;
-		} /* else ok - we are setting up session */
-	}
-	midQ = AllocMidQEntry(in_buf, ses);
-	if (midQ == NULL) {
+	rc = allocate_mid(ses, in_buf, &midQ);
+	if (rc) {
 		up(&ses->server->tcpSem);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return -ENOMEM;
+		/* Update # of requests on wire to server */
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+		return rc;
 	}
 
 	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
-		up(&ses->server->tcpSem);
 		cERROR(1, ("Illegal length, greater than maximum frame, %d",
 			in_buf->smb_buf_length));
 		DeleteMidQEntry(midQ);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
+		up(&ses->server->tcpSem);
+		/* Update # of requests on wire to server */
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
 		return -EIO;
 	}
 
@@ -677,27 +663,19 @@
 	atomic_dec(&ses->server->inSend);
 	midQ->when_sent = jiffies;
 #endif
-	if(rc < 0) {
-		DeleteMidQEntry(midQ);
-		up(&ses->server->tcpSem);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
-		return rc;
-	} else
-		up(&ses->server->tcpSem);
+	up(&ses->server->tcpSem);
+
+	if(rc < 0)
+		goto out;
+
 	if (long_op == -1)
-		goto cifs_no_response_exit;
+		goto out;
 	else if (long_op == 2) /* writes past end of file can take loong time */
 		timeout = 180 * HZ;
 	else if (long_op == 1)
 		timeout = 45 * HZ; /* should be greater than 
 			servers oplock break timeout (about 43 seconds) */
-	else if (long_op > 2) {
-		timeout = MAX_SCHEDULE_TIMEOUT;
-	} else
+	else
 		timeout = 15 * HZ;
 	/* wait for 15 seconds or until woken up due to response arriving or 
 	   due to last connection to this server being unmounted */
@@ -708,19 +686,7 @@
 	}   
 
 	/* No user interrupts in wait - wreaks havoc with performance */
-	if(timeout != MAX_SCHEDULE_TIMEOUT) {
-		timeout += jiffies;
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
-	} else {
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
-	}
+	wait_for_response(ses, midQ, timeout, 10 * HZ);
 
 	spin_lock(&GlobalMid_Lock);
 	if (midQ->resp_buf) {
@@ -748,11 +714,9 @@
 		}
 		spin_unlock(&GlobalMid_Lock);
 		DeleteMidQEntry(midQ);
-		/* If not lock req, update # of requests on wire to server */
-		if(long_op < 3) {
-			atomic_dec(&ses->server->inFlight); 
-			wake_up(&ses->server->request_q);
-		}
+		/* Update # of requests on wire to server */
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
 		return rc;
 	}
   
@@ -799,23 +763,253 @@
 			cERROR(1,("Bad MID state?"));
 		}
 	}
-cifs_no_response_exit:
-	DeleteMidQEntry(midQ);
 
-	if(long_op < 3) {
-		atomic_dec(&ses->server->inFlight); 
-		wake_up(&ses->server->request_q);
-	}
+out:
+
+	DeleteMidQEntry(midQ);
+	atomic_dec(&ses->server->inFlight); 
+	wake_up(&ses->server->request_q);
 
 	return rc;
+}
 
-out_unlock:
+/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
+
+static int
+send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
+		struct mid_q_entry *midQ)
+{
+	int rc = 0;
+	struct cifsSesInfo *ses = tcon->ses;
+	__u16 mid = in_buf->Mid;
+
+	header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
+	in_buf->Mid = mid;
+	down(&ses->server->tcpSem); 
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+	if (rc) {
+		up(&ses->server->tcpSem);
+		return rc;
+	}
+	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+	      (struct sockaddr *) &(ses->server->addr.sockAddr));
 	up(&ses->server->tcpSem);
-	/* If not lock req, update # of requests on wire to server */
-	if(long_op < 3) {
-		atomic_dec(&ses->server->inFlight); 
-		wake_up(&ses->server->request_q);
+	return rc;
+}
+
+/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
+   blocking lock to return. */
+
+static int
+send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
+			struct smb_hdr *in_buf,
+			struct smb_hdr *out_buf)
+{
+	int bytes_returned;
+	struct cifsSesInfo *ses = tcon->ses;
+	LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
+
+	/* We just modify the current in_buf to change
+	   the type of lock from LOCKING_ANDX_SHARED_LOCK
+	   or LOCKING_ANDX_EXCLUSIVE_LOCK to
+	   LOCKING_ANDX_CANCEL_LOCK. */
+
+	pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
+	pSMB->Timeout = 0;
+	pSMB->hdr.Mid = GetNextMid(ses->server);
+
+	return SendReceive(xid, ses, in_buf, out_buf,
+			&bytes_returned, 0);
+}
+
+int
+SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
+	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+	    int *pbytes_returned)
+{
+	int rc = 0;
+	int rstart = 0;
+	unsigned int receive_len;
+	struct mid_q_entry *midQ;
+	struct cifsSesInfo *ses;
+
+	if (tcon == NULL || tcon->ses == NULL) {
+		cERROR(1,("Null smb session"));
+		return -EIO;
+	}
+	ses = tcon->ses;
+
+	if(ses->server == NULL) {
+		cERROR(1,("Null tcp session"));
+		return -EIO;
 	}
 
+	if(ses->server->tcpStatus == CifsExiting)
+		return -ENOENT;
+
+	/* Ensure that we do not send more than 50 overlapping requests 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+
+	rc = wait_for_free_request(ses, 3);
+	if (rc)
+		return rc;
+
+	/* make sure that we sign in the same order that we send on this socket 
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
+
+	down(&ses->server->tcpSem); 
+
+	rc = allocate_mid(ses, in_buf, &midQ);
+	if (rc) {
+		up(&ses->server->tcpSem);
+		return rc;
+	}
+
+	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		up(&ses->server->tcpSem);
+		cERROR(1, ("Illegal length, greater than maximum frame, %d",
+			in_buf->smb_buf_length));
+		DeleteMidQEntry(midQ);
+		return -EIO;
+	}
+
+	rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
+
+	midQ->midState = MID_REQUEST_SUBMITTED;
+#ifdef CONFIG_CIFS_STATS2
+	atomic_inc(&ses->server->inSend);
+#endif
+	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+		      (struct sockaddr *) &(ses->server->addr.sockAddr));
+#ifdef CONFIG_CIFS_STATS2
+	atomic_dec(&ses->server->inSend);
+	midQ->when_sent = jiffies;
+#endif
+	up(&ses->server->tcpSem);
+
+	if(rc < 0) {
+		DeleteMidQEntry(midQ);
+		return rc;
+	}
+
+	/* Wait for a reply - allow signals to interrupt. */
+	rc = wait_event_interruptible(ses->server->response_q,
+		(!(midQ->midState == MID_REQUEST_SUBMITTED)) || 
+		((ses->server->tcpStatus != CifsGood) &&
+		 (ses->server->tcpStatus != CifsNew)));
+
+	/* Were we interrupted by a signal ? */
+	if ((rc == -ERESTARTSYS) &&
+		(midQ->midState == MID_REQUEST_SUBMITTED) &&
+		((ses->server->tcpStatus == CifsGood) ||
+		 (ses->server->tcpStatus == CifsNew))) {
+
+		if (in_buf->Command == SMB_COM_TRANSACTION2) {
+			/* POSIX lock. We send a NT_CANCEL SMB to cause the
+			   blocking lock to return. */
+
+			rc = send_nt_cancel(tcon, in_buf, midQ);
+			if (rc) {
+				DeleteMidQEntry(midQ);
+				return rc;
+			}
+		} else {
+			/* Windows lock. We send a LOCKINGX_CANCEL_LOCK
+			   to cause the blocking lock to return. */
+
+			rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
+
+			/* If we get -ENOLCK back the lock may have
+			   already been removed. Don't exit in this case. */
+			if (rc && rc != -ENOLCK) {
+				DeleteMidQEntry(midQ);
+				return rc;
+			}
+		}
+
+		/* Wait 5 seconds for the response. */
+		if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) {
+			/* We got the response - restart system call. */
+			rstart = 1;
+		}
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	if (midQ->resp_buf) {
+		spin_unlock(&GlobalMid_Lock);
+		receive_len = midQ->resp_buf->smb_buf_length;
+	} else {
+		cERROR(1,("No response for cmd %d mid %d",
+			  midQ->command, midQ->mid));
+		if(midQ->midState == MID_REQUEST_SUBMITTED) {
+			if(ses->server->tcpStatus == CifsExiting)
+				rc = -EHOSTDOWN;
+			else {
+				ses->server->tcpStatus = CifsNeedReconnect;
+				midQ->midState = MID_RETRY_NEEDED;
+			}
+		}
+
+		if (rc != -EHOSTDOWN) {
+			if(midQ->midState == MID_RETRY_NEEDED) {
+				rc = -EAGAIN;
+				cFYI(1,("marking request for retry"));
+			} else {
+				rc = -EIO;
+			}
+		}
+		spin_unlock(&GlobalMid_Lock);
+		DeleteMidQEntry(midQ);
+		return rc;
+	}
+  
+	if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
+		cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
+			receive_len, xid));
+		rc = -EIO;
+	} else {		/* rcvd frame is ok */
+
+		if (midQ->resp_buf && out_buf
+		    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
+			out_buf->smb_buf_length = receive_len;
+			memcpy((char *)out_buf + 4,
+			       (char *)midQ->resp_buf + 4,
+			       receive_len);
+
+			dump_smb(out_buf, 92);
+			/* convert the length into a more usable form */
+			if((receive_len > 24) &&
+			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
+					SECMODE_SIGN_ENABLED))) {
+				rc = cifs_verify_signature(out_buf,
+						ses->server->mac_signing_key,
+						midQ->sequence_number+1);
+				if(rc) {
+					cERROR(1,("Unexpected SMB signature"));
+					/* BB FIXME add code to kill session */
+				}
+			}
+
+			*pbytes_returned = out_buf->smb_buf_length;
+
+			/* BB special case reconnect tid and uid here? */
+			rc = map_smb_to_linux_error(out_buf);
+
+			/* convert ByteCount if necessary */
+			if (receive_len >=
+			    sizeof (struct smb_hdr) -
+			    4 /* do not count RFC1001 header */  +
+			    (2 * out_buf->WordCount) + 2 /* bcc */ )
+				BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
+		} else {
+			rc = -EIO;
+			cERROR(1,("Bad MID state?"));
+		}
+	}
+	DeleteMidQEntry(midQ);
+	if (rstart && rc == -EACCES)
+		return -ERESTARTSYS;
 	return rc;
 }
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 7754d64..067648b 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -330,11 +330,15 @@
 	sb = direntry->d_inode->i_sb;
 	if(sb == NULL)
 		return -EIO;
-	xid = GetXid();
 
 	cifs_sb = CIFS_SB(sb);
 	pTcon = cifs_sb->tcon;
 
+	if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+		return -EOPNOTSUPP;
+
+	xid = GetXid();
+
 	full_path = build_path_from_dentry(direntry);
 	if(full_path == NULL) {
 		FreeXid(xid);
diff --git a/fs/coda/file.c b/fs/coda/file.c
index cc66c68..dbfbcfa 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -136,10 +136,8 @@
 	coda_vfs_stat.open++;
 
 	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
-	if (!cfi) {
-		unlock_kernel();
+	if (!cfi)
 		return -ENOMEM;
-	}
 
 	lock_kernel();
 
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index e249cf7..1d30d2f 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -22,7 +22,7 @@
   
 	err = -ENAMETOOLONG;
 	if (size > 2 * EFS_BLOCKSIZE)
-		goto fail;
+		goto fail_notlocked;
   
 	lock_kernel();
 	/* read first 512 bytes of link target */
@@ -47,6 +47,7 @@
 	return 0;
 fail:
 	unlock_kernel();
+fail_notlocked:
 	SetPageError(page);
 	kunmap(page);
 	unlock_page(page);
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 19ffb04..3a35674 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1168,7 +1168,7 @@
 eexit_1:
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n",
-		     current, ep, epi->file, error));
+		     current, ep, epi->ffd.file, error));
 
 	return error;
 }
@@ -1236,7 +1236,7 @@
 	struct eventpoll *ep = epi->ep;
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
-		     current, epi->file, epi, ep));
+		     current, epi->ffd.file, epi, ep));
 
 	write_lock_irqsave(&ep->lock, flags);
 
diff --git a/fs/exec.c b/fs/exec.c
index 8344ba7..54135df 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -486,8 +486,6 @@
 		if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
 		    S_ISREG(inode->i_mode)) {
 			int err = vfs_permission(&nd, MAY_EXEC);
-			if (!err && !(inode->i_mode & 0111))
-				err = -EACCES;
 			file = ERR_PTR(err);
 			if (!err) {
 				file = nameidata_to_filp(&nd, O_RDONLY);
@@ -753,7 +751,7 @@
 
 		write_lock_irq(&tasklist_lock);
 		spin_lock(&oldsighand->siglock);
-		spin_lock(&newsighand->siglock);
+		spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING);
 
 		rcu_assign_pointer(current->sighand, newsighand);
 		recalc_sigpending();
@@ -922,12 +920,6 @@
 	int retval;
 
 	mode = inode->i_mode;
-	/*
-	 * Check execute perms again - if the caller has CAP_DAC_OVERRIDE,
-	 * generic_permission lets a non-executable through
-	 */
-	if (!(mode & 0111))	/* with at least _one_ execute bit set */
-		return -EACCES;
 	if (bprm->file->f_op == NULL)
 		return -EACCES;
 
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index f2702cd..681dea8 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -775,7 +775,7 @@
 	if (EXT2_INODE_SIZE(sb) == 0)
 		goto cantfind_ext2;
 	sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb);
-	if (sbi->s_inodes_per_block == 0)
+	if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0)
 		goto cantfind_ext2;
 	sbi->s_itb_per_group = sbi->s_inodes_per_group /
 					sbi->s_inodes_per_block;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index a504a40..063d994 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1269,12 +1269,12 @@
 		goal = le32_to_cpu(es->s_first_data_block);
 	group_no = (goal - le32_to_cpu(es->s_first_data_block)) /
 			EXT3_BLOCKS_PER_GROUP(sb);
+	goal_group = group_no;
+retry_alloc:
 	gdp = ext3_get_group_desc(sb, group_no, &gdp_bh);
 	if (!gdp)
 		goto io_error;
 
-	goal_group = group_no;
-retry:
 	free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
 	/*
 	 * if there is not enough free blocks to make a new resevation
@@ -1349,7 +1349,7 @@
 	if (my_rsv) {
 		my_rsv = NULL;
 		group_no = goal_group;
-		goto retry;
+		goto retry_alloc;
 	}
 	/* No space left on the device */
 	*errp = -ENOSPC;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index f804d5e..0f0b1ea 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1009,11 +1009,14 @@
 	buffer_trace_init(&dummy.b_history);
 	err = ext3_get_blocks_handle(handle, inode, block, 1,
 					&dummy, create, 1);
-	if (err == 1) {
+	/*
+	 * ext3_get_blocks_handle() returns number of blocks
+	 * mapped. 0 in case of a HOLE.
+	 */
+	if (err > 0) {
+		if (err > 1)
+			WARN_ON(1);
 		err = 0;
-	} else if (err >= 0) {
-		WARN_ON(1);
-		err = -EIO;
 	}
 	*errp = err;
 	if (!err && buffer_mapped(&dummy)) {
@@ -1158,7 +1161,7 @@
 		ret = PTR_ERR(handle);
 		goto out;
 	}
-	if (test_opt(inode->i_sb, NOBH))
+	if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
 		ret = nobh_prepare_write(page, from, to, ext3_get_block);
 	else
 		ret = block_prepare_write(page, from, to, ext3_get_block);
@@ -1244,7 +1247,7 @@
 	if (new_i_size > EXT3_I(inode)->i_disksize)
 		EXT3_I(inode)->i_disksize = new_i_size;
 
-	if (test_opt(inode->i_sb, NOBH))
+	if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
 		ret = nobh_commit_write(file, page, from, to);
 	else
 		ret = generic_commit_write(file, page, from, to);
@@ -1494,7 +1497,7 @@
 		goto out_fail;
 	}
 
-	if (test_opt(inode->i_sb, NOBH))
+	if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
 		ret = nobh_writepage(page, ext3_get_block, wbc);
 	else
 		ret = block_write_full_page(page, ext3_get_block, wbc);
@@ -2402,14 +2405,15 @@
 	struct buffer_head *bh;
 	struct ext3_group_desc * gdp;
 
-
-	if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO &&
-		ino != EXT3_RESIZE_INO && ino < EXT3_FIRST_INO(sb)) ||
-		ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) {
-		ext3_error(sb, "ext3_get_inode_block",
-			    "bad inode number: %lu", ino);
+	if (!ext3_valid_inum(sb, ino)) {
+		/*
+		 * This error is already checked for in namei.c unless we are
+		 * looking at an NFS filehandle, in which case no error
+		 * report is needed
+		 */
 		return 0;
 	}
+
 	block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
 	if (block_group >= EXT3_SB(sb)->s_groups_count) {
 		ext3_error(sb,"ext3_get_inode_block","group >= groups count");
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index d9176db..2aa7101 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1000,7 +1000,12 @@
 	if (bh) {
 		unsigned long ino = le32_to_cpu(de->inode);
 		brelse (bh);
-		inode = iget(dir->i_sb, ino);
+		if (!ext3_valid_inum(dir->i_sb, ino)) {
+			ext3_error(dir->i_sb, "ext3_lookup",
+				   "bad inode number: %lu", ino);
+			inode = NULL;
+		} else
+			inode = iget(dir->i_sb, ino);
 
 		if (!inode)
 			return ERR_PTR(-EACCES);
@@ -1028,7 +1033,13 @@
 		return ERR_PTR(-ENOENT);
 	ino = le32_to_cpu(de->inode);
 	brelse(bh);
-	inode = iget(child->d_inode->i_sb, ino);
+
+	if (!ext3_valid_inum(child->d_inode->i_sb, ino)) {
+		ext3_error(child->d_inode->i_sb, "ext3_get_parent",
+			   "bad inode number: %lu", ino);
+		inode = NULL;
+	} else
+		inode = iget(child->d_inode->i_sb, ino);
 
 	if (!inode)
 		return ERR_PTR(-EACCES);
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 29cce45..43886fa 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -246,6 +246,8 @@
 	u_long			page, npages, block, pblocks, nblocks, offset;
 	loff_t			pos;
 
+	lock_kernel();
+
 	switch ((long)fp->f_pos) {
 	case 0:
 		if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index a3bce3a..46fe60b 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -105,7 +105,7 @@
 
 /*
  * Add a connection to the control filesystem (if it exists).  Caller
- * must host fuse_mutex
+ * must hold fuse_mutex
  */
 int fuse_ctl_add_conn(struct fuse_conn *fc)
 {
@@ -139,7 +139,7 @@
 
 /*
  * Remove a connection from the control filesystem (if it exists).
- * Caller must host fuse_mutex
+ * Caller must hold fuse_mutex
  */
 void fuse_ctl_remove_conn(struct fuse_conn *fc)
 {
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 72a74cd..409ce6a 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -14,6 +14,33 @@
 #include <linux/sched.h>
 #include <linux/namei.h>
 
+#if BITS_PER_LONG >= 64
+static inline void fuse_dentry_settime(struct dentry *entry, u64 time)
+{
+	entry->d_time = time;
+}
+
+static inline u64 fuse_dentry_time(struct dentry *entry)
+{
+	return entry->d_time;
+}
+#else
+/*
+ * On 32 bit archs store the high 32 bits of time in d_fsdata
+ */
+static void fuse_dentry_settime(struct dentry *entry, u64 time)
+{
+	entry->d_time = time;
+	entry->d_fsdata = (void *) (unsigned long) (time >> 32);
+}
+
+static u64 fuse_dentry_time(struct dentry *entry)
+{
+	return (u64) entry->d_time +
+		((u64) (unsigned long) entry->d_fsdata << 32);
+}
+#endif
+
 /*
  * FUSE caches dentries and attributes with separate timeout.  The
  * time in jiffies until the dentry/attributes are valid is stored in
@@ -23,10 +50,13 @@
 /*
  * Calculate the time in jiffies until a dentry/attributes are valid
  */
-static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec)
+static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
 {
-	struct timespec ts = {sec, nsec};
-	return jiffies + timespec_to_jiffies(&ts);
+	if (sec || nsec) {
+		struct timespec ts = {sec, nsec};
+		return get_jiffies_64() + timespec_to_jiffies(&ts);
+	} else
+		return 0;
 }
 
 /*
@@ -35,7 +65,8 @@
  */
 static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
 {
-	entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
+	fuse_dentry_settime(entry,
+		time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
 	if (entry->d_inode)
 		get_fuse_inode(entry->d_inode)->i_time =
 			time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
@@ -47,7 +78,7 @@
  */
 void fuse_invalidate_attr(struct inode *inode)
 {
-	get_fuse_inode(inode)->i_time = jiffies - 1;
+	get_fuse_inode(inode)->i_time = 0;
 }
 
 /*
@@ -60,7 +91,7 @@
  */
 static void fuse_invalidate_entry_cache(struct dentry *entry)
 {
-	entry->d_time = jiffies - 1;
+	fuse_dentry_settime(entry, 0);
 }
 
 /*
@@ -102,7 +133,7 @@
 
 	if (inode && is_bad_inode(inode))
 		return 0;
-	else if (time_after(jiffies, entry->d_time)) {
+	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
 		int err;
 		struct fuse_entry_out outarg;
 		struct fuse_conn *fc;
@@ -666,7 +697,7 @@
 	if (!fuse_allow_task(fc, current))
 		return -EACCES;
 	if (get_node_id(inode) != FUSE_ROOT_ID &&
-	    time_before_eq(jiffies, fi->i_time))
+	    fi->i_time >= get_jiffies_64())
 		return 0;
 
 	return fuse_do_getattr(inode);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 63614ed..5c4fcd1 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -395,14 +395,16 @@
 	struct fuse_readpages_data data;
 	int err;
 
+	err = -EIO;
 	if (is_bad_inode(inode))
-		return -EIO;
+		goto clean_pages_up;
 
 	data.file = file;
 	data.inode = inode;
 	data.req = fuse_get_req(fc);
+	err = PTR_ERR(data.req);
 	if (IS_ERR(data.req))
-		return PTR_ERR(data.req);
+		goto clean_pages_up;
 
 	err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
 	if (!err) {
@@ -412,6 +414,10 @@
 			fuse_put_request(fc, data.req);
 	}
 	return err;
+
+clean_pages_up:
+	put_pages_list(pages);
+	return err;
 }
 
 static size_t fuse_send_write(struct fuse_req *req, struct file *file,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0dbf966..69c7750 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -59,7 +59,7 @@
 	struct fuse_req *forget_req;
 
 	/** Time in jiffies until the file attributes are valid */
-	unsigned long i_time;
+	u64 i_time;
 };
 
 /** FUSE specific file data */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index dcaaabd..7d250922 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -51,7 +51,7 @@
 		return NULL;
 
 	fi = get_fuse_inode(inode);
-	fi->i_time = jiffies - 1;
+	fi->i_time = 0;
 	fi->nodeid = 0;
 	fi->nlookup = 0;
 	fi->forget_req = fuse_request_alloc();
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index f238644..017cb0f 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -187,7 +187,7 @@
 {
 	struct inotify_kernel_event *kevent;
 
-	kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
+	kevent = kmem_cache_alloc(event_cachep, GFP_NOFS);
 	if (unlikely(!kevent))
 		return NULL;
 
diff --git a/fs/ioprio.c b/fs/ioprio.c
index 93aa571..78b1dea 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -44,6 +44,9 @@
 	task->ioprio = ioprio;
 
 	ioc = task->io_context;
+	/* see wmb() in current_io_context() */
+	smp_read_barrier_depends();
+
 	if (ioc && ioc->set_ioprio)
 		ioc->set_ioprio(ioc, ioprio);
 
@@ -111,9 +114,9 @@
 					continue;
 				ret = set_task_ioprio(p, ioprio);
 				if (ret)
-					break;
+					goto free_uid;
 			} while_each_thread(g, p);
-
+free_uid:
 			if (who)
 				free_uid(user);
 			break;
@@ -137,6 +140,29 @@
 	return ret;
 }
 
+int ioprio_best(unsigned short aprio, unsigned short bprio)
+{
+	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
+	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
+
+	if (!ioprio_valid(aprio))
+		return bprio;
+	if (!ioprio_valid(bprio))
+		return aprio;
+
+	if (aclass == IOPRIO_CLASS_NONE)
+		aclass = IOPRIO_CLASS_BE;
+	if (bclass == IOPRIO_CLASS_NONE)
+		bclass = IOPRIO_CLASS_BE;
+
+	if (aclass == bclass)
+		return min(aprio, bprio);
+	if (aclass > bclass)
+		return bprio;
+	else
+		return aprio;
+}
+
 asmlinkage long sys_ioprio_get(int which, int who)
 {
 	struct task_struct *g, *p;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 0971814..42da607 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -261,7 +261,7 @@
 			struct buffer_head *bh = jh2bh(jh);
 
 			jbd_lock_bh_state(bh);
-			kfree(jh->b_committed_data);
+			jbd_slab_free(jh->b_committed_data, bh->b_size);
 			jh->b_committed_data = NULL;
 			jbd_unlock_bh_state(bh);
 		}
@@ -745,14 +745,14 @@
 		 * Otherwise, we can just throw away the frozen data now.
 		 */
 		if (jh->b_committed_data) {
-			kfree(jh->b_committed_data);
+			jbd_slab_free(jh->b_committed_data, bh->b_size);
 			jh->b_committed_data = NULL;
 			if (jh->b_frozen_data) {
 				jh->b_committed_data = jh->b_frozen_data;
 				jh->b_frozen_data = NULL;
 			}
 		} else if (jh->b_frozen_data) {
-			kfree(jh->b_frozen_data);
+			jbd_slab_free(jh->b_frozen_data, bh->b_size);
 			jh->b_frozen_data = NULL;
 		}
 
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 8c9b28d..f66724c 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -84,6 +84,7 @@
 
 static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
 static void __journal_abort_soft (journal_t *journal, int errno);
+static int journal_create_jbd_slab(size_t slab_size);
 
 /*
  * Helper function used to manage commit timeouts
@@ -328,10 +329,10 @@
 		char *tmp;
 
 		jbd_unlock_bh_state(bh_in);
-		tmp = jbd_rep_kmalloc(bh_in->b_size, GFP_NOFS);
+		tmp = jbd_slab_alloc(bh_in->b_size, GFP_NOFS);
 		jbd_lock_bh_state(bh_in);
 		if (jh_in->b_frozen_data) {
-			kfree(tmp);
+			jbd_slab_free(tmp, bh_in->b_size);
 			goto repeat;
 		}
 
@@ -1069,17 +1070,17 @@
 int journal_load(journal_t *journal)
 {
 	int err;
+	journal_superblock_t *sb;
 
 	err = load_superblock(journal);
 	if (err)
 		return err;
 
+	sb = journal->j_superblock;
 	/* If this is a V2 superblock, then we have to check the
 	 * features flags on it. */
 
 	if (journal->j_format_version >= 2) {
-		journal_superblock_t *sb = journal->j_superblock;
-
 		if ((sb->s_feature_ro_compat &
 		     ~cpu_to_be32(JFS_KNOWN_ROCOMPAT_FEATURES)) ||
 		    (sb->s_feature_incompat &
@@ -1090,6 +1091,13 @@
 		}
 	}
 
+	/*
+	 * Create a slab for this blocksize
+	 */
+	err = journal_create_jbd_slab(cpu_to_be32(sb->s_blocksize));
+	if (err)
+		return err;
+
 	/* Let the recovery code check whether it needs to recover any
 	 * data from the journal. */
 	if (journal_recover(journal))
@@ -1612,6 +1620,77 @@
 }
 
 /*
+ * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed
+ * and allocate frozen and commit buffers from these slabs.
+ *
+ * Reason for doing this is to avoid, SLAB_DEBUG - since it could
+ * cause bh to cross page boundary.
+ */
+
+#define JBD_MAX_SLABS 5
+#define JBD_SLAB_INDEX(size)  (size >> 11)
+
+static kmem_cache_t *jbd_slab[JBD_MAX_SLABS];
+static const char *jbd_slab_names[JBD_MAX_SLABS] = {
+	"jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k"
+};
+
+static void journal_destroy_jbd_slabs(void)
+{
+	int i;
+
+	for (i = 0; i < JBD_MAX_SLABS; i++) {
+		if (jbd_slab[i])
+			kmem_cache_destroy(jbd_slab[i]);
+		jbd_slab[i] = NULL;
+	}
+}
+
+static int journal_create_jbd_slab(size_t slab_size)
+{
+	int i = JBD_SLAB_INDEX(slab_size);
+
+	BUG_ON(i >= JBD_MAX_SLABS);
+
+	/*
+	 * Check if we already have a slab created for this size
+	 */
+	if (jbd_slab[i])
+		return 0;
+
+	/*
+	 * Create a slab and force alignment to be same as slabsize -
+	 * this will make sure that allocations won't cross the page
+	 * boundary.
+	 */
+	jbd_slab[i] = kmem_cache_create(jbd_slab_names[i],
+				slab_size, slab_size, 0, NULL, NULL);
+	if (!jbd_slab[i]) {
+		printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+void * jbd_slab_alloc(size_t size, gfp_t flags)
+{
+	int idx;
+
+	idx = JBD_SLAB_INDEX(size);
+	BUG_ON(jbd_slab[idx] == NULL);
+	return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL);
+}
+
+void jbd_slab_free(void *ptr,  size_t size)
+{
+	int idx;
+
+	idx = JBD_SLAB_INDEX(size);
+	BUG_ON(jbd_slab[idx] == NULL);
+	kmem_cache_free(jbd_slab[idx], ptr);
+}
+
+/*
  * Journal_head storage management
  */
 static kmem_cache_t *journal_head_cache;
@@ -1799,13 +1878,13 @@
 				printk(KERN_WARNING "%s: freeing "
 						"b_frozen_data\n",
 						__FUNCTION__);
-				kfree(jh->b_frozen_data);
+				jbd_slab_free(jh->b_frozen_data, bh->b_size);
 			}
 			if (jh->b_committed_data) {
 				printk(KERN_WARNING "%s: freeing "
 						"b_committed_data\n",
 						__FUNCTION__);
-				kfree(jh->b_committed_data);
+				jbd_slab_free(jh->b_committed_data, bh->b_size);
 			}
 			bh->b_private = NULL;
 			jh->b_bh = NULL;	/* debug, really */
@@ -1961,6 +2040,7 @@
 	journal_destroy_revoke_caches();
 	journal_destroy_journal_head_cache();
 	journal_destroy_handle_cache();
+	journal_destroy_jbd_slabs();
 }
 
 static int __init journal_init(void)
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 508b2ea..f5169a9 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -666,8 +666,9 @@
 			if (!frozen_buffer) {
 				JBUFFER_TRACE(jh, "allocate memory for buffer");
 				jbd_unlock_bh_state(bh);
-				frozen_buffer = jbd_kmalloc(jh2bh(jh)->b_size,
-							    GFP_NOFS);
+				frozen_buffer =
+					jbd_slab_alloc(jh2bh(jh)->b_size,
+							 GFP_NOFS);
 				if (!frozen_buffer) {
 					printk(KERN_EMERG
 					       "%s: OOM for frozen_buffer\n",
@@ -726,7 +727,7 @@
 
 out:
 	if (unlikely(frozen_buffer))	/* It's usually NULL */
-		kfree(frozen_buffer);
+		jbd_slab_free(frozen_buffer, bh->b_size);
 
 	JBUFFER_TRACE(jh, "exit");
 	return error;
@@ -879,7 +880,7 @@
 
 repeat:
 	if (!jh->b_committed_data) {
-		committed_data = jbd_kmalloc(jh2bh(jh)->b_size, GFP_NOFS);
+		committed_data = jbd_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS);
 		if (!committed_data) {
 			printk(KERN_EMERG "%s: No memory for committed data\n",
 				__FUNCTION__);
@@ -906,7 +907,7 @@
 out:
 	journal_put_journal_head(jh);
 	if (unlikely(committed_data))
-		kfree(committed_data);
+		jbd_slab_free(committed_data, bh->b_size);
 	return err;
 }
 
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 43e3f56..a223cf4 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -168,16 +168,15 @@
 	set_cflag(COMMIT_Dirty, inode);
 }
 
-static int
-jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
-			struct buffer_head *bh_result, int create)
+int jfs_get_block(struct inode *ip, sector_t lblock,
+		  struct buffer_head *bh_result, int create)
 {
 	s64 lblock64 = lblock;
 	int rc = 0;
 	xad_t xad;
 	s64 xaddr;
 	int xflag;
-	s32 xlen = max_blocks;
+	s32 xlen = bh_result->b_size >> ip->i_blkbits;
 
 	/*
 	 * Take appropriate lock on inode
@@ -188,7 +187,7 @@
 		IREAD_LOCK(ip);
 
 	if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
-	    (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) &&
+	    (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) &&
 	    xaddr) {
 		if (xflag & XAD_NOTRECORDED) {
 			if (!create)
@@ -255,13 +254,6 @@
 	return rc;
 }
 
-static int jfs_get_block(struct inode *ip, sector_t lblock,
-			 struct buffer_head *bh_result, int create)
-{
-	return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits,
-			bh_result, create);
-}
-
 static int jfs_writepage(struct page *page, struct writeback_control *wbc)
 {
 	return nobh_writepage(page, jfs_get_block, wbc);
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index b5c7da6..1fc48df 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -32,6 +32,7 @@
 extern void jfs_free_zero_link(struct inode *);
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern void jfs_set_inode_flags(struct inode *);
+extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern const struct address_space_operations jfs_aops;
 extern struct inode_operations jfs_dir_inode_operations;
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 4f6cfeb..143bcd1 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -26,6 +26,7 @@
 #include <linux/moduleparam.h>
 #include <linux/kthread.h>
 #include <linux/posix_acl.h>
+#include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 #include <linux/seq_file.h>
 
@@ -298,7 +299,7 @@
 			break;
 		}
 
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
 		case Opt_quota:
 		case Opt_usrquota:
 			*flag |= JFS_USRQUOTA;
@@ -597,7 +598,7 @@
 	if (sbi->flag & JFS_NOINTEGRITY)
 		seq_puts(seq, ",nointegrity");
 
-#if defined(CONFIG_QUOTA)
+#ifdef CONFIG_QUOTA
 	if (sbi->flag & JFS_USRQUOTA)
 		seq_puts(seq, ",usrquota");
 
@@ -608,6 +609,113 @@
 	return 0;
 }
 
+#ifdef CONFIG_QUOTA
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data,
+			      size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> sb->s_blocksize_bits;
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	size_t toread;
+	struct buffer_head tmp_bh;
+	struct buffer_head *bh;
+	loff_t i_size = i_size_read(inode);
+
+	if (off > i_size)
+		return 0;
+	if (off+len > i_size)
+		len = i_size-off;
+	toread = len;
+	while (toread > 0) {
+		tocopy = sb->s_blocksize - offset < toread ?
+				sb->s_blocksize - offset : toread;
+
+		tmp_bh.b_state = 0;
+		tmp_bh.b_size = 1 << inode->i_blkbits;
+		err = jfs_get_block(inode, blk, &tmp_bh, 0);
+		if (err)
+			return err;
+		if (!buffer_mapped(&tmp_bh))	/* A hole? */
+			memset(data, 0, tocopy);
+		else {
+			bh = sb_bread(sb, tmp_bh.b_blocknr);
+			if (!bh)
+				return -EIO;
+			memcpy(data, bh->b_data+offset, tocopy);
+			brelse(bh);
+		}
+		offset = 0;
+		toread -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+	return len;
+}
+
+/* Write to quotafile */
+static ssize_t jfs_quota_write(struct super_block *sb, int type,
+			       const char *data, size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> sb->s_blocksize_bits;
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	size_t towrite = len;
+	struct buffer_head tmp_bh;
+	struct buffer_head *bh;
+
+	mutex_lock(&inode->i_mutex);
+	while (towrite > 0) {
+		tocopy = sb->s_blocksize - offset < towrite ?
+				sb->s_blocksize - offset : towrite;
+
+		tmp_bh.b_state = 0;
+		tmp_bh.b_size = 1 << inode->i_blkbits;
+		err = jfs_get_block(inode, blk, &tmp_bh, 1);
+		if (err)
+			goto out;
+		if (offset || tocopy != sb->s_blocksize)
+			bh = sb_bread(sb, tmp_bh.b_blocknr);
+		else
+			bh = sb_getblk(sb, tmp_bh.b_blocknr);
+		if (!bh) {
+			err = -EIO;
+			goto out;
+		}
+		lock_buffer(bh);
+		memcpy(bh->b_data+offset, data, tocopy);
+		flush_dcache_page(bh->b_page);
+		set_buffer_uptodate(bh);
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		brelse(bh);
+		offset = 0;
+		towrite -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+out:
+	if (len == towrite)
+		return err;
+	if (inode->i_size < off+len-towrite)
+		i_size_write(inode, off+len-towrite);
+	inode->i_version++;
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	mutex_unlock(&inode->i_mutex);
+	return len - towrite;
+}
+
+#endif
+
 static struct super_operations jfs_super_operations = {
 	.alloc_inode	= jfs_alloc_inode,
 	.destroy_inode	= jfs_destroy_inode,
@@ -621,7 +729,11 @@
 	.unlockfs       = jfs_unlockfs,
 	.statfs		= jfs_statfs,
 	.remount_fs	= jfs_remount,
-	.show_options	= jfs_show_options
+	.show_options	= jfs_show_options,
+#ifdef CONFIG_QUOTA
+	.quota_read	= jfs_quota_read,
+	.quota_write	= jfs_quota_write,
+#endif
 };
 
 static struct export_operations jfs_export_operations = {
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index baf5ae5..c9d4197 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -638,9 +638,6 @@
 	if (task->tk_status < 0) {
 		/* RPC error: Re-insert for retransmission */
 		timeout = 10 * HZ;
-	} else if (block->b_done) {
-		/* Block already removed, kill it for real */
-		timeout = 0;
 	} else {
 		/* Call was successful, now wait for client callback */
 		timeout = 60 * HZ;
@@ -709,13 +706,10 @@
 			break;
 	        if (time_after(block->b_when,jiffies))
 			break;
-		dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n",
-			block, block->b_when, block->b_done);
+		dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
+			block, block->b_when);
 		kref_get(&block->b_count);
-		if (block->b_done)
-			nlmsvc_unlink_block(block);
-		else
-			nlmsvc_grant_blocked(block);
+		nlmsvc_grant_blocked(block);
 		nlmsvc_release_block(block);
 	}
 
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 2a4df9b..01b4db9e 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -237,19 +237,22 @@
 nlm_traverse_files(struct nlm_host *host, int action)
 {
 	struct nlm_file	*file, **fp;
-	int		i;
+	int i, ret = 0;
 
 	mutex_lock(&nlm_file_mutex);
 	for (i = 0; i < FILE_NRHASH; i++) {
 		fp = nlm_files + i;
 		while ((file = *fp) != NULL) {
+			file->f_count++;
+			mutex_unlock(&nlm_file_mutex);
+
 			/* Traverse locks, blocks and shares of this file
 			 * and update file->f_locks count */
-			if (nlm_inspect_file(host, file, action)) {
-				mutex_unlock(&nlm_file_mutex);
-				return 1;
-			}
+			if (nlm_inspect_file(host, file, action))
+				ret = 1;
 
+			mutex_lock(&nlm_file_mutex);
+			file->f_count--;
 			/* No more references to this file. Let go of it. */
 			if (!file->f_blocks && !file->f_locks
 			 && !file->f_shares && !file->f_count) {
@@ -262,7 +265,7 @@
 		}
 	}
 	mutex_unlock(&nlm_file_mutex);
-	return 0;
+	return ret;
 }
 
 /*
diff --git a/fs/locks.c b/fs/locks.c
index b0b41a6..d7c5339 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1421,8 +1421,9 @@
 	if (!leases_enable)
 		goto out;
 
-	error = lease_alloc(filp, arg, &fl);
-	if (error)
+	error = -ENOMEM;
+	fl = locks_alloc_lock();
+	if (fl == NULL)
 		goto out;
 
 	locks_copy_lock(fl, lease);
@@ -1430,6 +1431,7 @@
 	locks_insert_lock(before, fl);
 
 	*flp = fl;
+	error = 0;
 out:
 	return error;
 }
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 9ea91c5..330ff9f 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -204,6 +204,8 @@
 	/*
 	 * Allocate the buffer map to keep the superblock small.
 	 */
+	if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
+		goto out_illegal_sb;
 	i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
 	map = kmalloc(i, GFP_KERNEL);
 	if (!map)
@@ -263,7 +265,7 @@
 
 out_no_bitmap:
 	printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
-    out_freemap:
+out_freemap:
 	for (i = 0; i < sbi->s_imap_blocks; i++)
 		brelse(sbi->s_imap[i]);
 	for (i = 0; i < sbi->s_zmap_blocks; i++)
@@ -276,11 +278,16 @@
 		printk("MINIX-fs: can't allocate map\n");
 	goto out_release;
 
+out_illegal_sb:
+	if (!silent)
+		printk("MINIX-fs: bad superblock\n");
+	goto out_release;
+
 out_no_fs:
 	if (!silent)
 		printk("VFS: Can't find a Minix or Minix V2 filesystem "
 			"on device %s\n", s->s_id);
-    out_release:
+out_release:
 	brelse(bh);
 	goto out;
 
@@ -290,7 +297,7 @@
 
 out_bad_sb:
 	printk("MINIX-fs: unable to read superblock\n");
- out:
+out:
 	s->s_fs_info = NULL;
 	kfree(sbi);
 	return -EINVAL;
diff --git a/fs/namei.c b/fs/namei.c
index e01070d..432d6bc 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -159,7 +159,7 @@
 #ifdef CONFIG_AUDITSYSCALL
 void putname(const char *name)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		audit_putname(name);
 	else
 		__putname(name);
@@ -227,10 +227,10 @@
 
 int permission(struct inode *inode, int mask, struct nameidata *nd)
 {
+	umode_t mode = inode->i_mode;
 	int retval, submask;
 
 	if (mask & MAY_WRITE) {
-		umode_t mode = inode->i_mode;
 
 		/*
 		 * Nobody gets write access to a read-only fs.
@@ -247,6 +247,13 @@
 	}
 
 
+	/*
+	 * MAY_EXEC on regular files requires special handling: We override
+	 * filesystem execute permissions if the mode bits aren't set.
+	 */
+	if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+		return -EACCES;
+
 	/* Ordinary permission routines do not understand MAY_APPEND. */
 	submask = mask & ~MAY_APPEND;
 	if (inode->i_op && inode->i_op->permission)
@@ -1125,7 +1132,7 @@
 	retval = link_path_walk(name, nd);
 out:
 	if (likely(retval == 0)) {
-		if (unlikely(current->audit_context && nd && nd->dentry &&
+		if (unlikely(!audit_dummy_context() && nd && nd->dentry &&
 				nd->dentry->d_inode))
 		audit_inode(name, nd->dentry->d_inode);
 	}
@@ -1357,7 +1364,7 @@
 		return -ENOENT;
 
 	BUG_ON(victim->d_parent->d_inode != dir);
-	audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino);
+	audit_inode_child(victim->d_name.name, victim->d_inode, dir);
 
 	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
@@ -1659,6 +1666,7 @@
 	 * It already exists.
 	 */
 	mutex_unlock(&dir->d_inode->i_mutex);
+	audit_inode_update(path.dentry->d_inode);
 
 	error = -EEXIST;
 	if (flag & O_EXCL)
@@ -1669,6 +1677,7 @@
 		if (flag & O_NOFOLLOW)
 			goto exit_dput;
 	}
+
 	error = -ENOENT;
 	if (!path.dentry->d_inode)
 		goto exit_dput;
@@ -1765,6 +1774,8 @@
 	if (nd->last_type != LAST_NORM)
 		goto fail;
 	nd->flags &= ~LOOKUP_PARENT;
+	nd->flags |= LOOKUP_CREATE;
+	nd->intent.open.flags = O_EXCL;
 
 	/*
 	 * Do the final lookup.
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index fecd3b09..76ca1cb 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -100,25 +100,6 @@
 	return atomic_dec_and_test(&dreq->io_count);
 }
 
-/*
- * "size" is never larger than rsize or wsize.
- */
-static inline int nfs_direct_count_pages(unsigned long user_addr, size_t size)
-{
-	int page_count;
-
-	page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-	page_count -= user_addr >> PAGE_SHIFT;
-	BUG_ON(page_count < 0);
-
-	return page_count;
-}
-
-static inline unsigned int nfs_max_pages(unsigned int size)
-{
-	return (size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-}
-
 /**
  * nfs_direct_IO - NFS address space operation for direct I/O
  * @rw: direction (read or write)
@@ -276,28 +257,24 @@
 	struct nfs_open_context *ctx = dreq->ctx;
 	struct inode *inode = ctx->dentry->d_inode;
 	size_t rsize = NFS_SERVER(inode)->rsize;
-	unsigned int rpages = nfs_max_pages(rsize);
 	unsigned int pgbase;
 	int result;
 	ssize_t started = 0;
 
 	get_dreq(dreq);
 
-	pgbase = user_addr & ~PAGE_MASK;
 	do {
 		struct nfs_read_data *data;
 		size_t bytes;
 
+		pgbase = user_addr & ~PAGE_MASK;
+		bytes = min(rsize,count);
+
 		result = -ENOMEM;
-		data = nfs_readdata_alloc(rpages);
+		data = nfs_readdata_alloc(pgbase + bytes);
 		if (unlikely(!data))
 			break;
 
-		bytes = rsize;
-		if (count < rsize)
-			bytes = count;
-
-		data->npages = nfs_direct_count_pages(user_addr, bytes);
 		down_read(&current->mm->mmap_sem);
 		result = get_user_pages(current, current->mm, user_addr,
 					data->npages, 1, 0, data->pagevec, NULL);
@@ -344,8 +321,10 @@
 		started += bytes;
 		user_addr += bytes;
 		pos += bytes;
+		/* FIXME: Remove this unnecessary math from final patch */
 		pgbase += bytes;
 		pgbase &= ~PAGE_MASK;
+		BUG_ON(pgbase != (user_addr & ~PAGE_MASK));
 
 		count -= bytes;
 	} while (count != 0);
@@ -524,7 +503,7 @@
 
 static void nfs_alloc_commit_data(struct nfs_direct_req *dreq)
 {
-	dreq->commit_data = nfs_commit_alloc(0);
+	dreq->commit_data = nfs_commit_alloc();
 	if (dreq->commit_data != NULL)
 		dreq->commit_data->req = (struct nfs_page *) dreq;
 }
@@ -605,28 +584,24 @@
 	struct nfs_open_context *ctx = dreq->ctx;
 	struct inode *inode = ctx->dentry->d_inode;
 	size_t wsize = NFS_SERVER(inode)->wsize;
-	unsigned int wpages = nfs_max_pages(wsize);
 	unsigned int pgbase;
 	int result;
 	ssize_t started = 0;
 
 	get_dreq(dreq);
 
-	pgbase = user_addr & ~PAGE_MASK;
 	do {
 		struct nfs_write_data *data;
 		size_t bytes;
 
+		pgbase = user_addr & ~PAGE_MASK;
+		bytes = min(wsize,count);
+
 		result = -ENOMEM;
-		data = nfs_writedata_alloc(wpages);
+		data = nfs_writedata_alloc(pgbase + bytes);
 		if (unlikely(!data))
 			break;
 
-		bytes = wsize;
-		if (count < wsize)
-			bytes = count;
-
-		data->npages = nfs_direct_count_pages(user_addr, bytes);
 		down_read(&current->mm->mmap_sem);
 		result = get_user_pages(current, current->mm, user_addr,
 					data->npages, 0, 0, data->pagevec, NULL);
@@ -676,8 +651,11 @@
 		started += bytes;
 		user_addr += bytes;
 		pos += bytes;
+
+		/* FIXME: Remove this useless math from the final patch */
 		pgbase += bytes;
 		pgbase &= ~PAGE_MASK;
+		BUG_ON(pgbase != (user_addr & ~PAGE_MASK));
 
 		count -= bytes;
 	} while (count != 0);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index cc2b874..48e8928 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -312,7 +312,13 @@
 
 static int nfs_release_page(struct page *page, gfp_t gfp)
 {
-	return !nfs_wb_page(page->mapping->host, page);
+	if (gfp & __GFP_FS)
+		return !nfs_wb_page(page->mapping->host, page);
+	else
+		/*
+		 * Avoid deadlock on nfs_wait_on_request().
+		 */
+		return 0;
 }
 
 const struct address_space_operations nfs_file_aops = {
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index b81e7ed..07a5dd5 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -130,9 +130,7 @@
 
 	if (!idmap)
 		return;
-	dput(idmap->idmap_dentry);
-	idmap->idmap_dentry = NULL;
-	rpc_unlink(idmap->idmap_path);
+	rpc_unlink(idmap->idmap_dentry);
 	clp->cl_idmap = NULL;
 	kfree(idmap);
 }
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 19b98ca..86b3169 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -51,7 +51,7 @@
 		namelen = dentry->d_name.len;
 		buflen -= namelen + 1;
 		if (buflen < 0)
-			goto Elong;
+			goto Elong_unlock;
 		end -= namelen;
 		memcpy(end, dentry->d_name.name, namelen);
 		*--end = '/';
@@ -68,6 +68,8 @@
 	end -= namelen;
 	memcpy(end, base, namelen);
 	return end;
+Elong_unlock:
+	spin_unlock(&dcache_lock);
 Elong:
 	return ERR_PTR(-ENAMETOOLONG);
 }
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e6ee97f..153898e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2668,7 +2668,7 @@
 	nfs4_set_cached_acl(inode, acl);
 }
 
-static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
 {
 	struct page *pages[NFS4ACL_MAXPAGES];
 	struct nfs_getaclargs args = {
@@ -2721,6 +2721,19 @@
 	return ret;
 }
 
+static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs4_exception exception = { };
+	ssize_t ret;
+	do {
+		ret = __nfs4_get_acl_uncached(inode, buf, buflen);
+		if (ret >= 0)
+			break;
+		ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
+	} while (exception.retry);
+	return ret;
+}
+
 static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -2737,7 +2750,7 @@
 	return nfs4_get_acl_uncached(inode, buf, buflen);
 }
 
-static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 	struct page *pages[NFS4ACL_MAXPAGES];
@@ -2763,6 +2776,18 @@
 	return ret;
 }
 
+static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				__nfs4_proc_set_acl(inode, buf, buflen),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
 static int
 nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
 {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 1750d99..730ec8f 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3355,7 +3355,7 @@
 	struct kvec	*iov = rcvbuf->head;
 	unsigned int	nr, pglen = rcvbuf->page_len;
 	uint32_t	*end, *entry, *p, *kaddr;
-	uint32_t	len, attrlen;
+	uint32_t	len, attrlen, xlen;
 	int 		hdrlen, recvd, status;
 
 	status = decode_op_hdr(xdr, OP_READDIR);
@@ -3377,10 +3377,10 @@
 
 	BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
 	kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
-	end = (uint32_t *) ((char *)p + pglen + readdir->pgbase);
+	end = p + ((pglen + readdir->pgbase) >> 2);
 	entry = p;
 	for (nr = 0; *p++; nr++) {
-		if (p + 3 > end)
+		if (end - p < 3)
 			goto short_pkt;
 		dprintk("cookie = %Lu, ", *((unsigned long long *)p));
 		p += 2;			/* cookie */
@@ -3389,18 +3389,19 @@
 			printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
 			goto err_unmap;
 		}
+		xlen = XDR_QUADLEN(len);
+		if (end - p < xlen + 1)
+			goto short_pkt;
 		dprintk("filename = %*s\n", len, (char *)p);
-		p += XDR_QUADLEN(len);
-		if (p + 1 > end)
-			goto short_pkt;
+		p += xlen;
 		len = ntohl(*p++);	/* bitmap length */
+		if (end - p < len + 1)
+			goto short_pkt;
 		p += len;
-		if (p + 1 > end)
-			goto short_pkt;
 		attrlen = XDR_QUADLEN(ntohl(*p++));
-		p += attrlen;		/* attributes */
-		if (p + 2 > end)
+		if (end - p < attrlen + 2)
 			goto short_pkt;
+		p += attrlen;		/* attributes */
 		entry = p;
 	}
 	if (!nr && (entry[0] != 0 || entry[1] == 0))
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 52bf634..7a9ee00 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -43,13 +43,15 @@
 
 #define MIN_POOL_READ	(32)
 
-struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
+struct nfs_read_data *nfs_readdata_alloc(size_t len)
 {
+	unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
 
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
+		p->npages = pagecount;
 		if (pagecount <= ARRAY_SIZE(p->page_array))
 			p->pagevec = p->page_array;
 		else {
@@ -63,7 +65,7 @@
 	return p;
 }
 
-void nfs_readdata_free(struct nfs_read_data *p)
+static void nfs_readdata_free(struct nfs_read_data *p)
 {
 	if (p && (p->pagevec != &p->page_array[0]))
 		kfree(p->pagevec);
@@ -116,10 +118,17 @@
 	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
 	base &= ~PAGE_CACHE_MASK;
 	pglen = PAGE_CACHE_SIZE - base;
-	if (pglen < remainder)
+	for (;;) {
+		if (remainder <= pglen) {
+			memclear_highpage_flush(*pages, base, remainder);
+			break;
+		}
 		memclear_highpage_flush(*pages, base, pglen);
-	else
-		memclear_highpage_flush(*pages, base, remainder);
+		pages++;
+		remainder -= pglen;
+		pglen = PAGE_CACHE_SIZE;
+		base = 0;
+	}
 }
 
 /*
@@ -133,7 +142,7 @@
 	int		result;
 	struct nfs_read_data *rdata;
 
-	rdata = nfs_readdata_alloc(1);
+	rdata = nfs_readdata_alloc(count);
 	if (!rdata)
 		return -ENOMEM;
 
@@ -329,25 +338,25 @@
 	struct nfs_page *req = nfs_list_entry(head->next);
 	struct page *page = req->wb_page;
 	struct nfs_read_data *data;
-	unsigned int rsize = NFS_SERVER(inode)->rsize;
-	unsigned int nbytes, offset;
+	size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
+	unsigned int offset;
 	int requests = 0;
 	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
 	nbytes = req->wb_bytes;
-	for(;;) {
-		data = nfs_readdata_alloc(1);
+	do {
+		size_t len = min(nbytes,rsize);
+
+		data = nfs_readdata_alloc(len);
 		if (!data)
 			goto out_bad;
 		INIT_LIST_HEAD(&data->pages);
 		list_add(&data->pages, &list);
 		requests++;
-		if (nbytes <= rsize)
-			break;
-		nbytes -= rsize;
-	}
+		nbytes -= len;
+	} while(nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
 
 	ClearPageError(page);
@@ -395,7 +404,7 @@
 	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
 		return nfs_pagein_multi(head, inode);
 
-	data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages);
+	data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize);
 	if (!data)
 		goto out_bad;
 
@@ -476,6 +485,8 @@
 	unsigned int base = data->args.pgbase;
 	struct page **pages;
 
+	if (data->res.eof)
+		count = data->args.count;
 	if (unlikely(count == 0))
 		return;
 	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
@@ -483,11 +494,7 @@
 	count += base;
 	for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
 		SetPageUptodate(*pages);
-	/*
-	 * Was this an eof or a short read? If the latter, don't mark the page
-	 * as uptodate yet.
-	 */
-	if (count > 0 && (data->res.eof || data->args.count == data->res.count))
+	if (count != 0)
 		SetPageUptodate(*pages);
 }
 
@@ -502,6 +509,8 @@
 	count += base;
 	for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
 		SetPageError(*pages);
+	if (count != 0)
+		SetPageError(*pages);
 }
 
 /*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 86bac6a..8ab3cf1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -90,22 +90,13 @@
 
 static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
 
-struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount)
+struct nfs_write_data *nfs_commit_alloc(void)
 {
 	struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
 
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
-		if (pagecount <= ARRAY_SIZE(p->page_array))
-			p->pagevec = p->page_array;
-		else {
-			p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
-			if (!p->pagevec) {
-				mempool_free(p, nfs_commit_mempool);
-				p = NULL;
-			}
-		}
 	}
 	return p;
 }
@@ -117,13 +108,15 @@
 	mempool_free(p, nfs_commit_mempool);
 }
 
-struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
+struct nfs_write_data *nfs_writedata_alloc(size_t len)
 {
+	unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS);
 
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
+		p->npages = pagecount;
 		if (pagecount <= ARRAY_SIZE(p->page_array))
 			p->pagevec = p->page_array;
 		else {
@@ -137,7 +130,7 @@
 	return p;
 }
 
-void nfs_writedata_free(struct nfs_write_data *p)
+static void nfs_writedata_free(struct nfs_write_data *p)
 {
 	if (p && (p->pagevec != &p->page_array[0]))
 		kfree(p->pagevec);
@@ -208,7 +201,7 @@
 	int		result, written = 0;
 	struct nfs_write_data *wdata;
 
-	wdata = nfs_writedata_alloc(1);
+	wdata = nfs_writedata_alloc(wsize);
 	if (!wdata)
 		return -ENOMEM;
 
@@ -999,24 +992,24 @@
 	struct nfs_page *req = nfs_list_entry(head->next);
 	struct page *page = req->wb_page;
 	struct nfs_write_data *data;
-	unsigned int wsize = NFS_SERVER(inode)->wsize;
-	unsigned int nbytes, offset;
+	size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
+	unsigned int offset;
 	int requests = 0;
 	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
 	nbytes = req->wb_bytes;
-	for (;;) {
-		data = nfs_writedata_alloc(1);
+	do {
+		size_t len = min(nbytes, wsize);
+
+		data = nfs_writedata_alloc(len);
 		if (!data)
 			goto out_bad;
 		list_add(&data->pages, &list);
 		requests++;
-		if (nbytes <= wsize)
-			break;
-		nbytes -= wsize;
-	}
+		nbytes -= len;
+	} while (nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
 
 	ClearPageError(page);
@@ -1070,7 +1063,7 @@
 	struct nfs_write_data	*data;
 	unsigned int		count;
 
-	data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages);
+	data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize);
 	if (!data)
 		goto out_bad;
 
@@ -1378,7 +1371,7 @@
 	struct nfs_write_data	*data;
 	struct nfs_page         *req;
 
-	data = nfs_commit_alloc(NFS_SERVER(inode)->wpages);
+	data = nfs_commit_alloc();
 
 	if (!data)
 		goto out_bad;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index ecc439d..501d838 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -187,6 +187,11 @@
 			goto out;
 		}
 
+		/* Set user creds for this exportpoint */
+		error = nfserrno(nfsd_setuser(rqstp, exp));
+		if (error)
+			goto out;
+
 		/*
 		 * Look up the dentry using the NFS file handle.
 		 */
@@ -241,16 +246,17 @@
 		dprintk("nfsd: fh_verify - just checking\n");
 		dentry = fhp->fh_dentry;
 		exp = fhp->fh_export;
+		/* Set user creds for this exportpoint; necessary even
+		 * in the "just checking" case because this may be a
+		 * filehandle that was created by fh_compose, and that
+		 * is about to be used in another nfsv4 compound
+		 * operation */
+		error = nfserrno(nfsd_setuser(rqstp, exp));
+		if (error)
+			goto out;
 	}
 	cache_get(&exp->h);
 
-	/* Set user creds for this exportpoint; necessary even in the "just
-	 * checking" case because this may be a filehandle that was created by
-	 * fh_compose, and that is about to be used in another nfsv4 compound
-	 * operation */
-	error = nfserrno(nfsd_setuser(rqstp, exp));
-	if (error)
-		goto out;
 
 	error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
 	if (error)
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 1b8346d..9503240 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2375,7 +2375,6 @@
 	mlog(0, "returning %d\n", ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(dlm_migrate_lockres);
 
 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock)
 {
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index b0c3134..37be4b2 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -155,7 +155,7 @@
 	else
 		status = dlm_get_unlock_actions(dlm, res, lock, lksb, &actions);
 
-	if (status != DLM_NORMAL)
+	if (status != DLM_NORMAL && (status != DLM_CANCELGRANT || !master_node))
 		goto leave;
 
 	/* By now this has been masked out of cancel requests. */
@@ -183,8 +183,7 @@
 		spin_lock(&lock->spinlock);
 		/* if the master told us the lock was already granted,
 		 * let the ast handle all of these actions */
-		if (status == DLM_NORMAL &&
-		    lksb->status == DLM_CANCELGRANT) {
+		if (status == DLM_CANCELGRANT) {
 			actions &= ~(DLM_UNLOCK_REMOVE_LOCK|
 				     DLM_UNLOCK_REGRANT_LOCK|
 				     DLM_UNLOCK_CLEAR_CONVERT_TYPE);
@@ -349,14 +348,9 @@
 					vec, veclen, owner, &status);
 	if (tmpret >= 0) {
 		// successfully sent and received
-		if (status == DLM_CANCELGRANT)
-			ret = DLM_NORMAL;
-		else if (status == DLM_FORWARD) {
+		if (status == DLM_FORWARD)
 			mlog(0, "master was in-progress.  retry\n");
-			ret = DLM_FORWARD;
-		} else
-			ret = status;
-		lksb->status = status;
+		ret = status;
 	} else {
 		mlog_errno(tmpret);
 		if (dlm_is_host_down(tmpret)) {
@@ -372,7 +366,6 @@
 			/* something bad.  this will BUG in ocfs2 */
 			ret = dlm_err_to_dlm_status(tmpret);
 		}
-		lksb->status = ret;
 	}
 
 	return ret;
@@ -483,6 +476,10 @@
 
 	/* lock was found on queue */
 	lksb = lock->lksb;
+	if (flags & (LKM_VALBLK|LKM_PUT_LVB) &&
+	    lock->ml.type != LKM_EXMODE)
+		flags &= ~(LKM_VALBLK|LKM_PUT_LVB);
+
 	/* unlockast only called on originating node */
 	if (flags & LKM_PUT_LVB) {
 		lksb->flags |= DLM_LKSB_PUT_LVB;
@@ -507,11 +504,8 @@
 			       "cookie=%u:%llu\n",
 			       dlm_get_lock_cookie_node(unlock->cookie),
 			       dlm_get_lock_cookie_seq(unlock->cookie));
-	else {
-		/* send the lksb->status back to the other node */
-		status = lksb->status;
+	else
 		dlm_lock_put(lock);
-	}
 
 leave:
 	if (res)
@@ -533,26 +527,22 @@
 
 	if (dlm_lock_on_list(&res->blocked, lock)) {
 		/* cancel this outright */
-		lksb->status = DLM_NORMAL;
 		status = DLM_NORMAL;
 		*actions = (DLM_UNLOCK_CALL_AST |
 			    DLM_UNLOCK_REMOVE_LOCK);
 	} else if (dlm_lock_on_list(&res->converting, lock)) {
 		/* cancel the request, put back on granted */
-		lksb->status = DLM_NORMAL;
 		status = DLM_NORMAL;
 		*actions = (DLM_UNLOCK_CALL_AST |
 			    DLM_UNLOCK_REMOVE_LOCK |
 			    DLM_UNLOCK_REGRANT_LOCK |
 			    DLM_UNLOCK_CLEAR_CONVERT_TYPE);
 	} else if (dlm_lock_on_list(&res->granted, lock)) {
-		/* too late, already granted.  DLM_CANCELGRANT */
-		lksb->status = DLM_CANCELGRANT;
-		status = DLM_NORMAL;
+		/* too late, already granted. */
+		status = DLM_CANCELGRANT;
 		*actions = DLM_UNLOCK_CALL_AST;
 	} else {
 		mlog(ML_ERROR, "lock to cancel is not on any list!\n");
-		lksb->status = DLM_IVLOCKID;
 		status = DLM_IVLOCKID;
 		*actions = 0;
 	}
@@ -569,13 +559,11 @@
 
 	/* unlock request */
 	if (!dlm_lock_on_list(&res->granted, lock)) {
-		lksb->status = DLM_DENIED;
 		status = DLM_DENIED;
 		dlm_error(status);
 		*actions = 0;
 	} else {
 		/* unlock granted lock */
-		lksb->status = DLM_NORMAL;
 		status = DLM_NORMAL;
 		*actions = (DLM_UNLOCK_FREE_LOCK |
 			    DLM_UNLOCK_CALL_AST |
@@ -632,6 +620,8 @@
 
 	spin_lock(&res->spinlock);
 	is_master = (res->owner == dlm->node_num);
+	if (flags & LKM_VALBLK && lock->ml.type != LKM_EXMODE)
+		flags &= ~LKM_VALBLK;
 	spin_unlock(&res->spinlock);
 
 	if (is_master) {
@@ -665,7 +655,7 @@
 	}
 
 	if (call_ast) {
-		mlog(0, "calling unlockast(%p, %d)\n", data, lksb->status);
+		mlog(0, "calling unlockast(%p, %d)\n", data, status);
 		if (is_master) {
 			/* it is possible that there is one last bast 
 			 * pending.  make sure it is flushed, then
@@ -677,9 +667,12 @@
 			wait_event(dlm->ast_wq, 
 				   dlm_lock_basts_flushed(dlm, lock));
 		}
-		(*unlockast)(data, lksb->status);
+		(*unlockast)(data, status);
 	}
 
+	if (status == DLM_CANCELGRANT)
+		status = DLM_NORMAL;
+
 	if (status == DLM_NORMAL) {
 		mlog(0, "kicking the thread\n");
 		dlm_kick_thread(dlm, res);
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 0d1973e..1f17a4d 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -840,6 +840,12 @@
 
 	mlog(0, "Allocating %u clusters for a new window.\n",
 	     ocfs2_local_alloc_window_bits(osb));
+
+	/* Instruct the allocation code to try the most recently used
+	 * cluster group. We'll re-record the group used this pass
+	 * below. */
+	ac->ac_last_group = osb->la_last_gd;
+
 	/* we used the generic suballoc reserve function, but we set
 	 * everything up nicely, so there's no reason why we can't use
 	 * the more specific cluster api to claim bits. */
@@ -852,6 +858,8 @@
 		goto bail;
 	}
 
+	osb->la_last_gd = ac->ac_last_group;
+
 	la->la_bm_off = cpu_to_le32(cluster_off);
 	alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count);
 	/* just in case... In the future when we find space ourselves,
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index cd4a6f2..0462a7f 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -197,7 +197,6 @@
 	struct ocfs2_node_map recovery_map;
 	struct ocfs2_node_map umount_map;
 
-	u32 num_clusters;
 	u64 root_blkno;
 	u64 system_dir_blkno;
 	u64 bitmap_blkno;
@@ -237,6 +236,7 @@
 
 	enum ocfs2_local_alloc_state local_alloc_state;
 	struct buffer_head *local_alloc_bh;
+	u64 la_last_gd;
 
 	/* Next two fields are for local node slot recovery during
 	 * mount. */
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 1955230..9d91e66 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -70,12 +70,6 @@
 				    struct buffer_head *group_bh,
 				    u32 bits_wanted, u32 min_bits,
 				    u16 *bit_off, u16 *bits_found);
-static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
-			      u32 bits_wanted,
-			      u32 min_bits,
-			      u16 *bit_off,
-			      unsigned int *num_bits,
-			      u64 *bg_blkno);
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 				     struct ocfs2_alloc_context *ac,
 				     u32 bits_wanted,
@@ -85,11 +79,6 @@
 				     u64 *bg_blkno);
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
 					 int nr);
-static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
-					     struct buffer_head *bg_bh,
-					     unsigned int bits_wanted,
-					     u16 *bit_off,
-					     u16 *bits_found);
 static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
 					     struct inode *alloc_inode,
 					     struct ocfs2_group_desc *bg,
@@ -143,6 +132,64 @@
 	return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
 }
 
+/* somewhat more expensive than our other checks, so use sparingly. */
+static int ocfs2_check_group_descriptor(struct super_block *sb,
+					struct ocfs2_dinode *di,
+					struct ocfs2_group_desc *gd)
+{
+	unsigned int max_bits;
+
+	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
+		OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd);
+		return -EIO;
+	}
+
+	if (di->i_blkno != gd->bg_parent_dinode) {
+		ocfs2_error(sb, "Group descriptor # %llu has bad parent "
+			    "pointer (%llu, expected %llu)",
+			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			    (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
+			    (unsigned long long)le64_to_cpu(di->i_blkno));
+		return -EIO;
+	}
+
+	max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
+	if (le16_to_cpu(gd->bg_bits) > max_bits) {
+		ocfs2_error(sb, "Group descriptor # %llu has bit count of %u",
+			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			    le16_to_cpu(gd->bg_bits));
+		return -EIO;
+	}
+
+	if (le16_to_cpu(gd->bg_chain) >=
+	    le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
+		ocfs2_error(sb, "Group descriptor # %llu has bad chain %u",
+			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			    le16_to_cpu(gd->bg_chain));
+		return -EIO;
+	}
+
+	if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
+		ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
+			    "claims that %u are free",
+			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			    le16_to_cpu(gd->bg_bits),
+			    le16_to_cpu(gd->bg_free_bits_count));
+		return -EIO;
+	}
+
+	if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
+		ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
+			    "max bitmap bits of %u",
+			    (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			    le16_to_cpu(gd->bg_bits),
+			    8 * le16_to_cpu(gd->bg_size));
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
 				  struct inode *alloc_inode,
 				  struct buffer_head *bg_bh,
@@ -663,6 +710,7 @@
 static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
 					     struct buffer_head *bg_bh,
 					     unsigned int bits_wanted,
+					     unsigned int total_bits,
 					     u16 *bit_off,
 					     u16 *bits_found)
 {
@@ -679,10 +727,8 @@
 	found = start = best_offset = best_size = 0;
 	bitmap = bg->bg_bitmap;
 
-	while((offset = ocfs2_find_next_zero_bit(bitmap,
-						 le16_to_cpu(bg->bg_bits),
-						 start)) != -1) {
-		if (offset == le16_to_cpu(bg->bg_bits))
+	while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) {
+		if (offset == total_bits)
 			break;
 
 		if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {
@@ -911,14 +957,35 @@
 {
 	int search = -ENOSPC;
 	int ret;
-	struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
+	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
 	u16 tmp_off, tmp_found;
+	unsigned int max_bits, gd_cluster_off;
 
 	BUG_ON(!ocfs2_is_cluster_bitmap(inode));
 
-	if (bg->bg_free_bits_count) {
+	if (gd->bg_free_bits_count) {
+		max_bits = le16_to_cpu(gd->bg_bits);
+
+		/* Tail groups in cluster bitmaps which aren't cpg
+		 * aligned are prone to partial extention by a failed
+		 * fs resize. If the file system resize never got to
+		 * update the dinode cluster count, then we don't want
+		 * to trust any clusters past it, regardless of what
+		 * the group descriptor says. */
+		gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb,
+							  le64_to_cpu(gd->bg_blkno));
+		if ((gd_cluster_off + max_bits) >
+		    OCFS2_I(inode)->ip_clusters) {
+			max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off;
+			mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n",
+			     (unsigned long long)le64_to_cpu(gd->bg_blkno),
+			     le16_to_cpu(gd->bg_bits),
+			     OCFS2_I(inode)->ip_clusters, max_bits);
+		}
+
 		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
 							group_bh, bits_wanted,
+							max_bits,
 							&tmp_off, &tmp_found);
 		if (ret)
 			return ret;
@@ -951,17 +1018,109 @@
 	if (bg->bg_free_bits_count)
 		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
 							group_bh, bits_wanted,
+							le16_to_cpu(bg->bg_bits),
 							bit_off, bits_found);
 
 	return ret;
 }
 
+static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
+				       struct ocfs2_journal_handle *handle,
+				       struct buffer_head *di_bh,
+				       u32 num_bits,
+				       u16 chain)
+{
+	int ret;
+	u32 tmp_used;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
+	struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
+
+	ret = ocfs2_journal_access(handle, inode, di_bh,
+				   OCFS2_JOURNAL_ACCESS_WRITE);
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	tmp_used = le32_to_cpu(di->id1.bitmap1.i_used);
+	di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used);
+	le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits);
+
+	ret = ocfs2_journal_dirty(handle, di_bh);
+	if (ret < 0)
+		mlog_errno(ret);
+
+out:
+	return ret;
+}
+
+static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
+				  u32 bits_wanted,
+				  u32 min_bits,
+				  u16 *bit_off,
+				  unsigned int *num_bits,
+				  u64 gd_blkno,
+				  u16 *bits_left)
+{
+	int ret;
+	u16 found;
+	struct buffer_head *group_bh = NULL;
+	struct ocfs2_group_desc *gd;
+	struct inode *alloc_inode = ac->ac_inode;
+	struct ocfs2_journal_handle *handle = ac->ac_handle;
+
+	ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
+			       &group_bh, OCFS2_BH_CACHED, alloc_inode);
+	if (ret < 0) {
+		mlog_errno(ret);
+		return ret;
+	}
+
+	gd = (struct ocfs2_group_desc *) group_bh->b_data;
+	if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
+		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
+				  bit_off, &found);
+	if (ret < 0) {
+		if (ret != -ENOSPC)
+			mlog_errno(ret);
+		goto out;
+	}
+
+	*num_bits = found;
+
+	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
+					       *num_bits,
+					       le16_to_cpu(gd->bg_chain));
+	if (ret < 0) {
+		mlog_errno(ret);
+		goto out;
+	}
+
+	ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
+					 *bit_off, *num_bits);
+	if (ret < 0)
+		mlog_errno(ret);
+
+	*bits_left = le16_to_cpu(gd->bg_free_bits_count);
+
+out:
+	brelse(group_bh);
+
+	return ret;
+}
+
 static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 			      u32 bits_wanted,
 			      u32 min_bits,
 			      u16 *bit_off,
 			      unsigned int *num_bits,
-			      u64 *bg_blkno)
+			      u64 *bg_blkno,
+			      u16 *bits_left)
 {
 	int status;
 	u16 chain, tmp_bits;
@@ -988,9 +1147,9 @@
 		goto bail;
 	}
 	bg = (struct ocfs2_group_desc *) group_bh->b_data;
-	if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-		status = -EIO;
+	status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
+	if (status) {
+		mlog_errno(status);
 		goto bail;
 	}
 
@@ -1018,9 +1177,9 @@
 			goto bail;
 		}
 		bg = (struct ocfs2_group_desc *) group_bh->b_data;
-		if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-			OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-			status = -EIO;
+		status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
+		if (status) {
+			mlog_errno(status);
 			goto bail;
 		}
 	}
@@ -1099,6 +1258,7 @@
 	     (unsigned long long)fe->i_blkno);
 
 	*bg_blkno = le64_to_cpu(bg->bg_blkno);
+	*bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
 	if (group_bh)
 		brelse(group_bh);
@@ -1120,6 +1280,8 @@
 {
 	int status;
 	u16 victim, i;
+	u16 bits_left = 0;
+	u64 hint_blkno = ac->ac_last_group;
 	struct ocfs2_chain_list *cl;
 	struct ocfs2_dinode *fe;
 
@@ -1146,6 +1308,28 @@
 		goto bail;
 	}
 
+	if (hint_blkno) {
+		/* Attempt to short-circuit the usual search mechanism
+		 * by jumping straight to the most recently used
+		 * allocation group. This helps us mantain some
+		 * contiguousness across allocations. */
+		status = ocfs2_search_one_group(ac, bits_wanted, min_bits,
+						bit_off, num_bits,
+						hint_blkno, &bits_left);
+		if (!status) {
+			/* Be careful to update *bg_blkno here as the
+			 * caller is expecting it to be filled in, and
+			 * ocfs2_search_one_group() won't do that for
+			 * us. */
+			*bg_blkno = hint_blkno;
+			goto set_hint;
+		}
+		if (status < 0 && status != -ENOSPC) {
+			mlog_errno(status);
+			goto bail;
+		}
+	}
+
 	cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
 
 	victim = ocfs2_find_victim_chain(cl);
@@ -1153,9 +1337,9 @@
 	ac->ac_allow_chain_relink = 1;
 
 	status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
-				    num_bits, bg_blkno);
+				    num_bits, bg_blkno, &bits_left);
 	if (!status)
-		goto bail;
+		goto set_hint;
 	if (status < 0 && status != -ENOSPC) {
 		mlog_errno(status);
 		goto bail;
@@ -1177,8 +1361,8 @@
 
 		ac->ac_chain = i;
 		status = ocfs2_search_chain(ac, bits_wanted, min_bits,
-					    bit_off, num_bits,
-					    bg_blkno);
+					    bit_off, num_bits, bg_blkno,
+					    &bits_left);
 		if (!status)
 			break;
 		if (status < 0 && status != -ENOSPC) {
@@ -1186,8 +1370,19 @@
 			goto bail;
 		}
 	}
-bail:
 
+set_hint:
+	if (status != -ENOSPC) {
+		/* If the next search of this group is not likely to
+		 * yield a suitable extent, then we reset the last
+		 * group hint so as to not waste a disk read */
+		if (bits_left < min_bits)
+			ac->ac_last_group = 0;
+		else
+			ac->ac_last_group = *bg_blkno;
+	}
+
+bail:
 	mlog_exit(status);
 	return status;
 }
@@ -1341,7 +1536,7 @@
 {
 	int status;
 	unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
-	u64 bg_blkno;
+	u64 bg_blkno = 0;
 	u16 bg_bit_off;
 
 	mlog_entry_void();
@@ -1494,9 +1689,9 @@
 	}
 
 	group = (struct ocfs2_group_desc *) group_bh->b_data;
-	if (!OCFS2_IS_VALID_GROUP_DESC(group)) {
-		OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group);
-		status = -EIO;
+	status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group);
+	if (status) {
+		mlog_errno(status);
 		goto bail;
 	}
 	BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits));
diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h
index a76c82a..c787838 100644
--- a/fs/ocfs2/suballoc.h
+++ b/fs/ocfs2/suballoc.h
@@ -49,6 +49,8 @@
 	u16    ac_chain;
 	int    ac_allow_chain_relink;
 	group_search_t *ac_group_search;
+
+	u64    ac_last_group;
 };
 
 void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac);
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 382706a..d17e33e 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1442,8 +1442,13 @@
 
 	osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;
 
+	/* We don't have a cluster lock on the bitmap here because
+	 * we're only interested in static information and the extra
+	 * complexity at mount time isn't worht it. Don't pass the
+	 * inode in to the read function though as we don't want it to
+	 * be put in the cache. */
 	status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0,
-				  inode);
+				  NULL);
 	iput(inode);
 	if (status < 0) {
 		mlog_errno(status);
@@ -1452,7 +1457,6 @@
 
 	di = (struct ocfs2_dinode *) bitmap_bh->b_data;
 	osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg);
-	osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
 	brelse(bitmap_bh);
 	mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n",
 	     (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg);
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index c9a4780..e478f19 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -99,7 +99,7 @@
 
 config MAC_PARTITION
 	bool "Macintosh partition map support" if PARTITION_ADVANCED
-	default y if MAC
+	default y if (MAC || PPC_PMAC)
 	help
 	  Say Y here if you would like to use hard disks under Linux which
 	  were partitioned on a Macintosh.
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index abe91ca..0a5927c 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -74,7 +74,7 @@
 	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
 	for (i = 0; i < 8; i++, p++) {
 		unsigned long st_sector;
-		int num_sectors;
+		unsigned int num_sectors;
 
 		st_sector = be32_to_cpu(p->start_cylinder) * spc;
 		num_sectors = be32_to_cpu(p->num_sectors);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 9f2cfc3..9421562 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -169,7 +169,7 @@
 		"Mapped:       %8lu kB\n"
 		"Slab:         %8lu kB\n"
 		"PageTables:   %8lu kB\n"
-		"NFS Unstable: %8lu kB\n"
+		"NFS_Unstable: %8lu kB\n"
 		"Bounce:       %8lu kB\n"
 		"CommitLimit:  %8lu kB\n"
 		"Committed_AS: %8lu kB\n"
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index f318b58..1627edd 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -48,8 +48,8 @@
 		return 0;
 	}
 
-	reiserfs_write_lock(inode->i_sb);
 	mutex_lock(&inode->i_mutex);
+	reiserfs_write_lock(inode->i_sb);
 	/* freeing preallocation only involves relogging blocks that
 	 * are already in the current transaction.  preallocation gets
 	 * freed at the end of each transaction, so it is impossible for
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 12dfdcf..52f1e21 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -39,14 +39,10 @@
 
 	/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
 	if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) {	/* also handles bad_inode case */
-		mutex_lock(&inode->i_mutex);
-
 		reiserfs_delete_xattrs(inode);
 
-		if (journal_begin(&th, inode->i_sb, jbegin_count)) {
-			mutex_unlock(&inode->i_mutex);
+		if (journal_begin(&th, inode->i_sb, jbegin_count))
 			goto out;
-		}
 		reiserfs_update_inode_transaction(inode);
 
 		err = reiserfs_delete_object(&th, inode);
@@ -57,12 +53,8 @@
 		if (!err) 
 			DQUOT_FREE_INODE(inode);
 
-		if (journal_end(&th, inode->i_sb, jbegin_count)) {
-			mutex_unlock(&inode->i_mutex);
+		if (journal_end(&th, inode->i_sb, jbegin_count))
 			goto out;
-		}
-
-		mutex_unlock(&inode->i_mutex);
 
 		/* check return value from reiserfs_delete_object after
 		 * ending the transaction
@@ -2348,6 +2340,7 @@
 	unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 	int error = 0;
 	unsigned long block;
+	sector_t last_block;
 	struct buffer_head *head, *bh;
 	int partial = 0;
 	int nr = 0;
@@ -2395,10 +2388,19 @@
 	}
 	bh = head;
 	block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
+	last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
 	/* first map all the buffers, logging any direct items we find */
 	do {
-		if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) ||
-						      (buffer_mapped(bh)
+		if (block > last_block) {
+			/*
+			 * This can happen when the block size is less than
+			 * the page size.  The corresponding bytes in the page
+			 * were zero filled above
+			 */
+			clear_buffer_dirty(bh);
+			set_buffer_uptodate(bh);
+		} else if ((checked || buffer_dirty(bh)) &&
+		           (!buffer_mapped(bh) || (buffer_mapped(bh)
 						       && bh->b_blocknr ==
 						       0))) {
 			/* not mapped yet, or it points to a direct item, search
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 745c881..a986b5e 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -116,12 +116,12 @@
 	if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
 		return 0;
 	}
-	reiserfs_write_lock(inode->i_sb);
 
 	/* we need to make sure nobody is changing the file size beneath
 	 ** us
 	 */
 	mutex_lock(&inode->i_mutex);
+	reiserfs_write_lock(inode->i_sb);
 
 	write_from = inode->i_size & (blocksize - 1);
 	/* if we are on a block boundary, we are already unpacked.  */
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 39fedaa..d935fb9 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -424,7 +424,7 @@
 	int res = -ENOTDIR;
 	if (!file->f_op || !file->f_op->readdir)
 		goto out;
-	mutex_lock(&inode->i_mutex);
+	mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR);
 //        down(&inode->i_zombie);
 	res = -ENOENT;
 	if (!IS_DEADDIR(inode)) {
diff --git a/fs/super.c b/fs/super.c
index 6d4e817..5c4c94d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -49,6 +49,7 @@
 
 /**
  *	alloc_super	-	create new superblock
+ *	@type:	filesystem type superblock should belong to
  *
  *	Allocates and initializes a new &struct super_block.  alloc_super()
  *	returns a pointer new superblock or %NULL if allocation had failed.
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 3873c67..3332347 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -75,6 +75,12 @@
 	}
 	*err = -ENOSPC;
 
+	UDF_I_UNIQUE(inode) = 0;
+	UDF_I_LENEXTENTS(inode) = 0;
+	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
+	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
+	UDF_I_STRAT4096(inode) = 0;
+
 	block = udf_new_block(dir->i_sb, NULL, UDF_I_LOCATION(dir).partitionReferenceNum,
 		start, err);
 	if (*err)
@@ -84,11 +90,6 @@
 	}
 
 	mutex_lock(&sbi->s_alloc_mutex);
-	UDF_I_UNIQUE(inode) = 0;
-	UDF_I_LENEXTENTS(inode) = 0;
-	UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
-	UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
-	UDF_I_STRAT4096(inode) = 0;
 	if (UDF_SB_LVIDBH(sb))
 	{
 		struct logicalVolHeaderDesc *lvhd;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 4df822c..fcce1a2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -115,6 +115,13 @@
 	ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL);
 	if (!ei)
 		return NULL;
+
+	ei->i_unique = 0;
+	ei->i_lenExtents = 0;
+	ei->i_next_alloc_block = 0;
+	ei->i_next_alloc_goal = 0;
+	ei->i_strat4096 = 0;
+
 	return &ei->vfs_inode;
 }
 
@@ -1652,7 +1659,7 @@
 		iput(inode);
 		goto error_out;
 	}
-	sb->s_maxbytes = MAX_LFS_FILESIZE;
+	sb->s_maxbytes = 1<<30;
 	return 0;
 
 error_out:
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index e1b0e8c..0abd66c 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -239,38 +239,52 @@
 	{
 		if (offset)
 		{
-			extoffset -= adsize;
-			etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
-			if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
-			{
-				extoffset -= adsize;
-				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
-				udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
-			}
-			else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
-			{
-				kernel_lb_addr neloc = { 0, 0 };
-				extoffset -= adsize;
-				nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
-					((elen + offset + inode->i_sb->s_blocksize - 1) &
-					~(inode->i_sb->s_blocksize - 1));
-				udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
-				udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
-			}
-			else
-			{
-				if (elen & (inode->i_sb->s_blocksize - 1))
-				{
-					extoffset -= adsize;
-					elen = EXT_RECORDED_ALLOCATED |
-						((elen + inode->i_sb->s_blocksize - 1) &
-						~(inode->i_sb->s_blocksize - 1));
-					udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
-				}
+			/*
+			 *  OK, there is not extent covering inode->i_size and
+			 *  no extent above inode->i_size => truncate is
+			 *  extending the file by 'offset'.
+			 */
+			if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) ||
+			    (bh && extoffset == sizeof(struct allocExtDesc))) {
+				/* File has no extents at all! */
 				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
 				udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
 			}
+			else {
+				extoffset -= adsize;
+				etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
+				if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
+				{
+					extoffset -= adsize;
+					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset);
+					udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0);
+				}
+				else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
+				{
+					kernel_lb_addr neloc = { 0, 0 };
+					extoffset -= adsize;
+					nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
+						((elen + offset + inode->i_sb->s_blocksize - 1) &
+						~(inode->i_sb->s_blocksize - 1));
+					udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);
+					udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
+				}
+				else
+				{
+					if (elen & (inode->i_sb->s_blocksize - 1))
+					{
+						extoffset -= adsize;
+						elen = EXT_RECORDED_ALLOCATED |
+							((elen + inode->i_sb->s_blocksize - 1) &
+							~(inode->i_sb->s_blocksize - 1));
+						udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
+					}
+					memset(&eloc, 0x00, sizeof(kernel_lb_addr));
+					elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
+					udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
+				}
+			}
 		}
 	}
 	UDF_I_LENEXTENTS(inode) = inode->i_size;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index b01804b..b823814 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -248,7 +248,7 @@
 
 		if (likely(cur_index != index)) {
 			page = ufs_get_locked_page(mapping, index);
-			if (IS_ERR(page))
+			if (!page || IS_ERR(page)) /* it was truncated or EIO */
 				continue;
 		} else
 			page = locked_page;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index e7c8615..30c6e8a9 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -169,18 +169,20 @@
 
 static struct buffer_head *
 ufs_clear_frags(struct inode *inode, sector_t beg,
-		unsigned int n)
+		unsigned int n, sector_t want)
 {
-	struct buffer_head *res, *bh;
+	struct buffer_head *res = NULL, *bh;
 	sector_t end = beg + n;
 
-	res = sb_getblk(inode->i_sb, beg);
-	ufs_clear_frag(inode, res);
-	for (++beg; beg < end; ++beg) {
+	for (; beg < end; ++beg) {
 		bh = sb_getblk(inode->i_sb, beg);
 		ufs_clear_frag(inode, bh);
-		brelse(bh);
+		if (want != beg)
+			brelse(bh);
+		else
+			res = bh;
 	}
+	BUG_ON(!res);
 	return res;
 }
 
@@ -265,7 +267,9 @@
 			lastfrag = ufsi->i_lastfrag;
 			
 		}
-		goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb;
+		tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]);
+		if (tmp)
+			goal = tmp + uspi->s_fpb;
 		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
 					 goal, required + blockoff,
 					 err, locked_page);
@@ -277,13 +281,15 @@
 		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
 					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
 					err, locked_page);
-	}
+	} else /* (lastblock > block) */ {
 	/*
 	 * We will allocate new block before last allocated block
 	 */
-	else /* (lastblock > block) */ {
-		if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1])))
-			goal = tmp + uspi->s_fpb;
+		if (block) {
+			tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]);
+			if (tmp)
+				goal = tmp + uspi->s_fpb;
+		}
 		tmp = ufs_new_fragments(inode, p, fragment - blockoff,
 					goal, uspi->s_fpb, err, locked_page);
 	}
@@ -296,7 +302,7 @@
 	}
 
 	if (!phys) {
-		result = ufs_clear_frags(inode, tmp + blockoff, required);
+		result = ufs_clear_frags(inode, tmp, required, tmp + blockoff);
 	} else {
 		*phys = tmp + blockoff;
 		result = NULL;
@@ -383,7 +389,7 @@
 		}
 	}
 
-	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb))
+	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1])))
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
@@ -397,7 +403,8 @@
 
 
 	if (!phys) {
-		result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb);
+		result = ufs_clear_frags(inode, tmp, uspi->s_fpb,
+					 tmp + blockoff);
 	} else {
 		*phys = tmp + blockoff;
 		*new = 1;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index abd5f23..d344b41 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -129,7 +129,7 @@
 	struct inode * inode;
 
 	if (l > sb->s_blocksize)
-		goto out;
+		goto out_notlocked;
 
 	lock_kernel();
 	inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
@@ -155,6 +155,7 @@
 	err = ufs_add_nondir(dentry, inode);
 out:
 	unlock_kernel();
+out_notlocked:
 	return err;
 
 out_fail:
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index c9b5587..ea11d04 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -375,17 +375,15 @@
 	int err = 0;
 	struct address_space *mapping = inode->i_mapping;
 	struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi;
-	struct ufs_inode_info *ufsi = UFS_I(inode);
 	unsigned lastfrag, i, end;
 	struct page *lastpage;
 	struct buffer_head *bh;
 
 	lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift;
 
-	if (!lastfrag) {
-		ufsi->i_lastfrag = 0;
+	if (!lastfrag)
 		goto out;
-	}
+
 	lastfrag--;
 
 	lastpage = ufs_get_locked_page(mapping, lastfrag >>
@@ -400,25 +398,25 @@
        for (i = 0; i < end; ++i)
                bh = bh->b_this_page;
 
-       if (!buffer_mapped(bh)) {
-               err = ufs_getfrag_block(inode, lastfrag, bh, 1);
 
-               if (unlikely(err))
-                       goto out_unlock;
+       err = ufs_getfrag_block(inode, lastfrag, bh, 1);
 
-               if (buffer_new(bh)) {
-                       clear_buffer_new(bh);
-                       unmap_underlying_metadata(bh->b_bdev,
-						 bh->b_blocknr);
-		       /*
-			* we do not zeroize fragment, because of
-			* if it maped to hole, it already contains zeroes
-			*/
-                       set_buffer_uptodate(bh);
-                       mark_buffer_dirty(bh);
-                       set_page_dirty(lastpage);
-               }
+       if (unlikely(err))
+	       goto out_unlock;
+
+       if (buffer_new(bh)) {
+	       clear_buffer_new(bh);
+	       unmap_underlying_metadata(bh->b_bdev,
+					 bh->b_blocknr);
+	       /*
+		* we do not zeroize fragment, because of
+		* if it maped to hole, it already contains zeroes
+		*/
+	       set_buffer_uptodate(bh);
+	       mark_buffer_dirty(bh);
+	       set_page_dirty(lastpage);
        }
+
 out_unlock:
        ufs_put_locked_page(lastpage);
 out:
@@ -440,23 +438,11 @@
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 		return -EPERM;
 
-	if (inode->i_size > old_i_size) {
-		/*
-		 * if we expand file we should care about
-		 * allocation of block for last byte first of all
-		 */
-		err = ufs_alloc_lastblock(inode);
+	err = ufs_alloc_lastblock(inode);
 
-		if (err) {
-			i_size_write(inode, old_i_size);
-			goto out;
-		}
-		/*
-		 * go away, because of we expand file, and we do not
-		 * need free blocks, and zeroizes page
-		 */
-		lock_kernel();
-		goto almost_end;
+	if (err) {
+		i_size_write(inode, old_i_size);
+		goto out;
 	}
 
 	block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
@@ -477,21 +463,8 @@
 		yield();
 	}
 
-	if (inode->i_size < old_i_size) {
-		/*
-		 * now we should have enough space
-		 * to allocate block for last byte
-		 */
-		err = ufs_alloc_lastblock(inode);
-		if (err)
-			/*
-			 * looks like all the same - we have no space,
-			 * but we truncate file already
-			 */
-			inode->i_size = (ufsi->i_lastfrag - 1) * uspi->s_fsize;
-	}
-almost_end:
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+	ufsi->i_lastfrag = DIRECT_FRAGMENT;
 	unlock_kernel();
 	mark_inode_dirty(inode);
 out:
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 337cf2c..22f820a 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -251,12 +251,12 @@
 {
 	struct page *page;
 
-try_again:
 	page = find_lock_page(mapping, index);
 	if (!page) {
 		page = read_cache_page(mapping, index,
 				       (filler_t*)mapping->a_ops->readpage,
 				       NULL);
+
 		if (IS_ERR(page)) {
 			printk(KERN_ERR "ufs_change_blocknr: "
 			       "read_cache_page error: ino %lu, index: %lu\n",
@@ -266,6 +266,14 @@
 
 		lock_page(page);
 
+		if (unlikely(page->mapping == NULL)) {
+			/* Truncate got there first */
+			unlock_page(page);
+			page_cache_release(page);
+			page = NULL;
+			goto out;
+		}
+
 		if (!PageUptodate(page) || PageError(page)) {
 			unlock_page(page);
 			page_cache_release(page);
@@ -275,15 +283,8 @@
 			       mapping->host->i_ino, index);
 
 			page = ERR_PTR(-EIO);
-			goto out;
 		}
 	}
-
-	if (unlikely(!page->mapping || !page_has_buffers(page))) {
-		unlock_page(page);
-		page_cache_release(page);
-		goto try_again;/*we really need these buffers*/
-	}
 out:
 	return page;
 }
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index ceda3a2..7858703 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -246,8 +246,8 @@
 #define BUF_BUSY		XBF_DONT_BLOCK
 
 #define XFS_BUF_BFLAGS(bp)	((bp)->b_flags)
-#define XFS_BUF_ZEROFLAGS(bp)	\
-	((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI))
+#define XFS_BUF_ZEROFLAGS(bp)	((bp)->b_flags &= \
+		~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI|XBF_ORDERED))
 
 #define XFS_BUF_STALE(bp)	((bp)->b_flags |= XFS_B_STALE)
 #define XFS_BUF_UNSTALE(bp)	((bp)->b_flags &= ~XFS_B_STALE)
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 9bdef9d..4754f34 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -314,6 +314,13 @@
 		return;
 	}
 
+	if (xfs_readonly_buftarg(mp->m_ddev_targp)) {
+		xfs_fs_cmn_err(CE_NOTE, mp,
+		  "Disabling barriers, underlying device is readonly");
+		mp->m_flags &= ~XFS_MOUNT_BARRIER;
+		return;
+	}
+
 	error = xfs_barrier_test(mp);
 	if (error) {
 		xfs_fs_cmn_err(CE_NOTE, mp,
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index e95e99f..f137856 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -217,17 +217,24 @@
 		return 0;
 	dp = &dqp->q_core;
 
-	limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit;
+	limit = dp->d_blk_softlimit ?
+		be64_to_cpu(dp->d_blk_softlimit) :
+		be64_to_cpu(dp->d_blk_hardlimit);
 	if (limit && statp->f_blocks > limit) {
 		statp->f_blocks = limit;
-		statp->f_bfree = (statp->f_blocks > dp->d_bcount) ?
-					(statp->f_blocks - dp->d_bcount) : 0;
+		statp->f_bfree =
+			(statp->f_blocks > be64_to_cpu(dp->d_bcount)) ?
+			 (statp->f_blocks - be64_to_cpu(dp->d_bcount)) : 0;
 	}
-	limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit;
+
+	limit = dp->d_ino_softlimit ?
+		be64_to_cpu(dp->d_ino_softlimit) :
+		be64_to_cpu(dp->d_ino_hardlimit);
 	if (limit && statp->f_files > limit) {
 		statp->f_files = limit;
-		statp->f_ffree = (statp->f_files > dp->d_icount) ?
-					(statp->f_ffree - dp->d_icount) : 0;
+		statp->f_ffree =
+			(statp->f_files > be64_to_cpu(dp->d_icount)) ?
+			 (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
 	}
 
 	xfs_qm_dqput(dqp);
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index eef6763..d2bbcd8 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -1835,40 +1835,47 @@
 				&agbp)))
 			return error;
 		if (!pag->pagf_init) {
+			ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
+			ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
 			args->agbp = NULL;
 			return 0;
 		}
 	} else
 		agbp = NULL;
 
-	/* If this is a metadata preferred pag and we are user data
+	/*
+	 * If this is a metadata preferred pag and we are user data
 	 * then try somewhere else if we are not being asked to
 	 * try harder at this point
 	 */
-	if (pag->pagf_metadata && args->userdata && flags) {
+	if (pag->pagf_metadata && args->userdata &&
+	    (flags & XFS_ALLOC_FLAG_TRYLOCK)) {
+		ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
 		args->agbp = NULL;
 		return 0;
 	}
 
-	need = XFS_MIN_FREELIST_PAG(pag, mp);
-	delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
-	/*
-	 * If it looks like there isn't a long enough extent, or enough
-	 * total blocks, reject it.
-	 */
-	longest = (pag->pagf_longest > delta) ?
-		(pag->pagf_longest - delta) :
-		(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
-	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-	    (!(flags & XFS_ALLOC_FLAG_FREEING) &&
-	     (int)(pag->pagf_freeblks + pag->pagf_flcount -
-		   need - args->total) <
-	     (int)args->minleft)) {
-		if (agbp)
-			xfs_trans_brelse(tp, agbp);
-		args->agbp = NULL;
-		return 0;
+	if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+		need = XFS_MIN_FREELIST_PAG(pag, mp);
+		delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
+		/*
+		 * If it looks like there isn't a long enough extent, or enough
+		 * total blocks, reject it.
+		 */
+		longest = (pag->pagf_longest > delta) ?
+			(pag->pagf_longest - delta) :
+			(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
+		if ((args->minlen + args->alignment + args->minalignslop - 1) >
+				longest ||
+		    ((int)(pag->pagf_freeblks + pag->pagf_flcount -
+			   need - args->total) < (int)args->minleft)) {
+			if (agbp)
+				xfs_trans_brelse(tp, agbp);
+			args->agbp = NULL;
+			return 0;
+		}
 	}
+
 	/*
 	 * Get the a.g. freespace buffer.
 	 * Can fail if we're not blocking on locks, and it's held.
@@ -1878,6 +1885,8 @@
 				&agbp)))
 			return error;
 		if (agbp == NULL) {
+			ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
+			ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
 			args->agbp = NULL;
 			return 0;
 		}
@@ -1887,22 +1896,24 @@
 	 */
 	agf = XFS_BUF_TO_AGF(agbp);
 	need = XFS_MIN_FREELIST(agf, mp);
-	delta = need > be32_to_cpu(agf->agf_flcount) ?
-		(need - be32_to_cpu(agf->agf_flcount)) : 0;
 	/*
 	 * If there isn't enough total or single-extent, reject it.
 	 */
-	longest = be32_to_cpu(agf->agf_longest);
-	longest = (longest > delta) ? (longest - delta) :
-		(be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
-	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-	     (!(flags & XFS_ALLOC_FLAG_FREEING) &&
-		(int)(be32_to_cpu(agf->agf_freeblks) +
-		   be32_to_cpu(agf->agf_flcount) - need - args->total) <
-	     (int)args->minleft)) {
-		xfs_trans_brelse(tp, agbp);
-		args->agbp = NULL;
-		return 0;
+	if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+		delta = need > be32_to_cpu(agf->agf_flcount) ?
+			(need - be32_to_cpu(agf->agf_flcount)) : 0;
+		longest = be32_to_cpu(agf->agf_longest);
+		longest = (longest > delta) ? (longest - delta) :
+			(be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
+		if ((args->minlen + args->alignment + args->minalignslop - 1) >
+				longest ||
+		    ((int)(be32_to_cpu(agf->agf_freeblks) +
+		     be32_to_cpu(agf->agf_flcount) - need - args->total) <
+				(int)args->minleft)) {
+			xfs_trans_brelse(tp, agbp);
+			args->agbp = NULL;
+			return 0;
+		}
 	}
 	/*
 	 * Make the freelist shorter if it's too long.
@@ -1950,12 +1961,11 @@
 		 * on a completely full ag.
 		 */
 		if (targs.agbno == NULLAGBLOCK) {
-			if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
-				xfs_trans_brelse(tp, agflbp);
-				args->agbp = NULL;
-				return 0;
-			}
-			break;
+			if (flags & XFS_ALLOC_FLAG_FREEING)
+				break;
+			xfs_trans_brelse(tp, agflbp);
+			args->agbp = NULL;
+			return 0;
 		}
 		/*
 		 * Put each allocated block on the list.
@@ -2442,31 +2452,26 @@
 	xfs_fsblock_t	bno,	/* starting block number of extent */
 	xfs_extlen_t	len)	/* length of extent */
 {
-#ifdef DEBUG
-	xfs_agf_t	*agf;	/* a.g. freespace header */
-#endif
-	xfs_alloc_arg_t	args;	/* allocation argument structure */
+	xfs_alloc_arg_t	args;
 	int		error;
 
 	ASSERT(len != 0);
+	memset(&args, 0, sizeof(xfs_alloc_arg_t));
 	args.tp = tp;
 	args.mp = tp->t_mountp;
 	args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
 	ASSERT(args.agno < args.mp->m_sb.sb_agcount);
 	args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
-	args.alignment = 1;
-	args.minlen = args.minleft = args.minalignslop = 0;
 	down_read(&args.mp->m_peraglock);
 	args.pag = &args.mp->m_perag[args.agno];
 	if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
 		goto error0;
 #ifdef DEBUG
 	ASSERT(args.agbp != NULL);
-	agf = XFS_BUF_TO_AGF(args.agbp);
-	ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length));
+	ASSERT((args.agbno + len) <=
+		be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length));
 #endif
-	error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno,
-		len, 0);
+	error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
 error0:
 	up_read(&args.mp->m_peraglock);
 	return error;
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 3a61375..bf46fae 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4993,7 +4993,7 @@
 				bma.firstblock = *firstblock;
 				bma.alen = alen;
 				bma.off = aoff;
-				bma.conv = (flags & XFS_BMAPI_CONVERT);
+				bma.conv = !!(flags & XFS_BMAPI_CONVERT);
 				bma.wasdel = wasdelay;
 				bma.minlen = minlen;
 				bma.low = flist->xbf_low;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 86c1bf0..1f8ecff 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -334,10 +334,9 @@
 #if !defined(__KERNEL__)
 	ni = 0;
 #elif defined(DEBUG)
-	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
-		(BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
+	ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog;
 #else	/* usual case */
-	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
+	ni = 1;
 #endif
 
 	for (i = 0; i < ni; i++) {
@@ -348,11 +347,15 @@
 					(i << mp->m_sb.sb_inodelog));
 		di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
 			    XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
-		if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
-				 XFS_RANDOM_ITOBP_INOTOBP))) {
+		if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
+						XFS_ERRTAG_ITOBP_INOTOBP,
+						XFS_RANDOM_ITOBP_INOTOBP))) {
+			if (imap_flags & XFS_IMAP_BULKSTAT) {
+				xfs_trans_brelse(tp, bp);
+				return XFS_ERROR(EINVAL);
+			}
 #ifdef DEBUG
-			if (!(imap_flags & XFS_IMAP_BULKSTAT))
-				cmn_err(CE_ALERT,
+			cmn_err(CE_ALERT,
 					"Device %s - bad inode magic/vsn "
 					"daddr %lld #%d (magic=%x)",
 				XFS_BUFTARG_NAME(mp->m_ddev_targp),
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index e730328..21ac1a6 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1413,7 +1413,7 @@
 	ops = iclog->ic_header.h_num_logops;
 	INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops);
 
-	bp	    = iclog->ic_bp;
+	bp = iclog->ic_bp;
 	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
 	XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 	XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT)));
@@ -1430,15 +1430,14 @@
 	}
 	XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
 	XFS_BUF_SET_FSPRIVATE(bp, iclog);	/* save for later */
+	XFS_BUF_ZEROFLAGS(bp);
 	XFS_BUF_BUSY(bp);
 	XFS_BUF_ASYNC(bp);
 	/*
 	 * Do an ordered write for the log block.
-	 *
-	 * It may not be needed to flush the first split block in the log wrap
-	 * case, but do it anyways to be safe -AK
+	 * Its unnecessary to flush the first split block in the log wrap case.
 	 */
-	if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
+	if (!split && (log->l_mp->m_flags & XFS_MOUNT_BARRIER))
 		XFS_BUF_ORDERED(bp);
 
 	ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
@@ -1460,7 +1459,7 @@
 		return error;
 	}
 	if (split) {
-		bp		= iclog->ic_log->l_xbuf;
+		bp = iclog->ic_log->l_xbuf;
 		ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) ==
 							(unsigned long)1);
 		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
@@ -1468,6 +1467,7 @@
 		XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
 					    (__psint_t)count), split);
 		XFS_BUF_SET_FSPRIVATE(bp, iclog);
+		XFS_BUF_ZEROFLAGS(bp);
 		XFS_BUF_BUSY(bp);
 		XFS_BUF_ASYNC(bp);
 		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 6c96391..b427d22 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -515,7 +515,7 @@
 	if (error)
 		goto error2;
 
-	if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY))
+	if (mp->m_flags & XFS_MOUNT_BARRIER)
 		xfs_mountfs_check_barriers(mp);
 
 	error = XFS_IOINIT(vfsp, args, flags);
diff --git a/include/asm-arm/arch-iop3xx/iop331-irqs.h b/include/asm-arm/arch-iop3xx/iop331-irqs.h
index 8ff73d4..7135ad7 100644
--- a/include/asm-arm/arch-iop3xx/iop331-irqs.h
+++ b/include/asm-arm/arch-iop3xx/iop331-irqs.h
@@ -91,7 +91,6 @@
 #define NR_IRQS			NR_IOP331_IRQS
 
 
-#if defined(CONFIG_ARCH_IQ80331)
 /*
  * Interrupts available on the IQ80331 board
  */
@@ -111,7 +110,6 @@
 #define	IRQ_IQ80331_INTC	IRQ_IOP331_XINT2
 #define	IRQ_IQ80331_INTD	IRQ_IOP331_XINT3
 
-#elif defined(CONFIG_MACH_IQ80332)
 /*
  * Interrupts available on the IQ80332 board
  */
@@ -131,6 +129,4 @@
 #define	IRQ_IQ80332_INTC	IRQ_IOP331_XINT2
 #define	IRQ_IQ80332_INTD	IRQ_IOP331_XINT3
 
-#endif
-
 #endif // _IOP331_IRQ_H_
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index 3c4eb9f..f83003f 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -48,8 +48,6 @@
 };
 
 extern unsigned int mpurate;
-extern struct list_head clocks;
-extern spinlock_t clockfw_lock;
 
 extern int clk_init(struct clk_functions * custom_clocks);
 extern int clk_register(struct clk *clk);
diff --git a/include/asm-arm/arch-pxa/ssp.h b/include/asm-arm/arch-pxa/ssp.h
index 949878c..ea20055 100644
--- a/include/asm-arm/arch-pxa/ssp.h
+++ b/include/asm-arm/arch-pxa/ssp.h
@@ -40,8 +40,8 @@
 };
 
 int ssp_write_word(struct ssp_dev *dev, u32 data);
-int ssp_read_word(struct ssp_dev *dev);
-void ssp_flush(struct ssp_dev *dev);
+int ssp_read_word(struct ssp_dev *dev, u32 *data);
+int ssp_flush(struct ssp_dev *dev);
 void ssp_enable(struct ssp_dev *dev);
 void ssp_disable(struct ssp_dev *dev);
 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
index 5675b17..40e8e27 100644
--- a/include/asm-arm/arch-s3c2410/anubis-cpld.h
+++ b/include/asm-arm/arch-s3c2410/anubis-cpld.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *
 */
 
 #ifndef __ASM_ARCH_ANUBISCPLD_H
diff --git a/include/asm-arm/arch-s3c2410/anubis-irq.h b/include/asm-arm/arch-s3c2410/anubis-irq.h
index 82f15db..4b5f423 100644
--- a/include/asm-arm/arch-s3c2410/anubis-irq.h
+++ b/include/asm-arm/arch-s3c2410/anubis-irq.h
@@ -9,9 +9,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- */
+*/
 
 #ifndef __ASM_ARCH_ANUBISIRQ_H
 #define __ASM_ARCH_ANUBISIRQ_H
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
index d529ffd..058a210 100644
--- a/include/asm-arm/arch-s3c2410/anubis-map.h
+++ b/include/asm-arm/arch-s3c2410/anubis-map.h
@@ -9,8 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
 */
 
 /* needs arch/map.h including with this */
diff --git a/include/asm-arm/arch-s3c2410/audio.h b/include/asm-arm/arch-s3c2410/audio.h
index 0d276e6..7e02222 100644
--- a/include/asm-arm/arch-s3c2410/audio.h
+++ b/include/asm-arm/arch-s3c2410/audio.h
@@ -9,10 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *	20-Nov-2004 BJD  Created file
- *	07-Mar-2005 BJD  Added suspend/resume calls
 */
 
 #ifndef __ASM_ARCH_AUDIO_H
diff --git a/include/asm-arm/arch-s3c2410/bast-cpld.h b/include/asm-arm/arch-s3c2410/bast-cpld.h
index e28ca51..8969cff 100644
--- a/include/asm-arm/arch-s3c2410/bast-cpld.h
+++ b/include/asm-arm/arch-s3c2410/bast-cpld.h
@@ -8,11 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  25-May-2003 BJD  Created file, added CTRL1 registers
- *  30-Aug-2004 BJD  Updated definitions from 2.4.26 port
- *  30-Aug-2004 BJD  Added CTRL3 and CTRL4 definitions
 */
 
 #ifndef __ASM_ARCH_BASTCPLD_H
diff --git a/include/asm-arm/arch-s3c2410/bast-irq.h b/include/asm-arm/arch-s3c2410/bast-irq.h
index b79b47f..15ffa66 100644
--- a/include/asm-arm/arch-s3c2410/bast-irq.h
+++ b/include/asm-arm/arch-s3c2410/bast-irq.h
@@ -8,11 +8,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  14-Sep-2004 BJD  Fixed IRQ_USBOC definition
- *  06-Jan-2003 BJD  Linux 2.6.0 version
- */
+*/
 
 #ifndef __ASM_ARCH_BASTIRQ_H
 #define __ASM_ARCH_BASTIRQ_H
diff --git a/include/asm-arm/arch-s3c2410/bast-map.h b/include/asm-arm/arch-s3c2410/bast-map.h
index 29c07e3..727cef8 100644
--- a/include/asm-arm/arch-s3c2410/bast-map.h
+++ b/include/asm-arm/arch-s3c2410/bast-map.h
@@ -8,10 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  06-Jan-2003 BJD  Linux 2.6.0 version, moved bast specifics from arch/map.h
- *  12-Mar-2004 BJD  Fixed header include protection
 */
 
 /* needs arch/map.h including with this */
diff --git a/include/asm-arm/arch-s3c2410/bast-pmu.h b/include/asm-arm/arch-s3c2410/bast-pmu.h
index 758c5c5..8283602 100644
--- a/include/asm-arm/arch-s3c2410/bast-pmu.h
+++ b/include/asm-arm/arch-s3c2410/bast-pmu.h
@@ -9,9 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *	08-Oct-2003	BJD	Initial creation
 */
 
 #ifndef __ASM_ARCH_BASTPMU_H
diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
index b7d15d1..9306486 100644
--- a/include/asm-arm/arch-s3c2410/debug-macro.S
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -10,9 +10,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <asm/arch/map.h>
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index 72964f9..3661e46 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -1,18 +1,13 @@
-/* linux/include/asm-arm/arch-bast/dma.h
+/* linux/include/asm-arm/arch-s3c2410/dma.h
  *
- * Copyright (C) 2003,2004 Simtec Electronics
+ * Copyright (C) 2003,2004,2006 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * Samsung S3C2410X DMA support
+ * Samsung S3C241XX DMA support
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  ??-May-2003 BJD   Created file
- *  ??-Jun-2003 BJD   Added more dma functionality to go with arch
- *  10-Nov-2004 BJD   Added sys_device support
 */
 
 #ifndef __ASM_ARCH_DMA_H
@@ -21,28 +16,26 @@
 #include <linux/sysdev.h>
 #include "hardware.h"
 
-
 /*
  * This is the maximum DMA address(physical address) that can be DMAd to.
  *
  */
-#define MAX_DMA_ADDRESS		0x20000000
+#define MAX_DMA_ADDRESS		0x40000000
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
-
 /* we have 4 dma channels */
 #define S3C2410_DMA_CHANNELS        (4)
 
 /* types */
 
-typedef enum {
+enum s3c2410_dma_state {
 	S3C2410_DMA_IDLE,
 	S3C2410_DMA_RUNNING,
 	S3C2410_DMA_PAUSED
-} s3c2410_dma_state_t;
+};
 
 
-/* s3c2410_dma_loadst_t
+/* enum s3c2410_dma_loadst
  *
  * This represents the state of the DMA engine, wrt to the loaded / running
  * transfers. Since we don't have any way of knowing exactly the state of
@@ -70,44 +63,40 @@
  * currently running.
 */
 
-typedef enum {
+enum s3c2410_dma_loadst {
 	S3C2410_DMALOAD_NONE,
 	S3C2410_DMALOAD_1LOADED,
 	S3C2410_DMALOAD_1RUNNING,
 	S3C2410_DMALOAD_1LOADED_1RUNNING,
-} s3c2410_dma_loadst_t;
+};
 
-typedef enum {
+enum s3c2410_dma_buffresult {
 	S3C2410_RES_OK,
 	S3C2410_RES_ERR,
 	S3C2410_RES_ABORT
-} s3c2410_dma_buffresult_t;
-
-
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
-
-enum s3c2410_dmasrc_e {
-	S3C2410_DMASRC_HW,      /* source is memory */
-	S3C2410_DMASRC_MEM      /* source is hardware */
 };
 
-/* enum s3c2410_chan_op_e
+enum s3c2410_dmasrc {
+	S3C2410_DMASRC_HW,		/* source is memory */
+	S3C2410_DMASRC_MEM		/* source is hardware */
+};
+
+/* enum s3c2410_chan_op
  *
  * operation codes passed to the DMA code by the user, and also used
  * to inform the current channel owner of any changes to the system state
 */
 
-enum s3c2410_chan_op_e {
+enum s3c2410_chan_op {
 	S3C2410_DMAOP_START,
 	S3C2410_DMAOP_STOP,
 	S3C2410_DMAOP_PAUSE,
 	S3C2410_DMAOP_RESUME,
 	S3C2410_DMAOP_FLUSH,
-	S3C2410_DMAOP_TIMEOUT,           /* internal signal to handler */
+	S3C2410_DMAOP_TIMEOUT,		/* internal signal to handler */
+	S3C2410_DMAOP_STARTED,		/* indicate channel started */
 };
 
-typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
-
 /* flags */
 
 #define S3C2410_DMAF_SLOW         (1<<0)   /* slow, so don't worry about
@@ -116,104 +105,100 @@
 
 /* dma buffer */
 
-typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
-
 struct s3c2410_dma_client {
 	char                *name;
 };
 
-typedef struct s3c2410_dma_client s3c2410_dma_client_t;
-
 /* s3c2410_dma_buf_s
  *
  * internally used buffer structure to describe a queued or running
  * buffer.
 */
 
-struct s3c2410_dma_buf_s {
-	s3c2410_dma_buf_t   *next;
-	int                  magic;        /* magic */
-	int                  size;         /* buffer size in bytes */
-	dma_addr_t           data;         /* start of DMA data */
-	dma_addr_t           ptr;          /* where the DMA got to [1] */
-	void                *id;           /* client's id */
+struct s3c2410_dma_buf;
+struct s3c2410_dma_buf {
+	struct s3c2410_dma_buf	*next;
+	int			 magic;		/* magic */
+	int			 size;		/* buffer size in bytes */
+	dma_addr_t		 data;		/* start of DMA data */
+	dma_addr_t		 ptr;		/* where the DMA got to [1] */
+	void			*id;		/* client's id */
 };
 
 /* [1] is this updated for both recv/send modes? */
 
-typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
+struct s3c2410_dma_chan;
 
 /* s3c2410_dma_cbfn_t
  *
  * buffer callback routine type
 */
 
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
-				   s3c2410_dma_buffresult_t result);
+typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
+				   void *buf, int size,
+				   enum s3c2410_dma_buffresult result);
 
-typedef int  (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
-				   s3c2410_chan_op_t );
+typedef int  (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
+				   enum s3c2410_chan_op );
 
-struct s3c2410_dma_stats_s {
-	unsigned long          loads;
-	unsigned long          timeout_longest;
-	unsigned long          timeout_shortest;
-	unsigned long          timeout_avg;
-	unsigned long          timeout_failed;
+struct s3c2410_dma_stats {
+	unsigned long		loads;
+	unsigned long		timeout_longest;
+	unsigned long		timeout_shortest;
+	unsigned long		timeout_avg;
+	unsigned long		timeout_failed;
 };
 
-typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
-
-/* struct s3c2410_dma_chan_s
+/* struct s3c2410_dma_chan
  *
  * full state information for each DMA channel
 */
 
-struct s3c2410_dma_chan_s {
+struct s3c2410_dma_chan {
 	/* channel state flags and information */
-	unsigned char          number;      /* number of this dma channel */
-	unsigned char          in_use;      /* channel allocated */
-	unsigned char          irq_claimed; /* irq claimed for channel */
-	unsigned char          irq_enabled; /* irq enabled for channel */
-	unsigned char          xfer_unit;   /* size of an transfer */
+	unsigned char		 number;      /* number of this dma channel */
+	unsigned char		 in_use;      /* channel allocated */
+	unsigned char		 irq_claimed; /* irq claimed for channel */
+	unsigned char		 irq_enabled; /* irq enabled for channel */
+	unsigned char		 xfer_unit;   /* size of an transfer */
 
 	/* channel state */
 
-	s3c2410_dma_state_t    state;
-	s3c2410_dma_loadst_t   load_state;
-	s3c2410_dma_client_t  *client;
+	enum s3c2410_dma_state	 state;
+	enum s3c2410_dma_loadst	 load_state;
+	struct s3c2410_dma_client *client;
 
 	/* channel configuration */
-	s3c2410_dmasrc_t       source;
-	unsigned long          dev_addr;
-	unsigned long          load_timeout;
-	unsigned int           flags;        /* channel flags */
+	enum s3c2410_dmasrc	 source;
+	unsigned long		 dev_addr;
+	unsigned long		 load_timeout;
+	unsigned int		 flags;		/* channel flags */
 
 	/* channel's hardware position and configuration */
-	void __iomem           *regs;        /* channels registers */
-	void __iomem           *addr_reg;    /* data address register */
-	unsigned int           irq;          /* channel irq */
-	unsigned long          dcon;         /* default value of DCON */
+	void __iomem		*regs;		/* channels registers */
+	void __iomem		*addr_reg;	/* data address register */
+	unsigned int		 irq;		/* channel irq */
+	unsigned long		 dcon;		/* default value of DCON */
 
 	/* driver handles */
-	s3c2410_dma_cbfn_t     callback_fn;  /* buffer done callback */
-	s3c2410_dma_opfn_t     op_fn;        /* channel operation callback */
+	s3c2410_dma_cbfn_t	 callback_fn;	/* buffer done callback */
+	s3c2410_dma_opfn_t	 op_fn;		/* channel op callback */
 
 	/* stats gathering */
-	s3c2410_dma_stats_t   *stats;
-	s3c2410_dma_stats_t    stats_store;
+	struct s3c2410_dma_stats *stats;
+	struct s3c2410_dma_stats  stats_store;
 
 	/* buffer list and information */
-	s3c2410_dma_buf_t      *curr;        /* current dma buffer */
-	s3c2410_dma_buf_t      *next;        /* next buffer to load */
-	s3c2410_dma_buf_t      *end;         /* end of queue */
+	struct s3c2410_dma_buf	*curr;		/* current dma buffer */
+	struct s3c2410_dma_buf	*next;		/* next buffer to load */
+	struct s3c2410_dma_buf	*end;		/* end of queue */
 
 	/* system device */
 	struct sys_device	dev;
 };
 
 /* the currently allocated channel information */
-extern s3c2410_dma_chan_t s3c2410_chans[];
+extern struct s3c2410_dma_chan s3c2410_chans[];
 
 /* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
@@ -226,7 +211,7 @@
 */
 
 extern int s3c2410_dma_request(dmach_t channel,
-			       s3c2410_dma_client_t *, void *dev);
+			       struct s3c2410_dma_client *, void *dev);
 
 
 /* s3c2410_dma_ctrl
@@ -234,7 +219,7 @@
  * change the state of the dma channel
 */
 
-extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
+extern int s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op);
 
 /* s3c2410_dma_setflags
  *
@@ -249,7 +234,7 @@
  * free the dma channel (will also abort any outstanding operations)
 */
 
-extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
+extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *);
 
 /* s3c2410_dma_enqueue
  *
@@ -273,7 +258,7 @@
  * configure the device we're talking to
 */
 
-extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
+extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
 				 int hwcfg, unsigned long devaddr);
 
 /* s3c2410_dma_getposition
diff --git a/include/asm-arm/arch-s3c2410/fb.h b/include/asm-arm/arch-s3c2410/fb.h
index 4790491..7116179 100644
--- a/include/asm-arm/arch-s3c2410/fb.h
+++ b/include/asm-arm/arch-s3c2410/fb.h
@@ -7,13 +7,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- *
- *  Changelog:
- *	07-Sep-2004	RTP	Created file
- *	03-Nov-2004	BJD	Updated and minor cleanups
- *	03-Aug-2005     RTP     Renamed to fb.h
- *	26-Oct-2005	BJD	Changed name of platdata init
 */
 
 #ifndef __ASM_ARM_FB_H
diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
index a2330bf..871f8af 100644
--- a/include/asm-arm/arch-s3c2410/hardware.h
+++ b/include/asm-arm/arch-s3c2410/hardware.h
@@ -8,16 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  21-May-2003 BJD  Created file
- *  06-Jun-2003 BJD  Added CPU frequency settings
- *  03-Sep-2003 BJD  Linux v2.6 support
- *  12-Mar-2004 BJD  Fixed include protection, fixed type of clock vars
- *  14-Sep-2004 BJD  Added misccr and getpin to gpio
- *  01-Oct-2004 BJD  Added the new gpio functions
- *  16-Oct-2004 BJD  Removed the clock variables
- *  15-Jan-2006 LCVR Added s3c2400_gpio_getirq()
 */
 
 #ifndef __ASM_ARCH_HARDWARE_H
diff --git a/include/asm-arm/arch-s3c2410/idle.h b/include/asm-arm/arch-s3c2410/idle.h
index 749227c..eed4506 100644
--- a/include/asm-arm/arch-s3c2410/idle.h
+++ b/include/asm-arm/arch-s3c2410/idle.h
@@ -8,10 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 CPU Idle controls
- *
- *  Changelog:
- *	28-Oct-2004  BJD  Initial version
- *
 */
 
 #ifndef __ASM_ARCH_IDLE_H
diff --git a/include/asm-arm/arch-s3c2410/iic.h b/include/asm-arm/arch-s3c2410/iic.h
index 518547f..ed3d6c7 100644
--- a/include/asm-arm/arch-s3c2410/iic.h
+++ b/include/asm-arm/arch-s3c2410/iic.h
@@ -8,10 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *	05-Oct-2004 BJD  Created file
- *	19-Oct-2004 BJD	 Updated for s3c2440
 */
 
 #ifndef __ASM_ARCH_IIC_H
diff --git a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h
index 16fbc8a..6b35a4f 100644
--- a/include/asm-arm/arch-s3c2410/io.h
+++ b/include/asm-arm/arch-s3c2410/io.h
@@ -4,13 +4,7 @@
  *
  * Copyright (C) 1997 Russell King
  *	     (C) 2003 Simtec Electronics
- *
- * Modifications:
- *  06-Dec-1997	RMK	Created.
- *  02-Sep-2003 BJD	Modified for S3C2410
- *  10-Mar-2005 LCVR	Changed S3C2410_VA to S3C24XX_VA
- *  13-Oct-2005 BJD	Fixed problems with LDRH/STRH offset range
- */
+*/
 
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
diff --git a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
index d9773d6..39a6982 100644
--- a/include/asm-arm/arch-s3c2410/irqs.h
+++ b/include/asm-arm/arch-s3c2410/irqs.h
@@ -6,14 +6,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  12-May-2003 BJD  Created file
- *  08-Jan-2003 BJD  Linux 2.6.0 version, moved BAST bits out
- *  12-Mar-2004 BJD  Fixed bug in header protection
- *  10-Feb-2005 BJD  Added camera IRQ from guillaume.gourat@nexvision.tv
- *  28-Feb-2005 BJD  Updated s3c2440 IRQs
- */
+*/
 
 
 #ifndef __ASM_ARCH_IRQS_H
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index fae2766..27ba0ac 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -8,13 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  12-May-2003 BJD   Created file
- *  06-Jan-2003 BJD   Linux 2.6.0 version, moved bast specifics out
- *  10-Feb-2005 BJD   Added CAMIF definition from guillaume.gourat@nexvision.tv
- *  10-Mar-2005 LCVR  Added support to S3C2400, changed {VA,SZ} names
- *  15-Jan-2006 LCVR  Added S3C24XX_PA macros for common S3C24XX resources
 */
 
 #ifndef __ASM_ARCH_MAP_H
diff --git a/include/asm-arm/arch-s3c2410/memory.h b/include/asm-arm/arch-s3c2410/memory.h
index 6ab834a..4be6a74 100644
--- a/include/asm-arm/arch-s3c2410/memory.h
+++ b/include/asm-arm/arch-s3c2410/memory.h
@@ -1,6 +1,4 @@
-/*
- *  linux/include/asm-arm/arch-s3c2410/memory.h
- *
+/* linux/include/asm-arm/arch-s3c2410/memory.h
  *  from linux/include/asm-arm/arch-rpc/memory.h
  *
  *  Copyright (C) 1996,1997,1998 Russell King.
@@ -8,16 +6,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- *  Changelog:
- *   20-Oct-1996 RMK	Created
- *   31-Dec-1997 RMK	Fixed definitions to reduce warnings
- *   11-Jan-1998 RMK	Uninlined to reduce hits on cache
- *   08-Feb-1998 RMK	Added __virt_to_bus and __bus_to_virt
- *   21-Mar-1999 RMK	Renamed to memory.h
- *		 RMK	Added TASK_SIZE and PAGE_OFFSET
- *   05-Apr-2004 BJD    Copied and altered for arch-s3c2410
- *   17-Mar-2005 LCVR   Modified for S3C2400
 */
 
 #ifndef __ASM_ARCH_MEMORY_H
diff --git a/include/asm-arm/arch-s3c2410/nand.h b/include/asm-arm/arch-s3c2410/nand.h
index 9148ac0..e350ae2 100644
--- a/include/asm-arm/arch-s3c2410/nand.h
+++ b/include/asm-arm/arch-s3c2410/nand.h
@@ -8,9 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *	23-Sep-2004 BJD  Created file
 */
 
 /* struct s3c2410_nand_set
diff --git a/include/asm-arm/arch-s3c2410/osiris-map.h b/include/asm-arm/arch-s3c2410/osiris-map.h
index 7c4b0cd..e2d4062 100644
--- a/include/asm-arm/arch-s3c2410/osiris-map.h
+++ b/include/asm-arm/arch-s3c2410/osiris-map.h
@@ -9,8 +9,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
 */
 
 /* needs arch/map.h including with this */
diff --git a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
index 15bfc2f..c7b90b3 100644
--- a/include/asm-arm/arch-s3c2410/regs-adc.h
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h
@@ -7,9 +7,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 ADC registers
- *
- *  Changelog:
- *    27-09-2004     SAH     Created file
 */
 
 #ifndef __ASM_ARCH_REGS_ADC_H
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index a7c61fe..b2f4690 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -8,18 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 clock register definitions
- *
- *  Changelog:
- *    18-Aug-2004 Ben Dooks         Added 2440 definitions
- *    08-Aug-2004 Herbert Pötzl     Added CLKCON definitions
- *    19-06-2003  Ben Dooks         Created file
- *    12-03-2004  Ben Dooks         Updated include protection
- *    29-Sep-2004 Ben Dooks	    Fixed usage for assembly inclusion
- *    10-Feb-2005 Ben Dooks	    Fixed CAMDIVN address (Guillaume Gourat)
- *    10-Mar-2005 Lucas Villa Real  Changed S3C2410_VA to S3C24XX_VA
- *    27-Aug-2005 Ben Dooks	    Add clock-slow info
- *    20-Oct-2005 Ben Dooks	    Fixed overflow in PLL (Guillaume Gourat)
- *    20-Oct-2005 Ben Dooks	    Add masks for DCLK (Guillaume Gourat)
 */
 
 #ifndef __ASM_ARM_REGS_CLOCK
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 6dd17f0f..93c4943 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -8,21 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 GPIO register definitions
- *
- *  Changelog:
- *    19-06-2003     BJD     Created file
- *    23-06-2003     BJD     Updated GSTATUS registers
- *    12-03-2004     BJD     Updated include protection
- *    20-07-2004     BJD     Added GPIO pin numbers, added Port A definitions
- *    04-10-2004     BJD     Fixed number of bugs, added EXT IRQ filter defs
- *    17-10-2004     BJD     Added GSTATUS1 register definitions
- *    18-11-2004     BJD     Fixed definitions of GPE3, GPE4, GPE5 and GPE6
- *    18-11-2004     BJD     Added S3C2440 AC97 controls
- *    10-Mar-2005    LCVR    Changed S3C2410_VA to S3C24XX_VA
- *    28-Mar-2005    LCVR    Fixed definition of GPB10
- *    26-Oct-2005    BJD     Added generic configuration types
- *    27-Nov-2005    LCVR    Added definitions to S3C2400 registers
- *    15-Jan-2006    LCVR    Written S3C24XX_GPIO_BASE() macro
 */
 
 
diff --git a/include/asm-arm/arch-s3c2410/regs-gpioj.h b/include/asm-arm/arch-s3c2410/regs-gpioj.h
index 18edae5..91cefa2 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpioj.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpioj.h
@@ -8,10 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2440 GPIO J register definitions
- *
- *  Changelog:
- *    11-Aug-2004     BJD     Created file
- *    10-Feb-2005     BJD     Fix GPJ12 definition (Guillaume Gourat)
 */
 
 
diff --git a/include/asm-arm/arch-s3c2410/regs-iic.h b/include/asm-arm/arch-s3c2410/regs-iic.h
index fed3288..2ae2952 100644
--- a/include/asm-arm/arch-s3c2410/regs-iic.h
+++ b/include/asm-arm/arch-s3c2410/regs-iic.h
@@ -8,10 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 I2C Controller
- *
- *  Changelog:
- *	03-Oct-2004  BJD  Initial include for Linux
- *	08-Nov-2004  BJD  Added S3C2440 filter register
 */
 
 #ifndef __ASM_ARCH_REGS_IIC_H
diff --git a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
index 7fdde9b..72cd250 100644
--- a/include/asm-arm/arch-s3c2410/regs-iis.h
+++ b/include/asm-arm/arch-s3c2410/regs-iis.h
@@ -8,17 +8,7 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 IIS register definition
- *
- *  Changelog:
- *    19-06-2003     BJD     Created file
- *    26-06-2003     BJD     Finished off definitions for register addresses
- *    12-03-2004     BJD     Updated include protection
- *    07-03-2005     BJD     Added FIFO size flags and S3C2440 MPLL
- *    05-04-2005     LCVR    Added IISFCON definitions for the S3C2400
- *    18-07-2005     DA      Change IISCON_MPLL to IISMOD_MPLL
- *                           Correct IISMOD_256FS and IISMOD_384FS
- *                           Add IISCON_PSCEN
- */
+*/
 
 #ifndef __ASM_ARCH_REGS_IIS_H
 #define __ASM_ARCH_REGS_IIS_H
diff --git a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
index 572fca5..29fb8ef 100644
--- a/include/asm-arm/arch-s3c2410/regs-irq.h
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h
@@ -6,14 +6,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- *
- *
- *  Changelog:
- *    19-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
- *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
- */
+*/
 
 
 #ifndef ___ASM_ARCH_REGS_IRQ_H
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index b6b1b4e..b306d6e 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -6,14 +6,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- *
- *
- *  Changelog:
- *    12-06-2003     BJD     Created file
- *    26-06-2003     BJD     Updated LCDCON register definitions
- *    12-03-2004     BJD     Updated include protection
- *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
diff --git a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
index a2d7d0c..375dca5 100644
--- a/include/asm-arm/arch-s3c2410/regs-mem.h
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h
@@ -8,12 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 Memory Control register definitions
- *
- *  Changelog:
- *	29-Sep-2004  BJD  Initial include for Linux
- *      10-Mar-2005  LCVR Changed S3C2410_VA to S3C24XX_VA
- *      04-Apr-2005  LCVR Added S3C2400 DRAM/BANKSIZE_MASK definitions
- *
 */
 
 #ifndef __ASM_ARM_MEMREGS_H
diff --git a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
index c1470c6..b824d37 100644
--- a/include/asm-arm/arch-s3c2410/regs-nand.h
+++ b/include/asm-arm/arch-s3c2410/regs-nand.h
@@ -8,10 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 NAND register definitions
- *
- *  Changelog:
- *    18-Aug-2004    BJD     Copied file from 2.4 and updated
- *    01-May-2005    BJD     Added definitions for s3c2440 controller
 */
 
 #ifndef __ASM_ARM_REGS_NAND
diff --git a/include/asm-arm/arch-s3c2410/regs-rtc.h b/include/asm-arm/arch-s3c2410/regs-rtc.h
index 228983f..cd88fd6 100644
--- a/include/asm-arm/arch-s3c2410/regs-rtc.h
+++ b/include/asm-arm/arch-s3c2410/regs-rtc.h
@@ -8,17 +8,12 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 Internal RTC register definition
- *
- *  Changelog:
- *    19-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
- *    15-01-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
 */
 
 #ifndef __ASM_ARCH_REGS_RTC_H
 #define __ASM_ARCH_REGS_RTC_H __FILE__
 
-#define S3C2410_RTCREG(x) ((x) + S3C24XX_VA_RTC)
+#define S3C2410_RTCREG(x) (x)
 
 #define S3C2410_RTCCON	      S3C2410_RTCREG(0x40)
 #define S3C2410_RTCCON_RTCEN  (1<<0)
diff --git a/include/asm-arm/arch-s3c2410/regs-sdi.h b/include/asm-arm/arch-s3c2410/regs-sdi.h
index ca9a26f..06e716e 100644
--- a/include/asm-arm/arch-s3c2410/regs-sdi.h
+++ b/include/asm-arm/arch-s3c2410/regs-sdi.h
@@ -8,11 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 MMC/SDIO register definitions
- *
- *  Changelog:
- *    18-Aug-2004 Ben Dooks      Created initial file
- *    29-Nov-2004 Koen Martens   Added some missing defines, fixed duplicates
- *    29-Nov-2004 Ben Dooks	 Updated Koen's patch
 */
 
 #ifndef __ASM_ARM_REGS_SDI
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 93f651a..19c77da 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -27,10 +27,7 @@
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Modifications:
- *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
- */
+*/
 
 #ifndef __ASM_ARM_REGS_SERIAL_H
 #define __ASM_ARM_REGS_SERIAL_H
diff --git a/include/asm-arm/arch-s3c2410/regs-spi.h b/include/asm-arm/arch-s3c2410/regs-spi.h
index 3382178..3552280 100644
--- a/include/asm-arm/arch-s3c2410/regs-spi.h
+++ b/include/asm-arm/arch-s3c2410/regs-spi.h
@@ -7,13 +7,7 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 SPI register definition
- *
- *  Changelog:
- *    20-04-2004     KF      Created file
- *    04-10-2004     BJD     Removed VA address (no longer mapped)
- *			     tidied file for submission
- *    03-04-2005     LCVR    Added S3C2400_SPPIN_nCS definition
- */
+*/
 
 #ifndef __ASM_ARCH_REGS_SPI_H
 #define __ASM_ARCH_REGS_SPI_H
diff --git a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
index 169064e..731918e 100644
--- a/include/asm-arm/arch-s3c2410/regs-timer.h
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h
@@ -8,13 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 Timer configuration
- *
- *  Changelog:
- *    05-06-2003     BJD     Created file
- *    26-06-2003     BJD     Added more timer definitions to mux / control
- *    12-03-2004     BJD     Updated include protection
- *    10-02-2005     BJD     Added S3C2410_TCFG1_MUX4_SHIFT (Guillaume Gourat)
- *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
diff --git a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
index bf315b7..3aa31a2 100644
--- a/include/asm-arm/arch-s3c2410/regs-udc.h
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h
@@ -6,13 +6,7 @@
  * 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.
- *
- *  Changelog:
- *    01-08-2004	Initial creation
- *    12-09-2004	Cleanup for submission
- *    24-10-2004	Fixed S3C2410_UDC_MAXP_REG definition
- *    10-03-2005	Changed S3C2410_VA to S3C24XX_VA
- */
+*/
 
 #ifndef __ASM_ARCH_REGS_UDC_H
 #define __ASM_ARCH_REGS_UDC_H
diff --git a/include/asm-arm/arch-s3c2410/regs-watchdog.h b/include/asm-arm/arch-s3c2410/regs-watchdog.h
index d199ca6..f4fff44 100644
--- a/include/asm-arm/arch-s3c2410/regs-watchdog.h
+++ b/include/asm-arm/arch-s3c2410/regs-watchdog.h
@@ -1,4 +1,4 @@
-/* linux/include/asm/arch-s3c2410/regs0watchdog.h
+/* linux/include/asm/arch-s3c2410/regs-watchdog.h
  *
  * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  *		      http://www.simtec.co.uk/products/SWLINUX/
@@ -8,11 +8,6 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 Watchdog timer control
- *
- *  Changelog:
- *    21-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
- *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
diff --git a/include/asm-arm/arch-s3c2410/system.h b/include/asm-arm/arch-s3c2410/system.h
index 9b0d850..718246d 100644
--- a/include/asm-arm/arch-s3c2410/system.h
+++ b/include/asm-arm/arch-s3c2410/system.h
@@ -8,14 +8,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  12-May-2003 BJD  Created file
- *  14-May-2003 BJD  Removed idle to aid debugging
- *  12-Jun-2003 BJD  Added reset via watchdog
- *  04-Sep-2003 BJD  Moved to v2.6
- *  28-Oct-2004 BJD  Added over-ride for idle, and fixed reset panic()
- */
+*/
 
 #include <asm/hardware.h>
 #include <asm/io.h>
diff --git a/include/asm-arm/arch-s3c2410/timex.h b/include/asm-arm/arch-s3c2410/timex.h
index 3558a3a..703c337 100644
--- a/include/asm-arm/arch-s3c2410/timex.h
+++ b/include/asm-arm/arch-s3c2410/timex.h
@@ -8,12 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  02-Sep-2003 BJD  Created file
- *  05-Jan-2004 BJD  Updated for Linux 2.6.0
- *  22-Nov-2004 BJD  Fixed CLOCK_TICK_RATE
- *  10-Jan-2004 BJD  Removed s3c2410_clock_tick_rate
 */
 
 #ifndef __ASM_ARCH_TIMEX_H
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index 8e152a0..81b3e91 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -8,15 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  22-May-2003 BJD  Created
- *  08-Sep-2003 BJD  Moved to linux v2.6
- *  12-Mar-2004 BJD  Updated header protection
- *  12-Oct-2004 BJD  Take account of debug uart configuration
- *  15-Nov-2004 BJD  Fixed uart configuration
- *  22-Feb-2005 BJD  Added watchdog to uncompress
- *  04-Apr-2005 LCVR Added support to S3C2400 (no cpuid at GSTATUS1)
 */
 
 #ifndef __ASM_ARCH_UNCOMPRESS_H
diff --git a/include/asm-arm/arch-s3c2410/usb-control.h b/include/asm-arm/arch-s3c2410/usb-control.h
index bd43b56..35723569 100644
--- a/include/asm-arm/arch-s3c2410/usb-control.h
+++ b/include/asm-arm/arch-s3c2410/usb-control.h
@@ -8,11 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  11-Sep-2004 BJD  Created file
- *  21-Sep-2004 BJD  Updated port info
- *  09-Aug-2005 BJD  Renamed s3c2410_report_oc s3c2410_usb_report_oc
 */
 
 #ifndef __ASM_ARCH_USBCONTROL_H
diff --git a/include/asm-arm/arch-s3c2410/vmalloc.h b/include/asm-arm/arch-s3c2410/vmalloc.h
index 33963cd..0ae3bdb 100644
--- a/include/asm-arm/arch-s3c2410/vmalloc.h
+++ b/include/asm-arm/arch-s3c2410/vmalloc.h
@@ -10,11 +10,7 @@
  * published by the Free Software Foundation.
  *
  * S3C2410 vmalloc definition
- *
- *  Changelog:
- *    12-Mar-2004 BJD	Fixed header, added include protection
- *    12=Mar-2004 BJD	Fixed VMALLOC_END definitions
- */
+*/
 
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
diff --git a/include/asm-arm/arch-s3c2410/vr1000-cpld.h b/include/asm-arm/arch-s3c2410/vr1000-cpld.h
index 0ee373a..a341b1e 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-cpld.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-cpld.h
@@ -8,10 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  25-May-2003 BJD  Created file, added CTRL1 registers
- *  19-Mar-2004 BJD  Added VR1000 CPLD definitions
 */
 
 #ifndef __ASM_ARCH_VR1000CPLD_H
diff --git a/include/asm-arm/arch-s3c2410/vr1000-irq.h b/include/asm-arm/arch-s3c2410/vr1000-irq.h
index 694f771..c39a0ff 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-irq.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-irq.h
@@ -8,11 +8,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  06-Jan-2003 BJD  Linux 2.6.0 version
- *  19-Mar-2004 BJD  Updates for VR1000
- */
+*/
 
 #ifndef __ASM_ARCH_VR1000IRQ_H
 #define __ASM_ARCH_VR1000IRQ_H
diff --git a/include/asm-arm/arch-s3c2410/vr1000-map.h b/include/asm-arm/arch-s3c2410/vr1000-map.h
index 867c935..1fe4db3 100644
--- a/include/asm-arm/arch-s3c2410/vr1000-map.h
+++ b/include/asm-arm/arch-s3c2410/vr1000-map.h
@@ -8,12 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Changelog:
- *  06-Jan-2003 BJD  Linux 2.6.0 version, split specifics from arch/map.h
- *  12-Mar-2004 BJD  Fixed header include protection
- *  19-Mar-2004 BJD  Copied to VR1000 machine headers.
- *  19-Jan-2005 BJD  Updated map definitions
 */
 
 /* needs arch/map.h including with this */
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index fe0c744..e4a2569 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -247,14 +247,12 @@
  */
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
-		flush_dcache_page(page);			\
+		flush_ptrace_access(vma, page, vaddr, dst, len, 1);\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
 	} while (0)
 
@@ -285,10 +283,24 @@
 		__cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
 	}
 }
+
+static inline void
+flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+			 unsigned long uaddr, void *kaddr,
+			 unsigned long len, int write)
+{
+	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
+		unsigned long addr = (unsigned long)kaddr;
+		__cpuc_coherent_kern_range(addr, addr + len);
+	}
+}
 #else
 extern void flush_cache_mm(struct mm_struct *mm);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
+extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+				unsigned long uaddr, void *kaddr,
+				unsigned long len, int write);
 #endif
 
 /*
diff --git a/include/asm-arm/hardware/ssp.h b/include/asm-arm/hardware/ssp.h
index 28aa11b..3b42e18 100644
--- a/include/asm-arm/hardware/ssp.h
+++ b/include/asm-arm/hardware/ssp.h
@@ -16,8 +16,8 @@
 };
 
 int ssp_write_word(u16 data);
-int ssp_read_word(void);
-void ssp_flush(void);
+int ssp_read_word(u16 *data);
+int ssp_flush(void);
 void ssp_enable(void);
 void ssp_disable(void);
 void ssp_save_state(struct ssp_state *ssp);
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index b3479fc..bf7b9de 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -291,5 +291,12 @@
  */
 #define xlate_dev_kmem_ptr(p)	p
 
+/*
+ * Register ISA memory and port locations for glibc iopl/inb/outb
+ * emulation.
+ */
+extern void register_isa_ports(unsigned int mmio, unsigned int io,
+			       unsigned int io_shift);
+
 #endif	/* __KERNEL__ */
 #endif	/* __ASM_ARM_IO_H */
diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
index edb7b65..91a31ad 100644
--- a/include/asm-arm/procinfo.h
+++ b/include/asm-arm/procinfo.h
@@ -55,5 +55,6 @@
 #define HWCAP_VFP	64
 #define HWCAP_EDSP	128
 #define HWCAP_JAVA	256
+#define HWCAP_IWMMXT	512
 
 #endif
diff --git a/include/asm-arm/spinlock.h b/include/asm-arm/spinlock.h
index 406ca97..01b7c26 100644
--- a/include/asm-arm/spinlock.h
+++ b/include/asm-arm/spinlock.h
@@ -199,7 +199,21 @@
 	: "cc");
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+	unsigned long tmp, tmp2 = 1;
+
+	__asm__ __volatile__(
+"1:	ldrex	%0, [%2]\n"
+"	adds	%0, %0, #1\n"
+"	strexpl	%1, %0, [%2]\n"
+	: "=&r" (tmp), "+r" (tmp2)
+	: "r" (&rw->lock)
+	: "cc");
+
+	smp_mb();
+	return tmp2 == 0;
+}
 
 /* read_can_lock - would read_trylock() succeed? */
 #define __raw_read_can_lock(x)		((x)->lock < 0x80000000)
diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h
new file mode 100644
index 0000000..0e87464
--- /dev/null
+++ b/include/asm-generic/audit_read.h
@@ -0,0 +1,8 @@
+__NR_readlink,
+__NR_quotactl,
+__NR_listxattr,
+__NR_llistxattr,
+__NR_flistxattr,
+__NR_getxattr,
+__NR_lgetxattr,
+__NR_fgetxattr,
diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h
new file mode 100644
index 0000000..f10d367
--- /dev/null
+++ b/include/asm-generic/audit_write.h
@@ -0,0 +1,11 @@
+#include <asm-generic/audit_dir_write.h>
+__NR_acct,
+__NR_swapon,
+__NR_quotactl,
+__NR_truncate,
+#ifdef __NR_truncate64
+__NR_truncate64,
+#endif
+#ifdef __NR_bind
+__NR_bind,		/* bind can affect fs object only in one way... */
+#endif
diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild
index c064a8e..335b2fa 100644
--- a/include/asm-i386/Kbuild
+++ b/include/asm-i386/Kbuild
@@ -1,5 +1,5 @@
 include include/asm-generic/Kbuild.asm
 
-header-y += boot.h cpufeature.h debugreg.h ldt.h setup.h ucontext.h
+header-y += boot.h debugreg.h ldt.h setup.h ucontext.h
 
 unifdef-y += mtrr.h vm86.h
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h
index 96adbab..b01a7ec 100644
--- a/include/asm-i386/alternative.h
+++ b/include/asm-i386/alternative.h
@@ -88,9 +88,6 @@
 /*
  * Alternative inline assembly for SMP.
  *
- * alternative_smp() takes two versions (SMP first, UP second) and is
- * for more complex stuff such as spinlocks.
- *
  * The LOCK_PREFIX macro defined here replaces the LOCK and
  * LOCK_PREFIX macros used everywhere in the source tree.
  *
@@ -110,21 +107,6 @@
  */
 
 #ifdef CONFIG_SMP
-#define alternative_smp(smpinstr, upinstr, args...)			\
-	asm volatile ("661:\n\t" smpinstr "\n662:\n" 			\
-		      ".section .smp_altinstructions,\"a\"\n"		\
-		      "  .align 4\n"					\
-		      "  .long 661b\n"            /* label */		\
-		      "  .long 663f\n"		  /* new instruction */	\
-		      "  .byte 0x68\n"            /* X86_FEATURE_UP */	\
-		      "  .byte 662b-661b\n"       /* sourcelen */	\
-		      "  .byte 664f-663f\n"       /* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .smp_altinstr_replacement,\"awx\"\n"   	\
-		      "663:\n\t" upinstr "\n"     /* replacement */	\
-		      "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
-		      ".previous" : args)
-
 #define LOCK_PREFIX \
 		".section .smp_locks,\"a\"\n"	\
 		"  .align 4\n"			\
@@ -133,8 +115,6 @@
 	       	"661:\n\tlock; "
 
 #else /* ! CONFIG_SMP */
-#define alternative_smp(smpinstr, upinstr, args...) \
-	asm volatile (upinstr : args)
 #define LOCK_PREFIX ""
 #endif
 
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 0730a20..8774d06 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -45,6 +45,7 @@
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define ARCH_SUPPORTS_KRETPROBES
 #define  ARCH_INACTIVE_KPROBE_COUNT 0
+#define flush_insn_slot(p)	do { } while (0)
 
 void arch_remove_kprobe(struct kprobe *p);
 void kretprobe_trampoline(void);
diff --git a/include/asm-i386/mach-default/mach_mpspec.h b/include/asm-i386/mach-default/mach_mpspec.h
index 6b5dadc..51c9a97 100644
--- a/include/asm-i386/mach-default/mach_mpspec.h
+++ b/include/asm-i386/mach-default/mach_mpspec.h
@@ -3,6 +3,10 @@
 
 #define MAX_IRQ_SOURCES 256
 
+#if CONFIG_BASE_SMALL == 0
+#define MAX_MP_BUSSES 256
+#else
 #define MAX_MP_BUSSES 32
+#endif
 
 #endif /* __ASM_MACH_MPSPEC_H */
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index e33e9f9..22cb07c 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -14,7 +14,7 @@
 
 #ifdef CONFIG_X86_NUMAQ
 	#include <asm/numaq.h>
-#else	/* summit or generic arch */
+#elif defined(CONFIG_ACPI_SRAT)/* summit or generic arch */
 	#include <asm/srat.h>
 #endif
 
diff --git a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h
index 96b0bef..87c069c 100644
--- a/include/asm-i386/rwlock.h
+++ b/include/asm-i386/rwlock.h
@@ -21,23 +21,21 @@
 #define RW_LOCK_BIAS_STR	"0x01000000"
 
 #define __build_read_lock_ptr(rw, helper)   \
-	alternative_smp("lock; subl $1,(%0)\n\t" \
+	asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" \
 			"jns 1f\n" \
 			"call " helper "\n\t" \
-			"1:\n", \
-			"subl $1,(%0)\n\t", \
-			:"a" (rw) : "memory")
+			"1:\n" \
+			::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
-	alternative_smp("lock; subl $1,%0\n\t" \
+	asm volatile(LOCK_PREFIX " subl $1,%0\n\t" \
 			"jns 1f\n" \
 			"pushl %%eax\n\t" \
 			"leal %0,%%eax\n\t" \
 			"call " helper "\n\t" \
 			"popl %%eax\n\t" \
-			"1:\n", \
-			"subl $1,%0\n\t", \
-			"+m" (*(volatile int *)rw) : : "memory")
+			"1:\n" \
+			:"+m" (*(volatile int *)rw) : : "memory")
 
 #define __build_read_lock(rw, helper)	do { \
 						if (__builtin_constant_p(rw)) \
@@ -47,23 +45,21 @@
 					} while (0)
 
 #define __build_write_lock_ptr(rw, helper) \
-	alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+	asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
 			"jz 1f\n" \
 			"call " helper "\n\t" \
-			"1:\n", \
-			"subl $" RW_LOCK_BIAS_STR ",(%0)\n\t", \
-			:"a" (rw) : "memory")
+			"1:\n" \
+			::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
-	alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+	asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
 			"jz 1f\n" \
 			"pushl %%eax\n\t" \
 			"leal %0,%%eax\n\t" \
 			"call " helper "\n\t" \
 			"popl %%eax\n\t" \
-			"1:\n", \
-			"subl $" RW_LOCK_BIAS_STR ",%0\n\t", \
-			"+m" (*(volatile int *)rw) : : "memory")
+			"1:\n" \
+			:"+m" (*(volatile int *)rw) : : "memory")
 
 #define __build_write_lock(rw, helper)	do { \
 						if (__builtin_constant_p(rw)) \
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index d816c62..d102036 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -22,7 +22,7 @@
 
 #define __raw_spin_lock_string \
 	"\n1:\t" \
-	"lock ; decb %0\n\t" \
+	LOCK_PREFIX " ; decb %0\n\t" \
 	"jns 3f\n" \
 	"2:\t" \
 	"rep;nop\n\t" \
@@ -38,7 +38,7 @@
  */
 #define __raw_spin_lock_string_flags \
 	"\n1:\t" \
-	"lock ; decb %0\n\t" \
+	LOCK_PREFIX " ; decb %0\n\t" \
 	"jns 5f\n" \
 	"2:\t" \
 	"testl $0x200, %1\n\t" \
@@ -57,15 +57,9 @@
 	"jmp 4b\n" \
 	"5:\n\t"
 
-#define __raw_spin_lock_string_up \
-	"\n\tdecb %0"
-
 static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-	alternative_smp(
-		__raw_spin_lock_string,
-		__raw_spin_lock_string_up,
-		"+m" (lock->slock) : : "memory");
+	asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory");
 }
 
 /*
@@ -76,10 +70,7 @@
 #ifndef CONFIG_PROVE_LOCKING
 static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
 {
-	alternative_smp(
-		__raw_spin_lock_string_flags,
-		__raw_spin_lock_string_up,
-		"+m" (lock->slock) : "r" (flags) : "memory");
+	asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory");
 }
 #endif
 
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index fc1c8dd..d983b74 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -324,8 +324,6 @@
 #define __NR_vmsplice		316
 #define __NR_move_pages		317
 
-#ifdef __KERNEL__
-
 #define NR_syscalls 318
 
 /*
@@ -425,6 +423,8 @@
 __syscall_return(type,__res); \
 }
 
+#ifdef __KERNEL__
+
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
index 69f0f1d..4c1a0b9 100644
--- a/include/asm-i386/unwind.h
+++ b/include/asm-i386/unwind.h
@@ -87,6 +87,7 @@
 #else
 
 #define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
 
 static inline int arch_unw_user_mode(const void *info)
 {
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 2418a78..9389049 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -125,5 +125,6 @@
 }
 extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
+extern void flush_insn_slot(struct kprobe *p);
 
 #endif				/* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index 894bc4d..6a33a07 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -56,6 +56,11 @@
   extern struct page *vmem_map;
   extern int find_largest_hole (u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
+  extern int vmemmap_find_next_valid_pfn(int, int);
+#else
+static inline int vmemmap_find_next_valid_pfn(int node, int i)
+{
+	return i + 1;
+}
 #endif
-
 #endif /* meminit_h */
diff --git a/include/asm-ia64/mman.h b/include/asm-ia64/mman.h
index 6ba179f..c73b878 100644
--- a/include/asm-ia64/mman.h
+++ b/include/asm-ia64/mman.h
@@ -22,4 +22,12 @@
 #define MCL_CURRENT	1		/* lock all current mappings */
 #define MCL_FUTURE	2		/* lock all future mappings */
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#define arch_mmap_check	ia64_mmap_check
+int ia64_mmap_check(unsigned long addr, unsigned long len,
+		unsigned long flags);
+#endif
+#endif
+
 #endif /* _ASM_IA64_MMAN_H */
diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h
index 37e52a2..20a8d61 100644
--- a/include/asm-ia64/pal.h
+++ b/include/asm-ia64/pal.h
@@ -1433,7 +1433,12 @@
 } pal_version_u_t;
 
 
-/* Return PAL version information */
+/*
+ * Return PAL version information.  While the documentation states that
+ * PAL_VERSION can be called in either physical or virtual mode, some
+ * implementations only allow physical calls.  We don't call it very often,
+ * so the overhead isn't worth eliminating.
+ */
 static inline s64
 ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version)
 {
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index bd4452b..ba826b3 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -706,12 +706,9 @@
 sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
 {
 	struct ia64_sal_retval ret_stuff;
-	unsigned long irq_flags;
 
-	local_irq_save(irq_flags);
 	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len,
 				(u64)nasid_array, perms, 0, 0, 0);
-	local_irq_restore(irq_flags);
 	return ret_stuff.status;
 }
 #define SN_MEMPROT_ACCESS_CLASS_0		0x14a080
@@ -1143,12 +1140,9 @@
 sn_inject_error(u64 paddr, u64 *data, u64 *ecc)
 {
 	struct ia64_sal_retval ret_stuff;
-	unsigned long irq_flags;
 
-	local_irq_save(irq_flags);
 	ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data,
 				(u64)ecc, 0, 0, 0, 0);
-	local_irq_restore(irq_flags);
 	return ret_stuff.status;
 }
 
diff --git a/include/asm-ia64/sn/xp.h b/include/asm-ia64/sn/xp.h
index 9bd2f9b..6f807e0 100644
--- a/include/asm-ia64/sn/xp.h
+++ b/include/asm-ia64/sn/xp.h
@@ -60,23 +60,37 @@
  * the bte_copy() once in the hope that the failure was due to a temporary
  * aberration (i.e., the link going down temporarily).
  *
- * See bte_copy for definition of the input parameters.
+ * 	src - physical address of the source of the transfer.
+ *	vdst - virtual address of the destination of the transfer.
+ *	len - number of bytes to transfer from source to destination.
+ *	mode - see bte_copy() for definition.
+ *	notification - see bte_copy() for definition.
  *
  * Note: xp_bte_copy() should never be called while holding a spinlock.
  */
 static inline bte_result_t
-xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
+xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification)
 {
 	bte_result_t ret;
+	u64 pdst = ia64_tpa(vdst);
 
 
-	ret = bte_copy(src, dest, len, mode, notification);
+	/*
+	 * Ensure that the physically mapped memory is contiguous.
+	 *
+	 * We do this by ensuring that the memory is from region 7 only.
+	 * If the need should arise to use memory from one of the other
+	 * regions, then modify the BUG_ON() statement to ensure that the
+	 * memory from that region is always physically contiguous.
+	 */
+	BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL);
 
+	ret = bte_copy(src, pdst, len, mode, notification);
 	if (ret != BTE_SUCCESS) {
 		if (!in_interrupt()) {
 			cond_resched();
 		}
-		ret = bte_copy(src, dest, len, mode, notification);
+		ret = bte_copy(src, pdst, len, mode, notification);
 	}
 
 	return ret;
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 8406f1e..35e1386 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -683,7 +683,9 @@
 extern struct xpc_rsvd_page *xpc_rsvd_page;
 extern struct xpc_vars_part *xpc_vars_part;
 extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1];
-extern char xpc_remote_copy_buffer[];
+extern char *xpc_remote_copy_buffer;
+extern void *xpc_remote_copy_buffer_base;
+extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **);
 extern struct xpc_rsvd_page *xpc_rsvd_page_init(void);
 extern void xpc_allow_IPI_ops(void);
 extern void xpc_restrict_IPI_ops(void);
@@ -1124,8 +1126,8 @@
 #define XPC_GET_IPI_FLAGS(_amo, _c)	((u8) (((_amo) >> ((_c) * 8)) & 0xff))
 #define XPC_SET_IPI_FLAGS(_amo, _c, _f)	(_amo) |= ((u64) (_f) << ((_c) * 8))
 
-#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f)
-#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & 0x1010101010101010)
+#define	XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x0f0f0f0f0f0f0f0f))
+#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo)       ((_amo) & __IA64_UL_CONST(0x1010101010101010))
 
 
 static inline void
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index fc9677b..384fbf7 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -24,7 +24,7 @@
  * 0xa000000000000000+2*PERCPU_PAGE_SIZE
  * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
  */
-#define KERNEL_START		 (GATE_ADDR+0x100000000)
+#define KERNEL_START		 (GATE_ADDR+__IA64_UL_CONST(0x100000000))
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index bb0eb72..f581662 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -286,8 +286,7 @@
 /* 1294, 1295 reserved for pselect/ppoll */
 #define __NR_unshare			1296
 #define __NR_splice			1297
-#define __NR_set_robust_list		1298
-#define __NR_get_robust_list		1299
+/* 1298, 1299 reserved for set_robust_list/get_robust_list */
 #define __NR_sync_file_range		1300
 #define __NR_tee			1301
 #define __NR_vmsplice			1302
diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h
index 58d4b6f..8cf5c37 100644
--- a/include/asm-powerpc/backlight.h
+++ b/include/asm-powerpc/backlight.h
@@ -30,8 +30,12 @@
 	pmac_backlight_key(1);
 }
 
+extern void pmac_backlight_set_legacy_brightness_pmu(int brightness);
 extern int pmac_backlight_set_legacy_brightness(int brightness);
 extern int pmac_backlight_get_legacy_brightness(void);
 
+extern void pmac_backlight_enable(void);
+extern void pmac_backlight_disable(void);
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index a9496f3..36c4c34b 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -72,6 +72,9 @@
  * Neither do the standard versions now, these are just here
  * for older code.
  */
+#define insb(port, buf, ns)	_insb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define insw(port, buf, ns)	_insw_ns((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
+#define insl(port, buf, nl)	_insl_ns((u8 __iomem *)((port)+pci_io_base), (buf), (nl))
 #define insw_ns(port, buf, ns)	_insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
 #define insl_ns(port, buf, nl)	_insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
 #else
@@ -137,12 +140,12 @@
 #define insw_ns(port, buf, ns)	eeh_insw_ns((port), (buf), (ns))
 #define insl_ns(port, buf, nl)	eeh_insl_ns((port), (buf), (nl))
 
+#endif
+
 #define outsb(port, buf, ns)  _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
 #define outsw(port, buf, ns)  _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
 #define outsl(port, buf, nl)  _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
 
-#endif
-
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
index 0fe396a..53079ec 100644
--- a/include/asm-powerpc/ipic.h
+++ b/include/asm-powerpc/ipic.h
@@ -69,9 +69,6 @@
 	IPIC_MCP_MU   = 7,
 };
 
-extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
-		unsigned int irq_offset,
-		unsigned char *senses, unsigned int senses_count);
 extern int ipic_set_priority(unsigned int irq, unsigned int priority);
 extern void ipic_set_highest_priority(unsigned int irq);
 extern void ipic_set_default_priority(void);
@@ -79,7 +76,16 @@
 extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
 extern u32 ipic_get_mcp_status(void);
 extern void ipic_clear_mcp_status(u32 mask);
+
+#ifdef CONFIG_PPC_MERGE
+extern void ipic_init(struct device_node *node, unsigned int flags);
+extern unsigned int ipic_get_irq(struct pt_regs *regs);
+#else
+extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses, unsigned int senses_count);
 extern int ipic_get_irq(struct pt_regs *regs);
+#endif
 
 #endif /* __ASM_IPIC_H__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h
index 8f7fd5c..11cbdf8 100644
--- a/include/asm-powerpc/kexec.h
+++ b/include/asm-powerpc/kexec.h
@@ -32,6 +32,7 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#include <linux/cpumask.h>
 
 #ifdef CONFIG_KEXEC
 
@@ -109,7 +110,6 @@
 
 #define MAX_NOTE_BYTES 1024
 
-#ifdef __powerpc64__
 extern void kexec_smp_wait(void);	/* get and clear naca physid, wait for
 					  master to copy new code to 0 */
 extern int crashing_cpu;
@@ -119,7 +119,6 @@
 {
 	return cpu_isset(cpu,cpus_in_sr);
 }
-#endif /* __powerpc64 __ */
 
 struct kimage;
 struct pt_regs;
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index 2d0af52..34e1f89 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -51,6 +51,7 @@
 
 #define ARCH_SUPPORTS_KRETPROBES
 #define  ARCH_INACTIVE_KPROBE_COUNT 1
+#define flush_insn_slot(p)	do { } while (0)
 
 void kretprobe_trampoline(void);
 extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index f260382..b85df45 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -23,8 +23,6 @@
 #define _ISA_MEM_BASE   isa_mem_base
 #ifdef CONFIG_PCI
 #define PCI_DRAM_OFFSET pci_dram_offset
-#else
-#define PCI_DRAM_OFFSET 0
 #endif
 
 #define CPU0_BOOT_RELEASE 0x01000000
@@ -33,7 +31,6 @@
 #define MCM_PORT_CONFIG_OFFSET 0x1010
 
 /* Offset from CCSRBAR */
-#define MPC86xx_OPENPIC_OFFSET	(0x40000)
 #define MPC86xx_MCM_OFFSET      (0x00000)
 #define MPC86xx_MCM_SIZE        (0x02000)
 
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index eb241c9..a9f9604 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -41,6 +41,7 @@
 #define MPIC_GREG_IPI_VECTOR_PRI_1	0x000b0
 #define MPIC_GREG_IPI_VECTOR_PRI_2	0x000c0
 #define MPIC_GREG_IPI_VECTOR_PRI_3	0x000d0
+#define MPIC_GREG_IPI_STRIDE		0x10
 #define MPIC_GREG_SPURIOUS		0x000e0
 #define MPIC_GREG_TIMER_FREQ		0x000f0
 
@@ -68,6 +69,7 @@
 #define MPIC_CPU_IPI_DISPATCH_1		0x00050
 #define MPIC_CPU_IPI_DISPATCH_2		0x00060
 #define MPIC_CPU_IPI_DISPATCH_3		0x00070
+#define MPIC_CPU_IPI_DISPATCH_STRIDE	0x00010
 #define MPIC_CPU_CURRENT_TASK_PRI	0x00080
 #define 	MPIC_CPU_TASKPRI_MASK			0x0000000f
 #define MPIC_CPU_WHOAMI			0x00090
@@ -114,6 +116,103 @@
 #define MPIC_VEC_TIMER_1	248
 #define MPIC_VEC_TIMER_0	247
 
+/*
+ * Tsi108 implementation of MPIC has many differences from the original one
+ */
+
+/*
+ * Global registers
+ */
+
+#define TSI108_GREG_BASE		0x00000
+#define TSI108_GREG_FEATURE_0		0x00000
+#define TSI108_GREG_GLOBAL_CONF_0	0x00004
+#define TSI108_GREG_VENDOR_ID		0x0000c
+#define TSI108_GREG_IPI_VECTOR_PRI_0	0x00204		/* Doorbell 0 */
+#define TSI108_GREG_IPI_STRIDE		0x0c
+#define TSI108_GREG_SPURIOUS		0x00010
+#define TSI108_GREG_TIMER_FREQ		0x00014
+
+/*
+ * Timer registers
+ */
+#define TSI108_TIMER_BASE		0x0030
+#define TSI108_TIMER_STRIDE		0x10
+#define TSI108_TIMER_CURRENT_CNT	0x00000
+#define TSI108_TIMER_BASE_CNT		0x00004
+#define TSI108_TIMER_VECTOR_PRI		0x00008
+#define TSI108_TIMER_DESTINATION	0x0000c
+
+/*
+ * Per-Processor registers
+ */
+#define TSI108_CPU_BASE			0x00300
+#define TSI108_CPU_STRIDE		0x00040
+#define TSI108_CPU_IPI_DISPATCH_0	0x00200
+#define TSI108_CPU_IPI_DISPATCH_STRIDE	0x00000
+#define TSI108_CPU_CURRENT_TASK_PRI	0x00000
+#define TSI108_CPU_WHOAMI		0xffffffff
+#define TSI108_CPU_INTACK		0x00004
+#define TSI108_CPU_EOI			0x00008
+
+/*
+ * Per-source registers
+ */
+#define TSI108_IRQ_BASE			0x00100
+#define TSI108_IRQ_STRIDE		0x00008
+#define TSI108_IRQ_VECTOR_PRI		0x00000
+#define TSI108_VECPRI_VECTOR_MASK	0x000000ff
+#define TSI108_VECPRI_POLARITY_POSITIVE	0x01000000
+#define TSI108_VECPRI_POLARITY_NEGATIVE	0x00000000
+#define TSI108_VECPRI_SENSE_LEVEL	0x02000000
+#define TSI108_VECPRI_SENSE_EDGE	0x00000000
+#define TSI108_VECPRI_POLARITY_MASK	0x01000000
+#define TSI108_VECPRI_SENSE_MASK	0x02000000
+#define TSI108_IRQ_DESTINATION		0x00004
+
+/* weird mpic register indices and mask bits in the HW info array */
+enum {
+	MPIC_IDX_GREG_BASE = 0,
+	MPIC_IDX_GREG_FEATURE_0,
+	MPIC_IDX_GREG_GLOBAL_CONF_0,
+	MPIC_IDX_GREG_VENDOR_ID,
+	MPIC_IDX_GREG_IPI_VECTOR_PRI_0,
+	MPIC_IDX_GREG_IPI_STRIDE,
+	MPIC_IDX_GREG_SPURIOUS,
+	MPIC_IDX_GREG_TIMER_FREQ,
+
+	MPIC_IDX_TIMER_BASE,
+	MPIC_IDX_TIMER_STRIDE,
+	MPIC_IDX_TIMER_CURRENT_CNT,
+	MPIC_IDX_TIMER_BASE_CNT,
+	MPIC_IDX_TIMER_VECTOR_PRI,
+	MPIC_IDX_TIMER_DESTINATION,
+
+	MPIC_IDX_CPU_BASE,
+	MPIC_IDX_CPU_STRIDE,
+	MPIC_IDX_CPU_IPI_DISPATCH_0,
+	MPIC_IDX_CPU_IPI_DISPATCH_STRIDE,
+	MPIC_IDX_CPU_CURRENT_TASK_PRI,
+	MPIC_IDX_CPU_WHOAMI,
+	MPIC_IDX_CPU_INTACK,
+	MPIC_IDX_CPU_EOI,
+
+	MPIC_IDX_IRQ_BASE,
+	MPIC_IDX_IRQ_STRIDE,
+	MPIC_IDX_IRQ_VECTOR_PRI,
+
+	MPIC_IDX_VECPRI_VECTOR_MASK,
+	MPIC_IDX_VECPRI_POLARITY_POSITIVE,
+	MPIC_IDX_VECPRI_POLARITY_NEGATIVE,
+	MPIC_IDX_VECPRI_SENSE_LEVEL,
+	MPIC_IDX_VECPRI_SENSE_EDGE,
+	MPIC_IDX_VECPRI_POLARITY_MASK,
+	MPIC_IDX_VECPRI_SENSE_MASK,
+	MPIC_IDX_IRQ_DESTINATION,
+	MPIC_IDX_END
+};
+
+
 #ifdef CONFIG_MPIC_BROKEN_U3
 /* Fixup table entry */
 struct mpic_irq_fixup
@@ -171,15 +270,29 @@
 	volatile u32 __iomem	*cpuregs[MPIC_MAX_CPUS];
 	volatile u32 __iomem	*isus[MPIC_MAX_ISU];
 
+#ifdef CONFIG_MPIC_WEIRD
+	/* Pointer to HW info array */
+	u32			*hw_set;
+#endif
+
 	/* link */
 	struct mpic		*next;
 };
 
+/*
+ * MPIC flags (passed to mpic_alloc)
+ *
+ * The top 4 bits contain an MPIC bhw id that is used to index the
+ * register offsets and some masks when CONFIG_MPIC_WEIRD is set.
+ * Note setting any ID (leaving those bits to 0) means standard MPIC
+ */
+
 /* This is the primary controller, only that one has IPIs and
  * has afinity control. A non-primary MPIC always uses CPU0
  * registers only
  */
 #define MPIC_PRIMARY			0x00000001
+
 /* Set this for a big-endian MPIC */
 #define MPIC_BIG_ENDIAN			0x00000002
 /* Broken U3 MPIC */
@@ -188,6 +301,18 @@
 #define MPIC_BROKEN_IPI			0x00000008
 /* MPIC wants a reset */
 #define MPIC_WANTS_RESET		0x00000010
+/* Spurious vector requires EOI */
+#define MPIC_SPV_EOI			0x00000020
+/* No passthrough disable */
+#define MPIC_NO_PTHROU_DIS		0x00000040
+
+/* MPIC HW modification ID */
+#define MPIC_REGSET_MASK		0xf0000000
+#define MPIC_REGSET(val)		(((val) & 0xf ) << 28)
+#define MPIC_GET_REGSET(flags)		(((flags) >> 28) & 0xf)
+
+#define	MPIC_REGSET_STANDARD		MPIC_REGSET(0)	/* Original MPIC */
+#define	MPIC_REGSET_TSI108		MPIC_REGSET(1)	/* Tsi108/109 PIC */
 
 /* Allocate the controller structure and setup the linux irq descs
  * for the range if interrupts passed in. No HW initialization is
diff --git a/include/asm-powerpc/pgalloc.h b/include/asm-powerpc/pgalloc.h
index 9f0917c..ae63db7 100644
--- a/include/asm-powerpc/pgalloc.h
+++ b/include/asm-powerpc/pgalloc.h
@@ -117,7 +117,7 @@
 	pte_free_kernel(page_address(ptepage));
 }
 
-#define PGF_CACHENUM_MASK	0xf
+#define PGF_CACHENUM_MASK	0x3
 
 typedef struct pgtable_free {
 	unsigned long val;
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index b095a28..d0fa1b9 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -276,6 +276,7 @@
  * of_irq_map_raw - Low level interrupt tree parsing
  * @parent:	the device interrupt parent
  * @intspec:	interrupt specifier ("interrupts" property of the device)
+ * @ointsize:   size of the passed in interrupt specifier
  * @addr:	address specifier (start of "reg" property of the device)
  * @out_irq:	structure of_irq filled by this function
  *
@@ -288,7 +289,8 @@
  *
  */
 
-extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr,
+extern int of_irq_map_raw(struct device_node *parent, u32 *intspec,
+			  u32 ointsize, u32 *addr,
 			  struct of_irq *out_irq);
 
 
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
index a33c6ac..82a27e9 100644
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -170,6 +170,7 @@
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
 extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 7307aa7..4c9f522 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -53,6 +53,15 @@
 #define smp_read_barrier_depends()	do { } while(0)
 #endif /* CONFIG_SMP */
 
+/*
+ * This is a barrier which prevents following instructions from being
+ * started until the value of the argument x is known.  For example, if
+ * x is a variable loaded from memory, this prevents following
+ * instructions from being executed until the load has been performed.
+ */
+#define data_barrier(x)	\
+	asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory");
+
 struct task_struct;
 struct pt_regs;
 
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index dcde441..5785ac4 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -30,10 +30,6 @@
 extern unsigned long tb_ticks_per_sec;
 extern u64 tb_to_xs;
 extern unsigned      tb_to_us;
-extern unsigned long tb_last_stamp;
-extern u64 tb_last_jiffy;
-
-DECLARE_PER_CPU(unsigned long, last_jiffy);
 
 struct rtc_time;
 extern void to_tm(int tim, struct rtc_time * tm);
diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h
index c4c278d..2c702d3 100644
--- a/include/asm-powerpc/tsi108.h
+++ b/include/asm-powerpc/tsi108.h
@@ -1,16 +1,18 @@
 /*
- * include/asm-ppc/tsi108.h
- *
  * common routine and memory layout for Tundra TSI108(Grendel) host bridge
  * memory controller.
  *
  * Author: Jacob Pan (jacob.pan@freescale.com)
  *	   Alex Bounine (alexandreb@tundra.com)
- * 2004 (c) Freescale Semiconductor Inc.  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.
+ *
+ * Copyright 2004-2006 Freescale Semiconductor, Inc.
+ *
+ * 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.
  */
+
 #ifndef __PPC_KERNEL_TSI108_H
 #define __PPC_KERNEL_TSI108_H
 
diff --git a/include/asm-powerpc/tsi108_irq.h b/include/asm-powerpc/tsi108_irq.h
new file mode 100644
index 0000000..3e4d04e
--- /dev/null
+++ b/include/asm-powerpc/tsi108_irq.h
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2005 Tundra Semiconductor Corp.
+ * Alex Bounine, <alexandreb at tundra.com).
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * definitions for interrupt controller initialization and external interrupt
+ * demultiplexing on TSI108EMU/SVB boards.
+ */
+
+#ifndef _ASM_PPC_TSI108_IRQ_H
+#define _ASM_PPC_TSI108_IRQ_H
+
+/*
+ * Tsi108 interrupts
+ */
+#ifndef TSI108_IRQ_REG_BASE
+#define TSI108_IRQ_REG_BASE		0
+#endif
+
+#define TSI108_IRQ(x)		(TSI108_IRQ_REG_BASE + (x))
+
+#define TSI108_MAX_VECTORS	(36 + 4)	/* 36 sources + PCI INT demux */
+#define MAX_TASK_PRIO	0xF
+
+#define TSI108_IRQ_SPURIOUS	(TSI108_MAX_VECTORS)
+
+#define DEFAULT_PRIO_LVL	10	/* initial priority level */
+
+/* Interrupt vectors assignment to external and internal
+ * sources of requests. */
+
+/* EXTERNAL INTERRUPT SOURCES */
+
+#define IRQ_TSI108_EXT_INT0	TSI108_IRQ(0)	/* External Source at INT[0] */
+#define IRQ_TSI108_EXT_INT1	TSI108_IRQ(1)	/* External Source at INT[1] */
+#define IRQ_TSI108_EXT_INT2	TSI108_IRQ(2)	/* External Source at INT[2] */
+#define IRQ_TSI108_EXT_INT3	TSI108_IRQ(3)	/* External Source at INT[3] */
+
+/* INTERNAL INTERRUPT SOURCES */
+
+#define IRQ_TSI108_RESERVED0	TSI108_IRQ(4)	/* Reserved IRQ */
+#define IRQ_TSI108_RESERVED1	TSI108_IRQ(5)	/* Reserved IRQ */
+#define IRQ_TSI108_RESERVED2	TSI108_IRQ(6)	/* Reserved IRQ */
+#define IRQ_TSI108_RESERVED3	TSI108_IRQ(7)	/* Reserved IRQ */
+#define IRQ_TSI108_DMA0		TSI108_IRQ(8)	/* DMA0 */
+#define IRQ_TSI108_DMA1		TSI108_IRQ(9)	/* DMA1 */
+#define IRQ_TSI108_DMA2		TSI108_IRQ(10)	/* DMA2 */
+#define IRQ_TSI108_DMA3		TSI108_IRQ(11)	/* DMA3 */
+#define IRQ_TSI108_UART0	TSI108_IRQ(12)	/* UART0 */
+#define IRQ_TSI108_UART1	TSI108_IRQ(13)	/* UART1 */
+#define IRQ_TSI108_I2C		TSI108_IRQ(14)	/* I2C */
+#define IRQ_TSI108_GPIO		TSI108_IRQ(15)	/* GPIO */
+#define IRQ_TSI108_GIGE0	TSI108_IRQ(16)	/* GIGE0 */
+#define IRQ_TSI108_GIGE1	TSI108_IRQ(17)	/* GIGE1 */
+#define IRQ_TSI108_RESERVED4	TSI108_IRQ(18)	/* Reserved IRQ */
+#define IRQ_TSI108_HLP		TSI108_IRQ(19)	/* HLP */
+#define IRQ_TSI108_SDRAM	TSI108_IRQ(20)	/* SDC */
+#define IRQ_TSI108_PROC_IF	TSI108_IRQ(21)	/* Processor IF */
+#define IRQ_TSI108_RESERVED5	TSI108_IRQ(22)	/* Reserved IRQ */
+#define IRQ_TSI108_PCI		TSI108_IRQ(23)	/* PCI/X block */
+
+#define IRQ_TSI108_MBOX0	TSI108_IRQ(24)	/* Mailbox 0 register */
+#define IRQ_TSI108_MBOX1	TSI108_IRQ(25)	/* Mailbox 1 register */
+#define IRQ_TSI108_MBOX2	TSI108_IRQ(26)	/* Mailbox 2 register */
+#define IRQ_TSI108_MBOX3	TSI108_IRQ(27)	/* Mailbox 3 register */
+
+#define IRQ_TSI108_DBELL0	TSI108_IRQ(28)	/* Doorbell 0 */
+#define IRQ_TSI108_DBELL1	TSI108_IRQ(29)	/* Doorbell 1 */
+#define IRQ_TSI108_DBELL2	TSI108_IRQ(30)	/* Doorbell 2 */
+#define IRQ_TSI108_DBELL3	TSI108_IRQ(31)	/* Doorbell 3 */
+
+#define IRQ_TSI108_TIMER0	TSI108_IRQ(32)	/* Global Timer 0 */
+#define IRQ_TSI108_TIMER1	TSI108_IRQ(33)	/* Global Timer 1 */
+#define IRQ_TSI108_TIMER2	TSI108_IRQ(34)	/* Global Timer 2 */
+#define IRQ_TSI108_TIMER3	TSI108_IRQ(35)	/* Global Timer 3 */
+
+/*
+ * PCI bus INTA# - INTD# lines demultiplexor
+ */
+#define IRQ_PCI_INTAD_BASE	TSI108_IRQ(36)
+#define IRQ_PCI_INTA		(IRQ_PCI_INTAD_BASE + 0)
+#define IRQ_PCI_INTB		(IRQ_PCI_INTAD_BASE + 1)
+#define IRQ_PCI_INTC		(IRQ_PCI_INTAD_BASE + 2)
+#define IRQ_PCI_INTD		(IRQ_PCI_INTAD_BASE + 3)
+#define NUM_PCI_IRQS		(4)
+
+/* number of entries in vector dispatch table */
+#define IRQ_TSI108_TAB_SIZE	(TSI108_MAX_VECTORS + 1)
+
+/* Mapping of MPIC outputs to processors' interrupt pins */
+
+#define IDIR_INT_OUT0		0x1
+#define IDIR_INT_OUT1		0x2
+#define IDIR_INT_OUT2		0x4
+#define IDIR_INT_OUT3		0x8
+
+/*---------------------------------------------------------------
+ * IRQ line configuration parameters */
+
+/* Interrupt delivery modes */
+typedef enum {
+	TSI108_IRQ_DIRECTED,
+	TSI108_IRQ_DISTRIBUTED,
+} TSI108_IRQ_MODE;
+#endif				/*  _ASM_PPC_TSI108_IRQ_H */
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index c70344b..f6a7ff0 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -1093,5 +1093,100 @@
 
 #define FCC_PSMR_RMII	((uint)0x00020000)	/* Use RMII interface */
 
+/* FCC iop & clock configuration. BSP code is responsible to define Fx_RXCLK & Fx_TXCLK
+ * in order to use clock-computing stuff below for the FCC x
+ */
+
+/* Automatically generates register configurations */
+#define PC_CLK(x)	((uint)(1<<(x-1)))	/* FCC CLK I/O ports */
+
+#define CMXFCR_RF1CS(x)	((uint)((x-5)<<27))	/* FCC1 Receive Clock Source */
+#define CMXFCR_TF1CS(x)	((uint)((x-5)<<24))	/* FCC1 Transmit Clock Source */
+#define CMXFCR_RF2CS(x)	((uint)((x-9)<<19))	/* FCC2 Receive Clock Source */
+#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16))	/* FCC2 Transmit Clock Source */
+#define CMXFCR_RF3CS(x)	((uint)((x-9)<<11))	/* FCC3 Receive Clock Source */
+#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8))	/* FCC3 Transmit Clock Source */
+
+#define PC_F1RXCLK	PC_CLK(F1_RXCLK)
+#define PC_F1TXCLK	PC_CLK(F1_TXCLK)
+#define CMX1_CLK_ROUTE	(CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK))
+#define CMX1_CLK_MASK	((uint)0xff000000)
+
+#define PC_F2RXCLK	PC_CLK(F2_RXCLK)
+#define PC_F2TXCLK	PC_CLK(F2_TXCLK)
+#define CMX2_CLK_ROUTE	(CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK))
+#define CMX2_CLK_MASK	((uint)0x00ff0000)
+
+#define PC_F3RXCLK	PC_CLK(F3_RXCLK)
+#define PC_F3TXCLK	PC_CLK(F3_TXCLK)
+#define CMX3_CLK_ROUTE	(CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK))
+#define CMX3_CLK_MASK	((uint)0x0000ff00)
+
+#define CPMUX_CLK_MASK (CMX3_CLK_MASK | CMX2_CLK_MASK)
+#define CPMUX_CLK_ROUTE (CMX3_CLK_ROUTE | CMX2_CLK_ROUTE)
+
+#define CLK_TRX (PC_F3TXCLK | PC_F3RXCLK | PC_F2TXCLK | PC_F2RXCLK)
+
+/* I/O Pin assignment for FCC1.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PA1_COL		0x00000001U
+#define PA1_CRS		0x00000002U
+#define PA1_TXER	0x00000004U
+#define PA1_TXEN	0x00000008U
+#define PA1_RXDV	0x00000010U
+#define PA1_RXER	0x00000020U
+#define PA1_TXDAT	0x00003c00U
+#define PA1_RXDAT	0x0003c000U
+#define PA1_PSORA0	(PA1_RXDAT | PA1_TXDAT)
+#define PA1_PSORA1	(PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \
+		PA1_RXDV | PA1_RXER)
+#define PA1_DIRA0	(PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV)
+#define PA1_DIRA1	(PA1_TXDAT | PA1_TXEN | PA1_TXER)
+
+
+/* I/O Pin assignment for FCC2.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB2_TXER	0x00000001U
+#define PB2_RXDV	0x00000002U
+#define PB2_TXEN	0x00000004U
+#define PB2_RXER	0x00000008U
+#define PB2_COL		0x00000010U
+#define PB2_CRS		0x00000020U
+#define PB2_TXDAT	0x000003c0U
+#define PB2_RXDAT	0x00003c00U
+#define PB2_PSORB0	(PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \
+		PB2_RXER | PB2_RXDV | PB2_TXER)
+#define PB2_PSORB1	(PB2_TXEN)
+#define PB2_DIRB0	(PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV)
+#define PB2_DIRB1	(PB2_TXDAT | PB2_TXEN | PB2_TXER)
+
+
+/* I/O Pin assignment for FCC3.  I don't yet know the best way to do this,
+ * but there is little variation among the choices.
+ */
+#define PB3_RXDV	0x00004000U
+#define PB3_RXER	0x00008000U
+#define PB3_TXER	0x00010000U
+#define PB3_TXEN	0x00020000U
+#define PB3_COL		0x00040000U
+#define PB3_CRS		0x00080000U
+#define PB3_TXDAT	0x0f000000U
+#define PC3_TXDAT	0x00000010U
+#define PB3_RXDAT	0x00f00000U
+#define PB3_PSORB0	(PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \
+		PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN)
+#define PB3_PSORB1	0
+#define PB3_DIRB0	(PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV)
+#define PB3_DIRB1	(PB3_TXDAT | PB3_TXEN | PB3_TXER)
+#define PC3_DIRC1	(PC3_TXDAT)
+
+/* Handy macro to specify mem for FCCs*/
+#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128))
+#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1)
+#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(2)
+
 #endif /* __CPM2__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 4b93481..23579d4 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -82,6 +82,7 @@
 	MPC82xx_CPM_SMC2,
 	MPC82xx_CPM_USB,
 	MPC82xx_SEC1,
+	MPC82xx_MDIO_BB,
 	NUM_PPC_SYS_DEVS,
 };
 
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index adcce33..d3a2f2f 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -110,6 +110,7 @@
 	MPC8xx_CPM_SMC1,
 	MPC8xx_CPM_SMC2,
 	MPC8xx_CPM_USB,
+	MPC8xx_MDIO_FEC,
 	NUM_PPC_SYS_DEVS,
 };
 
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index a5559e3..5a057b0 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -104,7 +104,7 @@
 
 /* PFN start number, because of __MEMORY_START */
 #define PFN_START		(__MEMORY_START >> PAGE_SHIFT)
-#define ARCH_PFN_OFFSET		(FPN_START)
+#define ARCH_PFN_OFFSET		(PFN_START)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define pfn_valid(pfn)		(((pfn) - PFN_START) < max_mapnr)
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h
index 88d1886..b7dc40b 100644
--- a/include/asm-sparc/mman.h
+++ b/include/asm-sparc/mman.h
@@ -35,4 +35,12 @@
 
 #define MADV_FREE	0x5		/* (Solaris) contents can be freed */
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#define arch_mmap_check	sparc_mmap_check
+int sparc_mmap_check(unsigned long addr, unsigned long len,
+		unsigned long flags);
+#endif
+#endif
+
 #endif /* __SPARC_MMAN_H__ */
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 15065af..c9f5c34 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -13,6 +13,7 @@
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define arch_remove_kprobe(p)	do {} while (0)
 #define  ARCH_INACTIVE_KPROBE_COUNT 0
+#define flush_insn_slot(p)	do { } while (0)
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h
index 6fd878e..8cc1860 100644
--- a/include/asm-sparc64/mman.h
+++ b/include/asm-sparc64/mman.h
@@ -35,4 +35,12 @@
 
 #define MADV_FREE	0x5		/* (Solaris) contents can be freed */
 
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+#define arch_mmap_check	sparc64_mmap_check
+int sparc64_mmap_check(unsigned long addr, unsigned long len,
+		unsigned long flags);
+#endif
+#endif
+
 #endif /* __SPARC64_MMAN_H__ */
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index 03f5bc9..ebfe395 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -234,7 +234,7 @@
 	sz_bits = 0UL;
 	if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) {
 		__asm__ __volatile__(
-		"\n661:	sethi		%uhi(%1), %0\n"
+		"\n661:	sethi		%%uhi(%1), %0\n"
 		"	sllx		%0, 32, %0\n"
 		"	.section	.sun4v_2insn_patch, \"ax\"\n"
 		"	.word		661b\n"
@@ -339,7 +339,7 @@
 	"	.section	.sun4v_2insn_patch, \"ax\"\n"
 	"	.word		661b\n"
 	"	andn		%0, %4, %0\n"
-	"	or		%0, %3, %0\n"
+	"	or		%0, %5, %0\n"
 	"	.previous\n"
 	: "=r" (val)
 	: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
diff --git a/include/asm-sparc64/sfp-machine.h b/include/asm-sparc64/sfp-machine.h
index 5015bb8..89d4243 100644
--- a/include/asm-sparc64/sfp-machine.h
+++ b/include/asm-sparc64/sfp-machine.h
@@ -34,7 +34,7 @@
 #define _FP_MUL_MEAT_D(R,X,Y)					\
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_Q(R,X,Y)					\
-  _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index aa67bfd..a584826 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -4,6 +4,7 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
+#include <asm/cpufeature.h>
 
 struct alt_instr {
 	u8 *instr; 		/* original instruction */
@@ -102,9 +103,6 @@
 /*
  * Alternative inline assembly for SMP.
  *
- * alternative_smp() takes two versions (SMP first, UP second) and is
- * for more complex stuff such as spinlocks.
- *
  * The LOCK_PREFIX macro defined here replaces the LOCK and
  * LOCK_PREFIX macros used everywhere in the source tree.
  *
@@ -124,21 +122,6 @@
  */
 
 #ifdef CONFIG_SMP
-#define alternative_smp(smpinstr, upinstr, args...)			\
-	asm volatile ("661:\n\t" smpinstr "\n662:\n"			\
-		      ".section .smp_altinstructions,\"a\"\n"		\
-		      "  .align 8\n"					\
-		      "  .quad 661b\n"            /* label */		\
-		      "  .quad 663f\n"		  /* new instruction */	\
-		      "  .byte 0x66\n"            /* X86_FEATURE_UP */	\
-		      "  .byte 662b-661b\n"       /* sourcelen */	\
-		      "  .byte 664f-663f\n"       /* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .smp_altinstr_replacement,\"awx\"\n"	\
-		      "663:\n\t" upinstr "\n"     /* replacement */	\
-		      "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
-		      ".previous" : args)
-
 #define LOCK_PREFIX \
 		".section .smp_locks,\"a\"\n"	\
 		"  .align 8\n"			\
@@ -147,8 +130,6 @@
 	       	"661:\n\tlock; "
 
 #else /* ! CONFIG_SMP */
-#define alternative_smp(smpinstr, upinstr, args...) \
-	asm volatile (upinstr : args)
 #define LOCK_PREFIX ""
 #endif
 
diff --git a/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h
index fbfb501..4e39195 100644
--- a/include/asm-x86_64/calgary.h
+++ b/include/asm-x86_64/calgary.h
@@ -60,9 +60,4 @@
 static inline void detect_calgary(void) { return; }
 #endif
 
-static inline unsigned int bus_to_phb(unsigned char busno)
-{
-	return ((busno % 15 == 0) ? 0 : busno / 2 + 1);
-}
-
 #endif /* _ASM_X86_64_CALGARY_H */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index d36febd..cf53178 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -47,6 +47,7 @@
 
 void kretprobe_trampoline(void);
 extern void arch_remove_kprobe(struct kprobe *p);
+#define flush_insn_slot(p)	do { } while (0)
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index f7bf875..10f3461 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -19,7 +19,7 @@
 #define EXCEPTION_STACK_ORDER 0
 #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
 
-#define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER
+#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1)
 #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER)
 
 #define IRQSTACK_ORDER 2
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 3b3c121..de9c314 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -232,8 +232,14 @@
 	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
 } __attribute__((packed)) ____cacheline_aligned;
 
+
 extern struct cpuinfo_x86 boot_cpu_data;
 DECLARE_PER_CPU(struct tss_struct,init_tss);
+/* Save the original ist values for checking stack pointers during debugging */
+struct orig_ist {
+	unsigned long ist[7];
+};
+DECLARE_PER_CPU(struct orig_ist, orig_ist);
 
 #ifdef CONFIG_X86_VSMP
 #define ARCH_MIN_TASKALIGN	(1 << INTERNODE_CACHE_SHIFT)
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 8d34219..248a79f 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -21,7 +21,7 @@
 
 #define __raw_spin_lock_string \
 	"\n1:\t" \
-	"lock ; decl %0\n\t" \
+	LOCK_PREFIX " ; decl %0\n\t" \
 	"js 2f\n" \
 	LOCK_SECTION_START("") \
 	"2:\t" \
@@ -40,10 +40,7 @@
 
 static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-	alternative_smp(
-		__raw_spin_lock_string,
-		__raw_spin_lock_string_up,
-		"=m" (lock->slock) : : "memory");
+	asm volatile(__raw_spin_lock_string : "=m" (lock->slock) : : "memory");
 }
 
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
@@ -125,12 +122,12 @@
 
 static inline void __raw_read_unlock(raw_rwlock_t *rw)
 {
-	asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
+	asm volatile(LOCK_PREFIX " ; incl %0" :"=m" (rw->lock) : : "memory");
 }
 
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
 {
-	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0"
+	asm volatile(LOCK_PREFIX " ; addl $" RW_LOCK_BIAS_STR ",%0"
 				: "=m" (rw->lock) : : "memory");
 }
 
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index 5f9a018..ba94ab3 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/include/asm-x86_64/swiotlb.h
@@ -42,6 +42,8 @@
 extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
 extern void swiotlb_init(void);
 
+extern int swiotlb_force;
+
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
 #else
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 94387c9..2d89d30 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -620,8 +620,6 @@
 #define __NR_move_pages		279
 __SYSCALL(__NR_move_pages, sys_move_pages)
 
-#ifdef __KERNEL__
-
 #define __NR_syscall_max __NR_move_pages
 
 #ifndef __NO_STUBS
@@ -746,6 +744,8 @@
 
 #else /* __KERNEL_SYSCALLS__ */
 
+#ifdef __KERNEL__
+
 #include <linux/syscalls.h>
 #include <asm/ptrace.h>
 
@@ -838,9 +838,9 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif	/* __ASSEMBLY__ */
+#endif
 
-#endif /* __NO_STUBS */
+#endif
 
 /*
  * "Conditional" syscalls
@@ -850,5 +850,6 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
+#endif
+
 #endif
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
index f3e7124..1f6e9bf 100644
--- a/include/asm-x86_64/unwind.h
+++ b/include/asm-x86_64/unwind.h
@@ -95,6 +95,7 @@
 #else
 
 #define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
 
 static inline int arch_unw_user_mode(const void *info)
 {
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 41788a3..2096e5c 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -7,7 +7,6 @@
 #define LINUX_ATMDEV_H
 
 
-#include <linux/device.h>
 #include <linux/atmapi.h>
 #include <linux/atm.h>
 #include <linux/atmioc.h>
@@ -210,6 +209,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/device.h>
 #include <linux/wait.h> /* wait_queue_head_t */
 #include <linux/time.h> /* struct timeval */
 #include <linux/net.h>
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b27d7de..40a6c26 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -132,6 +132,10 @@
 #define AUDIT_CLASS_DIR_WRITE_32 1
 #define AUDIT_CLASS_CHATTR 2
 #define AUDIT_CLASS_CHATTR_32 3
+#define AUDIT_CLASS_READ 4
+#define AUDIT_CLASS_READ_32 5
+#define AUDIT_CLASS_WRITE 6
+#define AUDIT_CLASS_WRITE_32 7
 
 /* This bitmask is used to validate user input.  It represents all bits that
  * are currently used in an audit field constant understood by the kernel.
@@ -177,6 +181,7 @@
 #define AUDIT_EXIT	103
 #define AUDIT_SUCCESS   104	/* exit >= 0; value ignored */
 #define AUDIT_WATCH	105
+#define AUDIT_PERM	106
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -252,6 +257,11 @@
 #define AUDIT_ARCH_V850		(EM_V850|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 
+#define AUDIT_PERM_EXEC		1
+#define AUDIT_PERM_WRITE	2
+#define AUDIT_PERM_READ		4
+#define AUDIT_PERM_ATTR		8
+
 struct audit_status {
 	__u32		mask;		/* Bit mask for valid entries */
 	__u32		enabled;	/* 1 = enabled, 0 = disabled */
@@ -314,6 +324,7 @@
 #define AUDITSC_FAILURE 2
 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
 extern int __init audit_register_class(int class, unsigned *list);
+extern int audit_classify_syscall(int abi, unsigned syscall);
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
 				/* Public API */
@@ -327,21 +338,31 @@
 extern void audit_putname(const char *name);
 extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
-				unsigned long pino);
+				const struct inode *parent);
+extern void __audit_inode_update(const struct inode *inode);
+static inline int audit_dummy_context(void)
+{
+	void *p = current->audit_context;
+	return !p || *(int *)p;
+}
 static inline void audit_getname(const char *name)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		__audit_getname(name);
 }
 static inline void audit_inode(const char *name, const struct inode *inode) {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		__audit_inode(name, inode);
 }
 static inline void audit_inode_child(const char *dname, 
-				     const struct inode *inode, 
-				     unsigned long pino) {
-	if (unlikely(current->audit_context))
-		__audit_inode_child(dname, inode, pino);
+				     const struct inode *inode,
+				     const struct inode *parent) {
+	if (unlikely(!audit_dummy_context()))
+		__audit_inode_child(dname, inode, parent);
+}
+static inline void audit_inode_update(const struct inode *inode) {
+	if (unlikely(!audit_dummy_context()))
+		__audit_inode_update(inode);
 }
 
 				/* Private API (for audit.c only) */
@@ -365,57 +386,61 @@
 
 static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_ipc_obj(ipcp);
 	return 0;
 }
 static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_ipc_set_perm(qbytes, uid, gid, mode);
 	return 0;
 }
 static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_mq_open(oflag, mode, u_attr);
 	return 0;
 }
 static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
 	return 0;
 }
 static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
 	return 0;
 }
 static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_mq_notify(mqdes, u_notification);
 	return 0;
 }
 static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
 {
-	if (unlikely(current->audit_context))
+	if (unlikely(!audit_dummy_context()))
 		return __audit_mq_getsetattr(mqdes, mqstat);
 	return 0;
 }
+extern int audit_n_rules;
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
 #define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0)
 #define audit_syscall_exit(f,r) do { ; } while (0)
+#define audit_dummy_context() 1
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
 #define __audit_inode(n,i) do { ; } while (0)
 #define __audit_inode_child(d,i,p) do { ; } while (0)
+#define __audit_inode_update(i) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
 #define audit_inode_child(d,i,p) do { ; } while (0)
+#define audit_inode_update(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_obj(i) ({ 0; })
@@ -430,6 +455,7 @@
 #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_n_rules 0
 #endif
 
 #ifdef CONFIG_AUDIT
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index dbb7769..1c86d65 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -57,7 +57,8 @@
 		PROC_EVENT_EXIT = 0x80000000
 	} what;
 	__u32 cpu;
-	struct timespec timestamp;
+	__u64 __attribute__((aligned(8))) timestamp_ns;
+		/* Number of nano seconds since system boot */
 	union { /* must be last field of proc_event struct */
 		struct {
 			__u32 err;
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 269d000..bea0255 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -216,6 +216,7 @@
 COMPATIBLE_IOCTL(VT_RESIZEX)
 COMPATIBLE_IOCTL(VT_LOCKSWITCH)
 COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+COMPATIBLE_IOCTL(VT_GETHIFONTMASK)
 /* Little p (/dev/rtc, /dev/envctrl, etc.) */
 COMPATIBLE_IOCTL(RTC_AIE_ON)
 COMPATIBLE_IOCTL(RTC_AIE_OFF)
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 6a70478..88dafa2 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_DEBUG_LOCKING_H
 #define __LINUX_DEBUG_LOCKING_H
 
+struct task_struct;
+
 extern int debug_locks;
 extern int debug_locks_silent;
 
diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h
index 7e8b601..561e2a7 100644
--- a/include/linux/delayacct.h
+++ b/include/linux/delayacct.h
@@ -55,14 +55,18 @@
 {
 	/* reinitialize in case parent's non-null pointer was dup'ed*/
 	tsk->delays = NULL;
-	if (unlikely(delayacct_on))
+	if (delayacct_on)
 		__delayacct_tsk_init(tsk);
 }
 
-static inline void delayacct_tsk_exit(struct task_struct *tsk)
+/* Free tsk->delays. Called from bad fork and __put_task_struct
+ * where there's no risk of tsk->delays being accessed elsewhere
+ */
+static inline void delayacct_tsk_free(struct task_struct *tsk)
 {
 	if (tsk->delays)
-		__delayacct_tsk_exit(tsk);
+		kmem_cache_free(delayacct_cache, tsk->delays);
+	tsk->delays = NULL;
 }
 
 static inline void delayacct_blkio_start(void)
@@ -80,9 +84,7 @@
 static inline int delayacct_add_tsk(struct taskstats *d,
 					struct task_struct *tsk)
 {
-	if (likely(!delayacct_on))
-		return -EINVAL;
-	if (!tsk->delays)
+	if (!delayacct_on || !tsk->delays)
 		return 0;
 	return __delayacct_add_tsk(d, tsk);
 }
@@ -103,7 +105,7 @@
 {}
 static inline void delayacct_tsk_init(struct task_struct *tsk)
 {}
-static inline void delayacct_tsk_exit(struct task_struct *tsk)
+static inline void delayacct_tsk_free(struct task_struct *tsk)
 {}
 static inline void delayacct_blkio_start(void)
 {}
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 5607e64..9f9cce7 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -492,6 +492,15 @@
 {
 	return container_of(inode, struct ext3_inode_info, vfs_inode);
 }
+
+static inline int ext3_valid_inum(struct super_block *sb, unsigned long ino)
+{
+	return ino == EXT3_ROOT_INO ||
+		ino == EXT3_JOURNAL_INO ||
+		ino == EXT3_RESIZE_INO ||
+		(ino >= EXT3_FIRST_INO(sb) &&
+		 ino <= le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count));
+}
 #else
 /* Assume that user mode programs are passing in an ext3fs superblock, not
  * a kernel struct super_block.  This will allow us to call the feature-test
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 405f44e..2f335e96 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_FB_H
 #define _LINUX_FB_H
 
-#include <linux/backlight.h>
 #include <asm/types.h>
 
 /* Definitions of frame buffers						*/
@@ -381,6 +380,7 @@
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
 #include <linux/list.h>
+#include <linux/backlight.h>
 #include <asm/io.h>
 
 struct vm_area_struct;
@@ -524,7 +524,7 @@
 
 extern int fb_register_client(struct notifier_block *nb);
 extern int fb_unregister_client(struct notifier_block *nb);
-
+extern int fb_notifier_call_chain(unsigned long val, void *v);
 /*
  * Pixmap structure definition
  *
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2561020..555bc19 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -570,13 +570,14 @@
  * 3: quota file
  *
  * The locking order between these classes is
- * parent -> child -> normal -> quota
+ * parent -> child -> normal -> xattr -> quota
  */
 enum inode_i_mutex_lock_class
 {
 	I_MUTEX_NORMAL,
 	I_MUTEX_PARENT,
 	I_MUTEX_CHILD,
+	I_MUTEX_XATTR,
 	I_MUTEX_QUOTA
 };
 
diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h
index 783c476..74ed35a 100644
--- a/include/linux/fs_enet_pd.h
+++ b/include/linux/fs_enet_pd.h
@@ -69,34 +69,21 @@
 	fsiop_porte,
 };
 
-struct fs_mii_bus_info {
-	int method;		/* mii method                  */
-	int id;			/* the id of the mii_bus       */
-	int disable_aneg;	/* if the controller needs to negothiate speed & duplex */
-	int lpa; 		/* the default board-specific vallues will be applied otherwise */
-
-	union {
-		struct {
-			int duplex;
-			int speed;
-		} fixed;
-
-		struct {
-			/* nothing */
-		} fec;
-		
-		struct {
-			/* nothing */
-		} scc;
-
-		struct {
-			int mdio_port;	/* port & bit for MDIO */
-			int mdio_bit;
-			int mdc_port;	/* port & bit for MDC  */
-			int mdc_bit;
-			int delay;	/* delay in us         */
-		} bitbang;
-	} i;
+struct fs_mii_bit {
+	u32 offset;
+	u8 bit;
+	u8 polarity;
+};
+struct fs_mii_bb_platform_info {
+	struct fs_mii_bit 	mdio_dir;
+	struct fs_mii_bit 	mdio_dat;
+	struct fs_mii_bit	mdc_dat;
+	int mdio_port;	/* port & bit for MDIO */
+	int mdio_bit;
+	int mdc_port;	/* port & bit for MDC  */
+	int mdc_bit;
+	int delay;	/* delay in us         */
+	int irq[32]; 	/* irqs per phy's */
 };
 
 struct fs_platform_info {
@@ -119,6 +106,7 @@
 	u32 device_flags;
 
 	int phy_addr;		/* the phy address (-1 no phy) */
+	const char*	bus_id;
 	int phy_irq;		/* the phy irq (if it exists)  */
 
 	const struct fs_mii_bus_info *bus_info;
@@ -130,6 +118,10 @@
 	int napi_weight;	/* NAPI weight                 */
 
 	int use_rmii;		/* use RMII mode 	       */
+	int has_phy;            /* if the network is phy container as well...*/
 };
-
+struct fs_mii_fec_platform_info {
+	u32 irq[32];
+	u32 mii_speed;
+};
 #endif
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index cc5dec7..d4f219f 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -67,7 +67,7 @@
 	if (source) {
 		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
 	}
-	audit_inode_child(new_name, source, new_dir->i_ino);
+	audit_inode_child(new_name, source, new_dir);
 }
 
 /*
@@ -98,7 +98,7 @@
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
 				  dentry->d_inode);
-	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
+	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
 }
 
 /*
@@ -109,7 +109,7 @@
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 
 				  dentry->d_name.name, dentry->d_inode);
-	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
+	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode);
 }
 
 /*
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 34c3a21..d097b5b7 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -96,7 +96,8 @@
 long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
 	      u32 __user *uaddr2, u32 val2, u32 val3);
 
-extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr);
+extern int
+handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi);
 
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index e4bccbc..4fc379d 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -80,6 +80,7 @@
  * @get_softirq_time:	function to retrieve the current time from the softirq
  * @curr_timer:		the timer which is executing a callback right now
  * @softirq_time:	the time when running the hrtimer queue in the softirq
+ * @lock_key:		the lock_class_key for use with lockdep
  */
 struct hrtimer_base {
 	clockid_t		index;
diff --git a/include/linux/ide.h b/include/linux/ide.h
index dc7abef..9962045 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -571,6 +571,7 @@
 	u8	waiting_for_dma;	/* dma currently in progress */
 	u8	unmask;			/* okay to unmask other irqs */
 	u8	bswap;			/* byte swap data */
+	u8	noflush;		/* don't attempt flushes */
 	u8	dsc_overlap;		/* DSC overlap */
 	u8	nice1;			/* give potential excess bandwidth */
 
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 383627a..ab274083 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -155,6 +155,11 @@
 {
 	struct net_device_stats *stats;
 
+	if (skb_bond_should_drop(skb)) {
+		dev_kfree_skb_any(skb);
+		return NET_RX_DROP;
+	}
+
 	skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
 	if (skb->dev == NULL) {
 		dev_kfree_skb_any(skb);
diff --git a/include/linux/input.h b/include/linux/input.h
index 56f1e0e..b3253ab 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -893,7 +893,6 @@
 
 	int (*open)(struct input_dev *dev);
 	void (*close)(struct input_dev *dev);
-	int (*accept)(struct input_dev *dev, struct file *file);
 	int (*flush)(struct input_dev *dev, struct file *file);
 	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 	int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
@@ -961,6 +960,26 @@
 
 struct input_handle;
 
+/**
+ * struct input_handler - implements one of interfaces for input devices
+ * @private: driver-specific data
+ * @event: event handler
+ * @connect: called when attaching a handler to an input device
+ * @disconnect: disconnects a handler from input device
+ * @start: starts handler for given handle. This function is called by
+ *	input core right after connect() method and also when a process
+ *	that "grabbed" a device releases it
+ * @fops: file operations this driver implements
+ * @minor: beginning of range of 32 minors for devices this driver
+ *	can provide
+ * @name: name of the handler, to be shown in /proc/bus/input/handlers
+ * @id_table: pointer to a table of input_device_ids this driver can
+ *	handle
+ * @blacklist: prointer to a table of input_device_ids this driver should
+ *	ignore even if they match @id_table
+ * @h_list: list of input handles associated with the handler
+ * @node: for placing the driver onto input_handler_list
+ */
 struct input_handler {
 
 	void *private;
@@ -968,6 +987,7 @@
 	void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 	struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
 	void (*disconnect)(struct input_handle *handle);
+	void (*start)(struct input_handle *handle);
 
 	const struct file_operations *fops;
 	int minor;
@@ -1030,10 +1050,10 @@
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
-int input_accept_process(struct input_handle *handle, struct file *file);
 int input_flush_device(struct input_handle* handle, struct file* file);
 
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 
 static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
 {
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
index 88d5961..8e2042b 100644
--- a/include/linux/ioprio.h
+++ b/include/linux/ioprio.h
@@ -59,27 +59,6 @@
 /*
  * For inheritance, return the highest of the two given priorities
  */
-static inline int ioprio_best(unsigned short aprio, unsigned short bprio)
-{
-	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
-	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
-
-	if (!ioprio_valid(aprio))
-		return bprio;
-	if (!ioprio_valid(bprio))
-		return aprio;
-
-	if (aclass == IOPRIO_CLASS_NONE)
-		aclass = IOPRIO_CLASS_BE;
-	if (bclass == IOPRIO_CLASS_NONE)
-		bclass = IOPRIO_CLASS_BE;
-
-	if (aclass == bclass)
-		return min(aprio, bprio);
-	if (aclass > bclass)
-		return bprio;
-	else
-		return aprio;
-}
+extern int ioprio_best(unsigned short aprio, unsigned short bprio);
 
 #endif
diff --git a/include/linux/irq.h b/include/linux/irq.h
index b48eae3..fbf6d90 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -47,8 +47,8 @@
 #define IRQ_WAITING		0x00200000	/* IRQ not yet seen - for autodetection */
 #define IRQ_LEVEL		0x00400000	/* IRQ level triggered */
 #define IRQ_MASKED		0x00800000	/* IRQ masked - shouldn't be seen again */
+#define IRQ_PER_CPU		0x01000000	/* IRQ is per CPU */
 #ifdef CONFIG_IRQ_PER_CPU
-# define IRQ_PER_CPU		0x01000000	/* IRQ is per CPU */
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
 #else
 # define CHECK_IRQ_PER_CPU(var) 0
@@ -58,6 +58,7 @@
 #define IRQ_NOREQUEST		0x04000000	/* IRQ cannot be requested */
 #define IRQ_NOAUTOEN		0x08000000	/* IRQ will not be enabled on request irq */
 #define IRQ_DELAYED_DISABLE	0x10000000	/* IRQ disable (masking) happens delayed. */
+#define IRQ_WAKEUP		0x20000000	/* IRQ triggers system wakeup */
 
 struct proc_dir_entry;
 
@@ -124,6 +125,7 @@
  * @action:		the irq action chain
  * @status:		status information
  * @depth:		disable-depth, for nested irq_disable() calls
+ * @wake_depth:		enable depth, for multiple set_irq_wake() callers
  * @irq_count:		stats field to detect stalled irqs
  * @irqs_unhandled:	stats field for spurious unhandled interrupts
  * @lock:		locking for SMP
@@ -147,6 +149,7 @@
 	unsigned int		status;		/* IRQ status */
 
 	unsigned int		depth;		/* nested irq disables */
+	unsigned int		wake_depth;	/* nested wake enables */
 	unsigned int		irq_count;	/* For detecting broken IRQs */
 	unsigned int		irqs_unhandled;
 	spinlock_t		lock;
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 20eb344..a04c154 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -72,6 +72,9 @@
 #endif
 
 extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry);
+extern void * jbd_slab_alloc(size_t size, gfp_t flags);
+extern void jbd_slab_free(void *ptr, size_t size);
+
 #define jbd_kmalloc(size, flags) \
 	__jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry)
 #define jbd_rep_kmalloc(size, flags) \
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 0433769..329ebcf 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -47,8 +47,8 @@
  *   - (NOM / DEN) fits in (32 - LSH) bits.
  *   - (NOM % DEN) fits in (32 - LSH) bits.
  */
-#define SH_DIV(NOM,DEN,LSH) (   ((NOM / DEN) << LSH)                    \
-                             + (((NOM % DEN) << LSH) + DEN / 2) / DEN)
+#define SH_DIV(NOM,DEN,LSH) (   (((NOM) / (DEN)) << (LSH))              \
+                             + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))
 
 /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
 #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 181c69c..851aa1b 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -210,6 +210,7 @@
 extern void dump_stack(void);
 
 #ifdef DEBUG
+/* If you are writing a driver, please use dev_dbg instead */
 #define pr_debug(fmt,arg...) \
 	printk(KERN_DEBUG fmt,##arg)
 #else
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 0503b2e..2d22932 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -46,8 +46,6 @@
 	KOBJ_UMOUNT	= (__force kobject_action_t) 0x05,	/* umount event for block devices (broken) */
 	KOBJ_OFFLINE	= (__force kobject_action_t) 0x06,	/* device offline */
 	KOBJ_ONLINE	= (__force kobject_action_t) 0x07,	/* device online */
-	KOBJ_UNDOCK	= (__force kobject_action_t) 0x08, 	/* undocking */
-	KOBJ_DOCK	= (__force kobject_action_t) 0x09,	/* dock */
 };
 
 struct kobject {
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index ed3396d..84eeecd 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -56,7 +56,8 @@
 #endif
 } ktime_t;
 
-#define KTIME_MAX			(~((u64)1 << 63))
+#define KTIME_MAX			((s64)~((u64)1 << 63))
+#define KTIME_SEC_MAX			(KTIME_MAX / NSEC_PER_SEC)
 
 /*
  * ktime_t definitions when using the 64-bit scalar representation:
@@ -73,6 +74,10 @@
  */
 static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
 {
+#if (BITS_PER_LONG == 64)
+	if (unlikely(secs >= KTIME_SEC_MAX))
+		return (ktime_t){ .tv64 = KTIME_MAX };
+#endif
 	return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
 }
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 6cc497a..66c3100 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -265,12 +265,14 @@
 
 	/* ata_eh_info->flags */
 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
-	ATA_EHI_RESUME_LINK	= (1 << 1),  /* need to resume link */
+	ATA_EHI_RESUME_LINK	= (1 << 1),  /* resume link (reset modifier) */
 	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
 	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
 
 	ATA_EHI_DID_RESET	= (1 << 16), /* already reset this port */
 
+	ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK,
+
 	/* max repeat if error condition is still set after ->error_handler */
 	ATA_EH_MAX_REPEAT	= 5,
 
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index aa4fe90..0d92c46 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -123,7 +123,6 @@
 	unsigned int		b_id;		/* block id */
 	unsigned char		b_queued;	/* re-queued */
 	unsigned char		b_granted;	/* VFS granted lock */
-	unsigned char		b_done;		/* callback complete */
 	struct nlm_file *	b_file;		/* file in question */
 };
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 990957e..f0b135c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -336,6 +336,7 @@
 }
 
 void put_page(struct page *page);
+void put_pages_list(struct list_head *pages);
 
 void split_page(struct page *page, unsigned int order);
 
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index c1f021e..ba095ae 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -77,7 +77,7 @@
 	struct device		*dev;
 	struct class_device	class_dev;
 	int			index;
-	struct mmc_host_ops	*ops;
+	const struct mmc_host_ops *ops;
 	unsigned int		f_min;
 	unsigned int		f_max;
 	u32			ocr_avail;
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 03a14a3..627e2c0 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -105,6 +105,8 @@
 extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int,
 	struct mmc_command *, int);
 
+extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int);
+
 extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card);
 
 static inline void mmc_claim_host(struct mmc_host *host)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 656b588..f45163c 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -77,6 +77,7 @@
 struct per_cpu_pageset {
 	struct per_cpu_pages pcp[2];	/* 0: hot.  1: cold */
 #ifdef CONFIG_SMP
+	s8 stat_threshold;
 	s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS];
 #endif
 } ____cacheline_aligned_in_smp;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 75f02d8..50a4719 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -320,6 +320,9 @@
 #define NETIF_F_TSO_ECN		(SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT)
 #define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
 
+	/* List of features with software fallbacks. */
+#define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
 #define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 #define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
 
@@ -1012,6 +1015,30 @@
 		unlikely(skb->ip_summed != CHECKSUM_HW));
 }
 
+/* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ */
+static inline int skb_bond_should_drop(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	struct net_device *master = dev->master;
+
+	if (master &&
+	    (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+		if (master->priv_flags & IFF_MASTER_ALB) {
+			if (skb->pkt_type != PACKET_BROADCAST &&
+			    skb->pkt_type != PACKET_MULTICAST)
+				return 0;
+		}
+		if (master->priv_flags & IFF_MASTER_8023AD &&
+		    skb->protocol == __constant_htons(ETH_P_SLOW))
+			return 0;
+
+		return 1;
+	}
+	return 0;
+}
+
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_DEV_H */
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 31f02ba03..427c67f 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -6,7 +6,6 @@
 
 #include <linux/netfilter.h>
 #if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
-#include <asm/atomic.h>
 #include <linux/if_ether.h>
 #endif
 
@@ -49,15 +48,25 @@
 
 /* Only used in br_forward.c */
 static inline
-void nf_bridge_maybe_copy_header(struct sk_buff *skb)
+int nf_bridge_maybe_copy_header(struct sk_buff *skb)
 {
+	int err;
+
 	if (skb->nf_bridge) {
 		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+			err = skb_cow(skb, 18);
+			if (err)
+				return err;
 			memcpy(skb->data - 18, skb->nf_bridge->data, 18);
 			skb_push(skb, 4);
-		} else
+		} else {
+			err = skb_cow(skb, 16);
+			if (err)
+				return err;
 			memcpy(skb->data - 16, skb->nf_bridge->data, 16);
+		}
 	}
+	return 0;
 }
 
 /* This is called by the IP fragmenting code and it ensures there is
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 55ea853..530b1e6 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -427,7 +427,7 @@
 extern void nfs_writedata_release(void *);
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount);
+struct nfs_write_data *nfs_commit_alloc(void);
 void nfs_commit_free(struct nfs_write_data *p);
 #endif
 
@@ -476,10 +476,9 @@
 }
 
 /*
- * Allocate and free nfs_write_data structures
+ * Allocate nfs_write_data structures
  */
-extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
-extern void nfs_writedata_free(struct nfs_write_data *p);
+extern struct nfs_write_data *nfs_writedata_alloc(size_t len);
 
 /*
  * linux/fs/nfs/read.c
@@ -491,10 +490,9 @@
 extern void nfs_readdata_release(void *data);
 
 /*
- * Allocate and free nfs_read_data structures
+ * Allocate nfs_read_data structures
  */
-extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
-extern void nfs_readdata_free(struct nfs_read_data *p);
+extern struct nfs_read_data *nfs_readdata_alloc(size_t len);
 
 /*
  * linux/fs/nfs3proc.c
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 2d3fb64..41e5a19 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -659,7 +659,7 @@
 struct nfs4_setclientid {
 	const nfs4_verifier *		sc_verifier;      /* request */
 	unsigned int			sc_name_len;
-	char				sc_name[32];	  /* request */
+	char				sc_name[48];	  /* request */
 	u32				sc_prog;          /* request */
 	unsigned int			sc_netid_len;
 	char				sc_netid[4];	  /* request */
@@ -729,7 +729,7 @@
 	struct list_head	pages;	/* Coalesced read requests */
 	struct nfs_page		*req;	/* multi ops per nfs_page */
 	struct page		**pagevec;
-	unsigned int		npages;	/* active pages in pagevec */
+	unsigned int		npages;	/* Max length of pagevec */
 	struct nfs_readargs args;
 	struct nfs_readres  res;
 #ifdef CONFIG_NFS_V4
@@ -748,7 +748,7 @@
 	struct list_head	pages;		/* Coalesced requests we wish to flush */
 	struct nfs_page		*req;		/* multi ops per nfs_page */
 	struct page		**pagevec;
-	unsigned int		npages;		/* active pages in pagevec */
+	unsigned int		npages;		/* Max length of pagevec */
 	struct nfs_writeargs	args;		/* argument struct */
 	struct nfs_writeres	res;		/* result struct */
 #ifdef CONFIG_NFS_V4
diff --git a/include/linux/node.h b/include/linux/node.h
index 81dcec8..bc001bc 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -30,12 +30,20 @@
 
 extern int register_node(struct node *, int, struct node *);
 extern void unregister_node(struct node *node);
+#ifdef CONFIG_NUMA
 extern int register_one_node(int nid);
 extern void unregister_one_node(int nid);
-#ifdef CONFIG_NUMA
 extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);
 extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
 #else
+static inline int register_one_node(int nid)
+{
+	return 0;
+}
+static inline int unregister_one_node(int nid)
+{
+	return 0;
+}
 static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid)
 {
 	return 0;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c09396d..7a24915 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -648,6 +648,8 @@
 #define PCI_DEVICE_ID_SI_962		0x0962
 #define PCI_DEVICE_ID_SI_963		0x0963
 #define PCI_DEVICE_ID_SI_965		0x0965
+#define PCI_DEVICE_ID_SI_966		0x0966
+#define PCI_DEVICE_ID_SI_968		0x0968
 #define PCI_DEVICE_ID_SI_5511		0x5511
 #define PCI_DEVICE_ID_SI_5513		0x5513
 #define PCI_DEVICE_ID_SI_5517		0x5517
@@ -1292,6 +1294,7 @@
 #define PCI_DEVICE_ID_VIA_8367_0	0x3099
 #define PCI_DEVICE_ID_VIA_8653_0	0x3101
 #define PCI_DEVICE_ID_VIA_8622		0x3102
+#define PCI_DEVICE_ID_VIA_8235_USB_2	0x3104
 #define PCI_DEVICE_ID_VIA_8233C_0	0x3109
 #define PCI_DEVICE_ID_VIA_8361		0x3112
 #define PCI_DEVICE_ID_VIA_XM266		0x3116
@@ -1726,6 +1729,9 @@
 #define PCI_VENDOR_ID_DOMEX		0x134a
 #define PCI_DEVICE_ID_DOMEX_DMX3191D	0x0001
 
+#define PCI_VENDOR_ID_INTASHIELD	0x135a
+#define PCI_DEVICE_ID_INTASHIELD_IS200	0x0d80
+
 #define PCI_VENDOR_ID_QUATECH		0x135C
 #define PCI_DEVICE_ID_QUATECH_QSC100	0x0010
 #define PCI_DEVICE_ID_QUATECH_DSC100	0x0020
@@ -2142,6 +2148,7 @@
 #define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
 #define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
 #define PCI_DEVICE_ID_INTEL_82860_HB	0x2531
+#define PCI_DEVICE_ID_INTEL_E7501_MCH	0x254c
 #define PCI_DEVICE_ID_INTEL_82845G_HB	0x2560
 #define PCI_DEVICE_ID_INTEL_82845G_IG	0x2562
 #define PCI_DEVICE_ID_INTEL_82865_HB	0x2570
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 331521a..9447a57 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -378,6 +378,7 @@
 		struct mii_ioctl_data *mii_data, int cmd);
 int phy_start_interrupts(struct phy_device *phydev);
 void phy_print_status(struct phy_device *phydev);
+struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
 
 extern struct bus_type mdio_bus_type;
 #endif /* __PHY_H */
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index 2ed807d..7831773 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -231,7 +231,6 @@
 extern unsigned int pmu_power_flags;
 
 /* Backlight */
-extern int disable_kernel_backlight;
-extern void pmu_backlight_init(struct device_node*);
+extern void pmu_backlight_init(void);
 
 #endif	/* __KERNEL__ */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6afa72e..34ed0d9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -994,7 +994,6 @@
 	 */
 	struct pipe_inode_info *splice_pipe;
 #ifdef	CONFIG_TASK_DELAY_ACCT
-	spinlock_t delays_lock;
 	struct task_delay_info *delays;
 #endif
 };
@@ -1558,6 +1557,14 @@
 }
 
 /*
+ * Sometimes we may need to cancel the previous 'freeze' request
+ */
+static inline void do_not_freeze(struct task_struct *p)
+{
+	p->flags &= ~PF_FREEZE;
+}
+
+/*
  * Wake up a frozen process
  */
 static inline int thaw_process(struct task_struct *p)
diff --git a/include/linux/security.h b/include/linux/security.h
index f753038..6bc2aad 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1109,6 +1109,16 @@
  *	@name contains the name of the security module being unstacked.
  *	@ops contains a pointer to the struct security_operations of the module to unstack.
  * 
+ * @secid_to_secctx:
+ *	Convert secid to security context.
+ *	@secid contains the security ID.
+ *	@secdata contains the pointer that stores the converted security context.
+ *
+ * @release_secctx:
+ *	Release the security context.
+ *	@secdata contains the security context.
+ *	@seclen contains the length of the security context.
+ *
  * This is the main security structure.
  */
 struct security_operations {
@@ -1289,6 +1299,8 @@
 
  	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
  	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
+	void (*release_secctx)(char *secdata, u32 seclen);
 
 #ifdef CONFIG_SECURITY_NETWORK
 	int (*unix_stream_connect) (struct socket * sock,
@@ -1317,7 +1329,7 @@
 	int (*socket_shutdown) (struct socket * sock, int how);
 	int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb);
 	int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
-	int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, u32 *seclen);
+	int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
 	int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
 	void (*sk_free_security) (struct sock *sk);
 	unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
@@ -2059,6 +2071,16 @@
 	return security_ops->netlink_recv(skb, cap);
 }
 
+static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+	return security_ops->secid_to_secctx(secid, secdata, seclen);
+}
+
+static inline void security_release_secctx(char *secdata, u32 seclen)
+{
+	return security_ops->release_secctx(secdata, seclen);
+}
+
 /* prototypes */
 extern int security_init	(void);
 extern int register_security	(struct security_operations *ops);
@@ -2725,6 +2747,14 @@
 {
 }
 
+static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void security_release_secctx(char *secdata, u32 seclen)
+{
+}
 #endif	/* CONFIG_SECURITY */
 
 #ifdef CONFIG_SECURITY_NETWORK
@@ -2840,10 +2870,9 @@
 	return security_ops->socket_getpeersec_stream(sock, optval, optlen, len);
 }
 
-static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
-						   u32 *seclen)
+static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
-	return security_ops->socket_getpeersec_dgram(skb, secdata, seclen);
+	return security_ops->socket_getpeersec_dgram(sock, skb, secid);
 }
 
 static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
@@ -2968,8 +2997,7 @@
 	return -ENOPROTOOPT;
 }
 
-static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
-						   u32 *seclen)
+static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
 	return -ENOPROTOOPT;
 }
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4307e76..755e9cd 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -604,12 +604,17 @@
 	return list_->qlen;
 }
 
-extern struct lock_class_key skb_queue_lock_key;
-
+/*
+ * This function creates a split out lock class for each invocation;
+ * this is needed for now since a whole lot of users of the skb-queue
+ * infrastructure in drivers have different locking usage (in hardirq)
+ * than the networking core (in softirq only). In the long run either the
+ * network layer or drivers should need annotation to consolidate the
+ * main types of usage into 3 classes.
+ */
 static inline void skb_queue_head_init(struct sk_buff_head *list)
 {
 	spin_lock_init(&list->lock);
-	lockdep_set_class(&list->lock, &skb_queue_lock_key);
 	list->prev = list->next = (struct sk_buff *)list;
 	list->qlen = 0;
 }
@@ -1035,6 +1040,21 @@
 }
 
 /**
+ *	pskb_trim_unique - remove end from a paged unique (not cloned) buffer
+ *	@skb: buffer to alter
+ *	@len: new length
+ *
+ *	This is identical to pskb_trim except that the caller knows that
+ *	the skb is not cloned so we should never get an error due to out-
+ *	of-memory.
+ */
+static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len)
+{
+	int err = pskb_trim(skb, len);
+	BUG_ON(err);
+}
+
+/**
  *	skb_orphan - orphan a buffer
  *	@skb: buffer to orphan
  *
@@ -1076,7 +1096,7 @@
  *	the headroom they think they need without accounting for the
  *	built in space. The built in space is used for optimisations.
  *
- *	%NULL is returned in there is no free memory.
+ *	%NULL is returned if there is no free memory.
  */
 static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
 					      gfp_t gfp_mask)
@@ -1096,7 +1116,7 @@
  *	the headroom they think they need without accounting for the
  *	built in space. The built in space is used for optimisations.
  *
- *	%NULL is returned in there is no free memory. Although this function
+ *	%NULL is returned if there is no free memory. Although this function
  *	allocates memory it can be called from an interrupt.
  */
 static inline struct sk_buff *dev_alloc_skb(unsigned int length)
@@ -1104,6 +1124,28 @@
 	return __dev_alloc_skb(length, GFP_ATOMIC);
 }
 
+extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+		unsigned int length, gfp_t gfp_mask);
+
+/**
+ *	netdev_alloc_skb - allocate an skbuff for rx on a specific device
+ *	@dev: network device to receive on
+ *	@length: length to allocate
+ *
+ *	Allocate a new &sk_buff and assign it a usage count of one. The
+ *	buffer has unspecified headroom built in. Users should allocate
+ *	the headroom they think they need without accounting for the
+ *	built in space. The built in space is used for optimisations.
+ *
+ *	%NULL is returned if there is no free memory. Although this function
+ *	allocates memory it can be called from an interrupt.
+ */
+static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
+		unsigned int length)
+{
+	return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
+}
+
 /**
  *	skb_cow - copy header of skb when it is required
  *	@skb: buffer to cow
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 2c2189c..a481472 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -42,9 +42,9 @@
 extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
 
 extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
-extern int rpc_rmdir(char *);
+extern int rpc_rmdir(struct dentry *);
 extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
-extern int rpc_unlink(char *);
+extern int rpc_unlink(struct dentry *);
 extern struct vfsmount *rpc_get_mount(void);
 extern void rpc_put_mount(void);
 
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index e8bbe81..3a0cca2 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -37,7 +37,7 @@
 
 #define RPC_MIN_RESVPORT	(1U)
 #define RPC_MAX_RESVPORT	(65535U)
-#define RPC_DEF_MIN_RESVPORT	(650U)
+#define RPC_DEF_MIN_RESVPORT	(665U)
 #define RPC_DEF_MAX_RESVPORT	(1023U)
 
 /*
@@ -229,7 +229,7 @@
 int			xprt_reserve_xprt_cong(struct rpc_task *task);
 int			xprt_prepare_transmit(struct rpc_task *task);
 void			xprt_transmit(struct rpc_task *task);
-void			xprt_abort_transmit(struct rpc_task *task);
+void			xprt_end_transmit(struct rpc_task *task);
 int			xprt_adjust_timeout(struct rpc_rqst *req);
 void			xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
 void			xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e421d5e..04827ca 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -59,6 +59,7 @@
 	struct tty_buffer *head;	/* Queue head */
 	struct tty_buffer *tail;	/* Active buffer */
 	struct tty_buffer *free;	/* Free queue head */
+	int memory_used;		/* Buffer space used excluding free queue */
 };
 /*
  * The pty uses char_buf and flag_buf as a contiguous buffer
diff --git a/include/linux/usb.h b/include/linux/usb.h
index c944e8f..d2bd0c8 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -103,8 +103,7 @@
  * @condition: binding state of the interface: not bound, binding
  *	(in probe()), bound to a driver, or unbinding (in disconnect())
  * @dev: driver model's view of this device
- * @usb_dev: if an interface is bound to the USB major, this will point
- *	to the sysfs representation for that device.
+ * @class_dev: driver model's class view of this device.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -144,7 +143,7 @@
 					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
 	struct device dev;		/* interface specific device info */
-	struct device *usb_dev;		/* pointer to the usb class's device, if any */
+	struct class_device *class_dev;
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define	interface_to_usbdev(intf) \
@@ -361,7 +360,7 @@
 	char *serial;			/* iSerialNumber string, if present */
 
 	struct list_head filelist;
-	struct device *usbfs_dev;
+	struct class_device *class_dev;
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
 
 	/*
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index f38f43f..e7fc5fe 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -44,7 +44,9 @@
 	US_FLAG(NO_WP_DETECT,	0x00000200)			\
 		/* Don't check for write-protect */		\
 	US_FLAG(MAX_SECTORS_64,	0x00000400)			\
-		/* Sets max_sectors to 64    */
+		/* Sets max_sectors to 64    */			\
+	US_FLAG(IGNORE_DEVICE,	0x00000800)			\
+		/* Don't claim device */
 
 #define US_FLAG(name, value)	US_FL_##name = value ,
 enum { US_DO_ALL_FLAGS };
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 41bc7e9..518c7a3 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -12,10 +12,11 @@
 #ifndef __LINUX_VIDEODEV_H
 #define __LINUX_VIDEODEV_H
 
-#define HAVE_V4L1 1
-
 #include <linux/videodev2.h>
 
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+#define HAVE_V4L1 1
+
 struct video_capability
 {
 	char name[32];
@@ -336,6 +337,8 @@
 #define VID_HARDWARE_SN9C102	38
 #define VID_HARDWARE_ARV	39
 
+#endif /* CONFIG_VIDEO_V4L1_COMPAT */
+
 #endif /* __LINUX_VIDEODEV_H */
 
 /*
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index a62673d..b714695 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -716,7 +716,7 @@
 		__s64 value64;
 		void *reserved;
 	};
-};
+} __attribute__ ((packed));
 
 struct v4l2_ext_controls
 {
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 1ab806c..2d9b1b6 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -41,23 +41,23 @@
 
 static inline void __count_vm_event(enum vm_event_item item)
 {
-	__get_cpu_var(vm_event_states.event[item])++;
+	__get_cpu_var(vm_event_states).event[item]++;
 }
 
 static inline void count_vm_event(enum vm_event_item item)
 {
-	get_cpu_var(vm_event_states.event[item])++;
+	get_cpu_var(vm_event_states).event[item]++;
 	put_cpu();
 }
 
 static inline void __count_vm_events(enum vm_event_item item, long delta)
 {
-	__get_cpu_var(vm_event_states.event[item]) += delta;
+	__get_cpu_var(vm_event_states).event[item] += delta;
 }
 
 static inline void count_vm_events(enum vm_event_item item, long delta)
 {
-	get_cpu_var(vm_event_states.event[item]) += delta;
+	get_cpu_var(vm_event_states).event[item] += delta;
 	put_cpu();
 }
 
diff --git a/include/linux/vt.h b/include/linux/vt.h
index 8ab334a..ba806e8 100644
--- a/include/linux/vt.h
+++ b/include/linux/vt.h
@@ -60,5 +60,6 @@
 #define VT_RESIZEX      0x560A  /* set kernel's idea of screensize + more */
 #define VT_LOCKSWITCH   0x560B  /* disallow vt switching */
 #define VT_UNLOCKSWITCH 0x560C  /* allow vt switching */
+#define VT_GETHIFONTMASK 0x560D  /* return hi font mask */
 
 #endif /* _LINUX_VT_H */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index 62dae1a..600d61d 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -16,7 +16,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/compiler.h> /* need __user */
-#ifdef CONFIG_VIDEO_V4L1
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
 #include <linux/videodev.h>
 #else
 #include <linux/videodev2.h>
@@ -341,11 +341,14 @@
 extern struct video_device* video_devdata(struct file*);
 
 #define to_video_device(cd) container_of(cd, struct video_device, class_dev)
-static inline void
+static inline int
 video_device_create_file(struct video_device *vfd,
 			 struct class_device_attribute *attr)
 {
-	class_device_create_file(&vfd->class_dev, attr);
+	int ret = class_device_create_file(&vfd->class_dev, attr);
+	if (ret < 0)
+		printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret);
+	return ret;
 }
 static inline void
 video_device_remove_file(struct video_device *vfd,
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 2fec827..c0398f5 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -54,15 +54,13 @@
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
-	char			*secdata;	/* Security context	*/
-	u32			seclen;		/* Security length	*/
+	u32			secid;		/* Security ID		*/
 #endif
 };
 
 #define UNIXCB(skb) 	(*(struct unix_skb_parms*)&((skb)->cb))
 #define UNIXCREDS(skb)	(&UNIXCB((skb)).creds)
-#define UNIXSECDATA(skb)	(&UNIXCB((skb)).secdata)
-#define UNIXSECLEN(skb)		(&UNIXCB((skb)).seclen)
+#define UNIXSID(skb)	(&UNIXCB((skb)).secid)
 
 #define unix_state_rlock(s)	spin_lock(&unix_sk(s)->lock)
 #define unix_state_runlock(s)	spin_unlock(&unix_sk(s)->lock)
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index ecc4286..b174ebb 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -240,6 +240,11 @@
 #define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
 #define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
 
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
 /* Status codes */
 enum ieee80211_statuscode {
 	WLAN_STATUS_SUCCESS = 0,
@@ -747,6 +752,8 @@
 #define NETWORK_HAS_IBSS_DFS            (1<<8)
 #define NETWORK_HAS_TPC_REPORT          (1<<9)
 
+#define NETWORK_HAS_ERP_VALUE           (1<<10)
+
 #define QOS_QUEUE_NUM                   4
 #define QOS_OUI_LEN                     3
 #define QOS_OUI_TYPE                    2
@@ -1252,6 +1259,8 @@
 			      int total_len, int encrypt_mpdu);
 
 /* ieee80211_rx.c */
+extern void ieee80211_rx_any(struct ieee80211_device *ieee,
+		     struct sk_buff *skb, struct ieee80211_rx_stats *stats);
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
 /* make sure to set stats->len */
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index 00ad810..425b3a5 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -86,9 +86,6 @@
 	
 	/* BSSID we're trying to associate to */
 	char bssid[ETH_ALEN];
-
-	/* Rates supported by the network */
-	struct ieee80211softmac_ratesinfo supported_rates;
 	
 	/* some flags.
 	 * static_essid is valid if the essid is constant,
@@ -103,6 +100,7 @@
 	 * bssfixed is used for SIOCSIWAP.
 	 */
 	u8 static_essid:1,
+	   short_preamble_available:1,
 	   associating:1,
 	   assoc_wait:1,
 	   bssvalid:1,
@@ -115,6 +113,19 @@
 	struct work_struct timeout;
 };
 
+struct ieee80211softmac_bss_info {
+	/* Rates supported by the network */
+	struct ieee80211softmac_ratesinfo supported_rates;
+
+	/* This indicates whether frames can currently be transmitted with
+	 * short preamble (only use this variable during TX at CCK rates) */
+	u8 short_preamble:1;
+
+	/* This indicates whether protection (e.g. self-CTS) should be used
+	 * when transmitting with OFDM modulation */
+	u8 use_protection:1;
+};
+
 enum {
 	IEEE80211SOFTMAC_AUTH_OPEN_REQUEST	= 1,
 	IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE	= 2,
@@ -157,6 +168,10 @@
 #define IEEE80211SOFTMAC_TXRATECHG_MCAST		(1 << 2) /* mcast_rate */
 #define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST		(1 << 3) /* mgt_mcast_rate */
 
+#define IEEE80211SOFTMAC_BSSINFOCHG_RATES		(1 << 0) /* supported_rates */
+#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE	(1 << 1) /* short_preamble */
+#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION		(1 << 2) /* use_protection */
+
 struct ieee80211softmac_device {
 	/* 802.11 structure for data stuff */
 	struct ieee80211_device *ieee;
@@ -200,10 +215,16 @@
 	 * The driver just needs to read them.
 	 */
 	struct ieee80211softmac_txrates txrates;
-	/* If the driver needs to do stuff on TX rate changes, assign this callback. */
+
+	/* If the driver needs to do stuff on TX rate changes, assign this
+	 * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */
 	void (*txrates_change)(struct net_device *dev,
-			       u32 changes, /* see IEEE80211SOFTMAC_TXRATECHG flags */
-			       const struct ieee80211softmac_txrates *rates_before_change);
+			       u32 changes);
+
+	/* If the driver needs to do stuff when BSS properties change, assign
+	 * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */
+	void (*bssinfo_change)(struct net_device *dev,
+			       u32 changes);
 
 	/* private stuff follows */
 	/* this lock protects this structure */
@@ -216,6 +237,7 @@
 	
 	struct ieee80211softmac_scaninfo *scaninfo;
 	struct ieee80211softmac_assoc_info associnfo;
+	struct ieee80211softmac_bss_info bssinfo;
 
 	struct list_head auth_queue;
 	struct list_head events;
@@ -257,6 +279,14 @@
  * Note that the rates need to be sorted. */
 extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
 
+/* Finds the highest rate which is:
+ *  1. Present in ri (optionally a basic rate)
+ *  2. Supported by the device
+ *  3. Less than or equal to the user-defined rate
+ */
+extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
+	struct ieee80211softmac_ratesinfo *ri, int basic_only);
+
 /* Helper function which advises you the rate at which a frame should be
  * transmitted at. */
 static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
@@ -279,6 +309,24 @@
 		return txrates->mcast_rate;
 }
 
+/* Helper function which advises you when it is safe to transmit with short
+ * preamble.
+ * You should only call this function when transmitting at CCK rates. */
+static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac,
+						    int is_multicast,
+						    int is_mgt)
+{
+	return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble;
+}
+
+/* Helper function which advises you whether protection (e.g. self-CTS) is
+ * needed. 1 = protection needed, 0 = no protection needed
+ * Only use this function when transmitting with OFDM modulation. */
+static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac)
+{
+	return mac->bssinfo.use_protection;
+}
+
 /* Start the SoftMAC. Call this after you initialized the device
  * and it is ready to run.
  */
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index ab29daf..96b0e66 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -139,16 +139,22 @@
 /*
  *	Store a destination cache entry in a socket
  */
-static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
-				     struct in6_addr *daddr)
+static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst,
+				   struct in6_addr *daddr)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct rt6_info *rt = (struct rt6_info *) dst;
 
-	write_lock(&sk->sk_dst_lock);
 	sk_setup_caps(sk, dst);
 	np->daddr_cache = daddr;
 	np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0;
+}
+
+static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst,
+				 struct in6_addr *daddr)
+{
+	write_lock(&sk->sk_dst_lock);
+	__ip6_dst_store(sk, dst, daddr);
 	write_unlock(&sk->sk_dst_lock);
 }
 
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index a8fdf79..ece7e8a 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -468,6 +468,9 @@
 extern int			ip6_dst_lookup(struct sock *sk,
 					       struct dst_entry **dst,
 					       struct flowi *fl);
+extern int			ip6_sk_dst_lookup(struct sock *sk,
+						  struct dst_entry **dst,
+						  struct flowi *fl);
 
 /*
  *	skb processing functions
diff --git a/include/net/netdma.h b/include/net/netdma.h
index ceae5ee..7f53cd1 100644
--- a/include/net/netdma.h
+++ b/include/net/netdma.h
@@ -29,7 +29,7 @@
 {
 	struct dma_chan *chan;
 	rcu_read_lock();
-	chan = rcu_dereference(__get_cpu_var(softnet_data.net_dma));
+	chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma);
 	if (chan)
 		dma_chan_get(chan);
 	rcu_read_unlock();
diff --git a/include/net/netevent.h b/include/net/netevent.h
new file mode 100644
index 0000000..e5d2162
--- /dev/null
+++ b/include/net/netevent.h
@@ -0,0 +1,33 @@
+#ifndef _NET_EVENT_H
+#define _NET_EVENT_H
+
+/*
+ *	Generic netevent notifiers
+ *
+ *	Authors:
+ *      Tom Tucker              <tom@opengridcomputing.com>
+ *      Steve Wise              <swise@opengridcomputing.com>
+ *
+ * 	Changes:
+ */
+#ifdef __KERNEL__
+
+#include <net/dst.h>
+
+struct netevent_redirect {
+	struct dst_entry *old;
+	struct dst_entry *new;
+};
+
+enum netevent_notif_type {
+	NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */
+	NETEVENT_PMTU_UPDATE,	   /* arg is struct dst_entry ptr */
+	NETEVENT_REDIRECT,	   /* arg is struct netevent_redirect ptr */
+};
+
+extern int register_netevent_notifier(struct notifier_block *nb);
+extern int unregister_netevent_notifier(struct notifier_block *nb);
+extern int call_netevent_notifiers(unsigned long val, void *v);
+
+#endif
+#endif
diff --git a/include/net/red.h b/include/net/red.h
index 5ccdbb3..a4eb379 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -212,7 +212,7 @@
 		 * Seems, it is the best solution to
 		 * problem of too coarse exponent tabulation.
 		 */
-		us_idle = (p->qavg * us_idle) >> p->Scell_log;
+		us_idle = (p->qavg * (u64)us_idle) >> p->Scell_log;
 
 		if (us_idle < (p->qavg >> 1))
 			return p->qavg - us_idle;
diff --git a/include/net/scm.h b/include/net/scm.h
index 02daa09..5637d5e 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -3,6 +3,7 @@
 
 #include <linux/limits.h>
 #include <linux/net.h>
+#include <linux/security.h>
 
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
@@ -20,8 +21,7 @@
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
-	char			*secdata;	/* Security context	*/
-	u32			seclen;		/* Security length	*/
+	u32			secid;		/* Passed security ID 	*/
 #endif
 	unsigned long		seq;		/* Connection seqno	*/
 };
@@ -32,6 +32,16 @@
 extern void __scm_destroy(struct scm_cookie *scm);
 extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
 
+#ifdef CONFIG_SECURITY_NETWORK
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
+{
+	security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
+}
+#else
+static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
+{ }
+#endif /* CONFIG_SECURITY_NETWORK */
+
 static __inline__ void scm_destroy(struct scm_cookie *scm)
 {
 	if (scm && scm->fp)
@@ -47,6 +57,7 @@
 	scm->creds.pid = p->tgid;
 	scm->fp = NULL;
 	scm->seq = 0;
+	unix_get_peersec_dgram(sock, scm);
 	if (msg->msg_controllen <= 0)
 		return 0;
 	return __scm_send(sock, msg, scm);
@@ -55,8 +66,18 @@
 #ifdef CONFIG_SECURITY_NETWORK
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
 {
-	if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL)
-		put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, scm->secdata);
+	char *secdata;
+	u32 seclen;
+	int err;
+
+	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
+		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
+
+		if (!err) {
+			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
+			security_release_secctx(secdata, seclen);
+		}
+	}
 }
 #else
 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index a9663b4..92eae0e 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -404,19 +404,6 @@
 	return ((head->next != head) && (head->next == head->prev));
 }
 
-/* Calculate the size (in bytes) occupied by the data of an iovec.  */
-static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
-{
-	size_t retval = 0;
-
-	for (; iovlen > 0; --iovlen) {
-		retval += iov->iov_len;
-		iov++;
-	}
-
-	return retval;
-}
-
 /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
 static inline __s32 sctp_jitter(__u32 rto)
 {
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 1eac3d0..de313de 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -221,8 +221,7 @@
 				      const struct sctp_chunk *,
 				      __u32 tsn);
 struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
-				   const struct sctp_chunk *,
-				   const struct msghdr *);
+					const struct msghdr *, size_t msg_len);
 struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
 				   const struct sctp_chunk *,
 				   const __u8 *,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 0720bdd..7a093d0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -914,6 +914,9 @@
 
 static inline void tcp_done(struct sock *sk)
 {
+	if(sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
+		TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
+
 	tcp_set_state(sk, TCP_CLOSE);
 	tcp_clear_xmit_timers(sk);
 
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index ba27608..41904f6 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -60,6 +60,7 @@
 #define TMABORT_SUCCESS			0x1
 #define TMABORT_FAILED			0x2
 #define TMABORT_TIMEDOUT		0x3
+#define TMABORT_NOT_FOUND		0x4
 
 /* Connection suspend "bit" */
 #define ISCSI_SUSPEND_BIT		1
@@ -83,6 +84,12 @@
 	struct list_head	running;
 };
 
+enum {
+	ISCSI_TASK_COMPLETED,
+	ISCSI_TASK_PENDING,
+	ISCSI_TASK_RUNNING,
+};
+
 struct iscsi_cmd_task {
 	/*
 	 * Becuae LLDs allocate their hdr differently, this is a pointer to
@@ -101,6 +108,8 @@
 	struct iscsi_conn	*conn;		/* used connection    */
 	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
 
+	/* state set/tested under session->lock */
+	int			state;
 	struct list_head	running;	/* running cmd list */
 	void			*dd_data;	/* driver/transport data */
 };
@@ -126,6 +135,14 @@
 	int			id;		/* CID */
 	struct list_head	item;		/* maintains list of conns */
 	int			c_stage;	/* connection state */
+	/*
+	 * Preallocated buffer for pdus that have data but do not
+	 * originate from scsi-ml. We never have two pdus using the
+	 * buffer at the same time. It is only allocated to
+	 * the default max recv size because the pdus we support
+	 * should always fit in this buffer
+	 */
+	char			*data;
 	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
 	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
 	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
@@ -134,7 +151,7 @@
 	struct kfifo		*immqueue;	/* immediate xmit queue */
 	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
 	struct list_head	mgmt_run_list;	/* list of control tasks */
-	struct kfifo		*xmitqueue;	/* data-path cmd queue */
+	struct list_head	xmitqueue;	/* data-path cmd queue */
 	struct list_head	run_list;	/* list of cmds in progress */
 	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
 	/*
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 5a3df1d..39e8332 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -57,8 +57,6 @@
  * @stop_conn:		suspend/recover/terminate connection
  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
  * @session_recovery_timedout: notify LLD a block during recovery timed out
- * @suspend_conn_recv:	susepend the recv side of the connection
- * @termincate_conn:	destroy socket connection. Called with mutex lock.
  * @init_cmd_task:	Initialize a iscsi_cmd_task and any internal structs.
  *			Called from queuecommand with session lock held.
  * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
@@ -112,8 +110,6 @@
 			 char *data, uint32_t data_size);
 	void (*get_stats) (struct iscsi_cls_conn *conn,
 			   struct iscsi_stats *stats);
-	void (*suspend_conn_recv) (struct iscsi_conn *conn);
-	void (*terminate_conn) (struct iscsi_conn *conn);
 	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
 	void (*init_mgmt_task) (struct iscsi_conn *conn,
 				struct iscsi_mgmt_task *mtask,
diff --git a/ipc/msg.c b/ipc/msg.c
index cd92d34..2b4fccf 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -1,6 +1,6 @@
 /*
  * linux/ipc/msg.c
- * Copyright (C) 1992 Krishna Balasubramanian 
+ * Copyright (C) 1992 Krishna Balasubramanian
  *
  * Removed all the remaining kerneld mess
  * Catch the -EFAULT stuff properly
@@ -41,22 +41,24 @@
 int msg_ctlmnb = MSGMNB;
 int msg_ctlmni = MSGMNI;
 
-/* one msg_receiver structure for each sleeping receiver */
+/*
+ * one msg_receiver structure for each sleeping receiver:
+ */
 struct msg_receiver {
-	struct list_head r_list;
-	struct task_struct* r_tsk;
+	struct list_head	r_list;
+	struct task_struct	*r_tsk;
 
-	int r_mode;
-	long r_msgtype;
-	long r_maxsize;
+	int			r_mode;
+	long			r_msgtype;
+	long			r_maxsize;
 
-	struct msg_msg* volatile r_msg;
+	volatile struct msg_msg	*r_msg;
 };
 
 /* one msg_sender for each sleeping sender */
 struct msg_sender {
-	struct list_head list;
-	struct task_struct* tsk;
+	struct list_head	list;
+	struct task_struct	*tsk;
 };
 
 #define SEARCH_ANY		1
@@ -64,45 +66,42 @@
 #define SEARCH_NOTEQUAL		3
 #define SEARCH_LESSEQUAL	4
 
-static atomic_t msg_bytes = ATOMIC_INIT(0);
-static atomic_t msg_hdrs = ATOMIC_INIT(0);
+static atomic_t msg_bytes =	ATOMIC_INIT(0);
+static atomic_t msg_hdrs =	ATOMIC_INIT(0);
 
 static struct ipc_ids msg_ids;
 
-#define msg_lock(id)	((struct msg_queue*)ipc_lock(&msg_ids,id))
-#define msg_unlock(msq)	ipc_unlock(&(msq)->q_perm)
-#define msg_rmid(id)	((struct msg_queue*)ipc_rmid(&msg_ids,id))
-#define msg_checkid(msq, msgid)	\
-	ipc_checkid(&msg_ids,&msq->q_perm,msgid)
-#define msg_buildid(id, seq) \
-	ipc_buildid(&msg_ids, id, seq)
+#define msg_lock(id)		((struct msg_queue *)ipc_lock(&msg_ids, id))
+#define msg_unlock(msq)		ipc_unlock(&(msq)->q_perm)
+#define msg_rmid(id)		((struct msg_queue *)ipc_rmid(&msg_ids, id))
+#define msg_checkid(msq, msgid)	ipc_checkid(&msg_ids, &msq->q_perm, msgid)
+#define msg_buildid(id, seq)	ipc_buildid(&msg_ids, id, seq)
 
-static void freeque (struct msg_queue *msq, int id);
-static int newque (key_t key, int msgflg);
+static void freeque(struct msg_queue *msq, int id);
+static int newque(key_t key, int msgflg);
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
-void __init msg_init (void)
+void __init msg_init(void)
 {
-	ipc_init_ids(&msg_ids,msg_ctlmni);
+	ipc_init_ids(&msg_ids, msg_ctlmni);
 	ipc_init_proc_interface("sysvipc/msg",
 				"       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
 				&msg_ids,
 				sysvipc_msg_proc_show);
 }
 
-static int newque (key_t key, int msgflg)
+static int newque(key_t key, int msgflg)
 {
-	int id;
-	int retval;
 	struct msg_queue *msq;
+	int id, retval;
 
-	msq  = ipc_rcu_alloc(sizeof(*msq));
-	if (!msq) 
+	msq = ipc_rcu_alloc(sizeof(*msq));
+	if (!msq)
 		return -ENOMEM;
 
-	msq->q_perm.mode = (msgflg & S_IRWXUGO);
+	msq->q_perm.mode = msgflg & S_IRWXUGO;
 	msq->q_perm.key = key;
 
 	msq->q_perm.security = NULL;
@@ -113,13 +112,13 @@
 	}
 
 	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
-	if(id == -1) {
+	if (id == -1) {
 		security_msg_queue_free(msq);
 		ipc_rcu_putref(msq);
 		return -ENOSPC;
 	}
 
-	msq->q_id = msg_buildid(id,msq->q_perm.seq);
+	msq->q_id = msg_buildid(id, msq->q_perm.seq);
 	msq->q_stime = msq->q_rtime = 0;
 	msq->q_ctime = get_seconds();
 	msq->q_cbytes = msq->q_qnum = 0;
@@ -133,44 +132,44 @@
 	return msq->q_id;
 }
 
-static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss)
+static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
 {
-	mss->tsk=current;
-	current->state=TASK_INTERRUPTIBLE;
-	list_add_tail(&mss->list,&msq->q_senders);
+	mss->tsk = current;
+	current->state = TASK_INTERRUPTIBLE;
+	list_add_tail(&mss->list, &msq->q_senders);
 }
 
-static inline void ss_del(struct msg_sender* mss)
+static inline void ss_del(struct msg_sender *mss)
 {
-	if(mss->list.next != NULL)
+	if (mss->list.next != NULL)
 		list_del(&mss->list);
 }
 
-static void ss_wakeup(struct list_head* h, int kill)
+static void ss_wakeup(struct list_head *h, int kill)
 {
 	struct list_head *tmp;
 
 	tmp = h->next;
 	while (tmp != h) {
-		struct msg_sender* mss;
-		
-		mss = list_entry(tmp,struct msg_sender,list);
+		struct msg_sender *mss;
+
+		mss = list_entry(tmp, struct msg_sender, list);
 		tmp = tmp->next;
-		if(kill)
-			mss->list.next=NULL;
+		if (kill)
+			mss->list.next = NULL;
 		wake_up_process(mss->tsk);
 	}
 }
 
-static void expunge_all(struct msg_queue* msq, int res)
+static void expunge_all(struct msg_queue *msq, int res)
 {
 	struct list_head *tmp;
 
 	tmp = msq->q_receivers.next;
 	while (tmp != &msq->q_receivers) {
-		struct msg_receiver* msr;
-		
-		msr = list_entry(tmp,struct msg_receiver,r_list);
+		struct msg_receiver *msr;
+
+		msr = list_entry(tmp, struct msg_receiver, r_list);
 		tmp = tmp->next;
 		msr->r_msg = NULL;
 		wake_up_process(msr->r_tsk);
@@ -178,26 +177,28 @@
 		msr->r_msg = ERR_PTR(res);
 	}
 }
-/* 
- * freeque() wakes up waiters on the sender and receiver waiting queue, 
- * removes the message queue from message queue ID 
+
+/*
+ * freeque() wakes up waiters on the sender and receiver waiting queue,
+ * removes the message queue from message queue ID
  * array, and cleans up all the messages associated with this queue.
  *
  * msg_ids.mutex and the spinlock for this message queue is hold
  * before freeque() is called. msg_ids.mutex remains locked on exit.
  */
-static void freeque (struct msg_queue *msq, int id)
+static void freeque(struct msg_queue *msq, int id)
 {
 	struct list_head *tmp;
 
-	expunge_all(msq,-EIDRM);
-	ss_wakeup(&msq->q_senders,1);
+	expunge_all(msq, -EIDRM);
+	ss_wakeup(&msq->q_senders, 1);
 	msq = msg_rmid(id);
 	msg_unlock(msq);
-		
+
 	tmp = msq->q_messages.next;
-	while(tmp != &msq->q_messages) {
-		struct msg_msg* msg = list_entry(tmp,struct msg_msg,m_list);
+	while (tmp != &msq->q_messages) {
+		struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list);
+
 		tmp = tmp->next;
 		atomic_dec(&msg_hdrs);
 		free_msg(msg);
@@ -207,10 +208,10 @@
 	ipc_rcu_putref(msq);
 }
 
-asmlinkage long sys_msgget (key_t key, int msgflg)
+asmlinkage long sys_msgget(key_t key, int msgflg)
 {
-	int id, ret = -EPERM;
 	struct msg_queue *msq;
+	int id, ret = -EPERM;
 	
 	mutex_lock(&msg_ids.mutex);
 	if (key == IPC_PRIVATE) 
@@ -224,31 +225,34 @@
 		ret = -EEXIST;
 	} else {
 		msq = msg_lock(id);
-		BUG_ON(msq==NULL);
+		BUG_ON(msq == NULL);
 		if (ipcperms(&msq->q_perm, msgflg))
 			ret = -EACCES;
 		else {
 			int qid = msg_buildid(id, msq->q_perm.seq);
-		    	ret = security_msg_queue_associate(msq, msgflg);
+
+			ret = security_msg_queue_associate(msq, msgflg);
 			if (!ret)
 				ret = qid;
 		}
 		msg_unlock(msq);
 	}
 	mutex_unlock(&msg_ids.mutex);
+
 	return ret;
 }
 
-static inline unsigned long copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
+static inline unsigned long
+copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
 {
 	switch(version) {
 	case IPC_64:
-		return copy_to_user (buf, in, sizeof(*in));
+		return copy_to_user(buf, in, sizeof(*in));
 	case IPC_OLD:
-	    {
+	{
 		struct msqid_ds out;
 
-		memset(&out,0,sizeof(out));
+		memset(&out, 0, sizeof(out));
 
 		ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
 
@@ -256,18 +260,18 @@
 		out.msg_rtime		= in->msg_rtime;
 		out.msg_ctime		= in->msg_ctime;
 
-		if(in->msg_cbytes > USHRT_MAX)
+		if (in->msg_cbytes > USHRT_MAX)
 			out.msg_cbytes	= USHRT_MAX;
 		else
 			out.msg_cbytes	= in->msg_cbytes;
 		out.msg_lcbytes		= in->msg_cbytes;
 
-		if(in->msg_qnum > USHRT_MAX)
+		if (in->msg_qnum > USHRT_MAX)
 			out.msg_qnum	= USHRT_MAX;
 		else
 			out.msg_qnum	= in->msg_qnum;
 
-		if(in->msg_qbytes > USHRT_MAX)
+		if (in->msg_qbytes > USHRT_MAX)
 			out.msg_qbytes	= USHRT_MAX;
 		else
 			out.msg_qbytes	= in->msg_qbytes;
@@ -276,8 +280,8 @@
 		out.msg_lspid		= in->msg_lspid;
 		out.msg_lrpid		= in->msg_lrpid;
 
-		return copy_to_user (buf, &out, sizeof(out));
-	    }
+		return copy_to_user(buf, &out, sizeof(out));
+	}
 	default:
 		return -EINVAL;
 	}
@@ -290,14 +294,15 @@
 	mode_t		mode;
 };
 
-static inline unsigned long copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
+static inline unsigned long
+copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
 {
 	switch(version) {
 	case IPC_64:
-	    {
+	{
 		struct msqid64_ds tbuf;
 
-		if (copy_from_user (&tbuf, buf, sizeof (tbuf)))
+		if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
 			return -EFAULT;
 
 		out->qbytes		= tbuf.msg_qbytes;
@@ -306,60 +311,61 @@
 		out->mode		= tbuf.msg_perm.mode;
 
 		return 0;
-	    }
+	}
 	case IPC_OLD:
-	    {
+	{
 		struct msqid_ds tbuf_old;
 
-		if (copy_from_user (&tbuf_old, buf, sizeof (tbuf_old)))
+		if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
 			return -EFAULT;
 
 		out->uid		= tbuf_old.msg_perm.uid;
 		out->gid		= tbuf_old.msg_perm.gid;
 		out->mode		= tbuf_old.msg_perm.mode;
 
-		if(tbuf_old.msg_qbytes == 0)
+		if (tbuf_old.msg_qbytes == 0)
 			out->qbytes	= tbuf_old.msg_lqbytes;
 		else
 			out->qbytes	= tbuf_old.msg_qbytes;
 
 		return 0;
-	    }
+	}
 	default:
 		return -EINVAL;
 	}
 }
 
-asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
+asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
 {
-	int err, version;
-	struct msg_queue *msq;
-	struct msq_setbuf setbuf;
 	struct kern_ipc_perm *ipcp;
-	
+	struct msq_setbuf setbuf;
+	struct msg_queue *msq;
+	int err, version;
+
 	if (msqid < 0 || cmd < 0)
 		return -EINVAL;
 
 	version = ipc_parse_version(&cmd);
 
 	switch (cmd) {
-	case IPC_INFO: 
-	case MSG_INFO: 
-	{ 
+	case IPC_INFO:
+	case MSG_INFO:
+	{
 		struct msginfo msginfo;
 		int max_id;
+
 		if (!buf)
 			return -EFAULT;
-		/* We must not return kernel stack data.
+		/*
+		 * We must not return kernel stack data.
 		 * due to padding, it's not enough
 		 * to set all member fields.
 		 */
-
 		err = security_msg_queue_msgctl(NULL, cmd);
 		if (err)
 			return err;
 
-		memset(&msginfo,0,sizeof(msginfo));	
+		memset(&msginfo, 0, sizeof(msginfo));
 		msginfo.msgmni = msg_ctlmni;
 		msginfo.msgmax = msg_ctlmax;
 		msginfo.msgmnb = msg_ctlmnb;
@@ -377,36 +383,37 @@
 		}
 		max_id = msg_ids.max_id;
 		mutex_unlock(&msg_ids.mutex);
-		if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
+		if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
 			return -EFAULT;
-		return (max_id < 0) ? 0: max_id;
+		return (max_id < 0) ? 0 : max_id;
 	}
 	case MSG_STAT:
 	case IPC_STAT:
 	{
 		struct msqid64_ds tbuf;
 		int success_return;
+
 		if (!buf)
 			return -EFAULT;
-		if(cmd == MSG_STAT && msqid >= msg_ids.entries->size)
+		if (cmd == MSG_STAT && msqid >= msg_ids.entries->size)
 			return -EINVAL;
 
-		memset(&tbuf,0,sizeof(tbuf));
+		memset(&tbuf, 0, sizeof(tbuf));
 
 		msq = msg_lock(msqid);
 		if (msq == NULL)
 			return -EINVAL;
 
-		if(cmd == MSG_STAT) {
+		if (cmd == MSG_STAT) {
 			success_return = msg_buildid(msqid, msq->q_perm.seq);
 		} else {
 			err = -EIDRM;
-			if (msg_checkid(msq,msqid))
+			if (msg_checkid(msq, msqid))
 				goto out_unlock;
 			success_return = 0;
 		}
 		err = -EACCES;
-		if (ipcperms (&msq->q_perm, S_IRUGO))
+		if (ipcperms(&msq->q_perm, S_IRUGO))
 			goto out_unlock;
 
 		err = security_msg_queue_msgctl(msq, cmd);
@@ -430,7 +437,7 @@
 	case IPC_SET:
 		if (!buf)
 			return -EFAULT;
-		if (copy_msqid_from_user (&setbuf, buf, version))
+		if (copy_msqid_from_user(&setbuf, buf, version))
 			return -EFAULT;
 		break;
 	case IPC_RMID:
@@ -441,12 +448,12 @@
 
 	mutex_lock(&msg_ids.mutex);
 	msq = msg_lock(msqid);
-	err=-EINVAL;
+	err = -EINVAL;
 	if (msq == NULL)
 		goto out_up;
 
 	err = -EIDRM;
-	if (msg_checkid(msq,msqid))
+	if (msg_checkid(msq, msqid))
 		goto out_unlock_up;
 	ipcp = &msq->q_perm;
 
@@ -454,15 +461,16 @@
 	if (err)
 		goto out_unlock_up;
 	if (cmd==IPC_SET) {
-		err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode);
+		err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
+					 setbuf.mode);
 		if (err)
 			goto out_unlock_up;
 	}
 
 	err = -EPERM;
-	if (current->euid != ipcp->cuid && 
+	if (current->euid != ipcp->cuid &&
 	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
-	    /* We _could_ check for CAP_CHOWN above, but we don't */
+		/* We _could_ check for CAP_CHOWN above, but we don't */
 		goto out_unlock_up;
 
 	err = security_msg_queue_msgctl(msq, cmd);
@@ -480,22 +488,22 @@
 
 		ipcp->uid = setbuf.uid;
 		ipcp->gid = setbuf.gid;
-		ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | 
-			(S_IRWXUGO & setbuf.mode);
+		ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
+			     (S_IRWXUGO & setbuf.mode);
 		msq->q_ctime = get_seconds();
 		/* sleeping receivers might be excluded by
 		 * stricter permissions.
 		 */
-		expunge_all(msq,-EAGAIN);
+		expunge_all(msq, -EAGAIN);
 		/* sleeping senders might be able to send
 		 * due to a larger queue size.
 		 */
-		ss_wakeup(&msq->q_senders,0);
+		ss_wakeup(&msq->q_senders, 0);
 		msg_unlock(msq);
 		break;
 	}
 	case IPC_RMID:
-		freeque (msq, msqid); 
+		freeque(msq, msqid);
 		break;
 	}
 	err = 0;
@@ -510,41 +518,44 @@
 	return err;
 }
 
-static int testmsg(struct msg_msg* msg,long type,int mode)
+static int testmsg(struct msg_msg *msg, long type, int mode)
 {
 	switch(mode)
 	{
 		case SEARCH_ANY:
 			return 1;
 		case SEARCH_LESSEQUAL:
-			if(msg->m_type <=type)
+			if (msg->m_type <=type)
 				return 1;
 			break;
 		case SEARCH_EQUAL:
-			if(msg->m_type == type)
+			if (msg->m_type == type)
 				return 1;
 			break;
 		case SEARCH_NOTEQUAL:
-			if(msg->m_type != type)
+			if (msg->m_type != type)
 				return 1;
 			break;
 	}
 	return 0;
 }
 
-static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg)
+static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
 {
-	struct list_head* tmp;
+	struct list_head *tmp;
 
 	tmp = msq->q_receivers.next;
 	while (tmp != &msq->q_receivers) {
-		struct msg_receiver* msr;
-		msr = list_entry(tmp,struct msg_receiver,r_list);
+		struct msg_receiver *msr;
+
+		msr = list_entry(tmp, struct msg_receiver, r_list);
 		tmp = tmp->next;
-		if(testmsg(msg,msr->r_msgtype,msr->r_mode) &&
-		   !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) {
+		if (testmsg(msg, msr->r_msgtype, msr->r_mode) &&
+		    !security_msg_queue_msgrcv(msq, msg, msr->r_tsk,
+					       msr->r_msgtype, msr->r_mode)) {
+
 			list_del(&msr->r_list);
-			if(msr->r_maxsize < msg->m_ts) {
+			if (msr->r_maxsize < msg->m_ts) {
 				msr->r_msg = NULL;
 				wake_up_process(msr->r_tsk);
 				smp_mb();
@@ -556,6 +567,7 @@
 				wake_up_process(msr->r_tsk);
 				smp_mb();
 				msr->r_msg = msg;
+
 				return 1;
 			}
 		}
@@ -563,40 +575,41 @@
 	return 0;
 }
 
-asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+asmlinkage long
+sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
 {
 	struct msg_queue *msq;
 	struct msg_msg *msg;
 	long mtype;
 	int err;
-	
+
 	if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0)
 		return -EINVAL;
 	if (get_user(mtype, &msgp->mtype))
-		return -EFAULT; 
+		return -EFAULT;
 	if (mtype < 1)
 		return -EINVAL;
 
 	msg = load_msg(msgp->mtext, msgsz);
-	if(IS_ERR(msg))
+	if (IS_ERR(msg))
 		return PTR_ERR(msg);
 
 	msg->m_type = mtype;
 	msg->m_ts = msgsz;
 
 	msq = msg_lock(msqid);
-	err=-EINVAL;
-	if(msq==NULL)
+	err = -EINVAL;
+	if (msq == NULL)
 		goto out_free;
 
 	err= -EIDRM;
-	if (msg_checkid(msq,msqid))
+	if (msg_checkid(msq, msqid))
 		goto out_unlock_free;
 
 	for (;;) {
 		struct msg_sender s;
 
-		err=-EACCES;
+		err = -EACCES;
 		if (ipcperms(&msq->q_perm, S_IWUGO))
 			goto out_unlock_free;
 
@@ -604,14 +617,14 @@
 		if (err)
 			goto out_unlock_free;
 
-		if(msgsz + msq->q_cbytes <= msq->q_qbytes &&
+		if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
 				1 + msq->q_qnum <= msq->q_qbytes) {
 			break;
 		}
 
 		/* queue full, wait: */
-		if(msgflg&IPC_NOWAIT) {
-			err=-EAGAIN;
+		if (msgflg & IPC_NOWAIT) {
+			err = -EAGAIN;
 			goto out_unlock_free;
 		}
 		ss_add(msq, &s);
@@ -626,9 +639,9 @@
 			goto out_unlock_free;
 		}
 		ss_del(&s);
-		
+
 		if (signal_pending(current)) {
-			err=-ERESTARTNOHAND;
+			err = -ERESTARTNOHAND;
 			goto out_unlock_free;
 		}
 	}
@@ -636,47 +649,47 @@
 	msq->q_lspid = current->tgid;
 	msq->q_stime = get_seconds();
 
-	if(!pipelined_send(msq,msg)) {
+	if (!pipelined_send(msq, msg)) {
 		/* noone is waiting for this message, enqueue it */
-		list_add_tail(&msg->m_list,&msq->q_messages);
+		list_add_tail(&msg->m_list, &msq->q_messages);
 		msq->q_cbytes += msgsz;
 		msq->q_qnum++;
-		atomic_add(msgsz,&msg_bytes);
+		atomic_add(msgsz, &msg_bytes);
 		atomic_inc(&msg_hdrs);
 	}
-	
+
 	err = 0;
 	msg = NULL;
 
 out_unlock_free:
 	msg_unlock(msq);
 out_free:
-	if(msg!=NULL)
+	if (msg != NULL)
 		free_msg(msg);
 	return err;
 }
 
-static inline int convert_mode(long* msgtyp, int msgflg)
+static inline int convert_mode(long *msgtyp, int msgflg)
 {
-	/* 
+	/*
 	 *  find message of correct type.
 	 *  msgtyp = 0 => get first.
 	 *  msgtyp > 0 => get first message of matching type.
-	 *  msgtyp < 0 => get message with least type must be < abs(msgtype).  
+	 *  msgtyp < 0 => get message with least type must be < abs(msgtype).
 	 */
-	if(*msgtyp==0)
+	if (*msgtyp == 0)
 		return SEARCH_ANY;
-	if(*msgtyp<0) {
-		*msgtyp=-(*msgtyp);
+	if (*msgtyp < 0) {
+		*msgtyp = -*msgtyp;
 		return SEARCH_LESSEQUAL;
 	}
-	if(msgflg & MSG_EXCEPT)
+	if (msgflg & MSG_EXCEPT)
 		return SEARCH_NOTEQUAL;
 	return SEARCH_EQUAL;
 }
 
-asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz,
-			    long msgtyp, int msgflg)
+asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+			   long msgtyp, int msgflg)
 {
 	struct msg_queue *msq;
 	struct msg_msg *msg;
@@ -684,44 +697,51 @@
 
 	if (msqid < 0 || (long) msgsz < 0)
 		return -EINVAL;
-	mode = convert_mode(&msgtyp,msgflg);
+	mode = convert_mode(&msgtyp, msgflg);
 
 	msq = msg_lock(msqid);
-	if(msq==NULL)
+	if (msq == NULL)
 		return -EINVAL;
 
 	msg = ERR_PTR(-EIDRM);
-	if (msg_checkid(msq,msqid))
+	if (msg_checkid(msq, msqid))
 		goto out_unlock;
 
 	for (;;) {
 		struct msg_receiver msr_d;
-		struct list_head* tmp;
+		struct list_head *tmp;
 
 		msg = ERR_PTR(-EACCES);
-		if (ipcperms (&msq->q_perm, S_IRUGO))
+		if (ipcperms(&msq->q_perm, S_IRUGO))
 			goto out_unlock;
 
 		msg = ERR_PTR(-EAGAIN);
 		tmp = msq->q_messages.next;
 		while (tmp != &msq->q_messages) {
 			struct msg_msg *walk_msg;
-			walk_msg = list_entry(tmp,struct msg_msg,m_list);
-			if(testmsg(walk_msg,msgtyp,mode) &&
-			   !security_msg_queue_msgrcv(msq, walk_msg, current, msgtyp, mode)) {
+
+			walk_msg = list_entry(tmp, struct msg_msg, m_list);
+			if (testmsg(walk_msg, msgtyp, mode) &&
+			    !security_msg_queue_msgrcv(msq, walk_msg, current,
+						       msgtyp, mode)) {
+
 				msg = walk_msg;
-				if(mode == SEARCH_LESSEQUAL && walk_msg->m_type != 1) {
-					msg=walk_msg;
-					msgtyp=walk_msg->m_type-1;
+				if (mode == SEARCH_LESSEQUAL &&
+						walk_msg->m_type != 1) {
+					msg = walk_msg;
+					msgtyp = walk_msg->m_type - 1;
 				} else {
-					msg=walk_msg;
+					msg = walk_msg;
 					break;
 				}
 			}
 			tmp = tmp->next;
 		}
-		if(!IS_ERR(msg)) {
-			/* Found a suitable message. Unlink it from the queue. */
+		if (!IS_ERR(msg)) {
+			/*
+			 * Found a suitable message.
+			 * Unlink it from the queue.
+			 */
 			if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
 				msg = ERR_PTR(-E2BIG);
 				goto out_unlock;
@@ -731,9 +751,9 @@
 			msq->q_rtime = get_seconds();
 			msq->q_lrpid = current->tgid;
 			msq->q_cbytes -= msg->m_ts;
-			atomic_sub(msg->m_ts,&msg_bytes);
+			atomic_sub(msg->m_ts, &msg_bytes);
 			atomic_dec(&msg_hdrs);
-			ss_wakeup(&msq->q_senders,0);
+			ss_wakeup(&msq->q_senders, 0);
 			msg_unlock(msq);
 			break;
 		}
@@ -742,13 +762,13 @@
 			msg = ERR_PTR(-ENOMSG);
 			goto out_unlock;
 		}
-		list_add_tail(&msr_d.r_list,&msq->q_receivers);
+		list_add_tail(&msr_d.r_list, &msq->q_receivers);
 		msr_d.r_tsk = current;
 		msr_d.r_msgtype = msgtyp;
 		msr_d.r_mode = mode;
-		if(msgflg & MSG_NOERROR)
+		if (msgflg & MSG_NOERROR)
 			msr_d.r_maxsize = INT_MAX;
-		 else
+		else
 			msr_d.r_maxsize = msgsz;
 		msr_d.r_msg = ERR_PTR(-EAGAIN);
 		current->state = TASK_INTERRUPTIBLE;
@@ -773,17 +793,17 @@
 		 * wake_up_process(). There is a race with exit(), see
 		 * ipc/mqueue.c for the details.
 		 */
-		msg = (struct msg_msg*) msr_d.r_msg;
+		msg = (struct msg_msg*)msr_d.r_msg;
 		while (msg == NULL) {
 			cpu_relax();
-			msg = (struct msg_msg*) msr_d.r_msg;
+			msg = (struct msg_msg *)msr_d.r_msg;
 		}
 
 		/* Lockless receive, part 3:
 		 * If there is a message or an error then accept it without
 		 * locking.
 		 */
-		if(msg != ERR_PTR(-EAGAIN)) {
+		if (msg != ERR_PTR(-EAGAIN)) {
 			rcu_read_unlock();
 			break;
 		}
@@ -798,7 +818,7 @@
 		 * Repeat test after acquiring the spinlock.
 		 */
 		msg = (struct msg_msg*)msr_d.r_msg;
-		if(msg != ERR_PTR(-EAGAIN))
+		if (msg != ERR_PTR(-EAGAIN))
 			goto out_unlock;
 
 		list_del(&msr_d.r_list);
@@ -810,14 +830,15 @@
 		}
 	}
 	if (IS_ERR(msg))
-       		return PTR_ERR(msg);
+		return PTR_ERR(msg);
 
 	msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
 	if (put_user (msg->m_type, &msgp->mtype) ||
 	    store_msg(msgp->mtext, msg, msgsz)) {
-		    msgsz = -EFAULT;
+		msgsz = -EFAULT;
 	}
 	free_msg(msg);
+
 	return msgsz;
 }
 
@@ -827,20 +848,20 @@
 	struct msg_queue *msq = it;
 
 	return seq_printf(s,
-			  "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
-			  msq->q_perm.key,
-			  msq->q_id,
-			  msq->q_perm.mode,
-			  msq->q_cbytes,
-			  msq->q_qnum,
-			  msq->q_lspid,
-			  msq->q_lrpid,
-			  msq->q_perm.uid,
-			  msq->q_perm.gid,
-			  msq->q_perm.cuid,
-			  msq->q_perm.cgid,
-			  msq->q_stime,
-			  msq->q_rtime,
-			  msq->q_ctime);
+			"%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
+			msq->q_perm.key,
+			msq->q_id,
+			msq->q_perm.mode,
+			msq->q_cbytes,
+			msq->q_qnum,
+			msq->q_lspid,
+			msq->q_lrpid,
+			msq->q_perm.uid,
+			msq->q_perm.gid,
+			msq->q_perm.cuid,
+			msq->q_perm.cgid,
+			msq->q_stime,
+			msq->q_rtime,
+			msq->q_ctime);
 }
 #endif
diff --git a/kernel/audit.c b/kernel/audit.c
index d417ca1..963fd15 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -690,9 +690,7 @@
 /* Initialize audit support at boot time. */
 static int __init audit_init(void)
 {
-#ifdef CONFIG_AUDITSYSCALL
 	int i;
-#endif
 
 	printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
 	       audit_default ? "enabled" : "disabled");
@@ -717,10 +715,10 @@
 	audit_ih = inotify_init(&audit_inotify_ops);
 	if (IS_ERR(audit_ih))
 		audit_panic("cannot initialize inotify handle");
+#endif
 
 	for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
 		INIT_LIST_HEAD(&audit_inode_hash[i]);
-#endif
 
 	return 0;
 }
@@ -1030,6 +1028,9 @@
 	struct sk_buff *skb;
 	static const unsigned char *hex = "0123456789ABCDEF";
 
+	if (!ab)
+		return;
+
 	BUG_ON(!ab->skb);
 	skb = ab->skb;
 	avail = skb_tailroom(skb);
@@ -1062,6 +1063,9 @@
 	unsigned char *ptr;
 	struct sk_buff *skb;
 
+	if (!ab)
+		return;
+
 	BUG_ON(!ab->skb);
 	skb = ab->skb;
 	avail = skb_tailroom(skb);
diff --git a/kernel/audit.h b/kernel/audit.h
index 6aa33b8..a337023 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -104,6 +104,7 @@
 	return (ino & (AUDIT_INODE_BUCKETS-1));
 }
 
+extern int audit_match_class(int class, unsigned syscall);
 extern int audit_comparator(const u32 left, const u32 op, const u32 right);
 extern int audit_compare_dname_path(const char *dname, const char *path,
 				    int *dirlen);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 5b4e162..a44879b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -302,6 +302,15 @@
 	return 0;
 }
 
+int audit_match_class(int class, unsigned syscall)
+{
+	if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32)))
+		return 0;
+	if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class]))
+		return 0;
+	return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -404,6 +413,7 @@
 		case AUDIT_PERS:
 		case AUDIT_ARCH:
 		case AUDIT_MSGTYPE:
+		case AUDIT_PPID:
 		case AUDIT_DEVMAJOR:
 		case AUDIT_DEVMINOR:
 		case AUDIT_EXIT:
@@ -413,6 +423,10 @@
 		case AUDIT_ARG2:
 		case AUDIT_ARG3:
 			break;
+		case AUDIT_PERM:
+			if (f->val & ~15)
+				goto exit_free;
+			break;
 		case AUDIT_INODE:
 			err = audit_to_inode(&entry->rule, f);
 			if (err)
@@ -442,6 +456,7 @@
 		case AUDIT_EQUAL:
 			break;
 		default:
+			err = -EINVAL;
 			goto exit_free;
 		}
 	}
@@ -566,6 +581,10 @@
 			entry->rule.buflen += f->val;
 			entry->rule.filterkey = str;
 			break;
+		case AUDIT_PERM:
+			if (f->val & ~15)
+				goto exit_free;
+			break;
 		default:
 			goto exit_free;
 		}
@@ -579,6 +598,7 @@
 		case AUDIT_EQUAL:
 			break;
 		default:
+			err = -EINVAL;
 			goto exit_free;
 		}
 	}
@@ -911,7 +931,7 @@
 		}
 
 		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-		audit_log_format(ab, "audit updated rules specifying watch=");
+		audit_log_format(ab, "audit updated rules specifying path=");
 		audit_log_untrustedstring(ab, owatch->path);
 		audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
 		audit_log_end(ab);
@@ -934,19 +954,28 @@
 	struct audit_watch *w, *nextw;
 	struct audit_krule *r, *nextr;
 	struct audit_entry *e;
+	struct audit_buffer *ab;
 
 	mutex_lock(&audit_filter_mutex);
 	parent->flags |= AUDIT_PARENT_INVALID;
 	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
 		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
 			e = container_of(r, struct audit_entry, rule);
+
+			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+			audit_log_format(ab, "audit implicitly removed rule path=");
+			audit_log_untrustedstring(ab, w->path);
+			if (r->filterkey) {
+				audit_log_format(ab, " key=");
+				audit_log_untrustedstring(ab, r->filterkey);
+			} else
+				audit_log_format(ab, " key=(null)");
+			audit_log_format(ab, " list=%d", r->listnr);
+			audit_log_end(ab);
+
 			list_del(&r->rlist);
 			list_del_rcu(&e->list);
 			call_rcu(&e->rcu, audit_free_rule_rcu);
-
-			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
-				 "audit implicitly removed rule from list=%d\n",
-				  AUDIT_FILTER_EXIT);
 		}
 		audit_remove_watch(w);
 	}
@@ -1134,6 +1163,14 @@
 	struct audit_watch *watch = entry->rule.watch;
 	struct nameidata *ndp, *ndw;
 	int h, err, putnd_needed = 0;
+#ifdef CONFIG_AUDITSYSCALL
+	int dont_count = 0;
+
+	/* If either of these, don't count towards total */
+	if (entry->rule.listnr == AUDIT_FILTER_USER ||
+		entry->rule.listnr == AUDIT_FILTER_TYPE)
+		dont_count = 1;
+#endif
 
 	if (inode_f) {
 		h = audit_hash_ino(inode_f->val);
@@ -1174,6 +1211,10 @@
 	} else {
 		list_add_tail_rcu(&entry->list, list);
 	}
+#ifdef CONFIG_AUDITSYSCALL
+	if (!dont_count)
+		audit_n_rules++;
+#endif
 	mutex_unlock(&audit_filter_mutex);
 
 	if (putnd_needed)
@@ -1198,6 +1239,14 @@
 	struct audit_watch *watch, *tmp_watch = entry->rule.watch;
 	LIST_HEAD(inotify_list);
 	int h, ret = 0;
+#ifdef CONFIG_AUDITSYSCALL
+	int dont_count = 0;
+
+	/* If either of these, don't count towards total */
+	if (entry->rule.listnr == AUDIT_FILTER_USER ||
+		entry->rule.listnr == AUDIT_FILTER_TYPE)
+		dont_count = 1;
+#endif
 
 	if (inode_f) {
 		h = audit_hash_ino(inode_f->val);
@@ -1235,6 +1284,10 @@
 	list_del_rcu(&e->list);
 	call_rcu(&e->rcu, audit_free_rule_rcu);
 
+#ifdef CONFIG_AUDITSYSCALL
+	if (!dont_count)
+		audit_n_rules--;
+#endif
 	mutex_unlock(&audit_filter_mutex);
 
 	if (!list_empty(&inotify_list))
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index ae40ac8..1bd8827 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -85,6 +85,9 @@
 /* Indicates that audit should log the full pathname. */
 #define AUDIT_NAME_FULL -1
 
+/* number of audit rules */
+int audit_n_rules;
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -174,6 +177,7 @@
 
 /* The per-task audit context. */
 struct audit_context {
+	int		    dummy;	/* must be the first element */
 	int		    in_syscall;	/* 1 if task is in a syscall */
 	enum audit_state    state;
 	unsigned int	    serial;     /* serial number for record */
@@ -205,6 +209,54 @@
 #endif
 };
 
+#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE])
+static inline int open_arg(int flags, int mask)
+{
+	int n = ACC_MODE(flags);
+	if (flags & (O_TRUNC | O_CREAT))
+		n |= AUDIT_PERM_WRITE;
+	return n & mask;
+}
+
+static int audit_match_perm(struct audit_context *ctx, int mask)
+{
+	unsigned n = ctx->major;
+	switch (audit_classify_syscall(ctx->arch, n)) {
+	case 0:	/* native */
+		if ((mask & AUDIT_PERM_WRITE) &&
+		     audit_match_class(AUDIT_CLASS_WRITE, n))
+			return 1;
+		if ((mask & AUDIT_PERM_READ) &&
+		     audit_match_class(AUDIT_CLASS_READ, n))
+			return 1;
+		if ((mask & AUDIT_PERM_ATTR) &&
+		     audit_match_class(AUDIT_CLASS_CHATTR, n))
+			return 1;
+		return 0;
+	case 1: /* 32bit on biarch */
+		if ((mask & AUDIT_PERM_WRITE) &&
+		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
+			return 1;
+		if ((mask & AUDIT_PERM_READ) &&
+		     audit_match_class(AUDIT_CLASS_READ_32, n))
+			return 1;
+		if ((mask & AUDIT_PERM_ATTR) &&
+		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
+			return 1;
+		return 0;
+	case 2: /* open */
+		return mask & ACC_MODE(ctx->argv[1]);
+	case 3: /* openat */
+		return mask & ACC_MODE(ctx->argv[2]);
+	case 4: /* socketcall */
+		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
+	case 5: /* execve */
+		return mask & AUDIT_PERM_EXEC;
+	default:
+		return 0;
+	}
+}
+
 /* Determine if any context name data matches a rule's watch data */
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise. */
@@ -393,6 +445,9 @@
 			/* ignore this field for filtering */
 			result = 1;
 			break;
+		case AUDIT_PERM:
+			result = audit_match_perm(ctx, f->val);
+			break;
 		}
 
 		if (!result)
@@ -514,7 +569,7 @@
 	context->return_valid = return_valid;
 	context->return_code  = return_code;
 
-	if (context->in_syscall && !context->auditable) {
+	if (context->in_syscall && !context->dummy && !context->auditable) {
 		enum audit_state state;
 
 		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
@@ -530,17 +585,7 @@
 	}
 
 get_context:
-	context->pid = tsk->pid;
-	context->ppid = sys_getppid();	/* sic.  tsk == current in all cases */
-	context->uid = tsk->uid;
-	context->gid = tsk->gid;
-	context->euid = tsk->euid;
-	context->suid = tsk->suid;
-	context->fsuid = tsk->fsuid;
-	context->egid = tsk->egid;
-	context->sgid = tsk->sgid;
-	context->fsgid = tsk->fsgid;
-	context->personality = tsk->personality;
+
 	tsk->audit_context = NULL;
 	return context;
 }
@@ -749,6 +794,17 @@
 	const char *tty;
 
 	/* tsk == current */
+	context->pid = tsk->pid;
+	context->ppid = sys_getppid();	/* sic.  tsk == current in all cases */
+	context->uid = tsk->uid;
+	context->gid = tsk->gid;
+	context->euid = tsk->euid;
+	context->suid = tsk->suid;
+	context->fsuid = tsk->fsuid;
+	context->egid = tsk->egid;
+	context->sgid = tsk->sgid;
+	context->fsgid = tsk->fsgid;
+	context->personality = tsk->personality;
 
 	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
 	if (!ab)
@@ -1066,7 +1122,8 @@
 	context->argv[3]    = a4;
 
 	state = context->state;
-	if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)
+	context->dummy = !audit_n_rules;
+	if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT))
 		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);
 	if (likely(state == AUDIT_DISABLED))
 		return;
@@ -1199,14 +1256,18 @@
 #endif
 }
 
-static void audit_inode_context(int idx, const struct inode *inode)
+/* Copy inode data into an audit_names. */
+static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
 {
-	struct audit_context *context = current->audit_context;
-
-	selinux_get_inode_sid(inode, &context->names[idx].osid);
+	name->ino   = inode->i_ino;
+	name->dev   = inode->i_sb->s_dev;
+	name->mode  = inode->i_mode;
+	name->uid   = inode->i_uid;
+	name->gid   = inode->i_gid;
+	name->rdev  = inode->i_rdev;
+	selinux_get_inode_sid(inode, &name->osid);
 }
 
-
 /**
  * audit_inode - store the inode and device from a lookup
  * @name: name being audited
@@ -1240,20 +1301,14 @@
 		++context->ino_count;
 #endif
 	}
-	context->names[idx].ino   = inode->i_ino;
-	context->names[idx].dev	  = inode->i_sb->s_dev;
-	context->names[idx].mode  = inode->i_mode;
-	context->names[idx].uid   = inode->i_uid;
-	context->names[idx].gid   = inode->i_gid;
-	context->names[idx].rdev  = inode->i_rdev;
-	audit_inode_context(idx, inode);
+	audit_copy_inode(&context->names[idx], inode);
 }
 
 /**
  * audit_inode_child - collect inode info for created/removed objects
  * @dname: inode's dentry name
  * @inode: inode being audited
- * @pino: inode number of dentry parent
+ * @parent: inode of dentry parent
  *
  * For syscalls that create or remove filesystem objects, audit_inode
  * can only collect information for the filesystem object's parent.
@@ -1264,7 +1319,7 @@
  * unsuccessful attempts.
  */
 void __audit_inode_child(const char *dname, const struct inode *inode,
-			 unsigned long pino)
+			 const struct inode *parent)
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
@@ -1278,7 +1333,7 @@
 	if (!dname)
 		goto update_context;
 	for (idx = 0; idx < context->name_count; idx++)
-		if (context->names[idx].ino == pino) {
+		if (context->names[idx].ino == parent->i_ino) {
 			const char *name = context->names[idx].name;
 
 			if (!name)
@@ -1302,16 +1357,47 @@
 	context->names[idx].name_len = AUDIT_NAME_FULL;
 	context->names[idx].name_put = 0;	/* don't call __putname() */
 
-	if (inode) {
-		context->names[idx].ino   = inode->i_ino;
-		context->names[idx].dev	  = inode->i_sb->s_dev;
-		context->names[idx].mode  = inode->i_mode;
-		context->names[idx].uid   = inode->i_uid;
-		context->names[idx].gid   = inode->i_gid;
-		context->names[idx].rdev  = inode->i_rdev;
-		audit_inode_context(idx, inode);
-	} else
-		context->names[idx].ino   = (unsigned long)-1;
+	if (!inode)
+		context->names[idx].ino = (unsigned long)-1;
+	else
+		audit_copy_inode(&context->names[idx], inode);
+
+	/* A parent was not found in audit_names, so copy the inode data for the
+	 * provided parent. */
+	if (!found_name) {
+		idx = context->name_count++;
+#if AUDIT_DEBUG
+		context->ino_count++;
+#endif
+		audit_copy_inode(&context->names[idx], parent);
+	}
+}
+
+/**
+ * audit_inode_update - update inode info for last collected name
+ * @inode: inode being audited
+ *
+ * When open() is called on an existing object with the O_CREAT flag, the inode
+ * data audit initially collects is incorrect.  This additional hook ensures
+ * audit has the inode data for the actual object to be opened.
+ */
+void __audit_inode_update(const struct inode *inode)
+{
+	struct audit_context *context = current->audit_context;
+	int idx;
+
+	if (!context->in_syscall || !inode)
+		return;
+
+	if (context->name_count == 0) {
+		context->name_count++;
+#if AUDIT_DEBUG
+		context->ino_count++;
+#endif
+	}
+	idx = context->name_count - 1;
+
+	audit_copy_inode(&context->names[idx], inode);
 }
 
 /**
@@ -1642,7 +1728,7 @@
 	unsigned long p, next;
 	void *to;
 
-	if (likely(!audit_enabled || !context))
+	if (likely(!audit_enabled || !context || context->dummy))
 		return 0;
 
 	ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p,
@@ -1680,7 +1766,7 @@
 	struct audit_aux_data_socketcall *ax;
 	struct audit_context *context = current->audit_context;
 
-	if (likely(!context))
+	if (likely(!context || context->dummy))
 		return 0;
 
 	ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL);
@@ -1708,7 +1794,7 @@
 	struct audit_aux_data_sockaddr *ax;
 	struct audit_context *context = current->audit_context;
 
-	if (likely(!context))
+	if (likely(!context || context->dummy))
 		return 0;
 
 	ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 1a649f2..4ea6f0d 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -816,6 +816,10 @@
 	struct cpuset trialcs;
 	int retval, cpus_unchanged;
 
+	/* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
+	if (cs == &top_cpuset)
+		return -EACCES;
+
 	trialcs = *cs;
 	retval = cpulist_parse(buf, trialcs.cpus_allowed);
 	if (retval < 0)
@@ -2033,6 +2037,33 @@
 	return err;
 }
 
+/*
+ * The top_cpuset tracks what CPUs and Memory Nodes are online,
+ * period.  This is necessary in order to make cpusets transparent
+ * (of no affect) on systems that are actively using CPU hotplug
+ * but making no active use of cpusets.
+ *
+ * This handles CPU hotplug (cpuhp) events.  If someday Memory
+ * Nodes can be hotplugged (dynamically changing node_online_map)
+ * then we should handle that too, perhaps in a similar way.
+ */
+
+#ifdef CONFIG_HOTPLUG_CPU
+static int cpuset_handle_cpuhp(struct notifier_block *nb,
+				unsigned long phase, void *cpu)
+{
+	mutex_lock(&manage_mutex);
+	mutex_lock(&callback_mutex);
+
+	top_cpuset.cpus_allowed = cpu_online_map;
+
+	mutex_unlock(&callback_mutex);
+	mutex_unlock(&manage_mutex);
+
+	return 0;
+}
+#endif
+
 /**
  * cpuset_init_smp - initialize cpus_allowed
  *
@@ -2043,6 +2074,8 @@
 {
 	top_cpuset.cpus_allowed = cpu_online_map;
 	top_cpuset.mems_allowed = node_online_map;
+
+	hotcpu_notifier(cpuset_handle_cpuhp, 0);
 }
 
 /**
@@ -2387,7 +2420,7 @@
 int cpuset_excl_nodes_overlap(const struct task_struct *p)
 {
 	const struct cpuset *cs1, *cs2;	/* my and p's cpuset ancestors */
-	int overlap = 0;		/* do cpusets overlap? */
+	int overlap = 1;		/* do cpusets overlap? */
 
 	task_lock(current);
 	if (current->flags & PF_EXITING) {
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index f05392d..36752f1 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -19,15 +19,15 @@
 #include <linux/sysctl.h>
 #include <linux/delayacct.h>
 
-int delayacct_on __read_mostly;	/* Delay accounting turned on/off */
+int delayacct_on __read_mostly = 1;	/* Delay accounting turned on/off */
 kmem_cache_t *delayacct_cache;
 
-static int __init delayacct_setup_enable(char *str)
+static int __init delayacct_setup_disable(char *str)
 {
-	delayacct_on = 1;
+	delayacct_on = 0;
 	return 1;
 }
-__setup("delayacct", delayacct_setup_enable);
+__setup("nodelayacct", delayacct_setup_disable);
 
 void delayacct_init(void)
 {
@@ -41,24 +41,11 @@
 
 void __delayacct_tsk_init(struct task_struct *tsk)
 {
-	spin_lock_init(&tsk->delays_lock);
-	/* No need to acquire tsk->delays_lock for allocation here unless
-	   __delayacct_tsk_init called after tsk is attached to tasklist
-	*/
 	tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL);
 	if (tsk->delays)
 		spin_lock_init(&tsk->delays->lock);
 }
 
-void __delayacct_tsk_exit(struct task_struct *tsk)
-{
-	struct task_delay_info *delays = tsk->delays;
-	spin_lock(&tsk->delays_lock);
-	tsk->delays = NULL;
-	spin_unlock(&tsk->delays_lock);
-	kmem_cache_free(delayacct_cache, delays);
-}
-
 /*
  * Start accounting for a delay statistic using
  * its starting timestamp (@start)
@@ -118,8 +105,6 @@
 	struct timespec ts;
 	unsigned long t1,t2,t3;
 
-	spin_lock(&tsk->delays_lock);
-
 	/* Though tsk->delays accessed later, early exit avoids
 	 * unnecessary returning of other data
 	 */
@@ -161,7 +146,6 @@
 	spin_unlock(&tsk->delays->lock);
 
 done:
-	spin_unlock(&tsk->delays_lock);
 	return 0;
 }
 
diff --git a/kernel/exit.c b/kernel/exit.c
index dba194a..d891883 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -908,7 +908,6 @@
 		audit_free(tsk);
 	taskstats_exit_send(tsk, tidstats, group_dead, mycpu);
 	taskstats_exit_free(tidstats);
-	delayacct_tsk_exit(tsk);
 
 	exit_mm(tsk);
 
@@ -1054,7 +1053,7 @@
 	 * Do not consider thread group leaders that are
 	 * in a non-empty thread group:
 	 */
-	if (current->tgid != p->tgid && delay_group_leader(p))
+	if (delay_group_leader(p))
 		return 2;
 
 	if (security_task_wait(p))
diff --git a/kernel/fork.c b/kernel/fork.c
index 1b0f7b1..f9b014e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -117,6 +117,7 @@
 	security_task_free(tsk);
 	free_uid(tsk->user);
 	put_group_info(tsk->group_info);
+	delayacct_tsk_free(tsk);
 
 	if (!profile_handoff_task(tsk))
 		free_task(tsk);
@@ -1011,7 +1012,7 @@
 	retval = -EFAULT;
 	if (clone_flags & CLONE_PARENT_SETTID)
 		if (put_user(p->pid, parent_tidptr))
-			goto bad_fork_cleanup;
+			goto bad_fork_cleanup_delays_binfmt;
 
 	INIT_LIST_HEAD(&p->children);
 	INIT_LIST_HEAD(&p->sibling);
@@ -1277,7 +1278,8 @@
 bad_fork_cleanup_cpuset:
 #endif
 	cpuset_exit(p);
-bad_fork_cleanup:
+bad_fork_cleanup_delays_binfmt:
+	delayacct_tsk_free(p);
 	if (p->binfmt)
 		module_put(p->binfmt->module);
 bad_fork_cleanup_put_domain:
@@ -1387,8 +1389,10 @@
 
 		if (clone_flags & CLONE_VFORK) {
 			wait_for_completion(&vfork);
-			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
+			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
+				current->ptrace_message = nr;
 				ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
+			}
 		}
 	} else {
 		free_pid(pid);
diff --git a/kernel/futex.c b/kernel/futex.c
index cf0c8e2..9d260e8 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -297,7 +297,7 @@
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
 
-	if (attempt >= 2 || !(vma = find_vma(mm, address)) ||
+	if (attempt > 2 || !(vma = find_vma(mm, address)) ||
 	    vma->vm_start > address || !(vma->vm_flags & VM_WRITE))
 		return -EFAULT;
 
@@ -397,7 +397,7 @@
 		p = NULL;
 		goto out_unlock;
 	}
-	if (p->state == EXIT_ZOMBIE || p->exit_state == EXIT_ZOMBIE) {
+	if (p->exit_state != 0) {
 		p = NULL;
 		goto out_unlock;
 	}
@@ -415,15 +415,15 @@
  */
 void exit_pi_state_list(struct task_struct *curr)
 {
-	struct futex_hash_bucket *hb;
 	struct list_head *next, *head = &curr->pi_state_list;
 	struct futex_pi_state *pi_state;
+	struct futex_hash_bucket *hb;
 	union futex_key key;
 
 	/*
 	 * We are a ZOMBIE and nobody can enqueue itself on
 	 * pi_state_list anymore, but we have to be careful
-	 * versus waiters unqueueing themselfs
+	 * versus waiters unqueueing themselves:
 	 */
 	spin_lock_irq(&curr->pi_lock);
 	while (!list_empty(head)) {
@@ -431,21 +431,24 @@
 		next = head->next;
 		pi_state = list_entry(next, struct futex_pi_state, list);
 		key = pi_state->key;
+		hb = hash_futex(&key);
 		spin_unlock_irq(&curr->pi_lock);
 
-		hb = hash_futex(&key);
 		spin_lock(&hb->lock);
 
 		spin_lock_irq(&curr->pi_lock);
+		/*
+		 * We dropped the pi-lock, so re-check whether this
+		 * task still owns the PI-state:
+		 */
 		if (head->next != next) {
 			spin_unlock(&hb->lock);
 			continue;
 		}
 
-		list_del_init(&pi_state->list);
-
 		WARN_ON(pi_state->owner != curr);
-
+		WARN_ON(list_empty(&pi_state->list));
+		list_del_init(&pi_state->list);
 		pi_state->owner = NULL;
 		spin_unlock_irq(&curr->pi_lock);
 
@@ -470,7 +473,7 @@
 	head = &hb->chain;
 
 	list_for_each_entry_safe(this, next, head, list) {
-		if (match_futex (&this->key, &me->key)) {
+		if (match_futex(&this->key, &me->key)) {
 			/*
 			 * Another waiter already exists - bump up
 			 * the refcount and return its pi_state:
@@ -482,6 +485,8 @@
 			if (unlikely(!pi_state))
 				return -EINVAL;
 
+			WARN_ON(!atomic_read(&pi_state->refcount));
+
 			atomic_inc(&pi_state->refcount);
 			me->pi_state = pi_state;
 
@@ -490,10 +495,13 @@
 	}
 
 	/*
-	 * We are the first waiter - try to look up the real owner and
-	 * attach the new pi_state to it:
+	 * We are the first waiter - try to look up the real owner and attach
+	 * the new pi_state to it, but bail out when the owner died bit is set
+	 * and TID = 0:
 	 */
 	pid = uval & FUTEX_TID_MASK;
+	if (!pid && (uval & FUTEX_OWNER_DIED))
+		return -ESRCH;
 	p = futex_find_get_task(pid);
 	if (!p)
 		return -ESRCH;
@@ -510,6 +518,7 @@
 	pi_state->key = me->key;
 
 	spin_lock_irq(&p->pi_lock);
+	WARN_ON(!list_empty(&pi_state->list));
 	list_add(&pi_state->list, &p->pi_state_list);
 	pi_state->owner = p;
 	spin_unlock_irq(&p->pi_lock);
@@ -573,20 +582,29 @@
 	 * kept enabled while there is PI state around. We must also
 	 * preserve the owner died bit.)
 	 */
-	newval = (uval & FUTEX_OWNER_DIED) | FUTEX_WAITERS | new_owner->pid;
+	if (!(uval & FUTEX_OWNER_DIED)) {
+		newval = FUTEX_WAITERS | new_owner->pid;
 
-	inc_preempt_count();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
-	dec_preempt_count();
+		inc_preempt_count();
+		curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+		dec_preempt_count();
+		if (curval == -EFAULT)
+			return -EFAULT;
+		if (curval != uval)
+			return -EINVAL;
+	}
 
-	if (curval == -EFAULT)
-		return -EFAULT;
-	if (curval != uval)
-		return -EINVAL;
+	spin_lock_irq(&pi_state->owner->pi_lock);
+	WARN_ON(list_empty(&pi_state->list));
+	list_del_init(&pi_state->list);
+	spin_unlock_irq(&pi_state->owner->pi_lock);
 
-	list_del_init(&pi_state->owner->pi_state_list);
+	spin_lock_irq(&new_owner->pi_lock);
+	WARN_ON(!list_empty(&pi_state->list));
 	list_add(&pi_state->list, &new_owner->pi_state_list);
 	pi_state->owner = new_owner;
+	spin_unlock_irq(&new_owner->pi_lock);
+
 	rt_mutex_unlock(&pi_state->pi_mutex);
 
 	return 0;
@@ -729,8 +747,10 @@
 		 */
 		if (attempt++) {
 			if (futex_handle_fault((unsigned long)uaddr2,
-					       attempt))
+						attempt)) {
+				ret = -EFAULT;
 				goto out;
+			}
 			goto retry;
 		}
 
@@ -930,6 +950,7 @@
 	/* In the common case we don't take the spinlock, which is nice. */
  retry:
 	lock_ptr = q->lock_ptr;
+	barrier();
 	if (lock_ptr != 0) {
 		spin_lock(lock_ptr);
 		/*
@@ -1099,9 +1120,10 @@
  * if there are waiters then it will block, it does PI, etc. (Due to
  * races the kernel might see a 0 value of the futex too.)
  */
-static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
-			    struct hrtimer_sleeper *to)
+static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
+			 long nsec, int trylock)
 {
+	struct hrtimer_sleeper timeout, *to = NULL;
 	struct task_struct *curr = current;
 	struct futex_hash_bucket *hb;
 	u32 uval, newval, curval;
@@ -1111,6 +1133,13 @@
 	if (refill_pi_state_cache())
 		return -ENOMEM;
 
+	if (sec != MAX_SCHEDULE_TIMEOUT) {
+		to = &timeout;
+		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+		hrtimer_init_sleeper(to, current);
+		to->timer.expires = ktime_set(sec, nsec);
+	}
+
 	q.pi_state = NULL;
  retry:
 	down_read(&curr->mm->mmap_sem);
@@ -1236,6 +1265,7 @@
 		/* Owner died? */
 		if (q.pi_state->owner != NULL) {
 			spin_lock_irq(&q.pi_state->owner->pi_lock);
+			WARN_ON(list_empty(&q.pi_state->list));
 			list_del_init(&q.pi_state->list);
 			spin_unlock_irq(&q.pi_state->owner->pi_lock);
 		} else
@@ -1244,6 +1274,7 @@
 		q.pi_state->owner = current;
 
 		spin_lock_irq(&current->pi_lock);
+		WARN_ON(!list_empty(&q.pi_state->list));
 		list_add(&q.pi_state->list, &current->pi_state_list);
 		spin_unlock_irq(&current->pi_lock);
 
@@ -1284,7 +1315,7 @@
 	if (!detect && ret == -EDEADLK && 0)
 		force_sig(SIGKILL, current);
 
-	return ret;
+	return ret != -EINTR ? ret : -ERESTARTNOINTR;
 
  out_unlock_release_sem:
 	queue_unlock(&q, hb);
@@ -1301,9 +1332,10 @@
 	 * still holding the mmap_sem.
 	 */
 	if (attempt++) {
-		if (futex_handle_fault((unsigned long)uaddr, attempt))
+		if (futex_handle_fault((unsigned long)uaddr, attempt)) {
+			ret = -EFAULT;
 			goto out_unlock_release_sem;
-
+		}
 		goto retry_locked;
 	}
 
@@ -1318,76 +1350,6 @@
 }
 
 /*
- * Restart handler
- */
-static long futex_lock_pi_restart(struct restart_block *restart)
-{
-	struct hrtimer_sleeper timeout, *to = NULL;
-	int ret;
-
-	restart->fn = do_no_restart_syscall;
-
-	if (restart->arg2 || restart->arg3) {
-		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
-		hrtimer_init_sleeper(to, current);
-		to->timer.expires.tv64 = ((u64)restart->arg1 << 32) |
-			(u64) restart->arg0;
-	}
-
-	pr_debug("lock_pi restart: %p, %d (%d)\n",
-		 (u32 __user *)restart->arg0, current->pid);
-
-	ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1,
-			       0, to);
-
-	if (ret != -EINTR)
-		return ret;
-
-	restart->fn = futex_lock_pi_restart;
-
-	/* The other values are filled in */
-	return -ERESTART_RESTARTBLOCK;
-}
-
-/*
- * Called from the syscall entry below.
- */
-static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
-			 long nsec, int trylock)
-{
-	struct hrtimer_sleeper timeout, *to = NULL;
-	struct restart_block *restart;
-	int ret;
-
-	if (sec != MAX_SCHEDULE_TIMEOUT) {
-		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
-		hrtimer_init_sleeper(to, current);
-		to->timer.expires = ktime_set(sec, nsec);
-	}
-
-	ret = do_futex_lock_pi(uaddr, detect, trylock, to);
-
-	if (ret != -EINTR)
-		return ret;
-
-	pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid);
-
-	restart = &current_thread_info()->restart_block;
-	restart->fn = futex_lock_pi_restart;
-	restart->arg0 = (unsigned long) uaddr;
-	restart->arg1 = detect;
-	if (to) {
-		restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF;
-		restart->arg3 = to->timer.expires.tv64 >> 32;
-	} else
-		restart->arg2 = restart->arg3 = 0;
-
-	return -ERESTART_RESTARTBLOCK;
-}
-
-/*
  * Userspace attempted a TID -> 0 atomic transition, and failed.
  * This is the in-kernel slowpath: we look up the PI state (if any),
  * and do the rt-mutex unlock.
@@ -1427,9 +1389,11 @@
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	inc_preempt_count();
-	uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
-	dec_preempt_count();
+	if (!(uval & FUTEX_OWNER_DIED)) {
+		inc_preempt_count();
+		uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
+		dec_preempt_count();
+	}
 
 	if (unlikely(uval == -EFAULT))
 		goto pi_faulted;
@@ -1462,9 +1426,11 @@
 	/*
 	 * No waiters - kernel unlocks the futex:
 	 */
-	ret = unlock_futex_pi(uaddr, uval);
-	if (ret == -EFAULT)
-		goto pi_faulted;
+	if (!(uval & FUTEX_OWNER_DIED)) {
+		ret = unlock_futex_pi(uaddr, uval);
+		if (ret == -EFAULT)
+			goto pi_faulted;
+	}
 
 out_unlock:
 	spin_unlock(&hb->lock);
@@ -1481,9 +1447,10 @@
 	 * still holding the mmap_sem.
 	 */
 	if (attempt++) {
-		if (futex_handle_fault((unsigned long)uaddr, attempt))
+		if (futex_handle_fault((unsigned long)uaddr, attempt)) {
+			ret = -EFAULT;
 			goto out_unlock;
-
+		}
 		goto retry_locked;
 	}
 
@@ -1683,9 +1650,9 @@
  * Process a futex-list entry, check whether it's owned by the
  * dying task, and do notification if so:
  */
-int handle_futex_death(u32 __user *uaddr, struct task_struct *curr)
+int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi)
 {
-	u32 uval, nval;
+	u32 uval, nval, mval;
 
 retry:
 	if (get_user(uval, uaddr))
@@ -1702,21 +1669,45 @@
 		 * thread-death.) The rest of the cleanup is done in
 		 * userspace.
 		 */
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval,
-						     uval | FUTEX_OWNER_DIED);
+		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
+		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
+
 		if (nval == -EFAULT)
 			return -1;
 
 		if (nval != uval)
 			goto retry;
 
-		if (uval & FUTEX_WAITERS)
-			futex_wake(uaddr, 1);
+		/*
+		 * Wake robust non-PI futexes here. The wakeup of
+		 * PI futexes happens in exit_pi_state():
+		 */
+		if (!pi) {
+			if (uval & FUTEX_WAITERS)
+				futex_wake(uaddr, 1);
+		}
 	}
 	return 0;
 }
 
 /*
+ * Fetch a robust-list pointer. Bit 0 signals PI futexes:
+ */
+static inline int fetch_robust_entry(struct robust_list __user **entry,
+				     struct robust_list __user **head, int *pi)
+{
+	unsigned long uentry;
+
+	if (get_user(uentry, (unsigned long *)head))
+		return -EFAULT;
+
+	*entry = (void *)(uentry & ~1UL);
+	*pi = uentry & 1;
+
+	return 0;
+}
+
+/*
  * Walk curr->robust_list (very carefully, it's a userspace list!)
  * and mark any locks found there dead, and notify any waiters.
  *
@@ -1726,14 +1717,14 @@
 {
 	struct robust_list_head __user *head = curr->robust_list;
 	struct robust_list __user *entry, *pending;
-	unsigned int limit = ROBUST_LIST_LIMIT;
+	unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
 	unsigned long futex_offset;
 
 	/*
 	 * Fetch the list head (which was registered earlier, via
 	 * sys_set_robust_list()):
 	 */
-	if (get_user(entry, &head->list.next))
+	if (fetch_robust_entry(&entry, &head->list.next, &pi))
 		return;
 	/*
 	 * Fetch the relative futex offset:
@@ -1744,10 +1735,11 @@
 	 * Fetch any possibly pending lock-add first, and handle it
 	 * if it exists:
 	 */
-	if (get_user(pending, &head->list_op_pending))
+	if (fetch_robust_entry(&pending, &head->list_op_pending, &pip))
 		return;
+
 	if (pending)
-		handle_futex_death((void *)pending + futex_offset, curr);
+		handle_futex_death((void *)pending + futex_offset, curr, pip);
 
 	while (entry != &head->list) {
 		/*
@@ -1756,12 +1748,12 @@
 		 */
 		if (entry != pending)
 			if (handle_futex_death((void *)entry + futex_offset,
-						curr))
+						curr, pi))
 				return;
 		/*
 		 * Fetch the next entry in the list:
 		 */
-		if (get_user(entry, &entry->next))
+		if (fetch_robust_entry(&entry, &entry->next, &pi))
 			return;
 		/*
 		 * Avoid excessively long or circular lists:
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index d1d92b4..c5cca3f 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -12,6 +12,23 @@
 
 #include <asm/uaccess.h>
 
+
+/*
+ * Fetch a robust-list pointer. Bit 0 signals PI futexes:
+ */
+static inline int
+fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry,
+		   compat_uptr_t *head, int *pi)
+{
+	if (get_user(*uentry, head))
+		return -EFAULT;
+
+	*entry = compat_ptr((*uentry) & ~1);
+	*pi = (unsigned int)(*uentry) & 1;
+
+	return 0;
+}
+
 /*
  * Walk curr->robust_list (very carefully, it's a userspace list!)
  * and mark any locks found there dead, and notify any waiters.
@@ -22,17 +39,16 @@
 {
 	struct compat_robust_list_head __user *head = curr->compat_robust_list;
 	struct robust_list __user *entry, *pending;
+	unsigned int limit = ROBUST_LIST_LIMIT, pi, pip;
 	compat_uptr_t uentry, upending;
-	unsigned int limit = ROBUST_LIST_LIMIT;
 	compat_long_t futex_offset;
 
 	/*
 	 * Fetch the list head (which was registered earlier, via
 	 * sys_set_robust_list()):
 	 */
-	if (get_user(uentry, &head->list.next))
+	if (fetch_robust_entry(&uentry, &entry, &head->list.next, &pi))
 		return;
-	entry = compat_ptr(uentry);
 	/*
 	 * Fetch the relative futex offset:
 	 */
@@ -42,11 +58,11 @@
 	 * Fetch any possibly pending lock-add first, and handle it
 	 * if it exists:
 	 */
-	if (get_user(upending, &head->list_op_pending))
+	if (fetch_robust_entry(&upending, &pending,
+			       &head->list_op_pending, &pip))
 		return;
-	pending = compat_ptr(upending);
 	if (upending)
-		handle_futex_death((void *)pending + futex_offset, curr);
+		handle_futex_death((void *)pending + futex_offset, curr, pip);
 
 	while (compat_ptr(uentry) != &head->list) {
 		/*
@@ -55,15 +71,15 @@
 		 */
 		if (entry != pending)
 			if (handle_futex_death((void *)entry + futex_offset,
-						curr))
+						curr, pi))
 				return;
 
 		/*
 		 * Fetch the next entry in the list:
 		 */
-		if (get_user(uentry, (compat_uptr_t *)&entry->next))
+		if (fetch_robust_entry(&uentry, &entry,
+				       (compat_uptr_t *)&entry->next, &pi))
 			return;
-		entry = compat_ptr(uentry);
 		/*
 		 * Avoid excessively long or circular lists:
 		 */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d17766d..21c38a7 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -187,7 +187,7 @@
 {
 	struct hrtimer_base *new_base;
 
-	new_base = &__get_cpu_var(hrtimer_bases[base->index]);
+	new_base = &__get_cpu_var(hrtimer_bases)[base->index];
 
 	if (base != new_base) {
 		/*
@@ -835,7 +835,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
+static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
 					unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -859,7 +859,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata hrtimers_nb = {
+static struct notifier_block __cpuinitdata hrtimers_nb = {
 	.notifier_call = hrtimer_cpu_notify,
 };
 
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index fc4e906..48a53f6 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -20,6 +20,11 @@
 
 /**
  * handle_bad_irq - handle spurious and unhandled irqs
+ * @irq:       the interrupt number
+ * @desc:      description of the interrupt
+ * @regs:      pointer to a register structure
+ *
+ * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
  */
 void fastcall
 handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 4e46143..92be519 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -137,16 +137,40 @@
  *	@irq:	interrupt to control
  *	@on:	enable/disable power management wakeup
  *
- *	Enable/disable power management wakeup mode
+ *	Enable/disable power management wakeup mode, which is
+ *	disabled by default.  Enables and disables must match,
+ *	just as they match for non-wakeup mode support.
+ *
+ *	Wakeup mode lets this IRQ wake the system from sleep
+ *	states like "suspend to RAM".
  */
 int set_irq_wake(unsigned int irq, unsigned int on)
 {
 	struct irq_desc *desc = irq_desc + irq;
 	unsigned long flags;
 	int ret = -ENXIO;
+	int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake;
 
+	/* wakeup-capable irqs can be shared between drivers that
+	 * don't need to have the same sleep mode behaviors.
+	 */
 	spin_lock_irqsave(&desc->lock, flags);
-	if (desc->chip->set_wake)
+	if (on) {
+		if (desc->wake_depth++ == 0)
+			desc->status |= IRQ_WAKEUP;
+		else
+			set_wake = NULL;
+	} else {
+		if (desc->wake_depth == 0) {
+			printk(KERN_WARNING "Unbalanced IRQ %d "
+					"wake disable\n", irq);
+			WARN_ON(1);
+		} else if (--desc->wake_depth == 0)
+			desc->status &= ~IRQ_WAKEUP;
+		else
+			set_wake = NULL;
+	}
+	if (set_wake)
 		ret = desc->chip->set_wake(irq, on);
 	spin_unlock_irqrestore(&desc->lock, flags);
 	return ret;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 64aab08..3f57dfd 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -393,6 +393,7 @@
 static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
 {
 	copy_kprobe(p, ap);
+	flush_insn_slot(ap);
 	ap->addr = p->addr;
 	ap->pre_handler = aggr_pre_handler;
 	ap->fault_handler = aggr_fault_handler;
diff --git a/kernel/panic.c b/kernel/panic.c
index d8a0bca..8010b9b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/nmi.h>
 #include <linux/kexec.h>
+#include <linux/debug_locks.h>
 
 int panic_on_oops;
 int tainted;
@@ -172,7 +173,7 @@
 
 void add_taint(unsigned flag)
 {
-	debug_locks_off(); /* can't trust the integrity of the kernel anymore */
+	debug_locks = 0; /* can't trust the integrity of the kernel anymore */
 	tainted |= flag;
 }
 EXPORT_SYMBOL(add_taint);
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ae44a70..619ecab 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -56,7 +56,7 @@
 
 config SOFTWARE_SUSPEND
 	bool "Software Suspend"
-	depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
+	depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP) && !X86_PAE) || ((FRV || PPC32) && !SMP))
 	---help---
 	  Enable the possibility of suspending the machine.
 	  It doesn't need ACPI or APM.
@@ -78,6 +78,10 @@
 
 	  For more information take a look at <file:Documentation/power/swsusp.txt>.
 
+	  (For now, swsusp is incompatible with PAE aka HIGHMEM_64G on i386.
+	  we need identity mapping for resume to work, and that is trivial
+	  to get with 4MB pages, but less than trivial on PAE).
+
 config PM_STD_PARTITION
 	string "Default resume partition"
 	depends on SOFTWARE_SUSPEND
diff --git a/kernel/power/process.c b/kernel/power/process.c
index b2a5f67..72e72d2 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -66,13 +66,25 @@
 	}
 }
 
+static void cancel_freezing(struct task_struct *p)
+{
+	unsigned long flags;
+
+	if (freezing(p)) {
+		pr_debug("  clean up: %s\n", p->comm);
+		do_not_freeze(p);
+		spin_lock_irqsave(&p->sighand->siglock, flags);
+		recalc_sigpending_tsk(p);
+		spin_unlock_irqrestore(&p->sighand->siglock, flags);
+	}
+}
+
 /* 0 = success, else # of processes that we failed to stop */
 int freeze_processes(void)
 {
 	int todo, nr_user, user_frozen;
 	unsigned long start_time;
 	struct task_struct *g, *p;
-	unsigned long flags;
 
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
@@ -85,6 +97,10 @@
 				continue;
 			if (frozen(p))
 				continue;
+			if (p->state == TASK_TRACED && frozen(p->parent)) {
+				cancel_freezing(p);
+				continue;
+			}
 			if (p->mm && !(p->flags & PF_BORROWED_MM)) {
 				/* The task is a user-space one.
 				 * Freeze it unless there's a vfork completion
@@ -126,13 +142,7 @@
 		do_each_thread(g, p) {
 			if (freezeable(p) && !frozen(p))
 				printk(KERN_ERR "  %s\n", p->comm);
-			if (freezing(p)) {
-				pr_debug("  clean up: %s\n", p->comm);
-				p->flags &= ~PF_FREEZE;
-				spin_lock_irqsave(&p->sighand->siglock, flags);
-				recalc_sigpending_tsk(p);
-				spin_unlock_irqrestore(&p->sighand->siglock, flags);
-			}
+			cancel_freezing(p);
 		} while_each_thread(g, p);
 		read_unlock(&tasklist_lock);
 		return todo;
diff --git a/kernel/printk.c b/kernel/printk.c
index 65ca068..1149365 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -799,6 +799,9 @@
 		up(&secondary_console_sem);
 		return;
 	}
+
+	console_may_schedule = 0;
+
 	for ( ; ; ) {
 		spin_lock_irqsave(&logbuf_lock, flags);
 		wake_klogd |= log_start - log_end;
@@ -812,7 +815,6 @@
 		local_irq_restore(flags);
 	}
 	console_locked = 0;
-	console_may_schedule = 0;
 	up(&console_sem);
 	spin_unlock_irqrestore(&logbuf_lock, flags);
 	if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) {
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 759805c..436ab35 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -548,7 +548,7 @@
 	tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
 }
 
-static int __devinit rcu_cpu_notify(struct notifier_block *self,
+static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -565,7 +565,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata rcu_nb = {
+static struct notifier_block __cpuinitdata rcu_nb = {
 	.notifier_call	= rcu_cpu_notify,
 };
 
diff --git a/kernel/resource.c b/kernel/resource.c
index 0dd3a85..4628643 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -244,6 +244,7 @@
 
 	start = res->start;
 	end = res->end;
+	BUG_ON(start >= end);
 
 	read_lock(&resource_lock);
 	for (p = iomem_resource.child; p ; p = p->sibling) {
@@ -254,15 +255,17 @@
 			p = NULL;
 			break;
 		}
-		if (p->start >= start)
+		if ((p->end >= start) && (p->start < end))
 			break;
 	}
 	read_unlock(&resource_lock);
 	if (!p)
 		return -1;
 	/* copy data */
-	res->start = p->start;
-	res->end = p->end;
+	if (res->start < p->start)
+		res->start = p->start;
+	if (res->end > p->end)
+		res->end = p->end;
 	return 0;
 }
 #endif
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index d2ef13b..3e13a1e 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -7,6 +7,8 @@
  *  Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
  *  Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
  *  Copyright (C) 2006 Esben Nielsen
+ *
+ *  See Documentation/rt-mutex-design.txt for details.
  */
 #include <linux/spinlock.h>
 #include <linux/module.h>
diff --git a/kernel/sched.c b/kernel/sched.c
index b44b9a4..a234fbe 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4162,10 +4162,8 @@
 		read_unlock_irq(&tasklist_lock);
 		return -ESRCH;
 	}
-	get_task_struct(p);
-	read_unlock_irq(&tasklist_lock);
 	retval = sched_setscheduler(p, policy, &lparam);
-	put_task_struct(p);
+	read_unlock_irq(&tasklist_lock);
 
 	return retval;
 }
@@ -4456,9 +4454,9 @@
 	return 0;
 }
 
-static inline int __resched_legal(void)
+static inline int __resched_legal(int expected_preempt_count)
 {
-	if (unlikely(preempt_count()))
+	if (unlikely(preempt_count() != expected_preempt_count))
 		return 0;
 	if (unlikely(system_state != SYSTEM_RUNNING))
 		return 0;
@@ -4484,7 +4482,7 @@
 
 int __sched cond_resched(void)
 {
-	if (need_resched() && __resched_legal()) {
+	if (need_resched() && __resched_legal(0)) {
 		__cond_resched();
 		return 1;
 	}
@@ -4510,7 +4508,7 @@
 		ret = 1;
 		spin_lock(lock);
 	}
-	if (need_resched() && __resched_legal()) {
+	if (need_resched() && __resched_legal(1)) {
 		spin_release(&lock->dep_map, 1, _THIS_IP_);
 		_raw_spin_unlock(lock);
 		preempt_enable_no_resched();
@@ -4526,7 +4524,7 @@
 {
 	BUG_ON(!in_softirq());
 
-	if (need_resched() && __resched_legal()) {
+	if (need_resched() && __resched_legal(0)) {
 		raw_local_irq_disable();
 		_local_bh_enable();
 		raw_local_irq_enable();
@@ -6494,7 +6492,12 @@
 	for (i = 0; i < MAX_NUMNODES; i++)
 		init_numa_sched_groups_power(sched_group_nodes[i]);
 
-	init_numa_sched_groups_power(sched_group_allnodes);
+	if (sched_group_allnodes) {
+		int group = cpu_to_allnodes_group(first_cpu(*cpu_map));
+		struct sched_group *sg = &sched_group_allnodes[group];
+
+		init_numa_sched_groups_power(sg);
+	}
 #endif
 
 	/* Attach the domains */
@@ -6761,6 +6764,11 @@
 	}
 
 	set_load_weight(&init_task);
+
+#ifdef CONFIG_RT_MUTEXES
+	plist_head_init(&init_task.pi_waiters, &init_task.pi_lock);
+#endif
+
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
diff --git a/kernel/signal.c b/kernel/signal.c
index 7fe874d..bfdb5686 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -791,22 +791,31 @@
 /*
  * Force a signal that the process can't ignore: if necessary
  * we unblock the signal and change any SIG_IGN to SIG_DFL.
+ *
+ * Note: If we unblock the signal, we always reset it to SIG_DFL,
+ * since we do not want to have a signal handler that was blocked
+ * be invoked when user space had explicitly blocked it.
+ *
+ * We don't want to have recursive SIGSEGV's etc, for example.
  */
-
 int
 force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
 	unsigned long int flags;
-	int ret;
+	int ret, blocked, ignored;
+	struct k_sigaction *action;
 
 	spin_lock_irqsave(&t->sighand->siglock, flags);
-	if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
-		t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
+	action = &t->sighand->action[sig-1];
+	ignored = action->sa.sa_handler == SIG_IGN;
+	blocked = sigismember(&t->blocked, sig);
+	if (blocked || ignored) {
+		action->sa.sa_handler = SIG_DFL;
+		if (blocked) {
+			sigdelset(&t->blocked, sig);
+			recalc_sigpending_tsk(t);
+		}
 	}
-	if (sigismember(&t->blocked, sig)) {
-		sigdelset(&t->blocked, sig);
-	}
-	recalc_sigpending_tsk(t);
 	ret = specific_send_sig_info(sig, info, t);
 	spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0f08a84..3789ca9 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -65,6 +65,7 @@
  * This one is for softirq.c-internal use,
  * where hardirqs are disabled legitimately:
  */
+#ifdef CONFIG_TRACE_IRQFLAGS
 static void __local_bh_disable(unsigned long ip)
 {
 	unsigned long flags;
@@ -80,6 +81,13 @@
 		trace_softirqs_off(ip);
 	raw_local_irq_restore(flags);
 }
+#else /* !CONFIG_TRACE_IRQFLAGS */
+static inline void __local_bh_disable(unsigned long ip)
+{
+	add_preempt_count(SOFTIRQ_OFFSET);
+	barrier();
+}
+#endif /* CONFIG_TRACE_IRQFLAGS */
 
 void local_bh_disable(void)
 {
@@ -121,12 +129,16 @@
 
 void local_bh_enable(void)
 {
+#ifdef CONFIG_TRACE_IRQFLAGS
 	unsigned long flags;
 
 	WARN_ON_ONCE(in_irq());
+#endif
 	WARN_ON_ONCE(irqs_disabled());
 
+#ifdef CONFIG_TRACE_IRQFLAGS
 	local_irq_save(flags);
+#endif
 	/*
 	 * Are softirqs going to be turned on now:
 	 */
@@ -142,18 +154,22 @@
 		do_softirq();
 
 	dec_preempt_count();
+#ifdef CONFIG_TRACE_IRQFLAGS
 	local_irq_restore(flags);
+#endif
 	preempt_check_resched();
 }
 EXPORT_SYMBOL(local_bh_enable);
 
 void local_bh_enable_ip(unsigned long ip)
 {
+#ifdef CONFIG_TRACE_IRQFLAGS
 	unsigned long flags;
 
 	WARN_ON_ONCE(in_irq());
 
 	local_irq_save(flags);
+#endif
 	/*
 	 * Are softirqs going to be turned on now:
 	 */
@@ -169,7 +185,9 @@
 		do_softirq();
 
 	dec_preempt_count();
+#ifdef CONFIG_TRACE_IRQFLAGS
 	local_irq_restore(flags);
+#endif
 	preempt_check_resched();
 }
 EXPORT_SYMBOL(local_bh_enable_ip);
@@ -547,7 +565,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit cpu_callback(struct notifier_block *nfb,
+static int __cpuinit cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
@@ -587,7 +605,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block __cpuinitdata cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 6b76caa..03e6a2b 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -104,7 +104,7 @@
 /*
  * Create/destroy watchdog threads as CPUs come and go:
  */
-static int __devinit
+static int __cpuinit
 cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
@@ -142,7 +142,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata cpu_nfb = {
+static struct notifier_block __cpuinitdata cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index bfd6ad9..fb524b0 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -72,7 +72,7 @@
  * not re-enabled during lock-acquire (which the preempt-spin-ops do):
  */
 #if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) || \
-	defined(CONFIG_PROVE_LOCKING)
+	defined(CONFIG_DEBUG_LOCK_ALLOC)
 
 void __lockfunc _read_lock(rwlock_t *lock)
 {
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index dcfb5d7..51cacd1 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -111,7 +111,6 @@
 	/* If some failed, kill them all. */
 	if (ret < 0) {
 		stopmachine_set_state(STOPMACHINE_EXIT);
-		up(&stopmachine_mutex);
 		return ret;
 	}
 
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index f45179c..e781876 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -121,46 +121,45 @@
 /*
  * Send taskstats data in @skb to listeners registered for @cpu's exit data
  */
-static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
+static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
 {
 	struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
 	struct listener_list *listeners;
 	struct listener *s, *tmp;
 	struct sk_buff *skb_next, *skb_cur = skb;
 	void *reply = genlmsg_data(genlhdr);
-	int rc, ret, delcount = 0;
+	int rc, delcount = 0;
 
 	rc = genlmsg_end(skb, reply);
 	if (rc < 0) {
 		nlmsg_free(skb);
-		return rc;
+		return;
 	}
 
 	rc = 0;
 	listeners = &per_cpu(listener_array, cpu);
 	down_read(&listeners->sem);
-	list_for_each_entry_safe(s, tmp, &listeners->list, list) {
+	list_for_each_entry(s, &listeners->list, list) {
 		skb_next = NULL;
 		if (!list_is_last(&s->list, &listeners->list)) {
 			skb_next = skb_clone(skb_cur, GFP_KERNEL);
-			if (!skb_next) {
-				nlmsg_free(skb_cur);
-				rc = -ENOMEM;
+			if (!skb_next)
 				break;
-			}
 		}
-		ret = genlmsg_unicast(skb_cur, s->pid);
-		if (ret == -ECONNREFUSED) {
+		rc = genlmsg_unicast(skb_cur, s->pid);
+		if (rc == -ECONNREFUSED) {
 			s->valid = 0;
 			delcount++;
-			rc = ret;
 		}
 		skb_cur = skb_next;
 	}
 	up_read(&listeners->sem);
 
+	if (skb_cur)
+		nlmsg_free(skb_cur);
+
 	if (!delcount)
-		return rc;
+		return;
 
 	/* Delete invalidated entries */
 	down_write(&listeners->sem);
@@ -171,13 +170,12 @@
 		}
 	}
 	up_write(&listeners->sem);
-	return rc;
 }
 
 static int fill_pid(pid_t pid, struct task_struct *pidtsk,
 		struct taskstats *stats)
 {
-	int rc;
+	int rc = 0;
 	struct task_struct *tsk = pidtsk;
 
 	if (!pidtsk) {
@@ -196,12 +194,10 @@
 	 * Each accounting subsystem adds calls to its functions to
 	 * fill in relevant parts of struct taskstsats as follows
 	 *
-	 *	rc = per-task-foo(stats, tsk);
-	 *	if (rc)
-	 *		goto err;
+	 *	per-task-foo(stats, tsk);
 	 */
 
-	rc = delayacct_add_tsk(stats, tsk);
+	delayacct_add_tsk(stats, tsk);
 	stats->version = TASKSTATS_VERSION;
 
 	/* Define err: label here if needed */
diff --git a/kernel/timer.c b/kernel/timer.c
index 05809c2..1d7dd62 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -84,7 +84,7 @@
 
 tvec_base_t boot_tvec_bases;
 EXPORT_SYMBOL(boot_tvec_bases);
-static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases };
+static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
 
 static inline void set_running_timer(tvec_base_t *base,
 					struct timer_list *timer)
@@ -408,7 +408,7 @@
  * This function cascades all vectors and executes all expired timer
  * vectors.
  */
-#define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK
+#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
 
 static inline void __run_timers(tvec_base_t *base)
 {
@@ -1324,46 +1324,19 @@
 }
 
 /*
- * Accessing ->group_leader->real_parent is not SMP-safe, it could
- * change from under us. However, rather than getting any lock
- * we can use an optimistic algorithm: get the parent
- * pid, and go back and check that the parent is still
- * the same. If it has changed (which is extremely unlikely
- * indeed), we just try again..
- *
- * NOTE! This depends on the fact that even if we _do_
- * get an old value of "parent", we can happily dereference
- * the pointer (it was and remains a dereferencable kernel pointer
- * no matter what): we just can't necessarily trust the result
- * until we know that the parent pointer is valid.
- *
- * NOTE2: ->group_leader never changes from under us.
+ * Accessing ->real_parent is not SMP-safe, it could
+ * change from under us. However, we can use a stale
+ * value of ->real_parent under rcu_read_lock(), see
+ * release_task()->call_rcu(delayed_put_task_struct).
  */
 asmlinkage long sys_getppid(void)
 {
 	int pid;
-	struct task_struct *me = current;
-	struct task_struct *parent;
 
-	parent = me->group_leader->real_parent;
-	for (;;) {
-		pid = parent->tgid;
-#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
-{
-		struct task_struct *old = parent;
+	rcu_read_lock();
+	pid = rcu_dereference(current->real_parent)->tgid;
+	rcu_read_unlock();
 
-		/*
-		 * Make sure we read the pid before re-reading the
-		 * parent pointer:
-		 */
-		smp_rmb();
-		parent = me->group_leader->real_parent;
-		if (old != parent)
-			continue;
-}
-#endif
-		break;
-	}
 	return pid;
 }
 
@@ -1688,7 +1661,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int __devinit timer_cpu_notify(struct notifier_block *self,
+static int __cpuinit timer_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -1708,7 +1681,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block __devinitdata timers_nb = {
+static struct notifier_block __cpuinitdata timers_nb = {
 	.notifier_call	= timer_cpu_notify,
 };
 
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index eebb1d8..835fe28 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -68,7 +68,7 @@
 
 /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove
    threads to each one as cpus come/go. */
-static DEFINE_SPINLOCK(workqueue_lock);
+static DEFINE_MUTEX(workqueue_mutex);
 static LIST_HEAD(workqueues);
 
 static int singlethread_cpu;
@@ -93,9 +93,12 @@
 	spin_unlock_irqrestore(&cwq->lock, flags);
 }
 
-/*
- * Queue work on a workqueue. Return non-zero if it was successfully
- * added.
+/**
+ * queue_work - queue work on a workqueue
+ * @wq: workqueue to use
+ * @work: work to queue
+ *
+ * Returns non-zero if it was successfully added.
  *
  * We queue the work to the CPU it was submitted, but there is no
  * guarantee that it will be processed by that CPU.
@@ -128,6 +131,14 @@
 	__queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work);
 }
 
+/**
+ * queue_delayed_work - queue work on a workqueue after delay
+ * @wq: workqueue to use
+ * @work: work to queue
+ * @delay: number of jiffies to wait before queueing
+ *
+ * Returns non-zero if it was successfully added.
+ */
 int fastcall queue_delayed_work(struct workqueue_struct *wq,
 			struct work_struct *work, unsigned long delay)
 {
@@ -150,6 +161,15 @@
 }
 EXPORT_SYMBOL_GPL(queue_delayed_work);
 
+/**
+ * queue_delayed_work_on - queue work on specific CPU after delay
+ * @cpu: CPU number to execute work on
+ * @wq: workqueue to use
+ * @work: work to queue
+ * @delay: number of jiffies to wait before queueing
+ *
+ * Returns non-zero if it was successfully added.
+ */
 int queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
 			struct work_struct *work, unsigned long delay)
 {
@@ -275,8 +295,9 @@
 	}
 }
 
-/*
+/**
  * flush_workqueue - ensure that any scheduled work has run to completion.
+ * @wq: workqueue to flush
  *
  * Forces execution of the workqueue and blocks until its completion.
  * This is typically used in driver shutdown handlers.
@@ -299,10 +320,10 @@
 	} else {
 		int cpu;
 
-		lock_cpu_hotplug();
+		mutex_lock(&workqueue_mutex);
 		for_each_online_cpu(cpu)
 			flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu));
-		unlock_cpu_hotplug();
+		mutex_unlock(&workqueue_mutex);
 	}
 }
 EXPORT_SYMBOL_GPL(flush_workqueue);
@@ -350,8 +371,7 @@
 	}
 
 	wq->name = name;
-	/* We don't need the distraction of CPUs appearing and vanishing. */
-	lock_cpu_hotplug();
+	mutex_lock(&workqueue_mutex);
 	if (singlethread) {
 		INIT_LIST_HEAD(&wq->list);
 		p = create_workqueue_thread(wq, singlethread_cpu);
@@ -360,9 +380,7 @@
 		else
 			wake_up_process(p);
 	} else {
-		spin_lock(&workqueue_lock);
 		list_add(&wq->list, &workqueues);
-		spin_unlock(&workqueue_lock);
 		for_each_online_cpu(cpu) {
 			p = create_workqueue_thread(wq, cpu);
 			if (p) {
@@ -372,7 +390,7 @@
 				destroy = 1;
 		}
 	}
-	unlock_cpu_hotplug();
+	mutex_unlock(&workqueue_mutex);
 
 	/*
 	 * Was there any error during startup? If yes then clean up:
@@ -400,6 +418,12 @@
 		kthread_stop(p);
 }
 
+/**
+ * destroy_workqueue - safely terminate a workqueue
+ * @wq: target workqueue
+ *
+ * Safely destroy a workqueue. All work currently pending will be done first.
+ */
 void destroy_workqueue(struct workqueue_struct *wq)
 {
 	int cpu;
@@ -407,17 +431,15 @@
 	flush_workqueue(wq);
 
 	/* We don't need the distraction of CPUs appearing and vanishing. */
-	lock_cpu_hotplug();
+	mutex_lock(&workqueue_mutex);
 	if (is_single_threaded(wq))
 		cleanup_workqueue_thread(wq, singlethread_cpu);
 	else {
 		for_each_online_cpu(cpu)
 			cleanup_workqueue_thread(wq, cpu);
-		spin_lock(&workqueue_lock);
 		list_del(&wq->list);
-		spin_unlock(&workqueue_lock);
 	}
-	unlock_cpu_hotplug();
+	mutex_unlock(&workqueue_mutex);
 	free_percpu(wq->cpu_wq);
 	kfree(wq);
 }
@@ -425,18 +447,41 @@
 
 static struct workqueue_struct *keventd_wq;
 
+/**
+ * schedule_work - put work task in global workqueue
+ * @work: job to be done
+ *
+ * This puts a job in the kernel-global workqueue.
+ */
 int fastcall schedule_work(struct work_struct *work)
 {
 	return queue_work(keventd_wq, work);
 }
 EXPORT_SYMBOL(schedule_work);
 
+/**
+ * schedule_delayed_work - put work task in global workqueue after delay
+ * @work: job to be done
+ * @delay: number of jiffies to wait
+ *
+ * After waiting for a given time this puts a job in the kernel-global
+ * workqueue.
+ */
 int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay)
 {
 	return queue_delayed_work(keventd_wq, work, delay);
 }
 EXPORT_SYMBOL(schedule_delayed_work);
 
+/**
+ * schedule_delayed_work_on - queue work in global workqueue on CPU after delay
+ * @cpu: cpu to use
+ * @work: job to be done
+ * @delay: number of jiffies to wait
+ *
+ * After waiting for a given time this puts a job in the kernel-global
+ * workqueue on the specified CPU.
+ */
 int schedule_delayed_work_on(int cpu,
 			struct work_struct *work, unsigned long delay)
 {
@@ -465,11 +510,13 @@
 	if (!works)
 		return -ENOMEM;
 
+	mutex_lock(&workqueue_mutex);
 	for_each_online_cpu(cpu) {
 		INIT_WORK(per_cpu_ptr(works, cpu), func, info);
 		__queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
 				per_cpu_ptr(works, cpu));
 	}
+	mutex_unlock(&workqueue_mutex);
 	flush_workqueue(keventd_wq);
 	free_percpu(works);
 	return 0;
@@ -585,6 +632,7 @@
 
 	switch (action) {
 	case CPU_UP_PREPARE:
+		mutex_lock(&workqueue_mutex);
 		/* Create a new workqueue thread for it. */
 		list_for_each_entry(wq, &workqueues, list) {
 			if (!create_workqueue_thread(wq, hotcpu)) {
@@ -603,6 +651,7 @@
 			kthread_bind(cwq->thread, hotcpu);
 			wake_up_process(cwq->thread);
 		}
+		mutex_unlock(&workqueue_mutex);
 		break;
 
 	case CPU_UP_CANCELED:
@@ -614,6 +663,15 @@
 				     any_online_cpu(cpu_online_map));
 			cleanup_workqueue_thread(wq, hotcpu);
 		}
+		mutex_unlock(&workqueue_mutex);
+		break;
+
+	case CPU_DOWN_PREPARE:
+		mutex_lock(&workqueue_mutex);
+		break;
+
+	case CPU_DOWN_FAILED:
+		mutex_unlock(&workqueue_mutex);
 		break;
 
 	case CPU_DEAD:
@@ -621,6 +679,7 @@
 			cleanup_workqueue_thread(wq, hotcpu);
 		list_for_each_entry(wq, &workqueues, list)
 			take_over_work(wq, hotcpu);
+		mutex_unlock(&workqueue_mutex);
 		break;
 	}
 
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2b1530f..7f20e7b 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -50,10 +50,6 @@
 		return "offline";
 	case KOBJ_ONLINE:
 		return "online";
-	case KOBJ_DOCK:
-		return "dock";
-	case KOBJ_UNDOCK:
-		return "undock";
 	default:
 		return NULL;
 	}
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index 3d9c4dc..58c577d 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -162,6 +162,7 @@
 
 #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
 
+#if 0		/* __write_lock_debug() can lock up - maybe this can too? */
 static void __read_lock_debug(rwlock_t *lock)
 {
 	int print_once = 1;
@@ -184,12 +185,12 @@
 		}
 	}
 }
+#endif
 
 void _raw_read_lock(rwlock_t *lock)
 {
 	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
-	if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
-		__read_lock_debug(lock);
+	__raw_read_lock(&lock->raw_lock);
 }
 
 int _raw_read_trylock(rwlock_t *lock)
@@ -235,6 +236,7 @@
 	lock->owner_cpu = -1;
 }
 
+#if 0		/* This can cause lockups */
 static void __write_lock_debug(rwlock_t *lock)
 {
 	int print_once = 1;
@@ -257,12 +259,12 @@
 		}
 	}
 }
+#endif
 
 void _raw_write_lock(rwlock_t *lock)
 {
 	debug_write_lock_before(lock);
-	if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
-		__write_lock_debug(lock);
+	__raw_write_lock(&lock->raw_lock);
 	debug_write_lock_after(lock);
 }
 
diff --git a/lib/ts_bm.c b/lib/ts_bm.c
index 0110e44..d90822c 100644
--- a/lib/ts_bm.c
+++ b/lib/ts_bm.c
@@ -111,15 +111,14 @@
 	return ret;
 }
 
-static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern,
-			       unsigned int len)
+static void compute_prefix_tbl(struct ts_bm *bm)
 {
 	int i, j, g;
 
 	for (i = 0; i < ASIZE; i++)
-		bm->bad_shift[i] = len;
-	for (i = 0; i < len - 1; i++)
-		bm->bad_shift[pattern[i]] = len - 1 - i;
+		bm->bad_shift[i] = bm->patlen;
+	for (i = 0; i < bm->patlen - 1; i++)
+		bm->bad_shift[bm->pattern[i]] = bm->patlen - 1 - i;
 
 	/* Compute the good shift array, used to match reocurrences 
 	 * of a subpattern */
@@ -150,8 +149,8 @@
 	bm = ts_config_priv(conf);
 	bm->patlen = len;
 	bm->pattern = (u8 *) bm->good_shift + prefix_tbl_len;
-	compute_prefix_tbl(bm, pattern, len);
 	memcpy(bm->pattern, pattern, len);
+	compute_prefix_tbl(bm);
 
 	return conf;
 }
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
index 7f922dc..fceb97c 100644
--- a/lib/zlib_inflate/inflate.c
+++ b/lib/zlib_inflate/inflate.c
@@ -347,7 +347,10 @@
     static const unsigned short order[19] = /* permutation of code lengths */
         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
 
-    if (strm == NULL || strm->state == NULL || strm->next_out == NULL ||
+    /* Do not check for strm->next_out == NULL here as ppc zImage
+       inflates to strm->next_out = 0 */
+
+    if (strm == NULL || strm->state == NULL ||
         (strm->next_in == NULL && strm->avail_in != 0))
         return Z_STREAM_ERROR;
 
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 60a5d55..168c78a 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -73,7 +73,6 @@
 		file->f_ra.ra_pages = bdi->ra_pages * 2;
 		break;
 	case POSIX_FADV_WILLNEED:
-	case POSIX_FADV_NOREUSE:
 		if (!mapping->a_ops->readpage) {
 			ret = -EINVAL;
 			break;
@@ -94,6 +93,8 @@
 		if (ret > 0)
 			ret = 0;
 		break;
+	case POSIX_FADV_NOREUSE:
+		break;
 	case POSIX_FADV_DONTNEED:
 		if (!bdi_write_congested(mapping->backing_dev_info))
 			filemap_flush(mapping);
diff --git a/mm/filemap.c b/mm/filemap.c
index d087fc3..b9a60c4 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -849,8 +849,6 @@
 		return;
 
 	ra->ra_pages /= 4;
-	printk(KERN_WARNING "Reducing readahead size to %luK\n",
-			ra->ra_pages << (PAGE_CACHE_SHIFT - 10));
 }
 
 /**
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 01c9fb9..c373195 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -52,6 +52,9 @@
 	int nr_pages = PAGES_PER_SECTION;
 	int ret;
 
+	if (pfn_valid(phys_start_pfn))
+		return -EEXIST;
+
 	ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages);
 
 	if (ret < 0)
@@ -76,15 +79,22 @@
 {
 	unsigned long i;
 	int err = 0;
+	int start_sec, end_sec;
+	/* during initialize mem_map, align hot-added range to section */
+	start_sec = pfn_to_section_nr(phys_start_pfn);
+	end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1);
 
-	for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) {
-		err = __add_section(zone, phys_start_pfn + i);
+	for (i = start_sec; i <= end_sec; i++) {
+		err = __add_section(zone, i << PFN_SECTION_SHIFT);
 
-		/* We want to keep adding the rest of the
-		 * sections if the first ones already exist
+		/*
+		 * EEXIST is finally dealed with by ioresource collision
+		 * check. see add_memory() => register_memory_resource()
+		 * Warning will be printed if there is collision.
 		 */
 		if (err && (err != -EEXIST))
 			break;
+		err = 0;
 	}
 
 	return err;
@@ -156,7 +166,7 @@
 	res.flags = IORESOURCE_MEM; /* we just need system ram */
 	section_end = res.end;
 
-	while (find_next_system_ram(&res) >= 0) {
+	while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) {
 		start_pfn = (unsigned long)(res.start >> PAGE_SHIFT);
 		nr_pages = (unsigned long)
                            ((res.end + 1 - res.start) >> PAGE_SHIFT);
@@ -213,10 +223,9 @@
 }
 
 /* add this memory to iomem resource */
-static void register_memory_resource(u64 start, u64 size)
+static struct resource *register_memory_resource(u64 start, u64 size)
 {
 	struct resource *res;
-
 	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	BUG_ON(!res);
 
@@ -228,7 +237,18 @@
 		printk("System RAM resource %llx - %llx cannot be added\n",
 		(unsigned long long)res->start, (unsigned long long)res->end);
 		kfree(res);
+		res = NULL;
 	}
+	return res;
+}
+
+static void release_memory_resource(struct resource *res)
+{
+	if (!res)
+		return;
+	release_resource(res);
+	kfree(res);
+	return;
 }
 
 
@@ -237,8 +257,13 @@
 {
 	pg_data_t *pgdat = NULL;
 	int new_pgdat = 0;
+	struct resource *res;
 	int ret;
 
+	res = register_memory_resource(start, size);
+	if (!res)
+		return -EEXIST;
+
 	if (!node_online(nid)) {
 		pgdat = hotadd_new_pgdat(nid, start);
 		if (!pgdat)
@@ -268,14 +293,13 @@
 		BUG_ON(ret);
 	}
 
-	/* register this memory as resource */
-	register_memory_resource(start, size);
-
 	return ret;
 error:
 	/* rollback pgdat allocation and others */
 	if (new_pgdat)
 		rollback_node_hotadd(nid, pgdat);
+	if (res)
+		release_memory_resource(res);
 
 	return ret;
 }
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e07e27e..a9963ce 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1176,7 +1176,15 @@
 	if (vma) {
 		unsigned long off;
 
-		off = vma->vm_pgoff;
+		/*
+		 * for small pages, there is no difference between
+		 * shift and PAGE_SHIFT, so the bit-shift is safe.
+		 * for huge pages, since vm_pgoff is in units of small
+		 * pages, we need to shift off the always 0 bits to get
+		 * a useful offset.
+		 */
+		BUG_ON(shift < PAGE_SHIFT);
+		off = vma->vm_pgoff >> (shift - PAGE_SHIFT);
 		off += (addr - vma->vm_start) >> shift;
 		return offset_il_node(pol, vma, off);
 	} else
diff --git a/mm/mempool.c b/mm/mempool.c
index fe6e052..ccd8cb8 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -238,8 +238,13 @@
 	init_wait(&wait);
 	prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
 	smp_mb();
-	if (!pool->curr_nr)
-		io_schedule();
+	if (!pool->curr_nr) {
+		/*
+		 * FIXME: this should be io_schedule().  The timeout is there
+		 * as a workaround for some DM problems in 2.6.18.
+		 */
+		io_schedule_timeout(5*HZ);
+	}
 	finish_wait(&pool->wait, &wait);
 
 	goto repeat_alloc;
diff --git a/mm/mmap.c b/mm/mmap.c
index c1868ec..e66a0b5 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -30,6 +30,10 @@
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
 
+#ifndef arch_mmap_check
+#define arch_mmap_check(addr, len, flags)	(0)
+#endif
+
 static void unmap_region(struct mm_struct *mm,
 		struct vm_area_struct *vma, struct vm_area_struct *prev,
 		unsigned long start, unsigned long end);
@@ -913,6 +917,10 @@
 	if (!len)
 		return -EINVAL;
 
+	error = arch_mmap_check(addr, len, flags);
+	if (error)
+		return error;
+
 	/* Careful about overflows.. */
 	len = PAGE_ALIGN(len);
 	if (!len || len > TASK_SIZE)
@@ -1859,6 +1867,7 @@
 	unsigned long flags;
 	struct rb_node ** rb_link, * rb_parent;
 	pgoff_t pgoff = addr >> PAGE_SHIFT;
+	int error;
 
 	len = PAGE_ALIGN(len);
 	if (!len)
@@ -1867,6 +1876,12 @@
 	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
 		return -EINVAL;
 
+	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
+
+	error = arch_mmap_check(addr, len, flags);
+	if (error)
+		return error;
+
 	/*
 	 * mlock MCL_FUTURE?
 	 */
@@ -1907,8 +1922,6 @@
 	if (security_vm_enough_memory(len >> PAGE_SHIFT))
 		return -ENOMEM;
 
-	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
-
 	/* Can we just expand an old private anonymous mapping? */
 	if (vma_merge(mm, prev, addr, addr + len, flags,
 					NULL, NULL, pgoff, NULL))
diff --git a/mm/slab.c b/mm/slab.c
index 0f20843..21ba060 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1106,7 +1106,7 @@
 
 #endif
 
-static int __devinit cpuup_callback(struct notifier_block *nfb,
+static int __cpuinit cpuup_callback(struct notifier_block *nfb,
 				    unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -3224,7 +3224,7 @@
 EXPORT_SYMBOL(kmem_cache_alloc);
 
 /**
- * kmem_cache_alloc - Allocate an object. The memory is set to zero.
+ * kmem_cache_zalloc - Allocate an object. The memory is set to zero.
  * @cache: The cache to allocate from.
  * @flags: See kmalloc().
  *
diff --git a/mm/swap.c b/mm/swap.c
index 8fd095c..687686a 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -54,6 +54,26 @@
 }
 EXPORT_SYMBOL(put_page);
 
+/**
+ * put_pages_list(): release a list of pages
+ *
+ * Release a list of pages which are strung together on page.lru.  Currently
+ * used by read_cache_pages() and related error recovery code.
+ *
+ * @pages: list of pages threaded on page->lru
+ */
+void put_pages_list(struct list_head *pages)
+{
+	while (!list_empty(pages)) {
+		struct page *victim;
+
+		victim = list_entry(pages->prev, struct page, lru);
+		list_del(&victim->lru);
+		page_cache_release(victim);
+	}
+}
+EXPORT_SYMBOL(put_pages_list);
+
 /*
  * Writeback is about to end against a page which has been marked for immediate
  * reclaim.  If it still appears to be reclaimable, move it to the tail of the
diff --git a/mm/swapfile.c b/mm/swapfile.c
index e70d6c6..f1f5ec7 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -442,11 +442,12 @@
 
 		if (!(swap_info[i].flags & SWP_WRITEOK))
 			continue;
+
 		if (!device) {
 			spin_unlock(&swap_lock);
 			return i;
 		}
-		inode = swap_info->swap_file->f_dentry->d_inode;
+		inode = swap_info[i].swap_file->f_dentry->d_inode;
 		if (S_ISBLK(inode->i_mode) &&
 		    device == MKDEV(imajor(inode), iminor(inode))) {
 			spin_unlock(&swap_lock);
diff --git a/mm/truncate.c b/mm/truncate.c
index cf1b015..c6ab55e 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -68,10 +68,10 @@
 		return 0;
 
 	write_lock_irq(&mapping->tree_lock);
-	if (PageDirty(page)) {
-		write_unlock_irq(&mapping->tree_lock);
-		return 0;
-	}
+	if (PageDirty(page))
+		goto failed;
+	if (page_count(page) != 2)	/* caller's ref + pagecache ref */
+		goto failed;
 
 	BUG_ON(PagePrivate(page));
 	__remove_from_page_cache(page);
@@ -79,6 +79,9 @@
 	ClearPageUptodate(page);
 	page_cache_release(page);	/* pagecache ref */
 	return 1;
+failed:
+	write_unlock_irq(&mapping->tree_lock);
+	return 0;
 }
 
 /**
diff --git a/mm/vmstat.c b/mm/vmstat.c
index dfdf241..c1b5f41 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 
 void __get_zone_counts(unsigned long *active, unsigned long *inactive,
 			unsigned long *free, struct pglist_data *pgdat)
@@ -114,17 +115,72 @@
 
 #ifdef CONFIG_SMP
 
-#define STAT_THRESHOLD 32
+static int calculate_threshold(struct zone *zone)
+{
+	int threshold;
+	int mem;	/* memory in 128 MB units */
+
+	/*
+	 * The threshold scales with the number of processors and the amount
+	 * of memory per zone. More memory means that we can defer updates for
+	 * longer, more processors could lead to more contention.
+ 	 * fls() is used to have a cheap way of logarithmic scaling.
+	 *
+	 * Some sample thresholds:
+	 *
+	 * Threshold	Processors	(fls)	Zonesize	fls(mem+1)
+	 * ------------------------------------------------------------------
+	 * 8		1		1	0.9-1 GB	4
+	 * 16		2		2	0.9-1 GB	4
+	 * 20 		2		2	1-2 GB		5
+	 * 24		2		2	2-4 GB		6
+	 * 28		2		2	4-8 GB		7
+	 * 32		2		2	8-16 GB		8
+	 * 4		2		2	<128M		1
+	 * 30		4		3	2-4 GB		5
+	 * 48		4		3	8-16 GB		8
+	 * 32		8		4	1-2 GB		4
+	 * 32		8		4	0.9-1GB		4
+	 * 10		16		5	<128M		1
+	 * 40		16		5	900M		4
+	 * 70		64		7	2-4 GB		5
+	 * 84		64		7	4-8 GB		6
+	 * 108		512		9	4-8 GB		6
+	 * 125		1024		10	8-16 GB		8
+	 * 125		1024		10	16-32 GB	9
+	 */
+
+	mem = zone->present_pages >> (27 - PAGE_SHIFT);
+
+	threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem));
+
+	/*
+	 * Maximum threshold is 125
+	 */
+	threshold = min(125, threshold);
+
+	return threshold;
+}
 
 /*
- * Determine pointer to currently valid differential byte given a zone and
- * the item number.
- *
- * Preemption must be off
+ * Refresh the thresholds for each zone.
  */
-static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item)
+static void refresh_zone_stat_thresholds(void)
 {
-	return &zone_pcp(zone, smp_processor_id())->vm_stat_diff[item];
+	struct zone *zone;
+	int cpu;
+	int threshold;
+
+	for_each_zone(zone) {
+
+		if (!zone->present_pages)
+			continue;
+
+		threshold = calculate_threshold(zone);
+
+		for_each_online_cpu(cpu)
+			zone_pcp(zone, cpu)->stat_threshold = threshold;
+	}
 }
 
 /*
@@ -133,17 +189,16 @@
 void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
 				int delta)
 {
-	s8 *p;
+	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	s8 *p = pcp->vm_stat_diff + item;
 	long x;
 
-	p = diff_pointer(zone, item);
 	x = delta + *p;
 
-	if (unlikely(x > STAT_THRESHOLD || x < -STAT_THRESHOLD)) {
+	if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) {
 		zone_page_state_add(x, zone, item);
 		x = 0;
 	}
-
 	*p = x;
 }
 EXPORT_SYMBOL(__mod_zone_page_state);
@@ -172,10 +227,12 @@
  * No overflow check is necessary and therefore the differential can be
  * incremented or decremented in place which may allow the compilers to
  * generate better code.
- *
  * The increment or decrement is known and therefore one boundary check can
  * be omitted.
  *
+ * NOTE: These functions are very performance sensitive. Change only
+ * with care.
+ *
  * Some processors have inc/dec instructions that are atomic vs an interrupt.
  * However, the code must first determine the differential location in a zone
  * based on the processor number and then inc/dec the counter. There is no
@@ -185,13 +242,16 @@
  */
 static void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
 {
-	s8 *p = diff_pointer(zone, item);
+	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	s8 *p = pcp->vm_stat_diff + item;
 
 	(*p)++;
 
-	if (unlikely(*p > STAT_THRESHOLD)) {
-		zone_page_state_add(*p, zone, item);
-		*p = 0;
+	if (unlikely(*p > pcp->stat_threshold)) {
+		int overstep = pcp->stat_threshold / 2;
+
+		zone_page_state_add(*p + overstep, zone, item);
+		*p = -overstep;
 	}
 }
 
@@ -204,13 +264,16 @@
 void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
 {
 	struct zone *zone = page_zone(page);
-	s8 *p = diff_pointer(zone, item);
+	struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id());
+	s8 *p = pcp->vm_stat_diff + item;
 
 	(*p)--;
 
-	if (unlikely(*p < -STAT_THRESHOLD)) {
-		zone_page_state_add(*p, zone, item);
-		*p = 0;
+	if (unlikely(*p < - pcp->stat_threshold)) {
+		int overstep = pcp->stat_threshold / 2;
+
+		zone_page_state_add(*p - overstep, zone, item);
+		*p = overstep;
 	}
 }
 EXPORT_SYMBOL(__dec_zone_page_state);
@@ -239,19 +302,9 @@
 void dec_zone_page_state(struct page *page, enum zone_stat_item item)
 {
 	unsigned long flags;
-	struct zone *zone;
-	s8 *p;
 
-	zone = page_zone(page);
 	local_irq_save(flags);
-	p = diff_pointer(zone, item);
-
-	(*p)--;
-
-	if (unlikely(*p < -STAT_THRESHOLD)) {
-		zone_page_state_add(*p, zone, item);
-		*p = 0;
-	}
+	__dec_zone_page_state(page, item);
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL(dec_zone_page_state);
@@ -525,6 +578,10 @@
 					   pageset->pcp[j].high,
 					   pageset->pcp[j].batch);
 			}
+#ifdef CONFIG_SMP
+			seq_printf(m, "\n  vm stats threshold: %d",
+					pageset->stat_threshold);
+#endif
 		}
 		seq_printf(m,
 			   "\n  all_unreclaimable: %u"
@@ -613,3 +670,35 @@
 
 #endif /* CONFIG_PROC_FS */
 
+#ifdef CONFIG_SMP
+/*
+ * Use the cpu notifier to insure that the thresholds are recalculated
+ * when necessary.
+ */
+static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
+		unsigned long action,
+		void *hcpu)
+{
+	switch (action) {
+		case CPU_UP_PREPARE:
+		case CPU_UP_CANCELED:
+		case CPU_DEAD:
+			refresh_zone_stat_thresholds();
+			break;
+		default:
+			break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata vmstat_notifier =
+	{ &vmstat_cpuup_callback, NULL, 0 };
+
+int __init setup_vmstat(void)
+{
+	refresh_zone_stat_thresholds();
+	register_cpu_notifier(&vmstat_notifier);
+	return 0;
+}
+module_init(setup_vmstat)
+#endif
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 3f95b08..91fe5f5 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -507,7 +507,7 @@
 	goto out;
 }
 
-void __exit atm_proc_exit(void)
+void atm_proc_exit(void)
 {
 	atm_proc_dirs_remove();
 }
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 6ccd32b..864fbbc 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -40,11 +40,15 @@
 	else {
 #ifdef CONFIG_BRIDGE_NETFILTER
 		/* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
-		nf_bridge_maybe_copy_header(skb);
+		if (nf_bridge_maybe_copy_header(skb))
+			kfree_skb(skb);
+		else
 #endif
-		skb_push(skb, ETH_HLEN);
+		{
+			skb_push(skb, ETH_HLEN);
 
-		dev_queue_xmit(skb);
+			dev_queue_xmit(skb);
+		}
 	}
 
 	return 0;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f55ef68..b1211d534 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -386,12 +386,17 @@
 			checksum = 0;
 
 		if (feature & NETIF_F_GSO)
-			feature |= NETIF_F_TSO;
+			feature |= NETIF_F_GSO_SOFTWARE;
 		feature |= NETIF_F_GSO;
 
 		features &= feature;
 	}
 
+	if (!(checksum & NETIF_F_ALL_CSUM))
+		features &= ~NETIF_F_SG;
+	if (!(features & NETIF_F_SG))
+		features &= ~NETIF_F_GSO_MASK;
+
 	br->dev->features = features | checksum | NETIF_F_LLTX |
 			    NETIF_F_GSO_ROBUST;
 }
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 06abb66..53086fb 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -85,7 +85,7 @@
 		goto err_out;
 
 	err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
-	if (err)
+	if (err < 0)
 		goto err_kfree;
 
 	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 02693a2..9f950db 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -74,6 +74,9 @@
 	if (timer_pending(&ub->timer))
 		del_timer(&ub->timer);
 
+	if (!ub->skb)
+		return;
+
 	/* last nlmsg needs NLMSG_DONE */
 	if (ub->qlen > 1)
 		ub->lastnlh->nlmsg_type = NLMSG_DONE;
diff --git a/net/core/Makefile b/net/core/Makefile
index e9bd246..2645ba4 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -7,7 +7,7 @@
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
-obj-y		     += dev.o ethtool.o dev_mcast.o dst.o \
+obj-y		     += dev.o ethtool.o dev_mcast.o dst.o netevent.o \
 			neighbour.o rtnetlink.o utils.o link_watch.o filter.o
 
 obj-$(CONFIG_XFRM) += flow.o
diff --git a/net/core/dev.c b/net/core/dev.c
index 4d2b516..d4a1ec3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -116,6 +116,7 @@
 #include <linux/audit.h>
 #include <linux/dmaengine.h>
 #include <linux/err.h>
+#include <linux/ctype.h>
 
 /*
  *	The list of packet types we will receive (as opposed to discard)
@@ -632,14 +633,22 @@
  *	@name: name string
  *
  *	Network device names need to be valid file names to
- *	to allow sysfs to work
+ *	to allow sysfs to work.  We also disallow any kind of
+ *	whitespace.
  */
 int dev_valid_name(const char *name)
 {
-	return !(*name == '\0' 
-		 || !strcmp(name, ".")
-		 || !strcmp(name, "..")
-		 || strchr(name, '/'));
+	if (*name == '\0')
+		return 0;
+	if (!strcmp(name, ".") || !strcmp(name, ".."))
+		return 0;
+
+	while (*name) {
+		if (*name == '/' || isspace(*name))
+			return 0;
+		name++;
+	}
+	return 1;
 }
 
 /**
@@ -1166,11 +1175,6 @@
 		goto out_set_summed;
 
 	if (unlikely(skb_shinfo(skb)->gso_size)) {
-		static int warned;
-
-		WARN_ON(!warned);
-		warned = 1;
-
 		/* Let GSO fix up the checksum. */
 		goto out_set_summed;
 	}
@@ -1220,11 +1224,6 @@
 	__skb_pull(skb, skb->mac_len);
 
 	if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
-		static int warned;
-
-		WARN_ON(!warned);
-		warned = 1;
-
 		if (skb_header_cloned(skb) &&
 		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
 			return ERR_PTR(err);
@@ -1629,26 +1628,10 @@
 	struct net_device *dev = skb->dev;
 
 	if (dev->master) {
-		/*
-		 * On bonding slaves other than the currently active
-		 * slave, suppress duplicates except for 802.3ad
-		 * ETH_P_SLOW and alb non-mcast/bcast.
-		 */
-		if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
-			if (dev->master->priv_flags & IFF_MASTER_ALB) {
-				if (skb->pkt_type != PACKET_BROADCAST &&
-				    skb->pkt_type != PACKET_MULTICAST)
-					goto keep;
-			}
-
-			if (dev->master->priv_flags & IFF_MASTER_8023AD &&
-			    skb->protocol == __constant_htons(ETH_P_SLOW))
-				goto keep;
-		
+		if (skb_bond_should_drop(skb)) {
 			kfree_skb(skb);
 			return NULL;
 		}
-keep:
 		skb->dev = dev->master;
 	}
 
@@ -3429,12 +3412,9 @@
 	unsigned int cpu, i, n;
 	struct dma_chan *chan;
 
-	lock_cpu_hotplug();
-
 	if (net_dma_count == 0) {
 		for_each_online_cpu(cpu)
-			rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL);
-		unlock_cpu_hotplug();
+			rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
 		return;
 	}
 
@@ -3447,15 +3427,13 @@
 		   + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
 
 		while(n) {
-			per_cpu(softnet_data.net_dma, cpu) = chan;
+			per_cpu(softnet_data, cpu).net_dma = chan;
 			cpu = next_cpu(cpu, cpu_online_map);
 			n--;
 		}
 		i++;
 	}
 	rcu_read_unlock();
-
-	unlock_cpu_hotplug();
 }
 
 /**
diff --git a/net/core/dst.c b/net/core/dst.c
index 470c05b..1a5e49d 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -95,12 +95,11 @@
 		dst_gc_timer_inc = DST_GC_INC;
 		dst_gc_timer_expires = DST_GC_MIN;
 	}
-	dst_gc_timer.expires = jiffies + dst_gc_timer_expires;
 #if RT_CACHE_DEBUG >= 2
 	printk("dst_total: %d/%d %ld\n",
 	       atomic_read(&dst_total), delayed,  dst_gc_timer_expires);
 #endif
-	add_timer(&dst_gc_timer);
+	mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires);
 
 out:
 	spin_unlock(&dst_lock);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7ad681f..5130d2e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -29,6 +29,7 @@
 #include <net/neighbour.h>
 #include <net/dst.h>
 #include <net/sock.h>
+#include <net/netevent.h>
 #include <linux/rtnetlink.h>
 #include <linux/random.h>
 #include <linux/string.h>
@@ -754,6 +755,7 @@
 			neigh->nud_state = NUD_STALE;
 			neigh->updated = jiffies;
 			neigh_suspect(neigh);
+			notify = 1;
 		}
 	} else if (state & NUD_DELAY) {
 		if (time_before_eq(now, 
@@ -762,6 +764,7 @@
 			neigh->nud_state = NUD_REACHABLE;
 			neigh->updated = jiffies;
 			neigh_connect(neigh);
+			notify = 1;
 			next = neigh->confirmed + neigh->parms->reachable_time;
 		} else {
 			NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
@@ -819,6 +822,8 @@
 out:
 		write_unlock(&neigh->lock);
 	}
+	if (notify)
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
 
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
@@ -926,9 +931,7 @@
 {
 	u8 old;
 	int err;
-#ifdef CONFIG_ARPD
 	int notify = 0;
-#endif
 	struct net_device *dev;
 	int update_isrouter = 0;
 
@@ -948,9 +951,7 @@
 			neigh_suspect(neigh);
 		neigh->nud_state = new;
 		err = 0;
-#ifdef CONFIG_ARPD
 		notify = old & NUD_VALID;
-#endif
 		goto out;
 	}
 
@@ -1022,9 +1023,7 @@
 		if (!(new & NUD_CONNECTED))
 			neigh->confirmed = jiffies -
 				      (neigh->parms->base_reachable_time << 1);
-#ifdef CONFIG_ARPD
 		notify = 1;
-#endif
 	}
 	if (new == old)
 		goto out;
@@ -1056,6 +1055,9 @@
 			(neigh->flags & ~NTF_ROUTER);
 	}
 	write_unlock_bh(&neigh->lock);
+
+	if (notify)
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
 		neigh_app_notify(neigh);
diff --git a/net/core/netevent.c b/net/core/netevent.c
new file mode 100644
index 0000000..35d02c3
--- /dev/null
+++ b/net/core/netevent.c
@@ -0,0 +1,69 @@
+/*
+ *	Network event notifiers
+ *
+ *	Authors:
+ *      Tom Tucker             <tom@opengridcomputing.com>
+ *      Steve Wise             <swise@opengridcomputing.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 the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *	Fixes:
+ */
+
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+
+static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
+
+/**
+ *	register_netevent_notifier - register a netevent notifier block
+ *	@nb: notifier
+ *
+ *	Register a notifier to be called when a netevent occurs.
+ *	The notifier passed is linked into the kernel structures and must
+ *	not be reused until it has been unregistered. A negative errno code
+ *	is returned on a failure.
+ */
+int register_netevent_notifier(struct notifier_block *nb)
+{
+	int err;
+
+	err = atomic_notifier_chain_register(&netevent_notif_chain, nb);
+	return err;
+}
+
+/**
+ *	netevent_unregister_notifier - unregister a netevent notifier block
+ *	@nb: notifier
+ *
+ *	Unregister a notifier previously registered by
+ *	register_neigh_notifier(). The notifier is unlinked into the
+ *	kernel structures and may then be reused. A negative errno code
+ *	is returned on a failure.
+ */
+
+int unregister_netevent_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&netevent_notif_chain, nb);
+}
+
+/**
+ *	call_netevent_notifiers - call all netevent notifier blocks
+ *      @val: value passed unmodified to notifier function
+ *      @v:   pointer passed unmodified to notifier function
+ *
+ *	Call all neighbour notifier blocks.  Parameters and return value
+ *	are as for notifier_call_chain().
+ */
+
+int call_netevent_notifiers(unsigned long val, void *v)
+{
+	return atomic_notifier_call_chain(&netevent_notif_chain, val, v);
+}
+
+EXPORT_SYMBOL_GPL(register_netevent_notifier);
+EXPORT_SYMBOL_GPL(unregister_netevent_notifier);
+EXPORT_SYMBOL_GPL(call_netevent_notifiers);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 67ed14d..6a7320b 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2149,6 +2149,8 @@
 	skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32);
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
+	skb->nh.iph = iph;
+	skb->h.uh = udph;
 
 	if (pkt_dev->nfrags <= 0)
 		pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
@@ -2460,6 +2462,8 @@
 	skb->protocol = protocol;
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
+	skb->nh.ipv6h = iph;
+	skb->h.uh = udph;
 
 	if (pkt_dev->nfrags <= 0)
 		pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 20e5bb7..30cc1ba 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -394,6 +394,9 @@
 	}
 
 	if (ida[IFLA_ADDRESS - 1]) {
+		struct sockaddr *sa;
+		int len;
+
 		if (!dev->set_mac_address) {
 			err = -EOPNOTSUPP;
 			goto out;
@@ -405,7 +408,17 @@
 		if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len))
 			goto out;
 
-		err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
+		len = sizeof(sa_family_t) + dev->addr_len;
+		sa = kmalloc(len, GFP_KERNEL);
+		if (!sa) {
+			err = -ENOMEM;
+			goto out;
+		}
+		sa->sa_family = dev->type;
+		memcpy(sa->sa_data, RTA_DATA(ida[IFLA_ADDRESS - 1]),
+		       dev->addr_len);
+		err = dev->set_mac_address(dev, sa);
+		kfree(sa);
 		if (err)
 			goto out;
 		send_addr_notify = 1;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 476aa39..c54f366 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -71,13 +71,6 @@
 static kmem_cache_t *skbuff_fclone_cache __read_mostly;
 
 /*
- * lockdep: lock class key used by skb_queue_head_init():
- */
-struct lock_class_key skb_queue_lock_key;
-
-EXPORT_SYMBOL(skb_queue_lock_key);
-
-/*
  *	Keep out-of-line to prevent kernel bloat.
  *	__builtin_return_address is not used because it is not always
  *	reliable.
@@ -256,6 +249,31 @@
 	goto out;
 }
 
+/**
+ *	__netdev_alloc_skb - allocate an skbuff for rx on a specific device
+ *	@dev: network device to receive on
+ *	@length: length to allocate
+ *	@gfp_mask: get_free_pages mask, passed to alloc_skb
+ *
+ *	Allocate a new &sk_buff and assign it a usage count of one. The
+ *	buffer has unspecified headroom built in. Users should allocate
+ *	the headroom they think they need without accounting for the
+ *	built in space. The built in space is used for optimisations.
+ *
+ *	%NULL is returned if there is no free memory.
+ */
+struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
+		unsigned int length, gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
+	if (likely(skb)) {
+		skb_reserve(skb, NET_SKB_PAD);
+		skb->dev = dev;
+	}
+	return skb;
+}
 
 static void skb_drop_list(struct sk_buff **listp)
 {
@@ -846,7 +864,11 @@
 	    unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
 		return err;
 
-	for (i = 0; i < nfrags; i++) {
+	i = 0;
+	if (offset >= len)
+		goto drop_pages;
+
+	for (; i < nfrags; i++) {
 		int end = offset + skb_shinfo(skb)->frags[i].size;
 
 		if (end < len) {
@@ -854,9 +876,9 @@
 			continue;
 		}
 
-		if (len > offset)
-			skb_shinfo(skb)->frags[i++].size = len - offset;
+		skb_shinfo(skb)->frags[i++].size = len - offset;
 
+drop_pages:
 		skb_shinfo(skb)->nr_frags = i;
 
 		for (; i < nfrags; i++)
@@ -864,7 +886,7 @@
 
 		if (skb_shinfo(skb)->frag_list)
 			skb_drop_fraglist(skb);
-		break;
+		goto done;
 	}
 
 	for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +901,7 @@
 				return -ENOMEM;
 
 			nfrag->next = frag->next;
+			kfree_skb(frag);
 			frag = nfrag;
 			*fragp = frag;
 		}
@@ -897,6 +920,7 @@
 		break;
 	}
 
+done:
 	if (len > skb_headlen(skb)) {
 		skb->data_len -= skb->len - len;
 		skb->len       = len;
@@ -2042,6 +2066,7 @@
 EXPORT_SYMBOL(kfree_skb);
 EXPORT_SYMBOL(__pskb_pull_tail);
 EXPORT_SYMBOL(__alloc_skb);
+EXPORT_SYMBOL(__netdev_alloc_skb);
 EXPORT_SYMBOL(pskb_copy);
 EXPORT_SYMBOL(pskb_expand_head);
 EXPORT_SYMBOL(skb_checksum);
diff --git a/net/core/utils.c b/net/core/utils.c
index 4f96f38..e31c90e 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -130,12 +130,13 @@
 static int net_random_reseed(void)
 {
 	int i;
-	unsigned long seed[NR_CPUS];
+	unsigned long seed;
 
-	get_random_bytes(seed, sizeof(seed));
 	for_each_possible_cpu(i) {
 		struct nrnd_state *state = &per_cpu(net_rand_state,i);
-		__net_srandom(state, seed[i]);
+
+		get_random_bytes(&seed, sizeof(seed));
+		__net_srandom(state, seed);
 	}
 	return 0;
 }
diff --git a/net/core/wireless.c b/net/core/wireless.c
index d2bc72d..de0bde4 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -82,6 +82,7 @@
 #include <linux/init.h>			/* for __init */
 #include <linux/if_arp.h>		/* ARPHRD_ETHER */
 #include <linux/etherdevice.h>		/* compare_ether_addr */
+#include <linux/interrupt.h>
 
 #include <linux/wireless.h>		/* Pretty obvious */
 #include <net/iw_handler.h>		/* New driver API */
@@ -1842,6 +1843,18 @@
  */
 
 #ifdef WE_EVENT_RTNETLINK
+static struct sk_buff_head wireless_nlevent_queue;
+
+static void wireless_nlevent_process(unsigned long data)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&wireless_nlevent_queue)))
+		netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+}
+
+static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0);
+
 /* ---------------------------------------------------------------- */
 /*
  * Fill a rtnetlink message with our event data.
@@ -1904,8 +1917,17 @@
 		return;
 	}
 	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
-	netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+	skb_queue_tail(&wireless_nlevent_queue, skb);
+	tasklet_schedule(&wireless_nlevent_tasklet);
 }
+
+static int __init wireless_nlevent_init(void)
+{
+	skb_queue_head_init(&wireless_nlevent_queue);
+	return 0;
+}
+
+subsys_initcall(wireless_nlevent_init);
 #endif	/* WE_EVENT_RTNETLINK */
 
 /* ---------------------------------------------------------------- */
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index c39bff7..090bc39 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2,7 +2,7 @@
  *  net/dccp/ccids/ccid3.c
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com>
+ *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *
  *  An implementation of the DCCP protocol
  *
@@ -342,6 +342,8 @@
 		new_packet->dccphtx_ccval =
 			DCCP_SKB_CB(skb)->dccpd_ccval =
 				hctx->ccid3hctx_last_win_count;
+		timeval_add_usecs(&hctx->ccid3hctx_t_nom,
+				  hctx->ccid3hctx_t_ipi);
 	}
 out:
 	return rc;
@@ -413,7 +415,8 @@
 	case TFRC_SSTATE_NO_FBACK:
 	case TFRC_SSTATE_FBACK:
 		if (len > 0) {
-			hctx->ccid3hctx_t_nom = now;
+			timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
+				  hctx->ccid3hctx_t_ipi);
 			ccid3_calc_new_t_ipi(hctx);
 			ccid3_calc_new_delta(hctx);
 			timeval_add_usecs(&hctx->ccid3hctx_t_nom,
@@ -757,8 +760,7 @@
 	}
 
 	hcrx->ccid3hcrx_tstamp_last_feedback = now;
-	hcrx->ccid3hcrx_last_counter	     = packet->dccphrx_ccval;
-	hcrx->ccid3hcrx_seqno_last_counter   = packet->dccphrx_seqno;
+	hcrx->ccid3hcrx_ccval_last_counter   = packet->dccphrx_ccval;
 	hcrx->ccid3hcrx_bytes_recv	     = 0;
 
 	/* Convert to multiples of 10us */
@@ -782,7 +784,7 @@
 	if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN))
 		return 0;
 
-	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
+	DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter;
 
 	if (dccp_packet_without_ack(skb))
 		return 0;
@@ -854,6 +856,11 @@
 		interval = 1;
 	}
 found:
+	if (!tail) {
+		LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n",
+		   __FUNCTION__);
+		return ~0;
+	}
 	rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
 	ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
 		       dccp_role(sk), sk, rtt);
@@ -864,9 +871,20 @@
 	delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
 	x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta);
 
+	if (x_recv == 0)
+		x_recv = hcrx->ccid3hcrx_x_recv;
+
 	tmp1 = (u64)x_recv * (u64)rtt;
 	do_div(tmp1,10000000);
 	tmp2 = (u32)tmp1;
+
+	if (!tmp2) {
+		LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 "
+		   "%s: x_recv = %u, rtt =%u\n",
+		   __FUNCTION__, x_recv, rtt);
+		return ~0;
+	}
+
 	fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
 	/* do not alter order above or you will get overflow on 32 bit */
 	p = tfrc_calc_x_reverse_lookup(fval);
@@ -882,31 +900,101 @@
 static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
+	struct dccp_li_hist_entry *next, *head;
+	u64 seq_temp;
 
-	if (seq_loss != DCCP_MAX_SEQNO + 1 &&
-	    list_empty(&hcrx->ccid3hcrx_li_hist)) {
-		struct dccp_li_hist_entry *li_tail;
-
-		li_tail = dccp_li_hist_interval_new(ccid3_li_hist,
-						    &hcrx->ccid3hcrx_li_hist,
-						    seq_loss, win_loss);
-		if (li_tail == NULL)
+	if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
+		if (!dccp_li_hist_interval_new(ccid3_li_hist,
+		   &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
 			return;
-		li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
-	} else
-		    LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of "
-				   "interval\n", __FUNCTION__);
+
+		next = (struct dccp_li_hist_entry *)
+		   hcrx->ccid3hcrx_li_hist.next;
+		next->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
+	} else {
+		struct dccp_li_hist_entry *entry;
+		struct list_head *tail;
+
+		head = (struct dccp_li_hist_entry *)
+		   hcrx->ccid3hcrx_li_hist.next;
+		/* FIXME win count check removed as was wrong */
+		/* should make this check with receive history */
+		/* and compare there as per section 10.2 of RFC4342 */
+
+		/* new loss event detected */
+		/* calculate last interval length */
+		seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+		entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC);
+
+		if (entry == NULL) {
+			printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__);
+			dump_stack();
+			return;
+		}
+
+		list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
+
+		tail = hcrx->ccid3hcrx_li_hist.prev;
+		list_del(tail);
+		kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
+
+		/* Create the newest interval */
+		entry->dccplih_seqno = seq_loss;
+		entry->dccplih_interval = seq_temp;
+		entry->dccplih_win_count = win_loss;
+	}
 }
 
-static void ccid3_hc_rx_detect_loss(struct sock *sk)
+static int ccid3_hc_rx_detect_loss(struct sock *sk,
+                                    struct dccp_rx_hist_entry *packet)
 {
 	struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
-	u8 win_loss;
-	const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist,
-						      &hcrx->ccid3hcrx_li_hist,
-						      &win_loss);
+	struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
+	u64 seqno = packet->dccphrx_seqno;
+	u64 tmp_seqno;
+	int loss = 0;
+	u8 ccval;
 
-	ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
+
+	tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
+
+	if (!rx_hist ||
+	   follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+		hcrx->ccid3hcrx_seqno_nonloss = seqno;
+		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+		goto detect_out;
+	}
+
+
+	while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
+	   > TFRC_RECV_NUM_LATE_LOSS) {
+		loss = 1;
+		ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
+		   hcrx->ccid3hcrx_ccval_nonloss);
+		tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
+		dccp_inc_seqno(&tmp_seqno);
+		hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+		dccp_inc_seqno(&tmp_seqno);
+		while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist,
+		   tmp_seqno, &ccval)) {
+		   	hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
+			hcrx->ccid3hcrx_ccval_nonloss = ccval;
+			dccp_inc_seqno(&tmp_seqno);
+		}
+	}
+
+	/* FIXME - this code could be simplified with above while */
+	/* but works at moment */
+	if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) {
+		hcrx->ccid3hcrx_seqno_nonloss = seqno;
+		hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval;
+	}
+
+detect_out:
+	dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
+		   &hcrx->ccid3hcrx_li_hist, packet,
+		   hcrx->ccid3hcrx_seqno_nonloss);
+	return loss;
 }
 
 static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -916,8 +1004,8 @@
 	struct dccp_rx_hist_entry *packet;
 	struct timeval now;
 	u8 win_count;
-	u32 p_prev, r_sample, t_elapsed;
-	int ins;
+	u32 p_prev, rtt_prev, r_sample, t_elapsed;
+	int loss;
 
 	BUG_ON(hcrx == NULL ||
 	       !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
@@ -932,7 +1020,7 @@
 	case DCCP_PKT_DATAACK:
 		if (opt_recv->dccpor_timestamp_echo == 0)
 			break;
-		p_prev = hcrx->ccid3hcrx_rtt;
+		rtt_prev = hcrx->ccid3hcrx_rtt;
 		dccp_timestamp(sk, &now);
 		timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10);
 		r_sample = timeval_usecs(&now);
@@ -951,8 +1039,8 @@
 			hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 +
 					      r_sample / 10;
 
-		if (p_prev != hcrx->ccid3hcrx_rtt)
-			ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
+		if (rtt_prev != hcrx->ccid3hcrx_rtt)
+			ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n",
 				       dccp_role(sk), hcrx->ccid3hcrx_rtt,
 				       opt_recv->dccpor_elapsed_time);
 		break;
@@ -973,8 +1061,7 @@
 
 	win_count = packet->dccphrx_ccval;
 
-	ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist,
-				      &hcrx->ccid3hcrx_li_hist, packet);
+	loss = ccid3_hc_rx_detect_loss(sk, packet);
 
 	if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
 		return;
@@ -991,7 +1078,7 @@
 	case TFRC_RSTATE_DATA:
 		hcrx->ccid3hcrx_bytes_recv += skb->len -
 					      dccp_hdr(skb)->dccph_doff * 4;
-		if (ins != 0)
+		if (loss)
 			break;
 
 		dccp_timestamp(sk, &now);
@@ -1012,7 +1099,6 @@
 	ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
 		       dccp_role(sk), sk, dccp_state_name(sk->sk_state));
 
-	ccid3_hc_rx_detect_loss(sk);
 	p_prev = hcrx->ccid3hcrx_p;
 	
 	/* Calculate loss event rate */
@@ -1022,6 +1108,9 @@
 		/* Scaling up by 1000000 as fixed decimal */
 		if (i_mean != 0)
 			hcrx->ccid3hcrx_p = 1000000 / i_mean;
+	} else {
+		printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__);
+		dump_stack();
 	}
 
 	if (hcrx->ccid3hcrx_p > p_prev) {
@@ -1230,7 +1319,7 @@
 }
 module_exit(ccid3_module_exit);
 
-MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
 	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
 MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
 MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 5ade4f6..0a2cb75 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -1,13 +1,13 @@
 /*
  *  net/dccp/ccids/ccid3.h
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
  *
  *  An implementation of the DCCP protocol
  *
  *  This code has been developed by the University of Waikato WAND
  *  research group. For further information please see http://www.wand.net.nz/
- *  or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *  or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
  *
  *  This code also uses code from Lulea University, rereleased as GPL by its
  *  authors:
@@ -120,9 +120,10 @@
 #define ccid3hcrx_x_recv	ccid3hcrx_tfrc.tfrcrx_x_recv
 #define ccid3hcrx_rtt		ccid3hcrx_tfrc.tfrcrx_rtt
 #define ccid3hcrx_p		ccid3hcrx_tfrc.tfrcrx_p
-  	u64			ccid3hcrx_seqno_last_counter:48,
+  	u64			ccid3hcrx_seqno_nonloss:48,
+				ccid3hcrx_ccval_nonloss:4,
 				ccid3hcrx_state:8,
-				ccid3hcrx_last_counter:4;
+				ccid3hcrx_ccval_last_counter:4;
   	u32			ccid3hcrx_bytes_recv;
   	struct timeval		ccid3hcrx_tstamp_last_feedback;
   	struct timeval		ccid3hcrx_tstamp_last_ack;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 5d7b7d8..906c81a 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -2,7 +2,7 @@
  *  net/dccp/ccids/lib/loss_interval.c
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <net/sock.h>
 
 #include "loss_interval.h"
 
@@ -90,13 +91,13 @@
 	u32 w_tot  = 0;
 
 	list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
-		if (i < DCCP_LI_HIST_IVAL_F_LENGTH) {
+		if (li_entry->dccplih_interval != ~0) {
 			i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
 			w_tot  += dccp_li_hist_w[i];
+			if (i != 0)
+				i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
 		}
 
-		if (i != 0)
-			i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
 
 		if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
 			break;
@@ -107,37 +108,36 @@
 
 	i_tot = max(i_tot0, i_tot1);
 
-	/* FIXME: Why do we do this? -Ian McDonald */
-	if (i_tot * 4 < w_tot)
-		i_tot = w_tot * 4;
+	if (!w_tot) {
+		LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__);
+		return 1;
+	}
 
-	return i_tot * 4 / w_tot;
+	return i_tot / w_tot;
 }
 
 EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
 
-struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-						     struct list_head *list,
-						     const u64 seq_loss,
-						     const u8 win_loss)
+int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+   struct list_head *list, const u64 seq_loss, const u8 win_loss)
 {
-	struct dccp_li_hist_entry *tail = NULL, *entry;
+	struct dccp_li_hist_entry *entry;
 	int i;
 
-	for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) {
+	for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
 		entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
 		if (entry == NULL) {
 			dccp_li_hist_purge(hist, list);
-			return NULL;
+			dump_stack();
+			return 0;
 		}
-		if (tail == NULL)
-			tail = entry;
+		entry->dccplih_interval = ~0;
 		list_add(&entry->dccplih_node, list);
 	}
 
 	entry->dccplih_seqno     = seq_loss;
 	entry->dccplih_win_count = win_loss;
-	return tail;
+	return 1;
 }
 
 EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 43bf782..0ae85f0 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -4,7 +4,7 @@
  *  net/dccp/ccids/lib/loss_interval.h
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -52,9 +52,6 @@
 
 extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
 
-extern struct dccp_li_hist_entry *
-			dccp_li_hist_interval_new(struct dccp_li_hist *hist,
-						  struct list_head *list,
-						  const u64 seq_loss,
-						  const u8 win_loss);
+extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
+   struct list_head *list, const u64 seq_loss, const u8 win_loss);
 #endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index ad98d6a..b876c9c 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -1,13 +1,13 @@
 /*
- *  net/dccp/packet_history.h
+ *  net/dccp/packet_history.c
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
  *
  *  An implementation of the DCCP protocol
  *
  *  This code has been developed by the University of Waikato WAND
  *  research group. For further information please see http://www.wand.net.nz/
- *  or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *  or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
  *
  *  This code also uses code from Lulea University, rereleased as GPL by its
  *  authors:
@@ -112,64 +112,27 @@
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
 
-int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
 			    struct list_head *rx_list,
 			    struct list_head *li_list,
-			    struct dccp_rx_hist_entry *packet)
+			    struct dccp_rx_hist_entry *packet,
+			    u64 nonloss_seqno)
 {
-	struct dccp_rx_hist_entry *entry, *next, *iter;
+	struct dccp_rx_hist_entry *entry, *next;
 	u8 num_later = 0;
 
-	iter = dccp_rx_hist_head(rx_list);
-	if (iter == NULL)
-		dccp_rx_hist_add_entry(rx_list, packet);
-	else {
-		const u64 seqno = packet->dccphrx_seqno;
+	list_add(&packet->dccphrx_node, rx_list);
 
-		if (after48(seqno, iter->dccphrx_seqno))
-			dccp_rx_hist_add_entry(rx_list, packet);
-		else {
-			if (dccp_rx_hist_entry_data_packet(iter))
-				num_later = 1;
-
-			list_for_each_entry_continue(iter, rx_list,
-						     dccphrx_node) {
-				if (after48(seqno, iter->dccphrx_seqno)) {
-					dccp_rx_hist_add_entry(&iter->dccphrx_node,
-							       packet);
-					goto trim_history;
-				}
-
-				if (dccp_rx_hist_entry_data_packet(iter))
-					num_later++;
-
-				if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
-					dccp_rx_hist_entry_delete(hist, packet);
-					return 1;
-				}
-			}
-
-			if (num_later < TFRC_RECV_NUM_LATE_LOSS)
-				dccp_rx_hist_add_entry(rx_list, packet);
-			/*
-			 * FIXME: else what? should we destroy the packet
-			 * like above?
-			 */
-		}
-	}
-
-trim_history:
-	/*
-	 * Trim history (remove all packets after the NUM_LATE_LOSS + 1
-	 * data packets)
-	 */
 	num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
 
 	if (!list_empty(li_list)) {
 		list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
 			if (num_later == 0) {
-				list_del_init(&entry->dccphrx_node);
-				dccp_rx_hist_entry_delete(hist, entry);
+				if (after48(nonloss_seqno,
+				   entry->dccphrx_seqno)) {
+					list_del_init(&entry->dccphrx_node);
+					dccp_rx_hist_entry_delete(hist, entry);
+				}
 			} else if (dccp_rx_hist_entry_data_packet(entry))
 				--num_later;
 		}
@@ -217,94 +180,10 @@
 				--num_later;
 		}
 	}
-
-	return 0;
 }
 
 EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
 
-u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
-			     struct list_head *li_list, u8 *win_loss)
-{
-	struct dccp_rx_hist_entry *entry, *next, *packet;
-	struct dccp_rx_hist_entry *a_loss = NULL;
-	struct dccp_rx_hist_entry *b_loss = NULL;
-	u64 seq_loss = DCCP_MAX_SEQNO + 1;
-	u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
-
-	list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
-		if (num_later == 0) {
-			b_loss = entry;
-			break;
-		} else if (dccp_rx_hist_entry_data_packet(entry))
-			--num_later;
-	}
-
-	if (b_loss == NULL)
-		goto out;
-
-	num_later = 1;
-	list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
-		if (num_later == 0) {
-			a_loss = entry;
-			break;
-		} else if (dccp_rx_hist_entry_data_packet(entry))
-			--num_later;
-	}
-
-	if (a_loss == NULL) {
-		if (list_empty(li_list)) {
-			/* no loss event have occured yet */
-			LIMIT_NETDEBUG("%s: TODO: find a lost data packet by "
-				       "comparing to initial seqno\n",
-				       __FUNCTION__);
-			goto out;
-		} else {
-			LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!",
-				       __FUNCTION__);
-			goto out;
-		}
-	}
-
-	/* Locate a lost data packet */
-	entry = packet = b_loss;
-	list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
-		u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
-					     packet->dccphrx_seqno);
-
-		if (delta != 0) {
-			if (dccp_rx_hist_entry_data_packet(packet))
-				--delta;
-			/*
-			 * FIXME: check this, probably this % usage is because
-			 * in earlier drafts the ndp count was just 8 bits
-			 * long, but now it cam be up to 24 bits long.
-			 */
-#if 0
-			if (delta % DCCP_NDP_LIMIT !=
-			    (packet->dccphrx_ndp -
-			     entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
-#endif
-			if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) {
-				seq_loss = entry->dccphrx_seqno;
-				dccp_inc_seqno(&seq_loss);
-			}
-		}
-		packet = entry;
-		if (packet == a_loss)
-			break;
-	}
-out:
-	if (seq_loss != DCCP_MAX_SEQNO + 1)
-		*win_loss = a_loss->dccphrx_ccval;
-	else
-		*win_loss = 0; /* Paranoia */
-
-	return seq_loss;
-}
-
-EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss);
-
 struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
 {
 	struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -365,6 +244,25 @@
 
 EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
 
+int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+   u8 *ccval)
+{
+	struct dccp_rx_hist_entry *packet = NULL, *entry;
+
+	list_for_each_entry(entry, list, dccphrx_node)
+		if (entry->dccphrx_seqno == seq) {
+			packet = entry;
+			break;
+		}
+
+	if (packet)
+		*ccval = packet->dccphrx_ccval;
+
+	return packet != NULL;
+}
+
+EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
+
 void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
 			      struct list_head *list,
 			      struct dccp_tx_hist_entry *packet)
@@ -391,7 +289,7 @@
 
 EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
 
-MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
+MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
 	      "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
 MODULE_DESCRIPTION("DCCP TFRC library");
 MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 673c209..067cf1c 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -1,13 +1,13 @@
 /*
  *  net/dccp/packet_history.h
  *
- *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
+ *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
  *
  *  An implementation of the DCCP protocol
  *
  *  This code has been developed by the University of Waikato WAND
  *  research group. For further information please see http://www.wand.net.nz/
- *  or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
+ *  or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
  *
  *  This code also uses code from Lulea University, rereleased as GPL by its
  *  authors:
@@ -106,6 +106,8 @@
 extern struct dccp_tx_hist_entry *
 			dccp_tx_hist_find_entry(const struct list_head *list,
 						const u64 seq);
+extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
+   u8 *ccval);
 
 static inline void dccp_tx_hist_add_entry(struct list_head *list,
 					  struct dccp_tx_hist_entry *entry)
@@ -164,12 +166,6 @@
 extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
 			       struct list_head *list);
 
-static inline void dccp_rx_hist_add_entry(struct list_head *list,
-					  struct dccp_rx_hist_entry *entry)
-{
-	list_add(&entry->dccphrx_node, list);
-}
-
 static inline struct dccp_rx_hist_entry *
 		dccp_rx_hist_head(struct list_head *list)
 {
@@ -188,10 +184,11 @@
 	       entry->dccphrx_type == DCCP_PKT_DATAACK;
 }
 
-extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
+extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
 				   struct list_head *rx_list,
 				   struct list_head *li_list,
-				   struct dccp_rx_hist_entry *packet);
+				   struct dccp_rx_hist_entry *packet,
+				   u64 nonloss_seqno);
 
 extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
 				    struct list_head *li_list, u8 *win_loss);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 130c4c4..45f30f5 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -4,7 +4,7 @@
  *  net/dccp/ccids/lib/tfrc.h
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *  Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
  *
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 4fd2ebe..44076e0 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -2,7 +2,7 @@
  *  net/dccp/ccids/lib/tfrc_equation.c
  *
  *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *  Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
  *
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d00a2f4..a5c5475 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -5,7 +5,7 @@
  *
  *  An implementation of the DCCP protocol
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *
  *	This program is free software; you can redistribute it and/or modify it
  *	under the terms of the GNU General Public License version 2 as
@@ -81,6 +81,14 @@
 	return after48(seq1, seq2) ? seq1 : seq2;
 }
 
+/* is seq1 next seqno after seq2 */
+static inline int follows48(const u64 seq1, const u64 seq2)
+{
+	int diff = (seq1 & 0xFFFF) - (seq2 & 0xFFFF);
+
+	return diff==1;
+}
+
 enum {
 	DCCP_MIB_NUM = 0,
 	DCCP_MIB_ACTIVEOPENS,			/* ActiveOpens */
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 9f3d4d7..610c722 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -230,7 +230,7 @@
 	ipv6_addr_copy(&np->saddr, saddr);
 	inet->rcv_saddr = LOOPBACK4_IPV6;
 
-	ip6_dst_store(sk, dst, NULL);
+	__ip6_dst_store(sk, dst, NULL);
 
 	icsk->icsk_ext_hdr_len = 0;
 	if (np->opt != NULL)
@@ -863,7 +863,7 @@
 	 * comment in that function for the gory details. -acme
 	 */
 
-	ip6_dst_store(newsk, dst, NULL);
+	__ip6_dst_store(newsk, dst, NULL);
 	newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM |
 						      NETIF_F_TSO);
 	newdp6 = (struct dccp6_sock *)newsk;
diff --git a/net/dccp/options.c b/net/dccp/options.c
index daf72bb..07a3469 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -4,7 +4,7 @@
  *  An implementation of the DCCP protocol
  *  Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
- *  Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
+ *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 1355614..743e9fc 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -925,8 +925,13 @@
 		for(dev_out = dev_base; dev_out; dev_out = dev_out->next) {
 			if (!dev_out->dn_ptr)
 				continue;
-			if (dn_dev_islocal(dev_out, oldflp->fld_src))
-				break;
+			if (!dn_dev_islocal(dev_out, oldflp->fld_src))
+				continue;
+			if ((dev_out->flags & IFF_LOOPBACK) &&
+			    oldflp->fld_dst &&
+			    !dn_dev_islocal(dev_out, oldflp->fld_dst))
+				continue;
+			break;
 		}
 		read_unlock(&dev_base_lock);
 		if (dev_out == NULL)
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig
index dbb0852..f7e84e9 100644
--- a/net/ieee80211/Kconfig
+++ b/net/ieee80211/Kconfig
@@ -58,6 +58,7 @@
 	depends on IEEE80211 && NET_RADIO
 	select CRYPTO
 	select CRYPTO_MICHAEL_MIC
+	select CRC32
 	---help---
 	Include software based cipher suites in support of IEEE 802.11i
 	(aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled
diff --git a/net/ieee80211/ieee80211_crypt_ccmp.c b/net/ieee80211/ieee80211_crypt_ccmp.c
index ed90a8a..098c668 100644
--- a/net/ieee80211/ieee80211_crypt_ccmp.c
+++ b/net/ieee80211/ieee80211_crypt_ccmp.c
@@ -271,6 +271,27 @@
 	return 0;
 }
 
+/*
+ * deal with seq counter wrapping correctly.
+ * refer to timer_after() for jiffies wrapping handling
+ */
+static inline int ccmp_replay_check(u8 *pn_n, u8 *pn_o)
+{
+	u32 iv32_n, iv16_n;
+	u32 iv32_o, iv16_o;
+
+	iv32_n = (pn_n[0] << 24) | (pn_n[1] << 16) | (pn_n[2] << 8) | pn_n[3];
+	iv16_n = (pn_n[4] << 8) | pn_n[5];
+
+	iv32_o = (pn_o[0] << 24) | (pn_o[1] << 16) | (pn_o[2] << 8) | pn_o[3];
+	iv16_o = (pn_o[4] << 8) | pn_o[5];
+
+	if ((s32)iv32_n - (s32)iv32_o < 0 ||
+	    (iv32_n == iv32_o && iv16_n <= iv16_o))
+		return 1;
+	return 0;
+}
+
 static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_ccmp_data *key = priv;
@@ -323,7 +344,7 @@
 	pn[5] = pos[0];
 	pos += 8;
 
-	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
+	if (ccmp_replay_check(pn, key->rx_pn)) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
 			       " previous PN %02x%02x%02x%02x%02x%02x "
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 34dba0b..f2df2f5 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -52,8 +52,10 @@
 
 	int key_idx;
 
-	struct crypto_tfm *tfm_arc4;
-	struct crypto_tfm *tfm_michael;
+	struct crypto_tfm *tx_tfm_arc4;
+	struct crypto_tfm *tx_tfm_michael;
+	struct crypto_tfm *rx_tfm_arc4;
+	struct crypto_tfm *rx_tfm_michael;
 
 	/* scratch buffers for virt_to_page() (crypto API) */
 	u8 rx_hdr[16], tx_hdr[16];
@@ -85,15 +87,29 @@
 
 	priv->key_idx = key_idx;
 
-	priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0);
-	if (priv->tfm_arc4 == NULL) {
+	priv->tx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
+	if (priv->tx_tfm_arc4 == NULL) {
 		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
 		       "crypto API arc4\n");
 		goto fail;
 	}
 
-	priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0);
-	if (priv->tfm_michael == NULL) {
+	priv->tx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
+	if (priv->tx_tfm_michael == NULL) {
+		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
+		       "crypto API michael_mic\n");
+		goto fail;
+	}
+
+	priv->rx_tfm_arc4 = crypto_alloc_tfm("arc4", 0);
+	if (priv->rx_tfm_arc4 == NULL) {
+		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
+		       "crypto API arc4\n");
+		goto fail;
+	}
+
+	priv->rx_tfm_michael = crypto_alloc_tfm("michael_mic", 0);
+	if (priv->rx_tfm_michael == NULL) {
 		printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
 		       "crypto API michael_mic\n");
 		goto fail;
@@ -103,10 +119,14 @@
 
       fail:
 	if (priv) {
-		if (priv->tfm_michael)
-			crypto_free_tfm(priv->tfm_michael);
-		if (priv->tfm_arc4)
-			crypto_free_tfm(priv->tfm_arc4);
+		if (priv->tx_tfm_michael)
+			crypto_free_tfm(priv->tx_tfm_michael);
+		if (priv->tx_tfm_arc4)
+			crypto_free_tfm(priv->tx_tfm_arc4);
+		if (priv->rx_tfm_michael)
+			crypto_free_tfm(priv->rx_tfm_michael);
+		if (priv->rx_tfm_arc4)
+			crypto_free_tfm(priv->rx_tfm_arc4);
 		kfree(priv);
 	}
 
@@ -116,10 +136,16 @@
 static void ieee80211_tkip_deinit(void *priv)
 {
 	struct ieee80211_tkip_data *_priv = priv;
-	if (_priv && _priv->tfm_michael)
-		crypto_free_tfm(_priv->tfm_michael);
-	if (_priv && _priv->tfm_arc4)
-		crypto_free_tfm(_priv->tfm_arc4);
+	if (_priv) {
+		if (_priv->tx_tfm_michael)
+			crypto_free_tfm(_priv->tx_tfm_michael);
+		if (_priv->tx_tfm_arc4)
+			crypto_free_tfm(_priv->tx_tfm_arc4);
+		if (_priv->rx_tfm_michael)
+			crypto_free_tfm(_priv->rx_tfm_michael);
+		if (_priv->rx_tfm_arc4)
+			crypto_free_tfm(_priv->rx_tfm_arc4);
+	}
 	kfree(priv);
 }
 
@@ -351,15 +377,28 @@
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
-	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
+	crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
 	sg.length = len + 4;
-	crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4);
+	crypto_cipher_encrypt(tkey->tx_tfm_arc4, &sg, &sg, len + 4);
 
 	return 0;
 }
 
+/*
+ * deal with seq counter wrapping correctly.
+ * refer to timer_after() for jiffies wrapping handling
+ */
+static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n,
+				    u32 iv32_o, u16 iv16_o)
+{
+	if ((s32)iv32_n - (s32)iv32_o < 0 ||
+	    (iv32_n == iv32_o && iv16_n <= iv16_o))
+		return 1;
+	return 0;
+}
+
 static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct ieee80211_tkip_data *tkey = priv;
@@ -414,8 +453,7 @@
 	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
 	pos += 8;
 
-	if (iv32 < tkey->rx_iv32 ||
-	    (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
+	if (tkip_replay_check(iv32, iv16, tkey->rx_iv32, tkey->rx_iv16)) {
 		if (net_ratelimit()) {
 			printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
 			       " previous TSC %08x%04x received TSC "
@@ -434,11 +472,11 @@
 
 	plen = skb->len - hdr_len - 12;
 
-	crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16);
+	crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
 	sg.length = plen + 4;
-	crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4);
+	crypto_cipher_decrypt(tkey->rx_tfm_arc4, &sg, &sg, plen + 4);
 
 	crc = ~crc32_le(~0, pos, plen);
 	icv[0] = crc;
@@ -472,12 +510,12 @@
 	return keyidx;
 }
 
-static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr,
+static int michael_mic(struct crypto_tfm *tfm_michael, u8 * key, u8 * hdr,
 		       u8 * data, size_t data_len, u8 * mic)
 {
 	struct scatterlist sg[2];
 
-	if (tkey->tfm_michael == NULL) {
+	if (tfm_michael == NULL) {
 		printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
 		return -1;
 	}
@@ -489,10 +527,10 @@
 	sg[1].offset = offset_in_page(data);
 	sg[1].length = data_len;
 
-	crypto_digest_init(tkey->tfm_michael);
-	crypto_digest_setkey(tkey->tfm_michael, key, 8);
-	crypto_digest_update(tkey->tfm_michael, sg, 2);
-	crypto_digest_final(tkey->tfm_michael, mic);
+	crypto_digest_init(tfm_michael);
+	crypto_digest_setkey(tfm_michael, key, 8);
+	crypto_digest_update(tfm_michael, sg, 2);
+	crypto_digest_final(tfm_michael, mic);
 
 	return 0;
 }
@@ -528,7 +566,7 @@
 	if (stype & IEEE80211_STYPE_QOS_DATA) {
 		const struct ieee80211_hdr_3addrqos *qoshdr =
 			(struct ieee80211_hdr_3addrqos *)skb->data;
-		hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
+		hdr[12] = qoshdr->qos_ctl & cpu_to_le16(IEEE80211_QCTL_TID);
 	} else
 		hdr[12] = 0;		/* priority */
 
@@ -550,7 +588,7 @@
 
 	michael_mic_hdr(skb, tkey->tx_hdr);
 	pos = skb_put(skb, 8);
-	if (michael_mic(tkey, &tkey->key[16], tkey->tx_hdr,
+	if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
 			skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
 		return -1;
 
@@ -588,7 +626,7 @@
 		return -1;
 
 	michael_mic_hdr(skb, tkey->rx_hdr);
-	if (michael_mic(tkey, &tkey->key[24], tkey->rx_hdr,
+	if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
 			skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
 		return -1;
 	if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
@@ -618,14 +656,18 @@
 {
 	struct ieee80211_tkip_data *tkey = priv;
 	int keyidx;
-	struct crypto_tfm *tfm = tkey->tfm_michael;
-	struct crypto_tfm *tfm2 = tkey->tfm_arc4;
+	struct crypto_tfm *tfm = tkey->tx_tfm_michael;
+	struct crypto_tfm *tfm2 = tkey->tx_tfm_arc4;
+	struct crypto_tfm *tfm3 = tkey->rx_tfm_michael;
+	struct crypto_tfm *tfm4 = tkey->rx_tfm_arc4;
 
 	keyidx = tkey->key_idx;
 	memset(tkey, 0, sizeof(*tkey));
 	tkey->key_idx = keyidx;
-	tkey->tfm_michael = tfm;
-	tkey->tfm_arc4 = tfm2;
+	tkey->tx_tfm_michael = tfm;
+	tkey->tx_tfm_arc4 = tfm2;
+	tkey->rx_tfm_michael = tfm3;
+	tkey->rx_tfm_arc4 = tfm4;
 	if (len == TKIP_KEY_LEN) {
 		memcpy(tkey->key, key, TKIP_KEY_LEN);
 		tkey->key_set = 1;
diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c
index 0ebf235..b435b28 100644
--- a/net/ieee80211/ieee80211_crypt_wep.c
+++ b/net/ieee80211/ieee80211_crypt_wep.c
@@ -32,7 +32,8 @@
 	u8 key[WEP_KEY_LEN + 1];
 	u8 key_len;
 	u8 key_idx;
-	struct crypto_tfm *tfm;
+	struct crypto_tfm *tx_tfm;
+	struct crypto_tfm *rx_tfm;
 };
 
 static void *prism2_wep_init(int keyidx)
@@ -44,13 +45,19 @@
 		goto fail;
 	priv->key_idx = keyidx;
 
-	priv->tfm = crypto_alloc_tfm("arc4", 0);
-	if (priv->tfm == NULL) {
+	priv->tx_tfm = crypto_alloc_tfm("arc4", 0);
+	if (priv->tx_tfm == NULL) {
 		printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
 		       "crypto API arc4\n");
 		goto fail;
 	}
 
+	priv->rx_tfm = crypto_alloc_tfm("arc4", 0);
+	if (priv->rx_tfm == NULL) {
+		printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
+		       "crypto API arc4\n");
+		goto fail;
+	}
 	/* start WEP IV from a random value */
 	get_random_bytes(&priv->iv, 4);
 
@@ -58,8 +65,10 @@
 
       fail:
 	if (priv) {
-		if (priv->tfm)
-			crypto_free_tfm(priv->tfm);
+		if (priv->tx_tfm)
+			crypto_free_tfm(priv->tx_tfm);
+		if (priv->rx_tfm)
+			crypto_free_tfm(priv->rx_tfm);
 		kfree(priv);
 	}
 	return NULL;
@@ -68,8 +77,12 @@
 static void prism2_wep_deinit(void *priv)
 {
 	struct prism2_wep_data *_priv = priv;
-	if (_priv && _priv->tfm)
-		crypto_free_tfm(_priv->tfm);
+	if (_priv) {
+		if (_priv->tx_tfm)
+			crypto_free_tfm(_priv->tx_tfm);
+		if (_priv->rx_tfm)
+			crypto_free_tfm(_priv->rx_tfm);
+	}
 	kfree(priv);
 }
 
@@ -151,11 +164,11 @@
 	icv[2] = crc >> 16;
 	icv[3] = crc >> 24;
 
-	crypto_cipher_setkey(wep->tfm, key, klen);
+	crypto_cipher_setkey(wep->tx_tfm, key, klen);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
 	sg.length = len + 4;
-	crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4);
+	crypto_cipher_encrypt(wep->tx_tfm, &sg, &sg, len + 4);
 
 	return 0;
 }
@@ -194,11 +207,11 @@
 	/* Apply RC4 to data and compute CRC32 over decrypted data */
 	plen = skb->len - hdr_len - 8;
 
-	crypto_cipher_setkey(wep->tfm, key, klen);
+	crypto_cipher_setkey(wep->rx_tfm, key, klen);
 	sg.page = virt_to_page(pos);
 	sg.offset = offset_in_page(pos);
 	sg.length = plen + 4;
-	crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4);
+	crypto_cipher_decrypt(wep->rx_tfm, &sg, &sg, plen + 4);
 
 	crc = ~crc32_le(~0, pos, plen);
 	icv[0] = crc;
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 72d4d4e..7707041 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -779,33 +779,44 @@
 	return 0;
 }
 
-/* Filter out unrelated packets, call ieee80211_rx[_mgt] */
-int ieee80211_rx_any(struct ieee80211_device *ieee,
+/* Filter out unrelated packets, call ieee80211_rx[_mgt]
+ * This function takes over the skb, it should not be used again after calling
+ * this function. */
+void ieee80211_rx_any(struct ieee80211_device *ieee,
 		     struct sk_buff *skb, struct ieee80211_rx_stats *stats)
 {
 	struct ieee80211_hdr_4addr *hdr;
 	int is_packet_for_us;
 	u16 fc;
 
-	if (ieee->iw_mode == IW_MODE_MONITOR)
-		return ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL;
+	if (ieee->iw_mode == IW_MODE_MONITOR) {
+		if (!ieee80211_rx(ieee, skb, stats))
+			dev_kfree_skb_irq(skb);
+		return;
+	}
+
+	if (skb->len < sizeof(struct ieee80211_hdr))
+		goto drop_free;
 
 	hdr = (struct ieee80211_hdr_4addr *)skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
 
 	if ((fc & IEEE80211_FCTL_VERS) != 0)
-		return -EINVAL;
+		goto drop_free;
 		
 	switch (fc & IEEE80211_FCTL_FTYPE) {
 	case IEEE80211_FTYPE_MGMT:
+		if (skb->len < sizeof(struct ieee80211_hdr_3addr))
+			goto drop_free;
 		ieee80211_rx_mgt(ieee, hdr, stats);
-		return 0;
+		dev_kfree_skb_irq(skb);
+		return;
 	case IEEE80211_FTYPE_DATA:
 		break;
 	case IEEE80211_FTYPE_CTL:
-		return 0;
+		return;
 	default:
-		return -EINVAL;
+		return;
 	}
 
 	is_packet_for_us = 0;
@@ -849,8 +860,14 @@
 	}
 
 	if (is_packet_for_us)
-		return (ieee80211_rx(ieee, skb, stats) ? 0 : -EINVAL);
-	return 0;
+		if (!ieee80211_rx(ieee, skb, stats))
+			dev_kfree_skb_irq(skb);
+	return;
+
+drop_free:
+	dev_kfree_skb_irq(skb);
+	ieee->stats.rx_dropped++;
+	return;
 }
 
 #define MGMT_FRAME_FIXED_PART_LENGTH		0x24
@@ -1061,13 +1078,16 @@
 
 	while (length >= sizeof(*info_element)) {
 		if (sizeof(*info_element) + info_element->len > length) {
-			IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
-					     "info_element->len + 2 > left : "
-					     "info_element->len+2=%zd left=%d, id=%d.\n",
-					     info_element->len +
-					     sizeof(*info_element),
-					     length, info_element->id);
-			return 1;
+			IEEE80211_ERROR("Info elem: parse failed: "
+					"info_element->len + 2 > left : "
+					"info_element->len+2=%zd left=%d, id=%d.\n",
+					info_element->len +
+					sizeof(*info_element),
+					length, info_element->id);
+			/* We stop processing but don't return an error here
+			 * because some misbehaviour APs break this rule. ie.
+			 * Orinoco AP1000. */
+			break;
 		}
 
 		switch (info_element->id) {
@@ -1166,6 +1186,7 @@
 
 		case MFIE_TYPE_ERP_INFO:
 			network->erp_value = info_element->data[0];
+			network->flags |= NETWORK_HAS_ERP_VALUE;
 			IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
 					     network->erp_value);
 			break;
@@ -1729,5 +1750,6 @@
 	}
 }
 
+EXPORT_SYMBOL_GPL(ieee80211_rx_any);
 EXPORT_SYMBOL(ieee80211_rx_mgt);
 EXPORT_SYMBOL(ieee80211_rx);
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index bf04213..ae25449 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -337,7 +337,7 @@
 		hdr_len += 2;
 
 		skb->priority = ieee80211_classify(skb);
-		header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID;
+		header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
 	}
 	header.frame_ctl = cpu_to_le16(fc);
 
@@ -532,13 +532,6 @@
 			return 0;
 		}
 
-		if (ret == NETDEV_TX_BUSY) {
-			printk(KERN_ERR "%s: NETDEV_TX_BUSY returned; "
-			       "driver should report queue full via "
-			       "ieee_device->is_queue_full.\n",
-			       ieee->dev->name);
-		}
-
 		ieee80211_txb_free(txb);
 	}
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 44215ce..589f6d2 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -96,7 +96,7 @@
 	mac->associated = 0;
 	mac->associnfo.bssvalid = 0;
 	mac->associnfo.associating = 0;
-	ieee80211softmac_init_txrates(mac);
+	ieee80211softmac_init_bss(mac);
 	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
 	spin_unlock_irqrestore(&mac->lock, flags);
 }
@@ -334,11 +334,19 @@
 	struct ieee80211_assoc_response * resp,
 	struct ieee80211softmac_network *net)
 {
+	u16 cap = le16_to_cpu(resp->capability);
+	u8 erp_value = net->erp_value;
+
 	mac->associnfo.associating = 0;
-	mac->associnfo.supported_rates = net->supported_rates;
+	mac->bssinfo.supported_rates = net->supported_rates;
 	ieee80211softmac_recalc_txrates(mac);
 
 	mac->associated = 1;
+
+	mac->associnfo.short_preamble_available =
+		(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0;
+	ieee80211softmac_process_erp(mac, erp_value);
+
 	if (mac->set_bssid_filter)
 		mac->set_bssid_filter(mac->dev, net->bssid);
 	memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN);
@@ -351,9 +359,9 @@
 int
 ieee80211softmac_handle_assoc_response(struct net_device * dev,
 				       struct ieee80211_assoc_response * resp,
-				       struct ieee80211_network * _ieee80211_network_do_not_use)
+				       struct ieee80211_network * _ieee80211_network)
 {
-	/* NOTE: the network parameter has to be ignored by
+	/* NOTE: the network parameter has to be mostly ignored by
 	 *       this code because it is the ieee80211's pointer
 	 *       to the struct, not ours (we made a copy)
 	 */
@@ -385,6 +393,11 @@
 	/* now that we know it was for us, we can cancel the timeout */
 	cancel_delayed_work(&mac->associnfo.timeout);
 
+	/* if the association response included an ERP IE, update our saved
+	 * copy */
+	if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE)
+		network->erp_value = _ieee80211_network->erp_value;
+
 	switch (status) {
 		case 0:
 			dprintk(KERN_INFO PFX "associated!\n");
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index ebc33ca..4cef39e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -116,6 +116,16 @@
 	kfree(auth);
 }
 
+/* Sends a response to an auth challenge (for shared key auth). */
+static void
+ieee80211softmac_auth_challenge_response(void *_aq)
+{
+	struct ieee80211softmac_auth_queue_item *aq = _aq;
+
+	/* Send our response */
+	ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
+}
+
 /* Handle the auth response from the AP
  * This should be registered with ieee80211 as handle_auth 
  */
@@ -197,24 +207,30 @@
 		case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE:
 			/* Check to make sure we have a challenge IE */
 			data = (u8 *)auth->info_element;
-			if(*data++ != MFIE_TYPE_CHALLENGE){
+			if (*data++ != MFIE_TYPE_CHALLENGE) {
 				printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n");
 				break;	
 			}
 			/* Save the challenge */
 			spin_lock_irqsave(&mac->lock, flags);
 			net->challenge_len = *data++; 	
-			if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
+			if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN)
 				net->challenge_len = WLAN_AUTH_CHALLENGE_LEN;
-			if(net->challenge != NULL)
+			if (net->challenge != NULL)
 				kfree(net->challenge);
 			net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC);
 			memcpy(net->challenge, data, net->challenge_len);
 			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
-			spin_unlock_irqrestore(&mac->lock, flags);
 
-			/* Send our response */
-			ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
+			/* We reuse the work struct from the auth request here.
+			 * It is safe to do so as each one is per-request, and
+			 * at this point (dealing with authentication response)
+			 * we have obviously already sent the initial auth
+			 * request. */
+			cancel_delayed_work(&aq->work);
+			INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq);
+			schedule_work(&aq->work);
+			spin_unlock_irqrestore(&mac->lock, flags);
 			return 0;
 		case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
 			kfree(net->challenge);
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index 6ae5a1d..82bfddb 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -467,3 +467,17 @@
 	kfree(pkt);
 	return 0;
 }
+
+/* Beacon handling */
+int ieee80211softmac_handle_beacon(struct net_device *dev,
+	struct ieee80211_beacon *beacon,
+	struct ieee80211_network *network)
+{
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+	if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0)
+		ieee80211softmac_process_erp(mac, network->erp_value);
+
+	return 0;
+}
+
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 4b2e57d..addea1c 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -44,6 +44,7 @@
 	softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response;
 	softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req;
 	softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc;
+ 	softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon;
 	softmac->scaninfo = NULL;
 
 	softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
@@ -178,21 +179,14 @@
 	return 0;
 }
 
-/* Finds the highest rate which is:
- *  1. Present in ri (optionally a basic rate)
- *  2. Supported by the device
- *  3. Less than or equal to the user-defined rate
- */
-static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
+u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac,
 	struct ieee80211softmac_ratesinfo *ri, int basic_only)
 {
 	u8 user_rate = mac->txrates.user_rate;
 	int i;
 
-	if (ri->count == 0) {
-		dprintk(KERN_ERR PFX "empty ratesinfo?\n");
+	if (ri->count == 0)
 		return IEEE80211_CCK_RATE_1MB;
-	}
 
 	for (i = ri->count - 1; i >= 0; i--) {
 		u8 rate = ri->rates[i];
@@ -208,36 +202,61 @@
 	/* If we haven't found a suitable rate by now, just trust the user */
 	return user_rate;
 }
+EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate);
+
+void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+	u8 erp_value)
+{
+ 	int use_protection;
+	int short_preamble;
+ 	u32 changes = 0;
+
+	/* Barker preamble mode */
+	short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0
+			  && mac->associnfo.short_preamble_available) ? 1 : 0;
+
+	/* Protection needed? */
+	use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+
+	if (mac->bssinfo.short_preamble != short_preamble) {
+		changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+		mac->bssinfo.short_preamble = short_preamble;
+	}
+
+	if (mac->bssinfo.use_protection != use_protection) {
+		changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+		mac->bssinfo.use_protection = use_protection;
+	}
+
+	if (mac->bssinfo_change && changes)
+		mac->bssinfo_change(mac->dev, changes);
+}
 
 void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
 {
 	struct ieee80211softmac_txrates *txrates = &mac->txrates;
-	struct ieee80211softmac_txrates oldrates;
 	u32 change = 0;
 
-	if (mac->txrates_change)
-		oldrates = mac->txrates;
-
 	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-	txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0);
+	txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0);
 
 	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
 	txrates->default_fallback = lower_rate(mac, txrates->default_rate);
 
 	change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
-	txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1);
+	txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1);
 
 	if (mac->txrates_change)
-		mac->txrates_change(mac->dev, change, &oldrates);
+		mac->txrates_change(mac->dev, change);
 
 }
 
-void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
+void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac)
 {
 	struct ieee80211_device *ieee = mac->ieee;
 	u32 change = 0;
 	struct ieee80211softmac_txrates *txrates = &mac->txrates;
-	struct ieee80211softmac_txrates oldrates;
+	struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo;
 
 	/* TODO: We need some kind of state machine to lower the default rates
 	 *       if we loose too many packets.
@@ -245,8 +264,6 @@
 	/* Change the default txrate to the highest possible value.
 	 * The txrate machine will lower it, if it is too high.
 	 */
-	if (mac->txrates_change)
-		oldrates = mac->txrates;
 	/* FIXME: We don't correctly handle backing down to lower
 	   rates, so 801.11g devices start off at 11M for now. People
 	   can manually change it if they really need to, but 11M is
@@ -272,7 +289,23 @@
 	change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
 
 	if (mac->txrates_change)
-		mac->txrates_change(mac->dev, change, &oldrates);
+		mac->txrates_change(mac->dev, change);
+
+	change = 0;
+
+	bssinfo->supported_rates.count = 0;
+	memset(bssinfo->supported_rates.rates, 0,
+		sizeof(bssinfo->supported_rates.rates));
+	change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES;
+
+	bssinfo->short_preamble = 0;
+	change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE;
+
+	bssinfo->use_protection = 0;
+	change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION;
+
+	if (mac->bssinfo_change)
+		mac->bssinfo_change(mac->dev, change);
 
 	mac->running = 1;
 }
@@ -282,7 +315,7 @@
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 
 	ieee80211softmac_start_check_rates(mac);
-	ieee80211softmac_init_txrates(mac);
+	ieee80211softmac_init_bss(mac);
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
@@ -335,7 +368,6 @@
 static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac,
 						 int amount)
 {
-	struct ieee80211softmac_txrates oldrates;
 	u8 default_rate = mac->txrates.default_rate;
 	u8 default_fallback = mac->txrates.default_fallback;
 	u32 changes = 0;
@@ -348,8 +380,6 @@
 	mac->txrate_badness += amount;
 	if (mac->txrate_badness <= -1000) {
 		/* Very small badness. Try a faster bitrate. */
-		if (mac->txrates_change)
-			memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
 		default_rate = raise_rate(mac, default_rate);
 		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
 		default_fallback = get_fallback_rate(mac, default_rate);
@@ -358,8 +388,6 @@
 printk("Bitrate raised to %u\n", default_rate);
 	} else if (mac->txrate_badness >= 10000) {
 		/* Very high badness. Try a slower bitrate. */
-		if (mac->txrates_change)
-			memcpy(&oldrates, &mac->txrates, sizeof(oldrates));
 		default_rate = lower_rate(mac, default_rate);
 		changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
 		default_fallback = get_fallback_rate(mac, default_rate);
@@ -372,7 +400,7 @@
 	mac->txrates.default_fallback = default_fallback;
 
 	if (changes && mac->txrates_change)
-		mac->txrates_change(mac->dev, changes, &oldrates);
+		mac->txrates_change(mac->dev, changes);
 }
 
 void ieee80211softmac_fragment_lost(struct net_device *dev,
@@ -416,7 +444,11 @@
 	memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len);
 	softnet->supported_rates.count += net->rates_ex_len;
 	sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL);
-	
+
+	/* we save the ERP value because it is needed at association time, and
+	 * many AP's do not include an ERP IE in the association response. */
+	softnet->erp_value = net->erp_value;
+
 	softnet->capabilities = net->capability;
 	return softnet;
 }
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index fa1f8e3..0642e09 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -116,9 +116,11 @@
 	struct ieee80211softmac_essid *essid);
 
 /* Rates related */
+void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac,
+	u8 erp_value);
 int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
 u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
-void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac);
+void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac);
 void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
 static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
 	return ieee80211softmac_lower_rate_delta(mac, rate, 1);
@@ -133,6 +135,9 @@
 /*** prototypes from _io.c */
 int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac,
 	void* ptrarg, u32 type, u32 arg);
+int ieee80211softmac_handle_beacon(struct net_device *dev,
+	struct ieee80211_beacon *beacon,
+	struct ieee80211_network *network);
 
 /*** prototypes from _auth.c */
 /* do these have to go into the public header? */
@@ -189,6 +194,7 @@
 	    authenticated:1,
 	    auth_desynced_once:1;
 
+	u8 erp_value;				/* Saved ERP value */
 	u16 capabilities;			/* Capabilities bitfield */
 	u8 challenge_len;			/* Auth Challenge length */
 	char *challenge;			/* Challenge Text */
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 9be53a8..5173800 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -159,7 +159,7 @@
 
 void fib_release_info(struct fib_info *fi)
 {
-	write_lock(&fib_info_lock);
+	write_lock_bh(&fib_info_lock);
 	if (fi && --fi->fib_treeref == 0) {
 		hlist_del(&fi->fib_hash);
 		if (fi->fib_prefsrc)
@@ -172,7 +172,7 @@
 		fi->fib_dead = 1;
 		fib_info_put(fi);
 	}
-	write_unlock(&fib_info_lock);
+	write_unlock_bh(&fib_info_lock);
 }
 
 static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
@@ -598,7 +598,7 @@
 	unsigned int old_size = fib_hash_size;
 	unsigned int i, bytes;
 
-	write_lock(&fib_info_lock);
+	write_lock_bh(&fib_info_lock);
 	old_info_hash = fib_info_hash;
 	old_laddrhash = fib_info_laddrhash;
 	fib_hash_size = new_size;
@@ -639,7 +639,7 @@
 	}
 	fib_info_laddrhash = new_laddrhash;
 
-	write_unlock(&fib_info_lock);
+	write_unlock_bh(&fib_info_lock);
 
 	bytes = old_size * sizeof(struct hlist_head *);
 	fib_hash_free(old_info_hash, bytes);
@@ -820,7 +820,7 @@
 
 	fi->fib_treeref++;
 	atomic_inc(&fi->fib_clntref);
-	write_lock(&fib_info_lock);
+	write_lock_bh(&fib_info_lock);
 	hlist_add_head(&fi->fib_hash,
 		       &fib_info_hash[fib_info_hashfn(fi)]);
 	if (fi->fib_prefsrc) {
@@ -839,7 +839,7 @@
 		head = &fib_info_devhash[hash];
 		hlist_add_head(&nh->nh_hash, head);
 	} endfor_nexthops(fi)
-	write_unlock(&fib_info_lock);
+	write_unlock_bh(&fib_info_lock);
 	return fi;
 
 err_inval:
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 9f4b752..8e8117c 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1793,29 +1793,35 @@
 	struct in_device *in_dev;
 	u32 group = imr->imr_multiaddr.s_addr;
 	u32 ifindex;
+	int ret = -EADDRNOTAVAIL;
 
 	rtnl_lock();
 	in_dev = ip_mc_find_dev(imr);
-	if (!in_dev) {
-		rtnl_unlock();
-		return -ENODEV;
-	}
 	ifindex = imr->imr_ifindex;
 	for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
-		if (iml->multi.imr_multiaddr.s_addr == group &&
-		    iml->multi.imr_ifindex == ifindex) {
-			(void) ip_mc_leave_src(sk, iml, in_dev);
+		if (iml->multi.imr_multiaddr.s_addr != group)
+			continue;
+		if (ifindex) {
+			if (iml->multi.imr_ifindex != ifindex)
+				continue;
+		} else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
+				iml->multi.imr_address.s_addr)
+			continue;
 
-			*imlp = iml->next;
+		(void) ip_mc_leave_src(sk, iml, in_dev);
 
+		*imlp = iml->next;
+
+		if (in_dev)
 			ip_mc_dec_group(in_dev, group);
-			rtnl_unlock();
-			sock_kfree_s(sk, iml, sizeof(*iml));
-			return 0;
-		}
+		rtnl_unlock();
+		sock_kfree_s(sk, iml, sizeof(*iml));
+		return 0;
 	}
+	if (!in_dev)
+		ret = -ENODEV;
 	rtnl_unlock();
-	return -EADDRNOTAVAIL;
+	return ret;
 }
 
 int ip_mc_source(int add, int omode, struct sock *sk, struct
@@ -2199,13 +2205,13 @@
 		struct in_device *in_dev;
 		inet->mc_list = iml->next;
 
-		if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) {
-			(void) ip_mc_leave_src(sk, iml, in_dev);
+		in_dev = inetdev_by_index(iml->multi.imr_ifindex);
+		(void) ip_mc_leave_src(sk, iml, in_dev);
+		if (in_dev != NULL) {
 			ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
 			in_dev_put(in_dev);
 		}
 		sock_kfree_s(sk, iml, sizeof(*iml));
-
 	}
 	rtnl_unlock();
 }
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 7c9f9a6..a2ede16 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -440,6 +440,7 @@
 	iph = skb->nh.iph;
 
 	if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
+		IP_INC_STATS(IPSTATS_MIB_FRAGFAILS);
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
 			  htonl(dst_mtu(&rt->u.dst)));
 		kfree_skb(skb);
@@ -526,6 +527,8 @@
 
 			err = output(skb);
 
+			if (!err)
+				IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
 			if (err || !frag)
 				break;
 
@@ -649,9 +652,6 @@
 		/*
 		 *	Put this fragment into the sending queue.
 		 */
-
-		IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
-
 		iph->tot_len = htons(len + hlen);
 
 		ip_send_check(iph);
@@ -659,6 +659,8 @@
 		err = output(skb2);
 		if (err)
 			goto fail;
+
+		IP_INC_STATS(IPSTATS_MIB_FRAGCREATES);
 	}
 	kfree_skb(skb);
 	IP_INC_STATS(IPSTATS_MIB_FRAGOKS);
@@ -946,7 +948,7 @@
 				skb_prev->csum = csum_sub(skb_prev->csum,
 							  skb->csum);
 				data += fraggap;
-				skb_trim(skb_prev, maxfraglen);
+				pskb_trim_unique(skb_prev, maxfraglen);
 			}
 
 			copy = datalen - transhdrlen - fraggap;
@@ -1141,7 +1143,7 @@
 					data, fraggap, 0);
 				skb_prev->csum = csum_sub(skb_prev->csum,
 							  skb->csum);
-				skb_trim(skb_prev, maxfraglen);
+				pskb_trim_unique(skb_prev, maxfraglen);
 			}
 
 			/*
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 84f43a3..2d05c41 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -112,14 +112,19 @@
 static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 {
 	char *secdata;
-	u32 seclen;
+	u32 seclen, secid;
 	int err;
 
-	err = security_socket_getpeersec_dgram(skb, &secdata, &seclen);
+	err = security_socket_getpeersec_dgram(NULL, skb, &secid);
+	if (err)
+		return;
+
+	err = security_secid_to_secctx(secid, &secdata, &seclen);
 	if (err)
 		return;
 
 	put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
+	security_release_secctx(secdata, seclen);
 }
 
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 80c73ca..8d1d7a6 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -236,7 +236,7 @@
 	struct arpt_entry *e, *back;
 	const char *indev, *outdev;
 	void *table_base;
-	struct xt_table_info *private = table->private;
+	struct xt_table_info *private;
 
 	/* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
 	if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
@@ -248,6 +248,7 @@
 	outdev = out ? out->name : nulldevname;
 
 	read_lock_bh(&table->lock);
+	private = table->private;
 	table_base = (void *)private->entries[smp_processor_id()];
 	e = get_entry(table_base, private->hook_entry[hook]);
 	back = get_entry(table_base, private->underflow[hook]);
@@ -1170,21 +1171,34 @@
 {
 	int ret;
 
-	xt_proto_init(NF_ARP);
+	ret = xt_proto_init(NF_ARP);
+	if (ret < 0)
+		goto err1;
 
 	/* Noone else will be downing sem now, so we won't sleep */
-	xt_register_target(&arpt_standard_target);
-	xt_register_target(&arpt_error_target);
+	ret = xt_register_target(&arpt_standard_target);
+	if (ret < 0)
+		goto err2;
+	ret = xt_register_target(&arpt_error_target);
+	if (ret < 0)
+		goto err3;
 
 	/* Register setsockopt */
 	ret = nf_register_sockopt(&arpt_sockopts);
-	if (ret < 0) {
-		duprintf("Unable to register sockopts.\n");
-		return ret;
-	}
+	if (ret < 0)
+		goto err4;
 
 	printk("arp_tables: (C) 2002 David S. Miller\n");
 	return 0;
+
+err4:
+	xt_unregister_target(&arpt_error_target);
+err3:
+	xt_unregister_target(&arpt_standard_target);
+err2:
+	xt_proto_fini(NF_ARP);
+err1:
+	return ret;
 }
 
 static void __exit arp_tables_fini(void)
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 33891bb..0d4cc92 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -415,21 +415,18 @@
 			cb->args[0], *id);
 
 	read_lock_bh(&ip_conntrack_lock);
+	last = (struct ip_conntrack *)cb->args[1];
 	for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
 restart:
-		last = (struct ip_conntrack *)cb->args[1];
 		list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
 			h = (struct ip_conntrack_tuple_hash *) i;
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = tuplehash_to_ctrack(h);
-			if (last != NULL) {
-				if (ct == last) {
-					ip_conntrack_put(last);
-					cb->args[1] = 0;
-					last = NULL;
-				} else
+			if (cb->args[1]) {
+				if (ct != last)
 					continue;
+				cb->args[1] = 0;
 			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
 		                        	cb->nlh->nlmsg_seq,
@@ -440,17 +437,17 @@
 				goto out;
 			}
 		}
-		if (last != NULL) {
-			ip_conntrack_put(last);
+		if (cb->args[1]) {
 			cb->args[1] = 0;
 			goto restart;
 		}
 	}
 out:
 	read_unlock_bh(&ip_conntrack_lock);
+	if (last)
+		ip_conntrack_put(last);
 
 	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
-
 	return skb->len;
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index fc87ce0..4f222d6 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -442,7 +442,7 @@
 		sip[i].tuple.src.u.udp.port = htons(ports[i]);
 		sip[i].mask.src.u.udp.port = 0xFFFF;
 		sip[i].mask.dst.protonum = 0xFF;
-		sip[i].max_expected = 1;
+		sip[i].max_expected = 2;
 		sip[i].timeout = 3 * 60; /* 3 minutes */
 		sip[i].me = THIS_MODULE;
 		sip[i].help = sip_help;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index fc5bdd5..048514f 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -230,7 +230,7 @@
 	const char *indev, *outdev;
 	void *table_base;
 	struct ipt_entry *e, *back;
-	struct xt_table_info *private = table->private;
+	struct xt_table_info *private;
 
 	/* Initialization */
 	ip = (*pskb)->nh.iph;
@@ -247,6 +247,7 @@
 
 	read_lock_bh(&table->lock);
 	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+	private = table->private;
 	table_base = (void *)private->entries[smp_processor_id()];
 	e = get_entry(table_base, private->hook_entry[hook]);
 
@@ -2239,22 +2240,39 @@
 {
 	int ret;
 
-	xt_proto_init(AF_INET);
+	ret = xt_proto_init(AF_INET);
+	if (ret < 0)
+		goto err1;
 
 	/* Noone else will be downing sem now, so we won't sleep */
-	xt_register_target(&ipt_standard_target);
-	xt_register_target(&ipt_error_target);
-	xt_register_match(&icmp_matchstruct);
+	ret = xt_register_target(&ipt_standard_target);
+	if (ret < 0)
+		goto err2;
+	ret = xt_register_target(&ipt_error_target);
+	if (ret < 0)
+		goto err3;
+	ret = xt_register_match(&icmp_matchstruct);
+	if (ret < 0)
+		goto err4;
 
 	/* Register setsockopt */
 	ret = nf_register_sockopt(&ipt_sockopts);
-	if (ret < 0) {
-		duprintf("Unable to register sockopts.\n");
-		return ret;
-	}
+	if (ret < 0)
+		goto err5;
 
 	printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
 	return 0;
+
+err5:
+	xt_unregister_match(&icmp_matchstruct);
+err4:
+	xt_unregister_target(&ipt_error_target);
+err3:
+	xt_unregister_target(&ipt_standard_target);
+err2:
+	xt_proto_fini(AF_INET);
+err1:
+	return ret;
 }
 
 static void __exit ip_tables_fini(void)
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index d7dd7fe..d46fd67 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -115,6 +115,11 @@
 		del_timer(&ub->timer);
 	}
 
+	if (!ub->skb) {
+		DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
+		return;
+	}
+
 	/* last nlmsg needs NLMSG_DONE */
 	if (ub->qlen > 1)
 		ub->lastnlh->nlmsg_type = NLMSG_DONE;
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 92980ab..3bd2368 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -454,15 +454,12 @@
 		dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
 							hinfo->cfg.burst);
 		dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
-
-		spin_unlock_bh(&hinfo->lock);
-		return 1;
+	} else {
+		/* update expiration timeout */
+		dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
+		rateinfo_recalc(dh, now);
 	}
 
-	/* update expiration timeout */
-	dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
-
-	rateinfo_recalc(dh, now);
 	if (dh->rateinfo.credit >= dh->rateinfo.cost) {
 		/* We're underlimit. */
 		dh->rateinfo.credit -= dh->rateinfo.cost;
@@ -508,6 +505,9 @@
 	if (!r->cfg.expire)
 		return 0;
 
+	if (r->name[sizeof(r->name) - 1] != '\0')
+		return 0;
+
 	/* This is the best we've got: We cannot release and re-grab lock,
 	 * since checkentry() is called before ip_tables.c grabs ipt_mutex.  
 	 * We also cannot grab the hashtable spinlock, since htable_create will 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2dc6dbb..b873cbc 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -104,6 +104,7 @@
 #include <net/icmp.h>
 #include <net/xfrm.h>
 #include <net/ip_mp_alg.h>
+#include <net/netevent.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -1125,6 +1126,7 @@
 	struct rtable *rth, **rthp;
 	u32  skeys[2] = { saddr, 0 };
 	int  ikeys[2] = { dev->ifindex, 0 };
+	struct netevent_redirect netevent;
 
 	if (!in_dev)
 		return;
@@ -1216,6 +1218,11 @@
 					rt_drop(rt);
 					goto do_next;
 				}
+				
+				netevent.old = &rth->u.dst;
+				netevent.new = &rt->u.dst;
+				call_netevent_notifiers(NETEVENT_REDIRECT, 
+						        &netevent);
 
 				rt_del(hash, rth);
 				if (!rt_intern_hash(hash, rt, &rt))
@@ -1452,6 +1459,7 @@
 		}
 		dst->metrics[RTAX_MTU-1] = mtu;
 		dst_set_expires(dst, ip_rt_mtu_expires);
+		call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
 	}
 }
 
@@ -3149,7 +3157,7 @@
 					rhash_entries,
 					(num_physpages >= 128 * 1024) ?
 					15 : 17,
-					HASH_HIGHMEM,
+					0,
 					&rt_hash_log,
 					&rt_hash_mask,
 					0);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f6a2d92..934396b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1132,7 +1132,7 @@
 	tp->ucopy.dma_chan = NULL;
 	preempt_disable();
 	if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
-	    !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) {
+	    !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) {
 		preempt_enable_no_resched();
 		tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
 	} else
@@ -1659,7 +1659,8 @@
 			const int tmo = tcp_fin_time(sk);
 
 			if (tmo > TCP_TIMEWAIT_LEN) {
-				inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk));
+				inet_csk_reset_keepalive_timer(sk,
+						tmo - TCP_TIMEWAIT_LEN);
 			} else {
 				tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);
 				goto out;
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 5765f9d..7ff2e4273 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -189,7 +189,7 @@
 			return;
 
 		/* We MAY increase by 2 if discovered delayed ack */
-		if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) {
+		if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) {
 			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
 				tp->snd_cwnd++;
 		}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 738dad9..111ff39 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2505,8 +2505,13 @@
 	if (before(ack, prior_snd_una))
 		goto old_ack;
 
-	if (sysctl_tcp_abc && icsk->icsk_ca_state < TCP_CA_CWR)
-		tp->bytes_acked += ack - prior_snd_una;
+	if (sysctl_tcp_abc) {
+		if (icsk->icsk_ca_state < TCP_CA_CWR)
+			tp->bytes_acked += ack - prior_snd_una;
+		else if (icsk->icsk_ca_state == TCP_CA_Loss)
+			/* we assume just one segment left network */
+			tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache);
+	}
 
 	if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
 		/* Window is constant, pure forward advance.
@@ -3541,7 +3546,8 @@
 	if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open &&
 	    sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
 		/* Limited by application or receiver window. */
-		u32 win_used = max(tp->snd_cwnd_used, 2U);
+		u32 init_win = tcp_init_cwnd(tp, __sk_dst_get(sk));
+		u32 win_used = max(tp->snd_cwnd_used, init_win);
 		if (win_used < tp->snd_cwnd) {
 			tp->snd_ssthresh = tcp_current_ssthresh(sk);
 			tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f6f39e8..4b04c3e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -438,7 +438,6 @@
 			       It can f.e. if SYNs crossed.
 			     */
 		if (!sock_owned_by_user(sk)) {
-			TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 			sk->sk_err = err;
 
 			sk->sk_error_report(sk);
@@ -874,7 +873,6 @@
 drop_and_free:
 	reqsk_free(req);
 drop:
-	TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 	return 0;
 }
 
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 0ccb7cb..624e2b2 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -589,8 +589,10 @@
 		/* RFC793: "second check the RST bit" and
 		 *	   "fourth, check the SYN bit"
 		 */
-		if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN))
+		if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) {
+			TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 			goto embryonic_reset;
+		}
 
 		/* ACK sequence verified above, just make sure ACK is
 		 * set.  If ACK not set, just silently drop the packet.
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5c08ea2..b4f3ffe 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -201,6 +201,7 @@
 		 * See RFC1323 for an explanation of the limit to 14 
 		 */
 		space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
+		space = min_t(u32, space, *window_clamp);
 		while (space > 65535 && (*rcv_wscale) < 14) {
 			space >>= 1;
 			(*rcv_wscale)++;
@@ -466,7 +467,8 @@
 	if (skb->len != tcp_header_size)
 		tcp_event_data_sent(tp, skb, sk);
 
-	TCP_INC_STATS(TCP_MIB_OUTSEGS);
+	if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
+		TCP_INC_STATS(TCP_MIB_OUTSEGS);
 
 	err = icsk->icsk_af_ops->queue_xmit(skb, 0);
 	if (likely(err <= 0))
@@ -2157,10 +2159,9 @@
 	skb_shinfo(buff)->gso_size = 0;
 	skb_shinfo(buff)->gso_type = 0;
 	buff->csum = 0;
+	tp->snd_nxt = tp->write_seq;
 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
-	tp->snd_nxt = tp->write_seq;
-	tp->pushed_seq = tp->write_seq;
 
 	/* Send it off. */
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
@@ -2170,6 +2171,12 @@
 	sk_charge_skb(sk, buff);
 	tp->packets_out += tcp_skb_pcount(buff);
 	tcp_transmit_skb(sk, buff, 1, GFP_KERNEL);
+
+	/* We change tp->snd_nxt after the tcp_transmit_skb() call
+	 * in order to make this packet get counted in tcpOutSegs.
+	 */
+	tp->snd_nxt = tp->write_seq;
+	tp->pushed_seq = tp->write_seq;
 	TCP_INC_STATS(TCP_MIB_ACTIVEOPENS);
 
 	/* Timer for repeating the SYN until an answer. */
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index d7d517a..dab37d2 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -114,7 +114,7 @@
 static ssize_t tcpprobe_read(struct file *file, char __user *buf,
 			     size_t len, loff_t *ppos)
 {
-	int error = 0, cnt;
+	int error = 0, cnt = 0;
 	unsigned char *tbuf;
 
 	if (!buf || len < 0)
@@ -130,11 +130,12 @@
 	error = wait_event_interruptible(tcpw.wait,
 					 __kfifo_len(tcpw.fifo) != 0);
 	if (error)
-		return error;
+		goto out_free;
 
 	cnt = kfifo_get(tcpw.fifo, tbuf, len);
 	error = copy_to_user(buf, tbuf, cnt);
 
+out_free:
 	vfree(tbuf);
 
 	return error ? error : cnt;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 2316a43..c7852b3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -578,6 +578,8 @@
 	ifa->flags = flags | IFA_F_TENTATIVE;
 	ifa->cstamp = ifa->tstamp = jiffies;
 
+	ifa->rt = rt;
+
 	ifa->idev = idev;
 	in6_dev_hold(idev);
 	/* For caller */
@@ -603,8 +605,6 @@
 	}
 #endif
 
-	ifa->rt = rt;
-
 	in6_ifa_hold(ifa);
 	write_unlock(&idev->lock);
 out2:
@@ -1869,15 +1869,21 @@
 /*
  *	Manual configuration of address on an interface
  */
-static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
+static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen,
+			  __u32 prefered_lft, __u32 valid_lft)
 {
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
 	struct net_device *dev;
+	__u8 ifa_flags = 0;
 	int scope;
 
 	ASSERT_RTNL();
 	
+	/* check the lifetime */
+	if (!valid_lft || prefered_lft > valid_lft)
+		return -EINVAL;
+
 	if ((dev = __dev_get_by_index(ifindex)) == NULL)
 		return -ENODEV;
 	
@@ -1889,10 +1895,29 @@
 
 	scope = ipv6_addr_scope(pfx);
 
-	ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT);
+	if (valid_lft == INFINITY_LIFE_TIME)
+		ifa_flags |= IFA_F_PERMANENT;
+	else if (valid_lft >= 0x7FFFFFFF/HZ)
+		valid_lft = 0x7FFFFFFF/HZ;
+
+	if (prefered_lft == 0)
+		ifa_flags |= IFA_F_DEPRECATED;
+	else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+		 (prefered_lft != INFINITY_LIFE_TIME))
+		prefered_lft = 0x7FFFFFFF/HZ;
+
+	ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags);
+
 	if (!IS_ERR(ifp)) {
+		spin_lock_bh(&ifp->lock);
+		ifp->valid_lft = valid_lft;
+		ifp->prefered_lft = prefered_lft;
+		ifp->tstamp = jiffies;
+		spin_unlock_bh(&ifp->lock);
+
 		addrconf_dad_start(ifp, 0);
 		in6_ifa_put(ifp);
+		addrconf_verify(0);
 		return 0;
 	}
 
@@ -1945,7 +1970,8 @@
 		return -EFAULT;
 
 	rtnl_lock();
-	err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen);
+	err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen,
+			     INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
 	rtnl_unlock();
 	return err;
 }
@@ -2771,12 +2797,16 @@
 					ifp->idev->nd_parms->retrans_time / HZ;
 #endif
 
-			if (age >= ifp->valid_lft) {
+			if (ifp->valid_lft != INFINITY_LIFE_TIME &&
+			    age >= ifp->valid_lft) {
 				spin_unlock(&ifp->lock);
 				in6_ifa_hold(ifp);
 				read_unlock(&addrconf_hash_lock);
 				ipv6_del_addr(ifp);
 				goto restart;
+			} else if (ifp->prefered_lft == INFINITY_LIFE_TIME) {
+				spin_unlock(&ifp->lock);
+				continue;
 			} else if (age >= ifp->prefered_lft) {
 				/* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
 				int deprecate = 0;
@@ -2853,7 +2883,8 @@
 		pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
 	}
 	if (rta[IFA_LOCAL-1]) {
-		if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+		if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+		    (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
 			return -EINVAL;
 		pfx = RTA_DATA(rta[IFA_LOCAL-1]);
 	}
@@ -2864,11 +2895,61 @@
 }
 
 static int
+inet6_addr_modify(int ifindex, struct in6_addr *pfx,
+		  __u32 prefered_lft, __u32 valid_lft)
+{
+	struct inet6_ifaddr *ifp = NULL;
+	struct net_device *dev;
+	int ifa_flags = 0;
+
+	if ((dev = __dev_get_by_index(ifindex)) == NULL)
+		return -ENODEV;
+
+	if (!(dev->flags&IFF_UP))
+		return -ENETDOWN;
+
+	if (!valid_lft || (prefered_lft > valid_lft))
+		return -EINVAL;
+
+	ifp = ipv6_get_ifaddr(pfx, dev, 1);
+	if (ifp == NULL)
+		return -ENOENT;
+
+	if (valid_lft == INFINITY_LIFE_TIME)
+		ifa_flags = IFA_F_PERMANENT;
+	else if (valid_lft >= 0x7FFFFFFF/HZ)
+		valid_lft = 0x7FFFFFFF/HZ;
+
+	if (prefered_lft == 0)
+		ifa_flags = IFA_F_DEPRECATED;
+	else if ((prefered_lft >= 0x7FFFFFFF/HZ) &&
+		 (prefered_lft != INFINITY_LIFE_TIME))
+		prefered_lft = 0x7FFFFFFF/HZ;
+
+	spin_lock_bh(&ifp->lock);
+	ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags;
+
+	ifp->tstamp = jiffies;
+	ifp->valid_lft = valid_lft;
+	ifp->prefered_lft = prefered_lft;
+
+	spin_unlock_bh(&ifp->lock);
+	if (!(ifp->flags&IFA_F_TENTATIVE))
+		ipv6_ifa_notify(0, ifp);
+	in6_ifa_put(ifp);
+
+	addrconf_verify(0);
+
+	return 0;
+}
+
+static int
 inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct rtattr  **rta = arg;
 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 	struct in6_addr *pfx;
+	__u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME;
 
 	pfx = NULL;
 	if (rta[IFA_ADDRESS-1]) {
@@ -2877,14 +2958,34 @@
 		pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
 	}
 	if (rta[IFA_LOCAL-1]) {
-		if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))
+		if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
+		    (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
 			return -EINVAL;
 		pfx = RTA_DATA(rta[IFA_LOCAL-1]);
 	}
 	if (pfx == NULL)
 		return -EINVAL;
 
-	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
+	if (rta[IFA_CACHEINFO-1]) {
+		struct ifa_cacheinfo *ci;
+		if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci))
+			return -EINVAL;
+		ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
+		valid_lft = ci->ifa_valid;
+		prefered_lft = ci->ifa_prefered;
+	}
+
+	if (nlh->nlmsg_flags & NLM_F_REPLACE) {
+		int ret;
+		ret = inet6_addr_modify(ifm->ifa_index, pfx,
+					prefered_lft, valid_lft);
+		if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
+			return ret;
+	}
+
+	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
+			      prefered_lft, valid_lft);
+
 }
 
 /* Maximum length of ifa_cacheinfo attributes */
@@ -3121,6 +3222,62 @@
 	return inet6_dump_addr(skb, cb, type);
 }
 
+static int inet6_rtm_getaddr(struct sk_buff *in_skb,
+		struct nlmsghdr* nlh, void *arg)
+{
+	struct rtattr **rta = arg;
+	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+	struct in6_addr *addr = NULL;
+	struct net_device *dev = NULL;
+	struct inet6_ifaddr *ifa;
+	struct sk_buff *skb;
+	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
+	int err;
+
+	if (rta[IFA_ADDRESS-1]) {
+		if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr))
+			return -EINVAL;
+		addr = RTA_DATA(rta[IFA_ADDRESS-1]);
+	}
+	if (rta[IFA_LOCAL-1]) {
+		if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) ||
+		    (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr))))
+			return -EINVAL;
+		addr = RTA_DATA(rta[IFA_LOCAL-1]);
+	}
+	if (addr == NULL)
+		return -EINVAL;
+
+	if (ifm->ifa_index)
+		dev = __dev_get_by_index(ifm->ifa_index);
+
+	if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL)
+		return -EADDRNOTAVAIL;
+
+	if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) {
+		err = -ENOBUFS;
+		goto out;
+	}
+
+	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
+	err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
+				nlh->nlmsg_seq, RTM_NEWADDR, 0);
+	if (err < 0) {
+		err = -EMSGSIZE;
+		goto out_free;
+	}
+
+	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
+	if (err > 0)
+		err = 0;
+out:
+	in6_ifa_put(ifa);
+	return err;
+out_free:
+	kfree_skb(skb);
+	goto out;
+}
+
 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 {
 	struct sk_buff *skb;
@@ -3363,7 +3520,8 @@
 	[RTM_GETLINK - RTM_BASE] = { .dumpit	= inet6_dump_ifinfo, },
 	[RTM_NEWADDR - RTM_BASE] = { .doit	= inet6_rtm_newaddr, },
 	[RTM_DELADDR - RTM_BASE] = { .doit	= inet6_rtm_deladdr, },
-	[RTM_GETADDR - RTM_BASE] = { .dumpit	= inet6_dump_ifaddr, },
+	[RTM_GETADDR - RTM_BASE] = { .doit	= inet6_rtm_getaddr,
+				     .dumpit	= inet6_dump_ifaddr, },
 	[RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, },
 	[RTM_GETANYCAST - RTM_BASE] = { .dumpit	= inet6_dump_ifacaddr, },
 	[RTM_NEWROUTE - RTM_BASE] = { .doit	= inet6_rtm_newroute, },
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 5a0ba58..ac85e9c 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -658,7 +658,7 @@
 			return err;
 		}
 
-		ip6_dst_store(sk, dst, NULL);
+		__ip6_dst_store(sk, dst, NULL);
 	}
 
 	return 0;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 9d0ee7f..86dac10 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -635,14 +635,17 @@
 	struct ipv6_txoptions *opt2;
 	int err;
 
-	if (newtype != IPV6_HOPOPTS && opt->hopopt)
-		tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
-	if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
-		tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
-	if (newtype != IPV6_RTHDR && opt->srcrt)
-		tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
-	if (newtype != IPV6_DSTOPTS && opt->dst1opt)
-		tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
+	if (opt) {
+		if (newtype != IPV6_HOPOPTS && opt->hopopt)
+			tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
+		if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
+			tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
+		if (newtype != IPV6_RTHDR && opt->srcrt)
+			tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
+		if (newtype != IPV6_DSTOPTS && opt->dst1opt)
+			tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
+	}
+
 	if (newopt && newoptlen)
 		tot_len += CMSG_ALIGN(newoptlen);
 
@@ -659,25 +662,25 @@
 	opt2->tot_len = tot_len;
 	p = (char *)(opt2 + 1);
 
-	err = ipv6_renew_option(opt->hopopt, newopt, newoptlen,
+	err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen,
 				newtype != IPV6_HOPOPTS,
 				&opt2->hopopt, &p);
 	if (err)
 		goto out;
 
-	err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen,
+	err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen,
 				newtype != IPV6_RTHDRDSTOPTS,
 				&opt2->dst0opt, &p);
 	if (err)
 		goto out;
 
-	err = ipv6_renew_option(opt->srcrt, newopt, newoptlen,
+	err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen,
 				newtype != IPV6_RTHDR,
-				(struct ipv6_opt_hdr **)opt2->srcrt, &p);
+				(struct ipv6_opt_hdr **)&opt2->srcrt, &p);
 	if (err)
 		goto out;
 
-	err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen,
+	err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen,
 				newtype != IPV6_DSTOPTS,
 				&opt2->dst1opt, &p);
 	if (err)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 1044b6f..3d6e9a3 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -712,6 +712,11 @@
 	return 0;
 }
 
+/*
+ * Special lock-class for __icmpv6_socket:
+ */
+static struct lock_class_key icmpv6_socket_sk_dst_lock_key;
+
 int __init icmpv6_init(struct net_proto_family *ops)
 {
 	struct sock *sk;
@@ -730,6 +735,14 @@
 
 		sk = per_cpu(__icmpv6_socket, i)->sk;
 		sk->sk_allocation = GFP_ATOMIC;
+		/*
+		 * Split off their lock-class, because sk->sk_dst_lock
+		 * gets used from softirqs, which is safe for
+		 * __icmpv6_socket (because those never get directly used
+		 * via userspace syscalls), but unsafe for normal sockets.
+		 */
+		lockdep_set_class(&sk->sk_dst_lock,
+				  &icmpv6_socket_sk_dst_lock_key);
 
 		/* Enough space for 2 64K ICMP packets, including
 		 * sk_buff struct overhead.
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 5c950cc..bf49107 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -185,7 +185,7 @@
 			return err;
 		}
 
-		ip6_dst_store(sk, dst, NULL);
+		__ip6_dst_store(sk, dst, NULL);
 	}
 
 	skb->dst = dst_clone(dst);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3bc74ce..4fb47a2 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -356,6 +356,7 @@
 		skb->dev = dst->dev;
 		icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
 			    0, skb->dev);
+		IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
 
 		kfree_skb(skb);
 		return -ETIMEDOUT;
@@ -595,6 +596,9 @@
 			}
 			
 			err = output(skb);
+			if(!err)
+				IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
+
 			if (err || !frag)
 				break;
 
@@ -706,12 +710,11 @@
 		/*
 		 *	Put this fragment into the sending queue.
 		 */
-
-		IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
-
 		err = output(frag);
 		if (err)
 			goto fail;
+
+		IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
 	}
 	kfree_skb(skb);
 	IP6_INC_STATS(IPSTATS_MIB_FRAGOKS);
@@ -723,48 +726,51 @@
 	return err;
 }
 
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
+					  struct dst_entry *dst,
+					  struct flowi *fl)
 {
-	int err = 0;
+	struct ipv6_pinfo *np = inet6_sk(sk);
+	struct rt6_info *rt = (struct rt6_info *)dst;
 
-	*dst = NULL;
-	if (sk) {
-		struct ipv6_pinfo *np = inet6_sk(sk);
-	
-		*dst = sk_dst_check(sk, np->dst_cookie);
-		if (*dst) {
-			struct rt6_info *rt = (struct rt6_info*)*dst;
-	
-			/* Yes, checking route validity in not connected
-			 * case is not very simple. Take into account,
-			 * that we do not support routing by source, TOS,
-			 * and MSG_DONTROUTE 		--ANK (980726)
-			 *
-			 * 1. If route was host route, check that
-			 *    cached destination is current.
-			 *    If it is network route, we still may
-			 *    check its validity using saved pointer
-			 *    to the last used address: daddr_cache.
-			 *    We do not want to save whole address now,
-			 *    (because main consumer of this service
-			 *    is tcp, which has not this problem),
-			 *    so that the last trick works only on connected
-			 *    sockets.
-			 * 2. oif also should be the same.
-			 */
-			if (((rt->rt6i_dst.plen != 128 ||
-			      !ipv6_addr_equal(&fl->fl6_dst,
-					       &rt->rt6i_dst.addr))
-			     && (np->daddr_cache == NULL ||
-				 !ipv6_addr_equal(&fl->fl6_dst,
-						  np->daddr_cache)))
-			    || (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
-				dst_release(*dst);
-				*dst = NULL;
-			}
-		}
+	if (!dst)
+		goto out;
+
+	/* Yes, checking route validity in not connected
+	 * case is not very simple. Take into account,
+	 * that we do not support routing by source, TOS,
+	 * and MSG_DONTROUTE 		--ANK (980726)
+	 *
+	 * 1. If route was host route, check that
+	 *    cached destination is current.
+	 *    If it is network route, we still may
+	 *    check its validity using saved pointer
+	 *    to the last used address: daddr_cache.
+	 *    We do not want to save whole address now,
+	 *    (because main consumer of this service
+	 *    is tcp, which has not this problem),
+	 *    so that the last trick works only on connected
+	 *    sockets.
+	 * 2. oif also should be the same.
+	 */
+	if (((rt->rt6i_dst.plen != 128 ||
+	      !ipv6_addr_equal(&fl->fl6_dst, &rt->rt6i_dst.addr))
+	     && (np->daddr_cache == NULL ||
+		 !ipv6_addr_equal(&fl->fl6_dst, np->daddr_cache)))
+	    || (fl->oif && fl->oif != dst->dev->ifindex)) {
+		dst_release(dst);
+		dst = NULL;
 	}
 
+out:
+	return dst;
+}
+
+static int ip6_dst_lookup_tail(struct sock *sk,
+			       struct dst_entry **dst, struct flowi *fl)
+{
+	int err;
+
 	if (*dst == NULL)
 		*dst = ip6_route_output(sk, fl);
 
@@ -773,7 +779,6 @@
 
 	if (ipv6_addr_any(&fl->fl6_src)) {
 		err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
-
 		if (err)
 			goto out_err_release;
 	}
@@ -786,8 +791,48 @@
 	return err;
 }
 
+/**
+ *	ip6_dst_lookup - perform route lookup on flow
+ *	@sk: socket which provides route info
+ *	@dst: pointer to dst_entry * for result
+ *	@fl: flow to lookup
+ *
+ *	This function performs a route lookup on the given flow.
+ *
+ *	It returns zero on success, or a standard errno code on error.
+ */
+int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+{
+	*dst = NULL;
+	return ip6_dst_lookup_tail(sk, dst, fl);
+}
 EXPORT_SYMBOL_GPL(ip6_dst_lookup);
 
+/**
+ *	ip6_sk_dst_lookup - perform socket cached route lookup on flow
+ *	@sk: socket which provides the dst cache and route info
+ *	@dst: pointer to dst_entry * for result
+ *	@fl: flow to lookup
+ *
+ *	This function performs a route lookup on the given flow with the
+ *	possibility of using the cached route in the socket if it is valid.
+ *	It will take the socket dst lock when operating on the dst cache.
+ *	As a result, this function can only be used in process context.
+ *
+ *	It returns zero on success, or a standard errno code on error.
+ */
+int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+{
+	*dst = NULL;
+	if (sk) {
+		*dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
+		*dst = ip6_sk_dst_check(sk, *dst, fl);
+	}
+
+	return ip6_dst_lookup_tail(sk, dst, fl);
+}
+EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup);
+
 static inline int ip6_ufo_append_data(struct sock *sk,
 			int getfrag(void *from, char *to, int offset, int len,
 			int odd, struct sk_buff *skb),
@@ -1050,7 +1095,7 @@
 				skb_prev->csum = csum_sub(skb_prev->csum,
 							  skb->csum);
 				data += fraggap;
-				skb_trim(skb_prev, maxfraglen);
+				pskb_trim_unique(skb_prev, maxfraglen);
 			}
 			copy = datalen - transhdrlen - fraggap;
 			if (copy < 0) {
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 9d697d4..639eb20 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -268,13 +268,14 @@
 			if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
 				struct inet6_dev *idev = in6_dev_get(dev);
 
+				(void) ip6_mc_leave_src(sk, mc_lst, idev);
 				if (idev) {
-					(void) ip6_mc_leave_src(sk,mc_lst,idev);
 					__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 					in6_dev_put(idev);
 				}
 				dev_put(dev);
-			}
+			} else
+				(void) ip6_mc_leave_src(sk, mc_lst, NULL);
 			sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 			return 0;
 		}
@@ -334,13 +335,14 @@
 		if (dev) {
 			struct inet6_dev *idev = in6_dev_get(dev);
 
+			(void) ip6_mc_leave_src(sk, mc_lst, idev);
 			if (idev) {
-				(void) ip6_mc_leave_src(sk, mc_lst, idev);
 				__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 				in6_dev_put(idev);
 			}
 			dev_put(dev);
-		}
+		} else
+			(void) ip6_mc_leave_src(sk, mc_lst, NULL);
 
 		sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index f26898b..c9d6b23 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1398,23 +1398,39 @@
 {
 	int ret;
 
-	xt_proto_init(AF_INET6);
+	ret = xt_proto_init(AF_INET6);
+	if (ret < 0)
+		goto err1;
 
 	/* Noone else will be downing sem now, so we won't sleep */
-	xt_register_target(&ip6t_standard_target);
-	xt_register_target(&ip6t_error_target);
-	xt_register_match(&icmp6_matchstruct);
+	ret = xt_register_target(&ip6t_standard_target);
+	if (ret < 0)
+		goto err2;
+	ret = xt_register_target(&ip6t_error_target);
+	if (ret < 0)
+		goto err3;
+	ret = xt_register_match(&icmp6_matchstruct);
+	if (ret < 0)
+		goto err4;
 
 	/* Register setsockopt */
 	ret = nf_register_sockopt(&ip6t_sockopts);
-	if (ret < 0) {
-		duprintf("Unable to register sockopts.\n");
-		xt_proto_fini(AF_INET6);
-		return ret;
-	}
+	if (ret < 0)
+		goto err5;
 
 	printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
 	return 0;
+
+err5:
+	xt_unregister_match(&icmp6_matchstruct);
+err4:
+	xt_unregister_target(&ip6t_error_target);
+err3:
+	xt_unregister_target(&ip6t_standard_target);
+err2:
+	xt_proto_fini(AF_INET6);
+err1:
+	return ret;
 }
 
 static void __exit ip6_tables_fini(void)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 87c39c9..d9baca0 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -53,6 +53,7 @@
 #include <linux/rtnetlink.h>
 #include <net/dst.h>
 #include <net/xfrm.h>
+#include <net/netevent.h>
 
 #include <asm/uaccess.h>
 
@@ -742,6 +743,7 @@
 			dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
 		}
 		dst->metrics[RTAX_MTU-1] = mtu;
+		call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
 	}
 }
 
@@ -1155,6 +1157,7 @@
 	struct rt6_info *rt, *nrt = NULL;
 	int strict;
 	struct fib6_node *fn;
+	struct netevent_redirect netevent;
 
 	/*
 	 * Get the "current" route for this destination and
@@ -1252,6 +1255,10 @@
 	if (ip6_ins_rt(nrt, NULL, NULL, NULL))
 		goto out;
 
+	netevent.old = &rt->u.dst;
+	netevent.new = &nrt->u.dst;
+	call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
+
 	if (rt->rt6i_flags&RTF_CACHE) {
 		ip6_del_rt(rt, NULL, NULL, NULL);
 		return;
@@ -1525,6 +1532,10 @@
 
 static int ip6_pkt_discard(struct sk_buff *skb)
 {
+	int type = ipv6_addr_type(&skb->nh.ipv6h->daddr);
+	if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED)
+		IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS);
+
 	IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
 	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev);
 	kfree_skb(skb);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 923989d..802a1a6 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -270,7 +270,7 @@
 	inet->rcv_saddr = LOOPBACK4_IPV6;
 
 	sk->sk_gso_type = SKB_GSO_TCPV6;
-	ip6_dst_store(sk, dst, NULL);
+	__ip6_dst_store(sk, dst, NULL);
 
 	icsk->icsk_ext_hdr_len = 0;
 	if (np->opt)
@@ -427,7 +427,6 @@
 	case TCP_SYN_RECV:  /* Cannot happen.
 			       It can, it SYNs are crossed. --ANK */ 
 		if (!sock_owned_by_user(sk)) {
-			TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 			sk->sk_err = err;
 			sk->sk_error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
 
@@ -831,7 +830,6 @@
 	if (req)
 		reqsk_free(req);
 
-	TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 	return 0; /* don't send reset */
 }
 
@@ -946,8 +944,8 @@
 	 * comment in that function for the gory details. -acme
 	 */
 
-	sk->sk_gso_type = SKB_GSO_TCPV6;
-	ip6_dst_store(newsk, dst, NULL);
+	newsk->sk_gso_type = SKB_GSO_TCPV6;
+	__ip6_dst_store(newsk, dst, NULL);
 
 	newtcp6sk = (struct tcp6_sock *)newsk;
 	inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index ccc57f4..3d54f24 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -782,7 +782,7 @@
 		connected = 0;
 	}
 
-	err = ip6_dst_lookup(sk, &dst, fl);
+	err = ip6_sk_dst_lookup(sk, &dst, fl);
 	if (err)
 		goto out;
 	if (final_p)
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 0eea60e..c8c8b44 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -125,7 +125,7 @@
 	if (!skb_is_gso(skb))
 		return xfrm6_output_finish2(skb);
 
-	skb->protocol = htons(ETH_P_IP);
+	skb->protocol = htons(ETH_P_IPV6);
 	segs = skb_gso_segment(skb, 0);
 	kfree_skb(skb);
 	if (unlikely(IS_ERR(segs)))
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index aa34ff4..bef3f61 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1642,13 +1642,17 @@
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto out;
 
-	ipx		= ipx_hdr(skb);
-	ipx_pktsize	= ntohs(ipx->ipx_pktsize);
+	if (!pskb_may_pull(skb, sizeof(struct ipxhdr)))
+		goto drop;
+
+	ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize);
 	
 	/* Too small or invalid header? */
-	if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
+	if (ipx_pktsize < sizeof(struct ipxhdr) ||
+	    !pskb_may_pull(skb, ipx_pktsize))
 		goto drop;
                         
+	ipx = ipx_hdr(skb);
 	if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
 	   ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
 		goto drop;
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c
index d504eed..7e6bc41 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -238,11 +238,13 @@
 		goto out_put;
 
 	if (lapb->state == LAPB_STATE_0) {
-		if (((parms->mode & LAPB_EXTENDED) &&
-		     (parms->window < 1 || parms->window > 127)) ||
-		    (parms->window < 1 || parms->window > 7))
-			goto out_put;
-
+		if (parms->mode & LAPB_EXTENDED) {
+			if (parms->window < 1 || parms->window > 127)
+				goto out_put;
+		} else {
+			if (parms->window < 1 || parms->window > 7)
+				goto out_put;
+		}
 		lapb->mode    = parms->mode;
 		lapb->window  = parms->window;
 	}
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index d6cfe84..2652ead 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -784,24 +784,20 @@
 		copied += used;
 		len -= used;
 
-		if (used + offset < skb->len)
-			continue;
-
 		if (!(flags & MSG_PEEK)) {
 			sk_eat_skb(sk, skb, 0);
 			*seq = 0;
 		}
+
+		/* For non stream protcols we get one packet per recvmsg call */
+		if (sk->sk_type != SOCK_STREAM)
+			goto copy_uaddr;
+
+		/* Partial read */
+		if (used + offset < skb->len)
+			continue;
 	} while (len > 0);
 
-	/* 
-	 * According to UNIX98, msg_name/msg_namelen are ignored
-	 * on connected socket. -ANK
-	 * But... af_llc still doesn't have separate sets of methods for
-	 * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will
-	 * eventually fix this tho :-) -acme
-	 */
-	if (sk->sk_type == SOCK_DGRAM)
-		goto copy_uaddr;
 out:
 	release_sock(sk);
 	return copied;
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 20c4eb5..61cb8cf 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -51,10 +51,10 @@
 {
 	struct sockaddr_llc *addr;
 
-	if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
-		return;
        /* save primitive for use by the user. */
 	addr		  = llc_ui_skb_cb(skb);
+
+	memset(addr, 0, sizeof(*addr));
 	addr->sllc_family = sk->sk_family;
 	addr->sllc_arphrd = skb->dev->type;
 	addr->sllc_test   = prim == LLC_TEST_PRIM;
@@ -330,6 +330,9 @@
 		if (llc->laddr.lsap != laddr->lsap)
 			continue;
 
+		if (llc->dev != skb->dev)
+			continue;
+
 		skb1 = skb_clone(skb, GFP_ATOMIC);
 		if (!skb1)
 			break;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index af48459..6527d4e 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -429,9 +429,9 @@
 			cb->args[0], *id);
 
 	read_lock_bh(&nf_conntrack_lock);
+	last = (struct nf_conn *)cb->args[1];
 	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
 restart:
-		last = (struct nf_conn *)cb->args[1];
 		list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
 			h = (struct nf_conntrack_tuple_hash *) i;
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
@@ -442,13 +442,10 @@
 			 * then dump everything. */
 			if (l3proto && L3PROTO(ct) != l3proto)
 				continue;
-			if (last != NULL) {
-				if (ct == last) {
-					nf_ct_put(last);
-					cb->args[1] = 0;
-					last = NULL;
-				} else
+			if (cb->args[1]) {
+				if (ct != last)
 					continue;
+				cb->args[1] = 0;
 			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
 		                        	cb->nlh->nlmsg_seq,
@@ -459,17 +456,17 @@
 				goto out;
 			}
 		}
-		if (last != NULL) {
-			nf_ct_put(last);
+		if (cb->args[1]) {
 			cb->args[1] = 0;
 			goto restart;
 		}
 	}
 out:
 	read_unlock_bh(&nf_conntrack_lock);
+	if (last)
+		nf_ct_put(last);
 
 	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
-
 	return skb->len;
 }
 
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 61cdda4..b59d3b2 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -366,6 +366,9 @@
 	if (timer_pending(&inst->timer))
 		del_timer(&inst->timer);
 
+	if (!inst->skb)
+		return 0;
+
 	if (inst->qlen > 1)
 		inst->lastnlh->nlmsg_type = NLMSG_DONE;
 
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index c2ce9c4..de9537a 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -57,6 +57,8 @@
 {
 	int err;
 	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
+	
+	sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0';
 
 	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
 	if (err) {
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index a9f4f6f..63a9654 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -10,6 +10,7 @@
 
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter/xt_physdev.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_bridge.h>
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 0ebb6ac..275330f 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -37,7 +37,7 @@
 
 	return (skb_find_text((struct sk_buff *)skb, conf->from_offset, 
 			     conf->to_offset, conf->config, &state) 
-			     != UINT_MAX) && !conf->invert;
+			     != UINT_MAX) ^ conf->invert;
 }
 
 #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
@@ -55,7 +55,10 @@
 	/* Damn, can't handle this case properly with iptables... */
 	if (conf->from_offset > conf->to_offset)
 		return 0;
-
+	if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
+	    	return 0;
+	if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
+		return 0;
 	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
 				     GFP_KERNEL, TS_AUTOLOAD);
 	if (IS_ERR(ts_conf))
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index b85c1f9..8b85036 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1273,8 +1273,7 @@
 	struct netlink_sock *nlk;
 	unsigned long *listeners = NULL;
 
-	if (!nl_table)
-		return NULL;
+	BUG_ON(!nl_table);
 
 	if (unit<0 || unit>=MAX_LINKS)
 		return NULL;
@@ -1745,11 +1744,8 @@
 		netlink_skb_parms_too_large();
 
 	nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
-	if (!nl_table) {
-enomem:
-		printk(KERN_CRIT "netlink_init: Cannot allocate nl_table\n");
-		return -ENOMEM;
-	}
+	if (!nl_table)
+		goto panic;
 
 	if (num_physpages >= (128 * 1024))
 		max = num_physpages >> (21 - PAGE_SHIFT);
@@ -1769,7 +1765,7 @@
 				nl_pid_hash_free(nl_table[i].hash.table,
 						 1 * sizeof(*hash->table));
 			kfree(nl_table);
-			goto enomem;
+			goto panic;
 		}
 		memset(hash->table, 0, 1 * sizeof(*hash->table));
 		hash->max_shift = order;
@@ -1786,6 +1782,8 @@
 	rtnetlink_init();
 out:
 	return err;
+panic:
+	panic("netlink_init: Cannot allocate nl_table\n");
 }
 
 core_initcall(netlink_proto_init);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index eea3669..0a6cfa0 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -796,7 +796,7 @@
 {
 	printk("u32 classifier\n");
 #ifdef CONFIG_CLS_U32_PERF
-	printk("    Perfomance counters on\n");
+	printk("    Performance counters on\n");
 #endif
 #ifdef CONFIG_NET_CLS_POLICE
 	printk("    OLD policer on \n");
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index c7844ba..a19eff1 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -430,7 +430,7 @@
 	}
 #endif
 
-	err = -EINVAL;
+	err = -ENOENT;
 	if (ops == NULL)
 		goto err_out;
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 4f11f58..17b5092 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -806,38 +806,26 @@
 
 /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error.  */
 struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
-				   const struct sctp_chunk *chunk,
-				   const struct msghdr *msg)
+					const struct msghdr *msg,
+					size_t paylen)
 {
 	struct sctp_chunk *retval;
-	void *payload = NULL, *payoff;
-	size_t paylen = 0;
-	struct iovec *iov = NULL;
-	int iovlen = 0;
+	void *payload = NULL;
+	int err;
 
-	if (msg) {
-		iov = msg->msg_iov;
-		iovlen = msg->msg_iovlen;
-		paylen = get_user_iov_size(iov, iovlen);
-	}
-
-	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
+	retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
 	if (!retval)
 		goto err_chunk;
 
 	if (paylen) {
 		/* Put the msg_iov together into payload.  */
-		payload = kmalloc(paylen, GFP_ATOMIC);
+		payload = kmalloc(paylen, GFP_KERNEL);
 		if (!payload)
 			goto err_payload;
-		payoff = payload;
 
-		for (; iovlen > 0; --iovlen) {
-			if (copy_from_user(payoff, iov->iov_base,iov->iov_len))
-				goto err_copy;
-			payoff += iov->iov_len;
-			iov++;
-		}
+		err = memcpy_fromiovec(payload, msg->msg_iov, paylen);
+		if (err < 0)
+			goto err_copy;
 	}
 
 	sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index ead3f1b..5b5ae79 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4031,18 +4031,12 @@
 	 * from its upper layer, but retransmits data to the far end
 	 * if necessary to fill gaps.
 	 */
-	struct msghdr *msg = arg;
-	struct sctp_chunk *abort;
+	struct sctp_chunk *abort = arg;
 	sctp_disposition_t retval;
 
 	retval = SCTP_DISPOSITION_CONSUME;
 
-	/* Generate ABORT chunk to send the peer.  */
-	abort = sctp_make_abort_user(asoc, NULL, msg);
-	if (!abort)
-		retval = SCTP_DISPOSITION_NOMEM;
-	else
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
 	/* Even if we can't send the ABORT due to low memory delete the
 	 * TCB.  This is a departure from our typical NOMEM handling.
@@ -4166,8 +4160,7 @@
 	void *arg,
 	sctp_cmd_seq_t *commands)
 {
-	struct msghdr *msg = arg;
-	struct sctp_chunk *abort;
+	struct sctp_chunk *abort = arg;
 	sctp_disposition_t retval;
 
 	/* Stop T1-init timer */
@@ -4175,12 +4168,7 @@
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
 	retval = SCTP_DISPOSITION_CONSUME;
 
-	/* Generate ABORT chunk to send the peer */
-	abort = sctp_make_abort_user(asoc, NULL, msg);
-	if (!abort)
-		retval = SCTP_DISPOSITION_NOMEM;
-	else
-		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 54722e6..dab1594 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1289,9 +1289,13 @@
 			}
 		}
 
-		if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)
-			sctp_primitive_ABORT(asoc, NULL);
-		else
+		if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
+			struct sctp_chunk *chunk;
+
+			chunk = sctp_make_abort_user(asoc, NULL, 0);
+			if (chunk)
+				sctp_primitive_ABORT(asoc, chunk);
+		} else
 			sctp_primitive_SHUTDOWN(asoc, NULL);
 	}
 
@@ -1520,8 +1524,16 @@
 			goto out_unlock;
 		}
 		if (sinfo_flags & SCTP_ABORT) {
+			struct sctp_chunk *chunk;
+
+			chunk = sctp_make_abort_user(asoc, msg, msg_len);
+			if (!chunk) {
+				err = -ENOMEM;
+				goto out_unlock;
+			}
+
 			SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
-			sctp_primitive_ABORT(asoc, msg);
+			sctp_primitive_ABORT(asoc, chunk);
 			err = 0;
 			goto out_unlock;
 		}
diff --git a/net/socket.c b/net/socket.c
index b4848ce..6d261bf 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1178,7 +1178,8 @@
  */
 
 	if (!(sock = sock_alloc())) {
-		printk(KERN_WARNING "socket: no more sockets\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "socket: no more sockets\n");
 		err = -ENFILE;		/* Not exactly a match, but its the
 					   closest posix thing */
 		goto out;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4a9aa93..ef1cf5b 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -718,8 +718,7 @@
 		auth, auth->au_flavor);
 
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	rpc_unlink(gss_auth->path);
-	dput(gss_auth->dentry);
+	rpc_unlink(gss_auth->dentry);
 	gss_auth->dentry = NULL;
 	gss_mech_put(gss_auth->mech);
 
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7026b08..00cb388 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -71,7 +71,12 @@
 	new = detail->alloc();
 	if (!new)
 		return NULL;
+	/* must fully initialise 'new', else
+	 * we might get lose if we need to
+	 * cache_put it soon.
+	 */
 	cache_init(new);
+	detail->init(new, key);
 
 	write_lock(&detail->hash_lock);
 
@@ -85,7 +90,6 @@
 			return tmp;
 		}
 	}
-	detail->init(new, key);
 	new->next = *head;
 	*head = new;
 	detail->entries++;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4ba271f..3e19d32 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -183,8 +183,7 @@
 
 out_no_auth:
 	if (!IS_ERR(clnt->cl_dentry)) {
-		rpc_rmdir(clnt->cl_pathname);
-		dput(clnt->cl_dentry);
+		rpc_rmdir(clnt->cl_dentry);
 		rpc_put_mount();
 	}
 out_no_path:
@@ -251,10 +250,8 @@
 	new->cl_autobind = 0;
 	new->cl_oneshot = 0;
 	new->cl_dead = 0;
-	if (!IS_ERR(new->cl_dentry)) {
+	if (!IS_ERR(new->cl_dentry))
 		dget(new->cl_dentry);
-		rpc_get_mount();
-	}
 	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
 	if (new->cl_auth)
 		atomic_inc(&new->cl_auth->au_count);
@@ -317,11 +314,15 @@
 		clnt->cl_auth = NULL;
 	}
 	if (clnt->cl_parent != clnt) {
+		if (!IS_ERR(clnt->cl_dentry))
+			dput(clnt->cl_dentry);
 		rpc_destroy_client(clnt->cl_parent);
 		goto out_free;
 	}
-	if (clnt->cl_pathname[0])
-		rpc_rmdir(clnt->cl_pathname);
+	if (!IS_ERR(clnt->cl_dentry)) {
+		rpc_rmdir(clnt->cl_dentry);
+		rpc_put_mount();
+	}
 	if (clnt->cl_xprt) {
 		xprt_destroy(clnt->cl_xprt);
 		clnt->cl_xprt = NULL;
@@ -331,10 +332,6 @@
 out_free:
 	rpc_free_iostats(clnt->cl_metrics);
 	clnt->cl_metrics = NULL;
-	if (!IS_ERR(clnt->cl_dentry)) {
-		dput(clnt->cl_dentry);
-		rpc_put_mount();
-	}
 	kfree(clnt);
 	return 0;
 }
@@ -921,26 +918,43 @@
 	task->tk_status = xprt_prepare_transmit(task);
 	if (task->tk_status != 0)
 		return;
+	task->tk_action = call_transmit_status;
 	/* Encode here so that rpcsec_gss can use correct sequence number. */
 	if (rpc_task_need_encode(task)) {
-		task->tk_rqstp->rq_bytes_sent = 0;
+		BUG_ON(task->tk_rqstp->rq_bytes_sent != 0);
 		call_encode(task);
 		/* Did the encode result in an error condition? */
 		if (task->tk_status != 0)
-			goto out_nosend;
+			return;
 	}
-	task->tk_action = call_transmit_status;
 	xprt_transmit(task);
 	if (task->tk_status < 0)
 		return;
-	if (!task->tk_msg.rpc_proc->p_decode) {
-		task->tk_action = rpc_exit_task;
-		rpc_wake_up_task(task);
-	}
-	return;
-out_nosend:
-	/* release socket write lock before attempting to handle error */
-	xprt_abort_transmit(task);
+	/*
+	 * On success, ensure that we call xprt_end_transmit() before sleeping
+	 * in order to allow access to the socket to other RPC requests.
+	 */
+	call_transmit_status(task);
+	if (task->tk_msg.rpc_proc->p_decode != NULL)
+		return;
+	task->tk_action = rpc_exit_task;
+	rpc_wake_up_task(task);
+}
+
+/*
+ * 5a.	Handle cleanup after a transmission
+ */
+static void
+call_transmit_status(struct rpc_task *task)
+{
+	task->tk_action = call_status;
+	/*
+	 * Special case: if we've been waiting on the socket's write_space()
+	 * callback, then don't call xprt_end_transmit().
+	 */
+	if (task->tk_status == -EAGAIN)
+		return;
+	xprt_end_transmit(task);
 	rpc_task_force_reencode(task);
 }
 
@@ -992,18 +1006,7 @@
 }
 
 /*
- * 6a.	Handle transmission errors.
- */
-static void
-call_transmit_status(struct rpc_task *task)
-{
-	if (task->tk_status != -EAGAIN)
-		rpc_task_force_reencode(task);
-	call_status(task);
-}
-
-/*
- * 6b.	Handle RPC timeout
+ * 6a.	Handle RPC timeout
  * 	We do not release the request slot, so we keep using the
  *	same XID for all retransmits.
  */
@@ -1178,6 +1181,17 @@
 	u32	*p = iov->iov_base, n;
 	int error = -EACCES;
 
+	if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
+		/* RFC-1014 says that the representation of XDR data must be a
+		 * multiple of four bytes
+		 * - if it isn't pointer subtraction in the NFS client may give
+		 *   undefined results
+		 */
+		printk(KERN_WARNING
+		       "call_verify: XDR representation not a multiple of"
+		       " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
+		goto out_eio;
+	}
 	if ((len -= 3) < 0)
 		goto out_overflow;
 	p += 1;	/* skip XID */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dc6cb93..0b1a1ac 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -539,6 +539,7 @@
 				rpc_close_pipes(dentry->d_inode);
 				simple_unlink(dir, dentry);
 			}
+			inode_dir_notify(dir, DN_DELETE);
 			dput(dentry);
 		} while (n);
 		goto repeat;
@@ -610,8 +611,8 @@
 	int error;
 
 	shrink_dcache_parent(dentry);
-	if (dentry->d_inode)
-		rpc_close_pipes(dentry->d_inode);
+	if (d_unhashed(dentry))
+		return 0;
 	if ((error = simple_rmdir(dir, dentry)) != 0)
 		return error;
 	if (!error) {
@@ -667,10 +668,11 @@
 			RPCAUTH_info, RPCAUTH_EOF);
 	if (error)
 		goto err_depopulate;
+	dget(dentry);
 out:
 	mutex_unlock(&dir->i_mutex);
 	rpc_release_path(&nd);
-	return dget(dentry);
+	return dentry;
 err_depopulate:
 	rpc_depopulate(dentry);
 	__rpc_rmdir(dir, dentry);
@@ -683,28 +685,20 @@
 }
 
 int
-rpc_rmdir(char *path)
+rpc_rmdir(struct dentry *dentry)
 {
-	struct nameidata nd;
-	struct dentry *dentry;
+	struct dentry *parent;
 	struct inode *dir;
 	int error;
 
-	if ((error = rpc_lookup_parent(path, &nd)) != 0)
-		return error;
-	dir = nd.dentry->d_inode;
+	parent = dget_parent(dentry);
+	dir = parent->d_inode;
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-	dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out_release;
-	}
 	rpc_depopulate(dentry);
 	error = __rpc_rmdir(dir, dentry);
 	dput(dentry);
-out_release:
 	mutex_unlock(&dir->i_mutex);
-	rpc_release_path(&nd);
+	dput(parent);
 	return error;
 }
 
@@ -731,10 +725,11 @@
 	rpci->flags = flags;
 	rpci->ops = ops;
 	inode_dir_notify(dir, DN_CREATE);
+	dget(dentry);
 out:
 	mutex_unlock(&dir->i_mutex);
 	rpc_release_path(&nd);
-	return dget(dentry);
+	return dentry;
 err_dput:
 	dput(dentry);
 	dentry = ERR_PTR(-ENOMEM);
@@ -744,32 +739,26 @@
 }
 
 int
-rpc_unlink(char *path)
+rpc_unlink(struct dentry *dentry)
 {
-	struct nameidata nd;
-	struct dentry *dentry;
+	struct dentry *parent;
 	struct inode *dir;
-	int error;
+	int error = 0;
 
-	if ((error = rpc_lookup_parent(path, &nd)) != 0)
-		return error;
-	dir = nd.dentry->d_inode;
+	parent = dget_parent(dentry);
+	dir = parent->d_inode;
 	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
-	dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
-	if (IS_ERR(dentry)) {
-		error = PTR_ERR(dentry);
-		goto out_release;
-	}
-	d_drop(dentry);
-	if (dentry->d_inode) {
-		rpc_close_pipes(dentry->d_inode);
-		error = simple_unlink(dir, dentry);
+	if (!d_unhashed(dentry)) {
+		d_drop(dentry);
+		if (dentry->d_inode) {
+			rpc_close_pipes(dentry->d_inode);
+			error = simple_unlink(dir, dentry);
+		}
+		inode_dir_notify(dir, DN_DELETE);
 	}
 	dput(dentry);
-	inode_dir_notify(dir, DN_DELETE);
-out_release:
 	mutex_unlock(&dir->i_mutex);
-	rpc_release_path(&nd);
+	dput(parent);
 	return error;
 }
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 313b68d..e8c2bc4 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -707,12 +707,9 @@
 	return err;
 }
 
-void
-xprt_abort_transmit(struct rpc_task *task)
+void xprt_end_transmit(struct rpc_task *task)
 {
-	struct rpc_xprt	*xprt = task->tk_xprt;
-
-	xprt_release_write(xprt, task);
+	xprt_release_write(task->tk_xprt, task);
 }
 
 /**
@@ -761,8 +758,6 @@
 			task->tk_status = -ENOTCONN;
 		else if (!req->rq_received)
 			rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
-
-		xprt->ops->release_xprt(xprt, task);
 		spin_unlock_bh(&xprt->transport_lock);
 		return;
 	}
@@ -772,18 +767,8 @@
 	 *	 schedq, and being picked up by a parallel run of rpciod().
 	 */
 	task->tk_status = status;
-
-	switch (status) {
-	case -ECONNREFUSED:
+	if (status == -ECONNREFUSED)
 		rpc_sleep_on(&xprt->sending, task, NULL, NULL);
-	case -EAGAIN:
-	case -ENOTCONN:
-		return;
-	default:
-		break;
-	}
-	xprt_release_write(xprt, task);
-	return;
 }
 
 static inline void do_xprt_reserve(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ee678ed..441bd53 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -414,6 +414,33 @@
 }
 
 /**
+ * xs_tcp_release_xprt - clean up after a tcp transmission
+ * @xprt: transport
+ * @task: rpc task
+ *
+ * This cleans up if an error causes us to abort the transmission of a request.
+ * In this case, the socket may need to be reset in order to avoid confusing
+ * the server.
+ */
+static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+	struct rpc_rqst *req;
+
+	if (task != xprt->snd_task)
+		return;
+	if (task == NULL)
+		goto out_release;
+	req = task->tk_rqstp;
+	if (req->rq_bytes_sent == 0)
+		goto out_release;
+	if (req->rq_bytes_sent == req->rq_snd_buf.len)
+		goto out_release;
+	set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
+out_release:
+	xprt_release_xprt(xprt, task);
+}
+
+/**
  * xs_close - close a socket
  * @xprt: transport
  *
@@ -1250,7 +1277,7 @@
 
 static struct rpc_xprt_ops xs_tcp_ops = {
 	.reserve_xprt		= xprt_reserve_xprt,
-	.release_xprt		= xprt_release_xprt,
+	.release_xprt		= xs_tcp_release_xprt,
 	.set_port		= xs_set_port,
 	.connect		= xs_connect,
 	.buf_alloc		= rpc_malloc,
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6f29092..de6ec51 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -128,23 +128,17 @@
 #define UNIX_ABSTRACT(sk)	(unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
 
 #ifdef CONFIG_SECURITY_NETWORK
-static void unix_get_peersec_dgram(struct sk_buff *skb)
+static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	int err;
-
-	err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
-					       UNIXSECLEN(skb));
-	if (err)
-		*(UNIXSECDATA(skb)) = NULL;
+	memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
 }
 
 static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 {
-	scm->secdata = *UNIXSECDATA(skb);
-	scm->seclen = *UNIXSECLEN(skb);
+	scm->secid = *UNIXSID(skb);
 }
 #else
-static inline void unix_get_peersec_dgram(struct sk_buff *skb)
+static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 { }
 
 static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
@@ -1322,8 +1316,7 @@
 	memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 	if (siocb->scm->fp)
 		unix_attach_fds(siocb->scm, skb);
-
-	unix_get_peersec_dgram(skb);
+	unix_get_secdata(siocb->scm, skb);
 
 	skb->h.raw = skb->data;
 	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f35bc676..3da67ca 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1134,12 +1134,33 @@
 }
 EXPORT_SYMBOL(__xfrm_route_forward);
 
+/* Optimize later using cookies and generation ids. */
+
 static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
 {
-	/* If it is marked obsolete, which is how we even get here,
-	 * then we have purged it from the policy bundle list and we
-	 * did that for a good reason.
+	/* Code (such as __xfrm4_bundle_create()) sets dst->obsolete
+	 * to "-1" to force all XFRM destinations to get validated by
+	 * dst_ops->check on every use.  We do this because when a
+	 * normal route referenced by an XFRM dst is obsoleted we do
+	 * not go looking around for all parent referencing XFRM dsts
+	 * so that we can invalidate them.  It is just too much work.
+	 * Instead we make the checks here on every use.  For example:
+	 *
+	 *	XFRM dst A --> IPv4 dst X
+	 *
+	 * X is the "xdst->route" of A (X is also the "dst->path" of A
+	 * in this example).  If X is marked obsolete, "A" will not
+	 * notice.  That's what we are validating here via the
+	 * stale_bundle() check.
+	 *
+	 * When a policy's bundle is pruned, we dst_free() the XFRM
+	 * dst which causes it's ->obsolete field to be set to a
+	 * positive non-zero integer.  If an XFRM dst has been pruned
+	 * like this, we want to force a new route lookup.
 	 */
+	if (dst->obsolete < 0 && !stale_bundle(dst))
+		return dst;
+
 	return NULL;
 }
 
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 2180c88..bb19c15 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -77,14 +77,20 @@
 
 # cc-version
 # Usage gcc-ver := $(call cc-version, $(CC))
-cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
-              $(if $(1), $(1), $(CC)))
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
 
 # cc-ifversion
 # Usage:  EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
 cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
                        echo $(3); fi;)
 
+# ld-option
+# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
+ld-option = $(shell if $(CC) $(1) \
+			     -nostdlib -o ldtest$$$$.out -xc /dev/null \
+             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi; \
+	     rm -f ldtest$$$$.out)
+
 ###
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
 # Usage:
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index a495502..0a64688 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -40,7 +40,7 @@
 include scripts/Makefile.lib
 
 kernelsymfile := $(objtree)/Module.symvers
-modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers
+modulesymfile := $(KBUILD_EXTMOD)/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
 __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 2ee48c3..a69d8ac 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -357,7 +357,7 @@
 		for (e = prop->expr; e; e = e->left.expr)
 			if (e->right.sym->visible != no)
 				flags &= e->right.sym->flags;
-		sym->flags |= flags & SYMBOL_DEF_USER;
+		sym->flags &= flags | ~SYMBOL_DEF_USER;
 	}
 
 	sym_change_count += conf_warnings || conf_unsaved;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index f9460a6..c9ca0c2 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1518,6 +1518,7 @@
     $prototype =~ s/^asmlinkage +//;
     $prototype =~ s/^inline +//;
     $prototype =~ s/^__inline__ +//;
+    $prototype =~ s/__devinit +//;
     $prototype =~ s/^#define +//; #ak added
     $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//;
 
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 37f67c2..e2de650 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -52,6 +52,23 @@
                 sprintf(str + strlen(str), "*");                \
 } while(0)
 
+/**
+ * Check that sizeof(device_id type) are consistent with size of section
+ * in .o file. If in-consistent then userspace and kernel does not agree
+ * on actual size which is a bug.
+ **/
+static void device_id_size_check(const char *modname, const char *device_id,
+				 unsigned long size, unsigned long id_size)
+{
+	if (size % id_size || size < id_size) {
+		fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
+		      "of the size of section __mod_%s_device_table=%lu.\n"
+		      "Fix definition of struct %s_device_id "
+		      "in mod_devicetable.h\n",
+		      modname, device_id, id_size, device_id, size, device_id);
+	}
+}
+
 /* USB is special because the bcdDevice can be matched against a numeric range */
 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
 static void do_usb_entry(struct usb_device_id *id,
@@ -152,10 +169,8 @@
 	unsigned int i;
 	const unsigned long id_size = sizeof(struct usb_device_id);
 
-	if (size % id_size || size < id_size) {
-		warn("%s ids %lu bad size "
-		     "(each on %lu)\n", mod->name, size, id_size);
-	}
+	device_id_size_check(mod->name, "usb", size, id_size);
+
 	/* Leave last one: it's the terminator. */
 	size -= id_size;
 
@@ -376,7 +391,7 @@
 	unsigned int i;
 
 	for (i = min; i < max; i++)
-		if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
+		if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
 			sprintf(alias + strlen(alias), "%X,*", i);
 }
 
@@ -434,6 +449,7 @@
 
 static void do_table(void *symval, unsigned long size,
 		     unsigned long id_size,
+		     const char *device_id,
 		     void *function,
 		     struct module *mod)
 {
@@ -441,10 +457,7 @@
 	char alias[500];
 	int (*do_entry)(const char *, void *entry, char *alias) = function;
 
-	if (size % id_size || size < id_size) {
-		warn("%s ids %lu bad size "
-		     "(each on %lu)\n", mod->name, size, id_size);
-	}
+	device_id_size_check(mod->name, device_id, size, id_size);
 	/* Leave last one: it's the terminator. */
 	size -= id_size;
 
@@ -476,40 +489,51 @@
 		+ sym->st_value;
 
 	if (sym_is(symname, "__mod_pci_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct pci_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct pci_device_id), "pci",
 			 do_pci_entry, mod);
 	else if (sym_is(symname, "__mod_usb_device_table"))
 		/* special case to handle bcdDevice ranges */
 		do_usb_table(symval, sym->st_size, mod);
 	else if (sym_is(symname, "__mod_ieee1394_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct ieee1394_device_id), "ieee1394",
 			 do_ieee1394_entry, mod);
 	else if (sym_is(symname, "__mod_ccw_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct ccw_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct ccw_device_id), "ccw",
 			 do_ccw_entry, mod);
 	else if (sym_is(symname, "__mod_serio_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct serio_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct serio_device_id), "serio",
 			 do_serio_entry, mod);
 	else if (sym_is(symname, "__mod_pnp_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct pnp_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct pnp_device_id), "pnp",
 			 do_pnp_entry, mod);
 	else if (sym_is(symname, "__mod_pnp_card_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct pnp_card_device_id), "pnp_card",
 			 do_pnp_card_entry, mod);
 	else if (sym_is(symname, "__mod_pcmcia_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct pcmcia_device_id), "pcmcia",
 			 do_pcmcia_entry, mod);
         else if (sym_is(symname, "__mod_of_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct of_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct of_device_id), "of",
 			 do_of_entry, mod);
         else if (sym_is(symname, "__mod_vio_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct vio_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct vio_device_id), "vio",
 			 do_vio_entry, mod);
 	else if (sym_is(symname, "__mod_i2c_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct i2c_device_id), "i2c",
 			 do_i2c_entry, mod);
 	else if (sym_is(symname, "__mod_input_device_table"))
-		do_table(symval, sym->st_size, sizeof(struct input_device_id),
+		do_table(symval, sym->st_size,
+			 sizeof(struct input_device_id), "input",
 			 do_input_entry, mod);
 }
 
diff --git a/security/dummy.c b/security/dummy.c
index bbbfda7..58c6d39 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -791,8 +791,7 @@
 	return -ENOPROTOOPT;
 }
 
-static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata,
-					 u32 *seclen)
+static int dummy_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
 	return -ENOPROTOOPT;
 }
@@ -876,6 +875,15 @@
 	return -EINVAL;
 }
 
+static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+	return -EOPNOTSUPP;
+}
+
+static void dummy_release_secctx(char *secdata, u32 seclen)
+{
+}
+
 #ifdef CONFIG_KEYS
 static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
 				  unsigned long flags)
@@ -1028,6 +1036,8 @@
 	set_to_dummy_if_null(ops, d_instantiate);
  	set_to_dummy_if_null(ops, getprocattr);
  	set_to_dummy_if_null(ops, setprocattr);
+ 	set_to_dummy_if_null(ops, secid_to_secctx);
+ 	set_to_dummy_if_null(ops, release_secctx);
 #ifdef CONFIG_SECURITY_NETWORK
 	set_to_dummy_if_null(ops, unix_stream_connect);
 	set_to_dummy_if_null(ops, unix_may_send);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a91c961..5d1b8c7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3524,25 +3524,21 @@
 	return err;
 }
 
-static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
+static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
 {
+	u32 peer_secid = SECSID_NULL;
 	int err = 0;
-	u32 peer_sid;
 
-	if (skb->sk->sk_family == PF_UNIX)
-		selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket),
-				      &peer_sid);
-	else
-		peer_sid = selinux_socket_getpeer_dgram(skb);
+	if (sock && (sock->sk->sk_family == PF_UNIX))
+		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
+	else if (skb)
+		peer_secid = selinux_socket_getpeer_dgram(skb);
 
-	if (peer_sid == SECSID_NULL)
-		return -EINVAL;
+	if (peer_secid == SECSID_NULL)
+		err = -EINVAL;
+	*secid = peer_secid;
 
-	err = security_sid_to_context(peer_sid, secdata, seclen);
-	if (err)
-		return err;
-
-	return 0;
+	return err;
 }
 
 static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -4407,6 +4403,17 @@
 	return size;
 }
 
+static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+	return security_sid_to_context(secid, secdata, seclen);
+}
+
+static void selinux_release_secctx(char *secdata, u32 seclen)
+{
+	if (secdata)
+		kfree(secdata);
+}
+
 #ifdef CONFIG_KEYS
 
 static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
@@ -4587,6 +4594,9 @@
 	.getprocattr =                  selinux_getprocattr,
 	.setprocattr =                  selinux_setprocattr,
 
+	.secid_to_secctx =		selinux_secid_to_secctx,
+	.release_secctx =		selinux_release_secctx,
+
         .unix_stream_connect =		selinux_socket_unix_stream_connect,
 	.unix_may_send =		selinux_socket_unix_may_send,
 
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0111990..f03960e 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -644,10 +644,18 @@
 	kfree(lra);
 
 	for (rt = p->range_tr; rt; rt = rt -> next) {
-		kfree(lrt);
+		if (lrt) {
+			ebitmap_destroy(&lrt->range.level[0].cat);
+			ebitmap_destroy(&lrt->range.level[1].cat);
+			kfree(lrt);
+		}
 		lrt = rt;
 	}
-	kfree(lrt);
+	if (lrt) {
+		ebitmap_destroy(&lrt->range.level[0].cat);
+		ebitmap_destroy(&lrt->range.level[1].cat);
+		kfree(lrt);
+	}
 
 	if (p->type_attr_map) {
 		for (i = 0; i < p->p_types.nprim; i++)
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d2e80e6..85e4298 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -833,6 +833,8 @@
 		goto out;
 	}
 
+	context_init(&newcontext);
+
 	POLICY_RDLOCK;
 
 	scontext = sidtab_search(&sidtab, ssid);
@@ -850,8 +852,6 @@
 		goto out_unlock;
 	}
 
-	context_init(&newcontext);
-
 	/* Set the user identity. */
 	switch (specified) {
 	case AVTAB_TRANSITION:
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
index bcc5556..3c7d1d8 100644
--- a/sound/aoa/codecs/snd-aoa-codec-toonie.c
+++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c
@@ -51,6 +51,13 @@
 	{}
 };
 
+static int toonie_usable(struct codec_info_item *cii,
+			 struct transfer_info *ti,
+			 struct transfer_info *out)
+{
+	return 1;
+}
+
 #ifdef CONFIG_PM
 static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
 {
@@ -69,6 +76,7 @@
 	.sysclock_factor = 256,
 	.bus_factor = 64,
 	.owner = THIS_MODULE,
+	.usable = toonie_usable,
 #ifdef CONFIG_PM
 	.suspend = toonie_suspend,
 	.resume = toonie_resume,
@@ -79,19 +87,20 @@
 {
 	struct toonie *toonie = codec_to_toonie(codec);
 
+	/* nothing connected? what a joke! */
+	if (toonie->codec.connected != 1)
+		return -ENOTCONN;
+
 	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) {
 		printk(KERN_ERR PFX "failed to create toonie snd device!\n");
 		return -ENODEV;
 	}
 
-	/* nothing connected? what a joke! */
-	if (toonie->codec.connected != 1)
-		return -ENOTCONN;
-
 	if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
 						     aoa_get_card(),
 						     &toonie_codec_info, toonie)) {
 		printk(KERN_ERR PFX "error creating toonie pcm\n");
+		snd_device_free(aoa_get_card(), toonie);
 		return -ENODEV;
 	}
 
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
index 7ae0c0b..f69d333 100644
--- a/sound/aoa/core/snd-aoa-gpio-feature.c
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -112,7 +112,10 @@
 
 static void get_irq(struct device_node * np, int *irqptr)
 {
-	*irqptr = irq_of_parse_and_map(np, 0);
+	if (np)
+		*irqptr = irq_of_parse_and_map(np, 0);
+	else
+		*irqptr = NO_IRQ;
 }
 
 /* 0x4 is outenable, 0x1 is out, thus 4 or 5 */
@@ -322,7 +325,7 @@
 		return -EINVAL;
 	}
 
-	if (irq == -1)
+	if (irq == NO_IRQ)
 		return -ENODEV;
 
 	mutex_lock(&notif->mutex);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
index 3d57fd1..2836c32 100644
--- a/sound/aoa/core/snd-aoa-gpio-pmf.c
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
@@ -18,7 +18,7 @@
 							\
 	if (unlikely(!rt)) return;				\
 	rc = pmf_call_function(rt->node, #name "-mute", &args);	\
-	if (rc)							\
+	if (rc && rc != -ENODEV)				\
 		printk(KERN_WARNING "pmf_gpio_set_" #name	\
 		" failed, rc: %d\n", rc);			\
 	rt->implementation_private &= ~(1<<bit);		\
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 71b5080..75a9505 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -988,13 +988,12 @@
 	if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) {
 		struct snd_ctl_elem_info *uinfo;
 
-		uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
+		uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
 		if (! uinfo) {
 			up_read(&mixer->card->controls_rwsem);
 			return -ENOMEM;
 		}
 			
-		memset(uinfo, 0, sizeof(*uinfo));
 		if (kctl->info(kctl, uinfo)) {
 			up_read(&mixer->card->controls_rwsem);
 			return 0;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index f5ff4f4..472fce0 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2228,6 +2228,8 @@
 	for (idx = 0; idx < 2; idx++) {
 		if (setup[idx].disable)
 			continue;
+		if (! pcm->streams[idx].substream_count)
+			continue; /* no matching substream */
 		if (idx == SNDRV_PCM_STREAM_PLAYBACK) {
 			if (! (f_mode & FMODE_WRITE))
 				continue;
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 4260de9..102ff54 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -372,10 +372,9 @@
 {
 	struct ops_list *ops;
 
-	ops = kmalloc(sizeof(*ops), GFP_KERNEL);
+	ops = kzalloc(sizeof(*ops), GFP_KERNEL);
 	if (ops == NULL)
 		return ops;
-	memset(ops, 0, sizeof(*ops));
 
 	/* set up driver entry */
 	strlcpy(ops->id, id, sizeof(ops->id));
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index 6e4d4ab..c30669f 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -68,21 +68,18 @@
 
 	dmab->area = NULL;
 	dmab->addr = 0;
-	dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL);
+	dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
 	if (! sgbuf)
 		return NULL;
-	memset(sgbuf, 0, sizeof(*sgbuf));
 	sgbuf->dev = device;
 	pages = snd_sgbuf_aligned_pages(size);
 	sgbuf->tblsize = sgbuf_align_table(pages);
-	sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
+	sgbuf->table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->table), GFP_KERNEL);
 	if (! sgbuf->table)
 		goto _failed;
-	memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize);
-	sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize, GFP_KERNEL);
+	sgbuf->page_table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->page_table), GFP_KERNEL);
 	if (! sgbuf->page_table)
 		goto _failed;
-	memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize);
 
 	/* allocate each page */
 	for (i = 0; i < pages; i++) {
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index c4af849..7e65a10 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1252,18 +1252,15 @@
 	chip->audio_info = rmh.Stat[1];
 
 	/* allocate pipes */
-	chip->playback_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_outs, GFP_KERNEL);
+	chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL);
 	if (!chip->playback_pipes)
 		return -ENOMEM;
-	chip->capture_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_ins, GFP_KERNEL);
+	chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL);
 	if (!chip->capture_pipes) {
 		kfree(chip->playback_pipes);
 		return -ENOMEM;
 	}
 
-	memset(chip->playback_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_outs);
-	memset(chip->capture_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_ins);
-
 	preferred = chip->ibl.size;
 	chip->ibl.size = 0;
 	vx_set_ibl(chip, &chip->ibl); /* query the info */
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index f4980ca..97e38b6 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -5,6 +5,20 @@
 #
 # Prompt user for primary drivers.
 
+config OSS_OBSOLETE_DRIVER
+	bool "Obsolete OSS drivers"
+	depends on SOUND_PRIME
+	help
+	  This option enables support for obsolete OSS drivers that
+	  are scheduled for removal in the near future since there
+	  are ALSA drivers for the same hardware.
+
+	  Please contact Adrian Bunk <bunk@stusta.de> if you had to
+	  say Y here because your soundcard is not properly supported
+	  by ALSA.
+
+	  If unsure, say N.
+
 config SOUND_BT878
 	tristate "BT878 audio dma"
 	depends on SOUND_PRIME && PCI
@@ -23,7 +37,7 @@
 
 config SOUND_EMU10K1
 	tristate "Creative SBLive! (EMU10K1)"
-	depends on SOUND_PRIME && PCI
+	depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
 	---help---
 	  Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
 	  such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -31,7 +45,7 @@
 	  For more information on this driver and the degree of support for
 	  the different card models please check:
 
-	        <http://sourceforge.net/projects/emu10k1/>
+		<http://sourceforge.net/projects/emu10k1/>
 
 	  It is now possible to load dsp microcode patches into the EMU10K1
 	  chip.  These patches are used to implement real time sound
@@ -49,7 +63,7 @@
 
 config SOUND_FUSION
 	tristate "Crystal SoundFusion (CS4280/461x)"
-	depends on SOUND_PRIME && PCI
+	depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER
 	help
 	  This module drives the Crystal SoundFusion devices (CS4280/46xx
 	  series) when wired as native sound drivers with AC97 codecs.  If
@@ -140,7 +154,7 @@
 	  system support" and "Sysctl support", and after the /proc file
 	  system has been mounted, executing the command
 
-	  	command			what is enabled
+		command			what is enabled
 
 	  echo 0>/proc/ALi5451	pcm out is also set to S/PDIF out. (Default).
 
@@ -440,7 +454,7 @@
 
 config SOUND_AD1816
 	tristate "AD1816(A) based cards (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SOUND_OSS
+	depends on EXPERIMENTAL && SOUND_OSS && OSS_OBSOLETE_DRIVER
 	help
 	  Say M here if you have a sound card based on the Analog Devices
 	  AD1816(A) chip.
@@ -450,21 +464,21 @@
 
 config SOUND_AD1889
 	tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && SOUND_OSS && PCI
+	depends on EXPERIMENTAL && SOUND_OSS && PCI && OSS_OBSOLETE_DRIVER
 	help
 	  Say M here if you have a sound card based on the Analog Devices
 	  AD1889 chip.
 
 config SOUND_ADLIB
 	tristate "Adlib Cards"
-	depends on SOUND_OSS
+	depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
 	help
 	  Includes ASB 64 4D. Information on programming AdLib cards is
 	  available at <http://www.itsnet.com/home/ldragon/Specs/adlib.html>.
 
 config SOUND_ACI_MIXER
 	tristate "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)"
-	depends on SOUND_OSS
+	depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
 	---help---
 	  ACI (Audio Command Interface) is a protocol used to communicate with
 	  the microcontroller on some sound cards produced by miro and
@@ -586,7 +600,7 @@
 
 config SOUND_NM256
 	tristate "NM256AV/NM256ZX audio support"
-	depends on SOUND_OSS
+	depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
 	help
 	  Say M here to include audio support for the NeoMagic 256AV/256ZX
 	  chipsets. These are the audio chipsets found in the Sony
@@ -706,7 +720,7 @@
 
 config SOUND_OPL3SA2
 	tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
-	depends on SOUND_OSS
+	depends on SOUND_OSS && OSS_OBSOLETE_DRIVER
 	help
 	  Say Y or M if you have a card based on one of these Yamaha sound
 	  chipsets or the "SAx", which is actually a SA3. Read
@@ -838,7 +852,7 @@
 
 config SOUND_TVMIXER
 	tristate "TV card (bt848) mixer support"
-	depends on SOUND_PRIME && I2C
+	depends on SOUND_PRIME && I2C && VIDEO_V4L1
 	help
 	  Support for audio mixer facilities on the BT848 TV frame-grabber
 	  card.
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index d7ad32f..e49c0fe 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -16,16 +16,16 @@
 	  will be called snd-ad1889.
 
 config SND_ALS300
-        tristate "Avance Logic ALS300/ALS300+"
-        depends on SND
-        select SND_PCM
-        select SND_AC97_CODEC
-        select SND_OPL3_LIB
-        help
-          Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
+	tristate "Avance Logic ALS300/ALS300+"
+	depends on SND
+	select SND_PCM
+	select SND_AC97_CODEC
+	select SND_OPL3_LIB
+	help
+	  Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+
 
-          To compile this driver as a module, choose M here: the module
-          will be called snd-als300
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-als300
 
 config SND_ALS4000
 	tristate "Avance Logic ALS4000"
@@ -78,49 +78,49 @@
 	  will be called snd-atiixp-modem.
 
 config SND_AU8810
-        tristate "Aureal Advantage"
-        depends on SND
+	tristate "Aureal Advantage"
+	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
-        help
+	help
 	  Say Y here to include support for Aureal Advantage soundcards.
 
 	  Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
-          3D support code is in place, but not yet useable. For more info, 
-          email the ALSA developer list, or <mjander@users.sourceforge.net>.
+	  3D support code is in place, but not yet useable. For more info,
+	  email the ALSA developer list, or <mjander@users.sourceforge.net>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-au8810.
- 
+
 config SND_AU8820
-        tristate "Aureal Vortex"
-        depends on SND
+	tristate "Aureal Vortex"
+	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
-        help
+	help
 	  Say Y here to include support for Aureal Vortex soundcards.
 
-          Supported features: Hardware Mixer and SRC. For more info, email 
-          the ALSA developer list, or <mjander@users.sourceforge.net>.
+	  Supported features: Hardware Mixer and SRC. For more info, email
+	  the ALSA developer list, or <mjander@users.sourceforge.net>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-au8820.
- 
+
 config SND_AU8830
-        tristate "Aureal Vortex 2"
-        depends on SND
+	tristate "Aureal Vortex 2"
+	depends on SND
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
-        help
+	help
 	  Say Y here to include support for Aureal Vortex 2 soundcards.
 
-          Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
-          3D support code is in place, but not yet useable. For more info, 
-          email the ALSA developer list, or <mjander@users.sourceforge.net>.
+	  Supported features: Hardware Mixer, SRC, EQ and SPDIF output.
+	  3D support code is in place, but not yet useable. For more info,
+	  email the ALSA developer list, or <mjander@users.sourceforge.net>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-au8830.
- 
+
 config SND_AZT3328
 	tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
 	depends on SND && EXPERIMENTAL
@@ -135,10 +135,10 @@
 	  will be called snd-azt3328.
 
 config SND_BT87X
-        tristate "Bt87x Audio Capture"
-        depends on SND
+	tristate "Bt87x Audio Capture"
+	depends on SND
 	select SND_PCM
-        help
+	help
 	  If you want to record audio from TV cards based on
 	  Brooktree Bt878/Bt879 chips, say Y here and read
 	  <file:Documentation/sound/alsa/Bt87x.txt>.
@@ -209,7 +209,7 @@
 config SND_CS46XX_NEW_DSP
 	bool "Cirrus Logic (Sound Fusion) New DSP support"
 	depends on SND_CS46XX
-        default y
+	default y
 	help
 	  Say Y here to use a new DSP image for SPDIF and dual codecs.
 
@@ -225,7 +225,7 @@
 	  referred to as NS CS5535 IO or AMD CS5535 IO companion in
 	  various literature. This driver also supports the CS5536 audio
 	  device. However, for both chips, on certain boards, you may
-	  need to use ac97_quirk=hp_only if your board has physically 
+	  need to use ac97_quirk=hp_only if your board has physically
 	  mapped headphone out to master output. If that works for you,
 	  send lspci -vvv output to the mailing list so that your board
 	  can be identified in the quirks list.
@@ -468,11 +468,13 @@
 	  FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media
 	  Forte SF256-PCS-02) into the snd-fm801 driver.
 
+	  This will enable support for the old V4L1 API.
+
 config SND_FM801_TEA575X
 	tristate
 	depends on SND_FM801_TEA575X_BOOL
 	default SND_FM801
-	select VIDEO_DEV
+	select VIDEO_V4L1
 
 config SND_HDA_INTEL
 	tristate "Intel HD Audio"
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 0abf280..51e83d7 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -573,7 +573,7 @@
 };
 
 static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
-	AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0);
+	AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
 
 
 static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
@@ -615,7 +615,7 @@
 AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
 AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
 AC97_ENUM("Mono Output Select", std_enum[2]),
-AC97_ENUM("Mic Select Capture Switch", std_enum[3]),
+AC97_ENUM("Mic Select", std_enum[3]),
 AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
 };
 
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 27a8dbe..c3dafa2 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -236,9 +236,9 @@
 	chip = snd_pcm_substream_chip(substream);
 	runtime = substream->runtime;
 
-	if (!(pipe = kmalloc(sizeof(struct audiopipe), GFP_KERNEL)))
+	pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL);
+	if (!pipe)
 		return -ENOMEM;
-	memset(pipe, 0, sizeof(struct audiopipe));
 	pipe->index = -1;		/* Not configured yet */
 
 	/* Set up hw capabilities and contraints */
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index f9b5c3d..79f24cd 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -936,6 +936,17 @@
 	 .ca0151_chip = 1,
 	 .spk71 = 1,
 	 .spdif_bug = 1} ,
+	/* Dell OEM/Creative Labs Audigy 2 ZS */
+	/* See ALSA bug#1365 */
+	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102,
+	 .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]",
+	 .id = "Audigy2",
+	 .emu10k2_chip = 1,
+	 .ca0102_chip = 1,
+	 .ca0151_chip = 1,
+	 .spk71 = 1,
+	 .spdif_bug = 1,
+	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
 	 .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", 
 	 .id = "Audigy2",
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index a8b3128..1076af4 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -37,9 +37,13 @@
 	int handled = 0;
 
 	while ((status = inl(emu->port + IPR)) != 0) {
-		//printk("emu10k1 irq - status = 0x%x\n", status);
+		//snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status);
 		orig_status = status;
 		handled = 1;
+		if ((status & 0xffffffff) == 0xffffffff) {
+			snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n");
+			break;
+		}
 		if (status & IPR_PCIERROR) {
 			snd_printk(KERN_ERR "interrupt: PCI error\n");
 			snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE);
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 82d791b..05dabe4 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -801,11 +801,10 @@
 	chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf;
 #ifdef PMAC_AMP_AVAIL
 	if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) {
-		struct awacs_amp *amp = kmalloc(sizeof(*amp), GFP_KERNEL);
+		struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL);
 		if (! amp)
 			return -ENOMEM;
 		chip->mixer_data = amp;
-		memset(amp, 0, sizeof(*amp));
 		chip->mixer_free = awacs_amp_free;
 		awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */
 		awacs_amp_set_vol(amp, 1, 63, 63, 0);
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 46eebf5..57202b0 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -258,10 +258,9 @@
 		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
-	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
 	if (! mix)
 		return -ENOMEM;
-	memset(mix, 0, sizeof(*mix));
 	chip->mixer_data = mix;
 	chip->mixer_free = daca_cleanup;
 	mix->amp_on = 1; /* default on */
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index fb05938..59482a4 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -64,11 +64,10 @@
 	if (strncmp(i2c_device_name(adapter), "mac-io", 6))
 		return 0; /* ignored */
 
-	new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (! new_client)
 		return -ENOMEM;
 
-	memset(new_client, 0, sizeof(*new_client));
 	new_client->addr = keywest_ctx->addr;
 	i2c_set_clientdata(new_client, keywest_ctx);
 	new_client->adapter = adapter;
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index fa9a44a..2264574 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -181,21 +181,14 @@
 	if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
 		return err;
 	device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0);
-	if (!IS_ERR(device)) {
-		if (platform_get_drvdata(device))
-			return 0;
-		platform_device_unregister(device);
-		err = -ENODEV;
-	} else
-		err = PTR_ERR(device);
-	platform_driver_unregister(&snd_pmac_driver);
-	return err;
+	return 0;
 
 }
 
 static void __exit alsa_card_pmac_exit(void)
 {
-	platform_device_unregister(device);
+	if (!IS_ERR(device))
+		platform_device_unregister(device);
 	platform_driver_unregister(&snd_pmac_driver);
 }
 
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 692c611..84f6b19 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -1316,10 +1316,9 @@
 		request_module("i2c-powermac");
 #endif /* CONFIG_KMOD */	
 
-	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
+	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
 	if (! mix)
 		return -ENOMEM;
-	memset(mix, 0, sizeof(*mix));
 	mix->headphone_irq = -1;
 
 	chip->mixer_data = mix;
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index d32d83d..1b7f499 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2260,10 +2260,9 @@
 	}
 
 	/* create a new pcm */
-	as = kmalloc(sizeof(*as), GFP_KERNEL);
+	as = kzalloc(sizeof(*as), GFP_KERNEL);
 	if (! as)
 		return -ENOMEM;
-	memset(as, 0, sizeof(*as));
 	as->pcm_index = chip->pcm_devs;
 	as->chip = chip;
 	as->fmt_type = fp->fmt_type;
@@ -2633,13 +2632,12 @@
 			csep = NULL;
 		}
 
-		fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+		fp = kzalloc(sizeof(*fp), GFP_KERNEL);
 		if (! fp) {
 			snd_printk(KERN_ERR "cannot malloc\n");
 			return -ENOMEM;
 		}
 
-		memset(fp, 0, sizeof(*fp));
 		fp->iface = iface_no;
 		fp->altsetting = altno;
 		fp->altset_idx = i;
diff --git a/usr/Makefile b/usr/Makefile
index e938242..5b31c0b 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -35,6 +35,9 @@
       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
 
 targets := initramfs_data.cpio.gz
+# do not try to update files included in initramfs
+$(deps_initramfs): ;
+
 $(deps_initramfs): klibcdirs
 # We rebuild initramfs_data.cpio.gz if:
 # 1) Any included file is newer then initramfs_data.cpio.gz