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

* git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86:
  x86: fix deadlock, make pgd_lock irq-safe
  virtio: fix trivial build bug
  x86: fix mttr trimming
  x86: delay CPA self-test and repeat it
  x86: fix 64-bit sections
  generic: add __FINITDATA
  x86: remove suprious ifdefs from pageattr.c
  x86: mark the .rodata section also NX
  x86: fix iret exception recovery on 64-bit
  cpuidle: dubious one-bit signed bitfield in cpuidle.h
  x86: fix sparse warnings in powernow-k8.c
  x86: fix sparse error in traps_32.c
  x86: trivial sparse/checkpatch in quirks.c
  x86 ptrace: disallow null cs/ss
  MAINTAINERS: RDC R-321x SoC maintainer
  brk randomization: introduce CONFIG_COMPAT_BRK
  brk: check the lower bound properly
  x86: remove X2 workaround
  x86: make spurious fault handler aware of large mappings
  x86: make traps on entry code be debuggable in user space, 64-bit
diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
index 6c81675..65022a8 100644
--- a/Documentation/BUG-HUNTING
+++ b/Documentation/BUG-HUNTING
@@ -214,6 +214,23 @@
   gdb vmlinux
   (gdb) p vt_ioctl
   (gdb) l *(0x<address of vt_ioctl> + 0xda8)
+or, as one command
+  (gdb) l *(vt_ioctl + 0xda8)
+
+If you have a call trace, such as :-
+>Call Trace:
+> [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
+> [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
+> [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
+> ...
+this shows the problem in the :jbd: module. You can load that module in gdb
+and list the relevant code.
+  gdb fs/jbd/jbd.ko
+  (gdb) p log_wait_commit
+  (gdb) l *(0x<address> + 0xa3)
+or
+  (gdb) l *(log_wait_commit + 0xa3)
+
 
 Another very useful option of the Kernel Hacking section in menuconfig is
 Debug memory allocations. This will help you see whether data has been
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 01825ee..2e9d6b4 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -717,7 +717,7 @@
     <para>
 For our first example, we assume that all operations are in user
 context (ie. from system calls), so we can sleep.  This means we can
-use a semaphore to protect the cache and all the objects within
+use a mutex to protect the cache and all the objects within
 it.  Here's the code:
     </para>
 
@@ -725,7 +725,7 @@
 #include &lt;linux/list.h&gt;
 #include &lt;linux/slab.h&gt;
 #include &lt;linux/string.h&gt;
-#include &lt;asm/semaphore.h&gt;
+#include &lt;linux/mutex.h&gt;
 #include &lt;asm/errno.h&gt;
 
 struct object
@@ -737,7 +737,7 @@
 };
 
 /* Protects the cache, cache_num, and the objects within it */
-static DECLARE_MUTEX(cache_lock);
+static DEFINE_MUTEX(cache_lock);
 static LIST_HEAD(cache);
 static unsigned int cache_num = 0;
 #define MAX_CACHE_SIZE 10
@@ -789,17 +789,17 @@
         obj-&gt;id = id;
         obj-&gt;popularity = 0;
 
-        down(&amp;cache_lock);
+        mutex_lock(&amp;cache_lock);
         __cache_add(obj);
-        up(&amp;cache_lock);
+        mutex_unlock(&amp;cache_lock);
         return 0;
 }
 
 void cache_delete(int id)
 {
-        down(&amp;cache_lock);
+        mutex_lock(&amp;cache_lock);
         __cache_delete(__cache_find(id));
-        up(&amp;cache_lock);
+        mutex_unlock(&amp;cache_lock);
 }
 
 int cache_find(int id, char *name)
@@ -807,13 +807,13 @@
         struct object *obj;
         int ret = -ENOENT;
 
-        down(&amp;cache_lock);
+        mutex_lock(&amp;cache_lock);
         obj = __cache_find(id);
         if (obj) {
                 ret = 0;
                 strcpy(name, obj-&gt;name);
         }
-        up(&amp;cache_lock);
+        mutex_unlock(&amp;cache_lock);
         return ret;
 }
 </programlisting>
@@ -853,7 +853,7 @@
          int popularity;
  };
 
--static DECLARE_MUTEX(cache_lock);
+-static DEFINE_MUTEX(cache_lock);
 +static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED;
  static LIST_HEAD(cache);
  static unsigned int cache_num = 0;
@@ -870,22 +870,22 @@
          obj-&gt;id = id;
          obj-&gt;popularity = 0;
 
--        down(&amp;cache_lock);
+-        mutex_lock(&amp;cache_lock);
 +        spin_lock_irqsave(&amp;cache_lock, flags);
          __cache_add(obj);
--        up(&amp;cache_lock);
+-        mutex_unlock(&amp;cache_lock);
 +        spin_unlock_irqrestore(&amp;cache_lock, flags);
          return 0;
  }
 
  void cache_delete(int id)
  {
--        down(&amp;cache_lock);
+-        mutex_lock(&amp;cache_lock);
 +        unsigned long flags;
 +
 +        spin_lock_irqsave(&amp;cache_lock, flags);
          __cache_delete(__cache_find(id));
--        up(&amp;cache_lock);
+-        mutex_unlock(&amp;cache_lock);
 +        spin_unlock_irqrestore(&amp;cache_lock, flags);
  }
 
@@ -895,14 +895,14 @@
          int ret = -ENOENT;
 +        unsigned long flags;
 
--        down(&amp;cache_lock);
+-        mutex_lock(&amp;cache_lock);
 +        spin_lock_irqsave(&amp;cache_lock, flags);
          obj = __cache_find(id);
          if (obj) {
                  ret = 0;
                  strcpy(name, obj-&gt;name);
          }
--        up(&amp;cache_lock);
+-        mutex_unlock(&amp;cache_lock);
 +        spin_unlock_irqrestore(&amp;cache_lock, flags);
          return ret;
  }
diff --git a/Documentation/fb/deferred_io.txt b/Documentation/fb/deferred_io.txt
index 63883a8..7483283 100644
--- a/Documentation/fb/deferred_io.txt
+++ b/Documentation/fb/deferred_io.txt
@@ -7,10 +7,10 @@
 works:
 
 - userspace app like Xfbdev mmaps framebuffer
-- deferred IO and driver sets up nopage and page_mkwrite handlers
+- deferred IO and driver sets up fault and page_mkwrite handlers
 - userspace app tries to write to mmaped vaddress
-- we get pagefault and reach nopage handler
-- nopage handler finds and returns physical page
+- we get pagefault and reach fault handler
+- fault handler finds and returns physical page
 - we get page_mkwrite where we add this page to a list
 - schedule a workqueue task to be run after a delay
 - app continues writing to that page with no additional cost. this is
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a7d9d17..68ce130 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -208,13 +208,6 @@
 
 ---------------------------
 
-What:  drivers depending on OSS_OBSOLETE
-When:  options in 2.6.23, code in 2.6.25
-Why:   obsolete OSS drivers
-Who:   Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What: libata spindown skipping and warning
 When: Dec 2008
 Why:  Some halt(8) implementations synchronize caches for and spin
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index e2799b5..5681e2f 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -1029,6 +1029,14 @@
 Denotes the  number  of  inodes the system has allocated. This number will
 grow and shrink dynamically.
 
+nr_open
+-------
+
+Denotes the maximum number of file-handles a process can
+allocate. Default value is 1024*1024 (1048576) which should be
+enough for most machines. Actual limit depends on RLIMIT_NOFILE
+resource limit.
+
 nr_free_inodes
 --------------
 
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 53a6389..30c1017 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -96,7 +96,9 @@
 The jprobe will work in either case, so long as the handler's
 prototype matches that of the probed function.
 
-1.3 How Does a Return Probe Work?
+1.3 Return Probes
+
+1.3.1 How Does a Return Probe Work?
 
 When you call register_kretprobe(), Kprobes establishes a kprobe at
 the entry to the function.  When the probed function is called and this
@@ -107,9 +109,9 @@
 
 When the probed function executes its return instruction, control
 passes to the trampoline and that probe is hit.  Kprobes' trampoline
-handler calls the user-specified handler associated with the kretprobe,
-then sets the saved instruction pointer to the saved return address,
-and that's where execution resumes upon return from the trap.
+handler calls the user-specified return handler associated with the
+kretprobe, then sets the saved instruction pointer to the saved return
+address, and that's where execution resumes upon return from the trap.
 
 While the probed function is executing, its return address is
 stored in an object of type kretprobe_instance.  Before calling
@@ -131,6 +133,30 @@
 time the probed function is entered but there is no kretprobe_instance
 object available for establishing the return probe.
 
+1.3.2 Kretprobe entry-handler
+
+Kretprobes also provides an optional user-specified handler which runs
+on function entry. This handler is specified by setting the entry_handler
+field of the kretprobe struct. Whenever the kprobe placed by kretprobe at the
+function entry is hit, the user-defined entry_handler, if any, is invoked.
+If the entry_handler returns 0 (success) then a corresponding return handler
+is guaranteed to be called upon function return. If the entry_handler
+returns a non-zero error then Kprobes leaves the return address as is, and
+the kretprobe has no further effect for that particular function instance.
+
+Multiple entry and return handler invocations are matched using the unique
+kretprobe_instance object associated with them. Additionally, a user
+may also specify per return-instance private data to be part of each
+kretprobe_instance object. This is especially useful when sharing private
+data between corresponding user entry and return handlers. The size of each
+private data object can be specified at kretprobe registration time by
+setting the data_size field of the kretprobe struct. This data can be
+accessed through the data field of each kretprobe_instance object.
+
+In case probed function is entered but there is no kretprobe_instance
+object available, then in addition to incrementing the nmissed count,
+the user entry_handler invocation is also skipped.
+
 2. Architectures Supported
 
 Kprobes, jprobes, and return probes are implemented on the following
@@ -274,6 +300,8 @@
 - ret_addr: the return address
 - rp: points to the corresponding kretprobe object
 - task: points to the corresponding task struct
+- data: points to per return-instance private data; see "Kretprobe
+	entry-handler" for details.
 
 The regs_return_value(regs) macro provides a simple abstraction to
 extract the return value from the appropriate register as defined by
@@ -556,23 +584,52 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kprobes.h>
+#include <linux/ktime.h>
+
+/* per-instance private data */
+struct my_data {
+	ktime_t entry_stamp;
+};
 
 static const char *probed_func = "sys_open";
 
-/* Return-probe handler: If the probed function fails, log the return value. */
-static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+/* Timestamp function entry. */
+static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	struct my_data *data;
+
+	if(!current->mm)
+		return 1; /* skip kernel threads */
+
+	data = (struct my_data *)ri->data;
+	data->entry_stamp = ktime_get();
+	return 0;
+}
+
+/* If the probed function failed, log the return value and duration.
+ * Duration may turn out to be zero consistently, depending upon the
+ * granularity of time accounting on the platform. */
+static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
 	int retval = regs_return_value(regs);
+	struct my_data *data = (struct my_data *)ri->data;
+	s64 delta;
+	ktime_t now;
+
 	if (retval < 0) {
-		printk("%s returns %d\n", probed_func, retval);
+		now = ktime_get();
+		delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
+		printk("%s: return val = %d (duration = %lld ns)\n",
+		       probed_func, retval, delta);
 	}
 	return 0;
 }
 
 static struct kretprobe my_kretprobe = {
-	.handler = ret_handler,
-	/* Probe up to 20 instances concurrently. */
-	.maxactive = 20
+	.handler = return_handler,
+	.entry_handler = entry_handler,
+	.data_size = sizeof(struct my_data),
+	.maxactive = 20, /* probe up to 20 instances concurrently */
 };
 
 static int __init kretprobe_init(void)
@@ -584,7 +641,7 @@
 		printk("register_kretprobe failed, returned %d\n", ret);
 		return -1;
 	}
-	printk("Planted return probe at %p\n", my_kretprobe.kp.addr);
+	printk("Kretprobe active on %s\n", my_kretprobe.kp.symbol_name);
 	return 0;
 }
 
@@ -594,7 +651,7 @@
 	printk("kretprobe unregistered\n");
 	/* nmissed > 0 suggests that maxactive was set too low. */
 	printk("Missed probing %d instances of %s\n",
-		my_kretprobe.nmissed, probed_func);
+	       my_kretprobe.nmissed, probed_func);
 }
 
 module_init(kretprobe_init)
diff --git a/Documentation/kref.txt b/Documentation/kref.txt
index f38b59d..130b6e8 100644
--- a/Documentation/kref.txt
+++ b/Documentation/kref.txt
@@ -141,10 +141,10 @@
 instance, you have a list of items that are each kref-ed, and you wish
 to get the first one.  You can't just pull the first item off the list
 and kref_get() it.  That violates rule 3 because you are not already
-holding a valid pointer.  You must add locks or semaphores.  For
-instance:
+holding a valid pointer.  You must add a mutex (or some other lock).
+For instance:
 
-static DECLARE_MUTEX(sem);
+static DEFINE_MUTEX(mutex);
 static LIST_HEAD(q);
 struct my_data
 {
@@ -155,12 +155,12 @@
 static struct my_data *get_entry()
 {
 	struct my_data *entry = NULL;
-	down(&sem);
+	mutex_lock(&mutex);
 	if (!list_empty(&q)) {
 		entry = container_of(q.next, struct my_q_entry, link);
 		kref_get(&entry->refcount);
 	}
-	up(&sem);
+	mutex_unlock(&mutex);
 	return entry;
 }
 
@@ -174,9 +174,9 @@
 
 static void put_entry(struct my_data *entry)
 {
-	down(&sem);
+	mutex_lock(&mutex);
 	kref_put(&entry->refcount, release_entry);
-	up(&sem);
+	mutex_unlock(&mutex);
 }
 
 The kref_put() return value is useful if you do not want to hold the
@@ -191,13 +191,13 @@
 
 static void put_entry(struct my_data *entry)
 {
-	down(&sem);
+	mutex_lock(&mutex);
 	if (kref_put(&entry->refcount, release_entry)) {
 		list_del(&entry->link);
-		up(&sem);
+		mutex_unlock(&mutex);
 		kfree(entry);
 	} else
-		up(&sem);
+		mutex_unlock(&mutex);
 }
 
 This is really more useful if you have to call other routines as part
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 5818628..396cdd9 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -416,6 +416,16 @@
      sectors in total that could need to be processed.  The two
      numbers are separated by a '/'  thus effectively showing one
      value, a fraction of the process that is complete.
+     A 'select' on this attribute will return when resync completes,
+     when it reaches the current sync_max (below) and possibly at
+     other times.
+
+   sync_max
+     This is a number of sectors at which point a resync/recovery
+     process will pause.  When a resync is active, the value can
+     only ever be increased, never decreased.  The value of 'max'
+     effectively disables the limit.
+
 
    sync_speed
      This shows the current actual speed, in K/sec, of the current
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index e20b19c..8deffcd 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -182,8 +182,8 @@
 	since the frequency is stored in the irq_freq member of the rtc_device
 	structure.  Your driver needs to initialize the irq_freq member during
 	init.  Make sure you check the requested frequency is in range of your
-	hardware in the irq_set_freq function.  If you cannot actually change
-	the frequency, just return -ENOTTY.
+	hardware in the irq_set_freq function.  If it isn't, return -EINVAL.  If
+	you cannot actually change the frequency, do not define irq_set_freq.
 
 If all else fails, check out the rtc-test.c driver!
 
@@ -268,8 +268,8 @@
 		/* This read will block */
 		retval = read(fd, &data, sizeof(unsigned long));
 		if (retval == -1) {
-		        perror("read");
-		        exit(errno);
+			perror("read");
+			exit(errno);
 		}
 		fprintf(stderr, " %d",i);
 		fflush(stderr);
@@ -326,11 +326,11 @@
 		rtc_tm.tm_sec %= 60;
 		rtc_tm.tm_min++;
 	}
-	if  (rtc_tm.tm_min == 60) {
+	if (rtc_tm.tm_min == 60) {
 		rtc_tm.tm_min = 0;
 		rtc_tm.tm_hour++;
 	}
-	if  (rtc_tm.tm_hour == 24)
+	if (rtc_tm.tm_hour == 24)
 		rtc_tm.tm_hour = 0;
 
 	retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
@@ -407,8 +407,8 @@
 					"\n...Periodic IRQ rate is fixed\n");
 				goto done;
 			}
-		        perror("RTC_IRQP_SET ioctl");
-		        exit(errno);
+			perror("RTC_IRQP_SET ioctl");
+			exit(errno);
 		}
 
 		fprintf(stderr, "\n%ldHz:\t", tmp);
@@ -417,27 +417,27 @@
 		/* Enable periodic interrupts */
 		retval = ioctl(fd, RTC_PIE_ON, 0);
 		if (retval == -1) {
-		        perror("RTC_PIE_ON ioctl");
-		        exit(errno);
+			perror("RTC_PIE_ON ioctl");
+			exit(errno);
 		}
 
 		for (i=1; i<21; i++) {
-		        /* This blocks */
-		        retval = read(fd, &data, sizeof(unsigned long));
-		        if (retval == -1) {
-				       perror("read");
-				       exit(errno);
-		        }
-		        fprintf(stderr, " %d",i);
-		        fflush(stderr);
-		        irqcount++;
+			/* This blocks */
+			retval = read(fd, &data, sizeof(unsigned long));
+			if (retval == -1) {
+				perror("read");
+				exit(errno);
+			}
+			fprintf(stderr, " %d",i);
+			fflush(stderr);
+			irqcount++;
 		}
 
 		/* Disable periodic interrupts */
 		retval = ioctl(fd, RTC_PIE_OFF, 0);
 		if (retval == -1) {
-		        perror("RTC_PIE_OFF ioctl");
-		        exit(errno);
+			perror("RTC_PIE_OFF ioctl");
+			exit(errno);
 		}
 	}
 
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index aa986a3..f992543 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -23,6 +23,7 @@
 - inode-max
 - inode-nr
 - inode-state
+- nr_open
 - overflowuid
 - overflowgid
 - suid_dumpable
@@ -91,6 +92,15 @@
 
 ==============================================================
 
+nr_open:
+
+This denotes the maximum number of file-handles a process can
+allocate. Default value is 1024*1024 (1048576) which should be
+enough for most machines. Actual limit depends on RLIMIT_NOFILE
+resource limit.
+
+==============================================================
+
 inode-max, inode-nr & inode-state:
 
 As with file handles, the kernel allocates the inode structures
diff --git a/Documentation/unaligned-memory-access.txt b/Documentation/unaligned-memory-access.txt
new file mode 100644
index 0000000..6223eac
--- /dev/null
+++ b/Documentation/unaligned-memory-access.txt
@@ -0,0 +1,226 @@
+UNALIGNED MEMORY ACCESSES
+=========================
+
+Linux runs on a wide variety of architectures which have varying behaviour
+when it comes to memory access. This document presents some details about
+unaligned accesses, why you need to write code that doesn't cause them,
+and how to write such code!
+
+
+The definition of an unaligned access
+=====================================
+
+Unaligned memory accesses occur when you try to read N bytes of data starting
+from an address that is not evenly divisible by N (i.e. addr % N != 0).
+For example, reading 4 bytes of data from address 0x10004 is fine, but
+reading 4 bytes of data from address 0x10005 would be an unaligned memory
+access.
+
+The above may seem a little vague, as memory access can happen in different
+ways. The context here is at the machine code level: certain instructions read
+or write a number of bytes to or from memory (e.g. movb, movw, movl in x86
+assembly). As will become clear, it is relatively easy to spot C statements
+which will compile to multiple-byte memory access instructions, namely when
+dealing with types such as u16, u32 and u64.
+
+
+Natural alignment
+=================
+
+The rule mentioned above forms what we refer to as natural alignment:
+When accessing N bytes of memory, the base memory address must be evenly
+divisible by N, i.e. addr % N == 0.
+
+When writing code, assume the target architecture has natural alignment
+requirements.
+
+In reality, only a few architectures require natural alignment on all sizes
+of memory access. However, we must consider ALL supported architectures;
+writing code that satisfies natural alignment requirements is the easiest way
+to achieve full portability.
+
+
+Why unaligned access is bad
+===========================
+
+The effects of performing an unaligned memory access vary from architecture
+to architecture. It would be easy to write a whole document on the differences
+here; a summary of the common scenarios is presented below:
+
+ - Some architectures are able to perform unaligned memory accesses
+   transparently, but there is usually a significant performance cost.
+ - Some architectures raise processor exceptions when unaligned accesses
+   happen. The exception handler is able to correct the unaligned access,
+   at significant cost to performance.
+ - Some architectures raise processor exceptions when unaligned accesses
+   happen, but the exceptions do not contain enough information for the
+   unaligned access to be corrected.
+ - Some architectures are not capable of unaligned memory access, but will
+   silently perform a different memory access to the one that was requested,
+   resulting a a subtle code bug that is hard to detect!
+
+It should be obvious from the above that if your code causes unaligned
+memory accesses to happen, your code will not work correctly on certain
+platforms and will cause performance problems on others.
+
+
+Code that does not cause unaligned access
+=========================================
+
+At first, the concepts above may seem a little hard to relate to actual
+coding practice. After all, you don't have a great deal of control over
+memory addresses of certain variables, etc.
+
+Fortunately things are not too complex, as in most cases, the compiler
+ensures that things will work for you. For example, take the following
+structure:
+
+	struct foo {
+		u16 field1;
+		u32 field2;
+		u8 field3;
+	};
+
+Let us assume that an instance of the above structure resides in memory
+starting at address 0x10000. With a basic level of understanding, it would
+not be unreasonable to expect that accessing field2 would cause an unaligned
+access. You'd be expecting field2 to be located at offset 2 bytes into the
+structure, i.e. address 0x10002, but that address is not evenly divisible
+by 4 (remember, we're reading a 4 byte value here).
+
+Fortunately, the compiler understands the alignment constraints, so in the
+above case it would insert 2 bytes of padding in between field1 and field2.
+Therefore, for standard structure types you can always rely on the compiler
+to pad structures so that accesses to fields are suitably aligned (assuming
+you do not cast the field to a type of different length).
+
+Similarly, you can also rely on the compiler to align variables and function
+parameters to a naturally aligned scheme, based on the size of the type of
+the variable.
+
+At this point, it should be clear that accessing a single byte (u8 or char)
+will never cause an unaligned access, because all memory addresses are evenly
+divisible by one.
+
+On a related topic, with the above considerations in mind you may observe
+that you could reorder the fields in the structure in order to place fields
+where padding would otherwise be inserted, and hence reduce the overall
+resident memory size of structure instances. The optimal layout of the
+above example is:
+
+	struct foo {
+		u32 field2;
+		u16 field1;
+		u8 field3;
+	};
+
+For a natural alignment scheme, the compiler would only have to add a single
+byte of padding at the end of the structure. This padding is added in order
+to satisfy alignment constraints for arrays of these structures.
+
+Another point worth mentioning is the use of __attribute__((packed)) on a
+structure type. This GCC-specific attribute tells the compiler never to
+insert any padding within structures, useful when you want to use a C struct
+to represent some data that comes in a fixed arrangement 'off the wire'.
+
+You might be inclined to believe that usage of this attribute can easily
+lead to unaligned accesses when accessing fields that do not satisfy
+architectural alignment requirements. However, again, the compiler is aware
+of the alignment constraints and will generate extra instructions to perform
+the memory access in a way that does not cause unaligned access. Of course,
+the extra instructions obviously cause a loss in performance compared to the
+non-packed case, so the packed attribute should only be used when avoiding
+structure padding is of importance.
+
+
+Code that causes unaligned access
+=================================
+
+With the above in mind, let's move onto a real life example of a function
+that can cause an unaligned memory access. The following function adapted
+from include/linux/etherdevice.h is an optimized routine to compare two
+ethernet MAC addresses for equality.
+
+unsigned int compare_ether_addr(const u8 *addr1, const u8 *addr2)
+{
+	const u16 *a = (const u16 *) addr1;
+	const u16 *b = (const u16 *) addr2;
+	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+}
+
+In the above function, the reference to a[0] causes 2 bytes (16 bits) to
+be read from memory starting at address addr1. Think about what would happen
+if addr1 was an odd address such as 0x10003. (Hint: it'd be an unaligned
+access.)
+
+Despite the potential unaligned access problems with the above function, it
+is included in the kernel anyway but is understood to only work on
+16-bit-aligned addresses. It is up to the caller to ensure this alignment or
+not use this function at all. This alignment-unsafe function is still useful
+as it is a decent optimization for the cases when you can ensure alignment,
+which is true almost all of the time in ethernet networking context.
+
+
+Here is another example of some code that could cause unaligned accesses:
+	void myfunc(u8 *data, u32 value)
+	{
+		[...]
+		*((u32 *) data) = cpu_to_le32(value);
+		[...]
+	}
+
+This code will cause unaligned accesses every time the data parameter points
+to an address that is not evenly divisible by 4.
+
+In summary, the 2 main scenarios where you may run into unaligned access
+problems involve:
+ 1. Casting variables to types of different lengths
+ 2. Pointer arithmetic followed by access to at least 2 bytes of data
+
+
+Avoiding unaligned accesses
+===========================
+
+The easiest way to avoid unaligned access is to use the get_unaligned() and
+put_unaligned() macros provided by the <asm/unaligned.h> header file.
+
+Going back to an earlier example of code that potentially causes unaligned
+access:
+
+	void myfunc(u8 *data, u32 value)
+	{
+		[...]
+		*((u32 *) data) = cpu_to_le32(value);
+		[...]
+	}
+
+To avoid the unaligned memory access, you would rewrite it as follows:
+
+	void myfunc(u8 *data, u32 value)
+	{
+		[...]
+		value = cpu_to_le32(value);
+		put_unaligned(value, (u32 *) data);
+		[...]
+	}
+
+The get_unaligned() macro works similarly. Assuming 'data' is a pointer to
+memory and you wish to avoid unaligned access, its usage is as follows:
+
+	u32 value = get_unaligned((u32 *) data);
+
+These macros work work for memory accesses of any length (not just 32 bits as
+in the examples above). Be aware that when compared to standard access of
+aligned memory, using these macros to access unaligned memory can be costly in
+terms of performance.
+
+If use of such macros is not convenient, another option is to use memcpy(),
+where the source or destination (or both) are of type u8* or unsigned char*.
+Due to the byte-wise nature of this operation, unaligned accesses are avoided.
+
+--
+Author: Daniel Drake <dsd@gentoo.org>
+With help from: Alan Cox, Avuton Olrich, Heikki Orsila, Jan Engelhardt,
+Johannes Berg, Kyle McMartin, Kyle Moffett, Randy Dunlap, Robert Hancock,
+Uli Kunitz, Vadim Lobanov
+
diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX
index 752613c..7b0ceaa 100644
--- a/Documentation/w1/masters/00-INDEX
+++ b/Documentation/w1/masters/00-INDEX
@@ -4,3 +4,5 @@
 	- The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses.
 ds2490
 	- The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges.
+w1-gpio
+	- GPIO 1-wire bus master driver.
diff --git a/Documentation/w1/masters/w1-gpio b/Documentation/w1/masters/w1-gpio
new file mode 100644
index 0000000..af5d3b4
--- /dev/null
+++ b/Documentation/w1/masters/w1-gpio
@@ -0,0 +1,33 @@
+Kernel driver w1-gpio
+=====================
+
+Author: Ville Syrjala <syrjala@sci.fi>
+
+
+Description
+-----------
+
+GPIO 1-wire bus master driver. The driver uses the GPIO API to control the
+wire and the GPIO pin can be specified using platform data.
+
+
+Example (mach-at91)
+-------------------
+
+#include <linux/w1-gpio.h>
+
+static struct w1_gpio_platform_data foo_w1_gpio_pdata = {
+	.pin		= AT91_PIN_PB20,
+	.is_open_drain	= 1,
+};
+
+static struct platform_device foo_w1_device = {
+	.name			= "w1-gpio",
+	.id			= -1,
+	.dev.platform_data	= &foo_w1_gpio_pdata,
+};
+
+...
+	at91_set_GPIO_periph(foo_w1_gpio_pdata.pin, 1);
+	at91_set_multi_drive(foo_w1_gpio_pdata.pin, 1);
+	platform_device_register(&foo_w1_device);
diff --git a/MAINTAINERS b/MAINTAINERS
index cffe13d..0885aa2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -338,13 +338,12 @@
 AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
 P:	Thomas Dahlmann
 M:	thomas.dahlmann@amd.com
-L:	info-linux@geode.amd.com
+L:	info-linux@geode.amd.com	(subscribers-only)
 S:	Supported
 
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
 P:	Jordan Crouse
-M:	info-linux@geode.amd.com
-L:	info-linux@geode.amd.com
+L:	info-linux@geode.amd.com	(subscribers-only)
 W:	http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:	Supported
 
@@ -841,6 +840,12 @@
 T:	git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
 S:	Maintained
 
+BLOCK2MTD DRIVER
+P:	Joern Engel
+M:	joern@lazybastard.org
+L:	linux-mtd@lists.infradead.org
+S:	Maintained
+
 BLUETOOTH SUBSYSTEM
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
@@ -3031,8 +3036,8 @@
 S:	Maintained
 
 PHRAM MTD DRIVER
-P:	Jörn Engel
-M:	joern@wh.fh-wedel.de
+P:	Joern Engel
+M:	joern@lazybastard.org
 L:	linux-mtd@lists.infradead.org
 S:	Maintained
 
@@ -3862,6 +3867,12 @@
 L:	linux-usb@vger.kernel.org
 S:	Maintained
 
+USB AUERSWALD DRIVER
+P:	Wolfgang Muees
+M:	wolfgang@iksw-muees.de
+L:      linux-usb@vger.kernel.org
+S:	Maintained
+
 USB BLOCK DRIVER (UB ub)
 P:	Pete Zaitcev
 M:	zaitcev@redhat.com
@@ -4012,12 +4023,6 @@
 W:	http://geocities.com/i0xox0i
 W:	http://firstlight.net/cvs
 
-USB AUERSWALD DRIVER
-P:	Wolfgang Muees
-M:	wolfgang@iksw-muees.de
-L:      linux-usb@vger.kernel.org
-S:	Maintained
-
 USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
 P:	Gary Brubaker
 M:	xavyer@ix.netcom.com
diff --git a/arch/alpha/Kconfig.debug b/arch/alpha/Kconfig.debug
index f45f28c..3f6265f 100644
--- a/arch/alpha/Kconfig.debug
+++ b/arch/alpha/Kconfig.debug
@@ -7,15 +7,6 @@
 	depends on ALPHA_GENERIC || ALPHA_SRM
 	default y
 
-config DEBUG_RWLOCK
-	bool "Read-write spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here then read-write lock processing will count how many
-	  times it has tried to get the lock and issue an error message after
-	  too many attempts.  If you suspect a rwlock problem or a kernel
-	  hacker asks for this option then say Y.  Otherwise say N.
-
 config ALPHA_LEGACY_START_ADDRESS
 	bool "Legacy kernel start address"
 	depends on ALPHA_GENERIC
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 6da9c3d..e43f68f 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -882,7 +882,6 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_EARLY_PRINTK=y
-# CONFIG_DEBUG_RWLOCK is not set
 # CONFIG_DEBUG_SEMAPHORE is not set
 CONFIG_ALPHA_LEGACY_START_ADDRESS=y
 CONFIG_MATHEMU=y
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 6413c5f..72f9a61 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -430,7 +430,7 @@
 asmlinkage unsigned long
 sys_getdtablesize(void)
 {
-	return NR_OPEN;
+	return sysctl_nr_open;
 }
 
 /*
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index f4ab233..63c2073 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -77,10 +77,6 @@
 int smp_num_cpus = 1;		/* Number that came online.  */
 EXPORT_SYMBOL(smp_num_cpus);
 
-extern void calibrate_delay(void);
-
-
-
 /*
  * Called by both boot and secondaries to move global data into
  *  per-processor storage.
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index aa29ea5..0ce38df 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -383,6 +383,7 @@
 }
 
 static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.lcdcon_is_backlight		= true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
 	.default_lcdcon2		= AT91SAM9261_DEFAULT_TFT_LCDCON2,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index f09347a8..38313ab 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -253,6 +253,7 @@
 
 /* Driver datas */
 static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+	.lcdcon_is_backlight		= true,
 	.default_bpp			= 16,
 	.default_dmacon			= ATMEL_LCDC_DMAEN,
 	.default_lcdcon2		= AT91SAM9263_DEFAULT_LCDCON2,
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index a454451..eca558c 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -17,7 +17,7 @@
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/serial_8250.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 
 #include <asm/elf.h>
 #include <asm/io.h>
diff --git a/arch/avr32/lib/delay.c b/arch/avr32/lib/delay.c
index b3bc0b5..9aa8800 100644
--- a/arch/avr32/lib/delay.c
+++ b/arch/avr32/lib/delay.c
@@ -12,13 +12,15 @@
 
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/timex.h>
 #include <linux/param.h>
 #include <linux/types.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 
-int read_current_timer(unsigned long *timer_value)
+int __devinit read_current_timer(unsigned long *timer_value)
 {
 	*timer_value = sysreg_read(COUNT);
 	return 0;
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index f8c411a..1795aab 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -37,7 +37,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/sl811.h>
diff --git a/arch/blackfin/mach-bf533/boards/H8606.c b/arch/blackfin/mach-bf533/boards/H8606.c
index a72c7a6..97378b0 100644
--- a/arch/blackfin/mach-bf533/boards/H8606.c
+++ b/arch/blackfin/mach-bf533/boards/H8606.c
@@ -38,7 +38,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 
 #include <asm/dma.h>
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 21df2f3..886f260 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index c37dd45..4026c2f 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index ac52b04..0185350 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -38,7 +38,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 8703b67..f7c1f96 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -36,7 +36,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 3e52f3f..8a3397d 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -38,7 +38,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/sl811.h>
diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c
index b8bbba8..d71e0be 100644
--- a/arch/blackfin/mach-bf537/boards/minotaur.c
+++ b/arch/blackfin/mach-bf537/boards/minotaur.c
@@ -10,7 +10,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb_isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb_sl811.h>
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 7725415..119e6ea 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -38,7 +38,7 @@
 #if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
 #include <linux/usb/isp1362.h>
 #endif
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/usb/sl811.h>
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 3a79a90..bf9e738 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -34,7 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/usb/isp1362.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/irq.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 7601c3b..ed863ce 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -35,7 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <asm/dma.h>
 #include <asm/bfin5xx_spi.h>
 #include <asm/portmux.h>
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index a74c087..b38ae1f 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -708,7 +708,7 @@
 /*
  * calibrate the delay loop
  */
-void __init calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
 {
 	loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ);
 
diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c
index 8dec4dd..5a1b4cf 100644
--- a/arch/h8300/kernel/irq.c
+++ b/arch/h8300/kernel/irq.c
@@ -14,6 +14,7 @@
 #include <linux/random.h>
 #include <linux/bootmem.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/traps.h>
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 480b1a5..32ee597 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -120,7 +120,6 @@
 
 #define DEBUG_ITC_SYNC	0
 
-extern void __devinit calibrate_delay (void);
 extern void start_ap (void);
 extern unsigned long ia64_iobase;
 
@@ -477,7 +476,7 @@
 	return 0;
 }
 
-struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
 {
 	return NULL;
 }
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index ab3eaf8..2c676cc 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -100,11 +100,11 @@
 static irqreturn_t
 pcibr_error_intr_handler(int irq, void *arg)
 {
-	struct pcibus_info *soft = (struct pcibus_info *)arg;
+	struct pcibus_info *soft = arg;
 
-	if (sal_pcibr_error_interrupt(soft) < 0) {
+	if (sal_pcibr_error_interrupt(soft) < 0)
 		panic("pcibr_error_intr_handler(): Fatal Bridge Error");
-	}
+
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index d10726f..cbe3653 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -32,12 +32,10 @@
     if (!AMIGAHW_PRESENT(CHIP_RAM))
 	return;
 
-#ifndef CONFIG_APUS_FAST_EXCEPT
     /*
      *  Remove the first 4 pages where PPC exception handlers will be located
      */
     amiga_chip_size -= 0x4000;
-#endif
     chipram_res.end = amiga_chip_size-1;
     request_resource(&iomem_resource, &chipram_res);
 
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index c4a4ffd..343fab4 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -84,7 +84,7 @@
 
 static irqreturn_t cia_handler(int irq, void *dev_id)
 {
-	struct ciabase *base = (struct ciabase *)dev_id;
+	struct ciabase *base = dev_id;
 	int mach_irq;
 	unsigned char ints;
 
diff --git a/arch/m68knommu/lib/memcpy.c b/arch/m68knommu/lib/memcpy.c
index 0d55775..b50dbca 100644
--- a/arch/m68knommu/lib/memcpy.c
+++ b/arch/m68knommu/lib/memcpy.c
@@ -1,6 +1,5 @@
 
 #include <linux/types.h>
-#include <linux/autoconf.h>
 
 void * memcpy(void * to, const void * from, size_t n)
 {
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index 8527856..0b658f1 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -27,7 +27,6 @@
  * 	others have a second one : GPIO2
  */
 
-#include <linux/autoconf.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/types.h>
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 1e5dfc2..9d41dab 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -52,7 +52,6 @@
 EXPORT_SYMBOL(phys_cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 
-extern void __init calibrate_delay(void);
 extern void cpu_idle(void);
 
 /* Number of TCs (or siblings in Intel speak) per CPU core */
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 4c477c7..22fd41e 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -356,7 +356,7 @@
 			retval = NGROUPS_MAX;
 			goto out;
 		case 5:
-			retval = NR_OPEN;
+			retval = sysctl_nr_open;
 			goto out;
 		case 6:
 			retval = 1;
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index 9166bd1..bc989e5 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -2,15 +2,6 @@
 
 source "lib/Kconfig.debug"
 
-config DEBUG_RWLOCK
-        bool "Read-write spinlock debugging"
-        depends on DEBUG_KERNEL && SMP
-        help
-          If you say Y here then read-write lock processing will count how many
-          times it has tried to get the lock and issue an error message after
-          too many attempts.  If you suspect a rwlock problem or a kernel
-          hacker asks for this option then say Y.  Otherwise say N.
-
 config DEBUG_RODATA
        bool "Write protect kernel read-only data structures"
        depends on DEBUG_KERNEL
diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
index ea07121..ddacc72 100644
--- a/arch/parisc/configs/a500_defconfig
+++ b/arch/parisc/configs/a500_defconfig
@@ -1050,7 +1050,6 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_FAULT_INJECTION is not set
-# CONFIG_DEBUG_RWLOCK is not set
 # CONFIG_DEBUG_RODATA is not set
 
 #
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 5cd3db5..3b26fbd6 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -66,6 +66,7 @@
 #include <asm/smp.h>
 #include <asm/vdso_datapage.h>
 #include <asm/firmware.h>
+#include <asm/cputime.h>
 #ifdef CONFIG_PPC_ISERIES
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/hv_call_xm.h>
@@ -189,6 +190,8 @@
 EXPORT_SYMBOL(__cputime_sec_factor);
 u64 __cputime_clockt_factor;
 EXPORT_SYMBOL(__cputime_clockt_factor);
+DEFINE_PER_CPU(unsigned long, cputime_last_delta);
+DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
 
 static void calc_cputime_factors(void)
 {
@@ -257,8 +260,8 @@
 	}
 	account_system_time(tsk, 0, delta);
 	account_system_time_scaled(tsk, deltascaled);
-	get_paca()->purrdelta = delta;
-	get_paca()->spurrdelta = deltascaled;
+	per_cpu(cputime_last_delta, smp_processor_id()) = delta;
+	per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled;
 	local_irq_restore(flags);
 }
 
@@ -276,10 +279,7 @@
 	get_paca()->user_time = 0;
 	account_user_time(tsk, utime);
 
-	/* Estimate the scaled utime by scaling the real utime based
-	 * on the last spurr to purr ratio */
-	utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta;
-	get_paca()->spurrdelta = get_paca()->purrdelta = 0;
+	utimescaled = cputime_to_scaled(utime);
 	account_user_time_scaled(tsk, utimescaled);
 }
 
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index c04abcc..792d3ce 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -113,8 +113,6 @@
 	 * result. We backup/restore the value to avoid affecting the
 	 * core cpufreq framework's own calculation.
 	 */
-	extern void calibrate_delay(void);
-
 	unsigned long save_lpj = loops_per_jiffy;
 	calibrate_delay();
 	loops_per_jiffy = save_lpj;
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 25ef55ba..ec1defe 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -418,7 +418,7 @@
 	struct	sk_buff *skb;
 	ushort	pkt_len;
 
-	cep = (struct scc_enet_private *)dev->priv;
+	cep = dev->priv;
 
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index a3a27da..bcc3aa9 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -682,7 +682,7 @@
 	struct	sk_buff *skb;
 	ushort	pkt_len;
 
-	cep = (struct fcc_enet_private *)dev->priv;
+	cep = dev->priv;
 
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 52b64fc..8a24bc4 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -143,11 +143,6 @@
 
   . = ALIGN(4096);
   __init_end = .;
-
-  . = ALIGN(4096);
-  _sextratext = .;
-  _eextratext = .;
-
   __bss_start = .;
   .bss       :
   {
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 3c56654..3844985 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -91,20 +91,11 @@
 #define cached_21	(((char *)(ppc_cached_irq_mask))[3])
 #define cached_A1	(((char *)(ppc_cached_irq_mask))[2])
 
-#ifdef CONFIG_SOUND_CS4232
-long ppc_cs4232_dma, ppc_cs4232_dma2;
-#endif
-
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern int probingmem;
 extern unsigned long loops_per_jiffy;
 
-#ifdef CONFIG_SOUND_CS4232
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
-
 /* useful ISA ports */
 #define PREP_SYSCTL	0x81c
 /* present in the IBM reference design; possibly identical in Mot boxes: */
@@ -569,74 +560,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SOUND_CS4232
-static long __init masktoint(unsigned int i)
-{
-	int t = -1;
-	while (i >> ++t)
-		;
-	return (t-1);
-}
-
-/*
- * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
- * to distinguish sound dma-channels from others. This is because
- * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
- * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
- */
-
-static void __init prep_init_sound(void)
-{
-	PPC_DEVICE *audiodevice = NULL;
-
-	/*
-	 * Get the needed resource information from residual data.
-	 *
-	 */
-	if (have_residual_data)
-		audiodevice = residual_find_device(~0, NULL,
-				MultimediaController, AudioController, -1, 0);
-
-	if (audiodevice != NULL) {
-		PnP_TAG_PACKET *pkt;
-
-		pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
-				S5_Packet, 0);
-		if (pkt != NULL)
-			ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
-		pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
-				S5_Packet, 1);
-		if (pkt != NULL)
-			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
-	}
-
-	/*
-	 * These are the PReP specs' defaults for the cs4231.  We use these
-	 * as fallback incase we don't have residual data.
-	 * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
-	 * will use the other values.
-	 */
-	if (audiodevice == NULL) {
-		switch (_prep_type) {
-		case _PREP_IBM:
-			ppc_cs4232_dma = 1;
-			ppc_cs4232_dma2 = -1;
-			break;
-		default:
-			ppc_cs4232_dma = 6;
-			ppc_cs4232_dma2 = 7;
-		}
-	}
-
-	/*
-	 * Find a way to push this information to the cs4232 driver
-	 * Give it out with printk, when not in cmd_line?
-	 * Append it to cmd_line and boot_command_line?
-	 * Format is cs4232=io,irq,dma,dma2
-	 */
-}
-#endif /* CONFIG_SOUND_CS4232 */
-
 /*
  * Fill out screen_info according to the residual data. This allows us to use
  * at least vesafb.
@@ -898,10 +821,6 @@
 		}
 	}
 
-#ifdef CONFIG_SOUND_CS4232
-	prep_init_sound();
-#endif /* CONFIG_SOUND_CS4232 */
-
 	prep_init_vesa();
 
 	switch (_prep_type) {
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index eda7176..2b708ec 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -14,7 +14,7 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/pm.h>
 #include <linux/mm.h>
 #include <asm/machvec.h>
diff --git a/arch/sh/boards/lboxre2/setup.c b/arch/sh/boards/lboxre2/setup.c
index 9c830fd..c74440d 100644
--- a/arch/sh/boards/lboxre2/setup.c
+++ b/arch/sh/boards/lboxre2/setup.c
@@ -13,7 +13,7 @@
 
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <asm/machvec.h>
 #include <asm/addrspace.h>
 #include <asm/lboxre2.h>
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index a43b477..f7a8d5c 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -15,7 +15,7 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/types.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 3452b07..a0ef81b 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -10,7 +10,7 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/serial_8250.h>
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
diff --git a/arch/sh/boards/renesas/sdk7780/setup.c b/arch/sh/boards/renesas/sdk7780/setup.c
index 5df32f2..acc5932 100644
--- a/arch/sh/boards/renesas/sdk7780/setup.c
+++ b/arch/sh/boards/renesas/sdk7780/setup.c
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <asm/machvec.h>
 #include <asm/sdk7780.h>
 #include <asm/heartbeat.h>
diff --git a/arch/sh/boards/se/7722/setup.c b/arch/sh/boards/se/7722/setup.c
index eb97dca..b1a3d9d 100644
--- a/arch/sh/boards/se/7722/setup.c
+++ b/arch/sh/boards/se/7722/setup.c
@@ -12,7 +12,7 @@
  */
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <asm/machvec.h>
 #include <asm/se7722.h>
 #include <asm/io.h>
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 89a6de95..0def481 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -19,12 +19,12 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/profile.h>
+#include <linux/delay.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 #include <asm/irq_regs.h>
 
-#include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -41,8 +41,6 @@
 
 extern ctxd_t *srmmu_ctx_table_phys;
 
-extern void calibrate_delay(void);
-
 static volatile int smp_processors_ready = 0;
 static int smp_highest_cpu;
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 730eb57..0b94072 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -16,6 +16,8 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/profile.h>
+#include <linux/delay.h>
+
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/irq_regs.h>
@@ -23,7 +25,6 @@
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 
-#include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -39,8 +40,6 @@
 
 extern ctxd_t *srmmu_ctx_table_phys;
 
-extern void calibrate_delay(void);
-
 extern volatile unsigned long cpu_callin_map[NR_CPUS];
 extern unsigned char boot_cpu_id;
 
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index ee010f4..9064485 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -79,7 +79,8 @@
 /*295*/	.long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/	.long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
 /*305*/	.long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/	.long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
+/*310*/	.long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+/*315*/	.long sys_timerfd_settime, sys_timerfd_gettime
 
 #ifdef CONFIG_SUNOS_EMUL
 	/* Now the SunOS syscall table. */
@@ -197,6 +198,7 @@
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys
 /*310*/	.long sunos_nosys, sunos_nosys, sunos_nosys
-	.long sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys
 
 #endif
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f62d9f6..833d74b 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.24-rc4
-# Tue Dec  4 00:37:59 2007
+# Linux kernel version: 2.6.24
+# Tue Feb  5 17:28:19 2008
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -17,6 +17,7 @@
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
@@ -30,13 +31,15 @@
 # CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_HOTPLUG_CPU=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # General setup
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
@@ -76,6 +79,7 @@
 CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_VM_EVENT_COUNTERS=y
@@ -83,6 +87,14 @@
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=m
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -92,6 +104,7 @@
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_BLK_DEV_BSG=y
@@ -109,6 +122,8 @@
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_PREEMPT_RCU is not set
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_GENERIC_HARDIRQS=y
 
@@ -119,7 +134,8 @@
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-# CONFIG_SMP is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=64
 # CONFIG_CPU_FREQ is not set
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -169,9 +185,12 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_SOLARIS_EMUL=y
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
+# CONFIG_RCU_TRACE is not set
 # CONFIG_CMDLINE_BOOL is not set
 
 #
@@ -189,6 +208,7 @@
 CONFIG_XFRM_USER=m
 # CONFIG_XFRM_SUB_POLICY is not set
 CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
 CONFIG_NET_KEY=m
 CONFIG_NET_KEY_MIGRATE=y
 CONFIG_INET=y
@@ -249,9 +269,9 @@
 CONFIG_IP_DCCP_CCID2=m
 # CONFIG_IP_DCCP_CCID2_DEBUG is not set
 CONFIG_IP_DCCP_CCID3=m
-CONFIG_IP_DCCP_TFRC_LIB=m
 # CONFIG_IP_DCCP_CCID3_DEBUG is not set
 CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=m
 
 #
 # DCCP Kernel Hacking
@@ -279,6 +299,7 @@
 CONFIG_NET_PKTGEN=m
 CONFIG_NET_TCPPROBE=m
 # CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
@@ -343,6 +364,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
@@ -359,7 +381,6 @@
 # PCI IDE chipsets support
 #
 CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
 CONFIG_IDEPCI_PCIBUS_ORDER=y
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -389,7 +410,6 @@
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_BLK_DEV_TC86C001 is not set
-# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDE_ARCH_OBSOLETE_INIT=y
 # CONFIG_BLK_DEV_HD is not set
@@ -501,7 +521,6 @@
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
-# CONFIG_IP1000 is not set
 # CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
@@ -533,6 +552,7 @@
 # CONFIG_NE2K_PCI is not set
 # CONFIG_8139CP is not set
 # CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -545,6 +565,9 @@
 CONFIG_E1000_NAPI=y
 # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_E1000E is not set
+# CONFIG_E1000E_ENABLED is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -570,6 +593,7 @@
 CONFIG_NIU=m
 # CONFIG_MLX4_CORE is not set
 # CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
 # CONFIG_TR is not set
 
 #
@@ -602,7 +626,6 @@
 # CONFIG_SLIP is not set
 CONFIG_SLHC=m
 # CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
@@ -679,6 +702,7 @@
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
 
 #
 # Serial drivers
@@ -747,13 +771,13 @@
 #
 # Miscellaneous I2C Chip support
 #
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
 # CONFIG_DS1682 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_TPS65010 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -990,6 +1014,7 @@
 # CONFIG_SND_BT87X is not set
 # CONFIG_SND_CA0106 is not set
 # CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_DARLA20 is not set
@@ -1014,6 +1039,7 @@
 # CONFIG_SND_HDA_INTEL is not set
 # CONFIG_SND_HDSP is not set
 # CONFIG_SND_HDSPM is not set
+# CONFIG_SND_HIFIER is not set
 # CONFIG_SND_ICE1712 is not set
 # CONFIG_SND_ICE1724 is not set
 # CONFIG_SND_INTEL8X0 is not set
@@ -1031,6 +1057,7 @@
 # CONFIG_SND_TRIDENT is not set
 # CONFIG_SND_VIA82XX is not set
 # CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
 # CONFIG_SND_AC97_POWER_SAVE is not set
@@ -1058,6 +1085,10 @@
 #
 
 #
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
 # Open Sound System
 #
 # CONFIG_SOUND_PRIME is not set
@@ -1080,6 +1111,7 @@
 CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
@@ -1093,7 +1125,6 @@
 # USB Host Controller Drivers
 #
 CONFIG_USB_EHCI_HCD=m
-# 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
@@ -1143,10 +1174,6 @@
 #
 # USB port drivers
 #
-
-#
-# USB Serial Converter support
-#
 # CONFIG_USB_SERIAL is not set
 
 #
@@ -1172,14 +1199,6 @@
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
-
-#
-# USB DSL modem support
-#
-
-#
-# USB Gadget Support
-#
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
 # CONFIG_NEW_LEDS is not set
@@ -1332,11 +1351,6 @@
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 # CONFIG_DLM is not set
-CONFIG_INSTRUMENTATION=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_KPROBES=y
-# CONFIG_MARKERS is not set
 
 #
 # Kernel hacking
@@ -1374,6 +1388,8 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_LKDTM is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_SAMPLES is not set
@@ -1396,8 +1412,9 @@
 CONFIG_ASYNC_XOR=m
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD=y
 CONFIG_CRYPTO_BLKCIPHER=y
+# CONFIG_CRYPTO_SEQIV is not set
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
@@ -1416,6 +1433,9 @@
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_XTS=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CCM is not set
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_FCRYPT=m
@@ -1431,13 +1451,16 @@
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_SEED=m
+# CONFIG_CRYPTO_SALSA20 is not set
 CONFIG_CRYPTO_DEFLATE=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_CAMELLIA=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_AUTHENC=m
+# CONFIG_CRYPTO_LZO is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
 
 #
 # Library routines
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index ef50d21..4b78b24 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -11,7 +11,7 @@
 		   traps.o auxio.o una_asm.o sysfs.o iommu.o \
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
-		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
+		   power.o sbus.o sparc64_ksyms.o chmc.o \
 		   visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 4b9115a..5623a4d 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -472,94 +472,15 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-#define SG_ENT_PHYS_ADDRESS(SG)	(__pa(sg_virt((SG))))
-
-static void fill_sg(iopte_t *iopte, struct scatterlist *sg,
-		    int nused, int nelems,
-		    unsigned long iopte_protection)
-{
-	struct scatterlist *dma_sg = sg;
-	int i;
-
-	for (i = 0; i < nused; i++) {
-		unsigned long pteval = ~0UL;
-		u32 dma_npages;
-
-		dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
-			      dma_sg->dma_length +
-			      ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
-		do {
-			unsigned long offset;
-			signed int len;
-
-			/* If we are here, we know we have at least one
-			 * more page to map.  So walk forward until we
-			 * hit a page crossing, and begin creating new
-			 * mappings from that spot.
-			 */
-			for (;;) {
-				unsigned long tmp;
-
-				tmp = SG_ENT_PHYS_ADDRESS(sg);
-				len = sg->length;
-				if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = tmp & IO_PAGE_MASK;
-					offset = tmp & (IO_PAGE_SIZE - 1UL);
-					break;
-				}
-				if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
-					offset = 0UL;
-					len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
-					break;
-				}
-				sg = sg_next(sg);
-				nelems--;
-			}
-
-			pteval = iopte_protection | (pteval & IOPTE_PAGE);
-			while (len > 0) {
-				*iopte++ = __iopte(pteval);
-				pteval += IO_PAGE_SIZE;
-				len -= (IO_PAGE_SIZE - offset);
-				offset = 0;
-				dma_npages--;
-			}
-
-			pteval = (pteval & IOPTE_PAGE) + len;
-			sg = sg_next(sg);
-			nelems--;
-
-			/* Skip over any tail mappings we've fully mapped,
-			 * adjusting pteval along the way.  Stop when we
-			 * detect a page crossing event.
-			 */
-			while (nelems &&
-			       (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
-			       (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
-			       ((pteval ^
-				 (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
-				pteval += sg->length;
-				sg = sg_next(sg);
-				nelems--;
-			}
-			if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
-				pteval = ~0UL;
-		} while (dma_npages != 0);
-		dma_sg = sg_next(dma_sg);
-	}
-}
-
 static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 {
-	struct iommu *iommu;
+	unsigned long flags, ctx, i, npages, iopte_protection;
+	struct scatterlist *sg;
 	struct strbuf *strbuf;
-	unsigned long flags, ctx, npages, iopte_protection;
+	struct iommu *iommu;
 	iopte_t *base;
 	u32 dma_base;
-	struct scatterlist *sgtmp;
-	int used;
 
 	/* Fast path single entry scatterlists. */
 	if (nelems == 1) {
@@ -578,11 +499,7 @@
 	if (unlikely(direction == DMA_NONE))
 		goto bad_no_ctx;
 
-	/* Step 1: Prepare scatter list. */
-
-	npages = prepare_sg(dev, sglist, nelems);
-
-	/* Step 2: Allocate a cluster and context, if necessary. */
+	npages = calc_npages(sglist, nelems);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
@@ -599,18 +516,6 @@
 	dma_base = iommu->page_table_map_base +
 		((base - iommu->page_table) << IO_PAGE_SHIFT);
 
-	/* Step 3: Normalize DMA addresses. */
-	used = nelems;
-
-	sgtmp = sglist;
-	while (used && sgtmp->dma_length) {
-		sgtmp->dma_address += dma_base;
-		sgtmp = sg_next(sgtmp);
-		used--;
-	}
-	used = nelems - used;
-
-	/* Step 4: Create the mappings. */
 	if (strbuf->strbuf_enabled)
 		iopte_protection = IOPTE_STREAMING(ctx);
 	else
@@ -618,13 +523,27 @@
 	if (direction != DMA_TO_DEVICE)
 		iopte_protection |= IOPTE_WRITE;
 
-	fill_sg(base, sglist, used, nelems, iopte_protection);
+	for_each_sg(sglist, sg, nelems, i) {
+		unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
+		unsigned long slen = sg->length;
+		unsigned long this_npages;
 
-#ifdef VERIFY_SG
-	verify_sglist(sglist, nelems, base, npages);
-#endif
+		this_npages = iommu_num_pages(paddr, slen);
 
-	return used;
+		sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
+		sg->dma_length = slen;
+
+		paddr &= IO_PAGE_MASK;
+		while (this_npages--) {
+			iopte_val(*base) = iopte_protection | paddr;
+
+			base++;
+			paddr += IO_PAGE_SIZE;
+			dma_base += IO_PAGE_SIZE;
+		}
+	}
+
+	return nelems;
 
 bad:
 	iommu_free_ctx(iommu, ctx);
@@ -637,11 +556,10 @@
 static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 {
-	struct iommu *iommu;
-	struct strbuf *strbuf;
-	iopte_t *base;
 	unsigned long flags, ctx, i, npages;
-	struct scatterlist *sg, *sgprv;
+	struct strbuf *strbuf;
+	struct iommu *iommu;
+	iopte_t *base;
 	u32 bus_addr;
 
 	if (unlikely(direction == DMA_NONE)) {
@@ -654,15 +572,7 @@
 
 	bus_addr = sglist->dma_address & IO_PAGE_MASK;
 
-	sgprv = NULL;
-	for_each_sg(sglist, sg, nelems, i) {
-		if (sg->dma_length == 0)
-			break;
-		sgprv = sg;
-	}
-
-	npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
-		  bus_addr) >> IO_PAGE_SHIFT;
+	npages = calc_npages(sglist, nelems);
 
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
deleted file mode 100644
index 72a4acf..0000000
--- a/arch/sparc64/kernel/iommu_common.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* $Id: iommu_common.c,v 1.9 2001/12/17 07:05:09 davem Exp $
- * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
- *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- */
-
-#include <linux/dma-mapping.h>
-#include "iommu_common.h"
-
-/* You are _strongly_ advised to enable the following debugging code
- * any time you make changes to the sg code below, run it for a while
- * with filesystems mounted read-only before buying the farm... -DaveM
- */
-
-#ifdef VERIFY_SG
-static int verify_lengths(struct scatterlist *sglist, int nents, int npages)
-{
-	int sg_len, dma_len;
-	int i, pgcount;
-	struct scatterlist *sg;
-
-	sg_len = 0;
-	for_each_sg(sglist, sg, nents, i)
-		sg_len += sg->length;
-
-	dma_len = 0;
-	for_each_sg(sglist, sg, nents, i) {
-		if (!sg->dma_length)
-			break;
-		dma_len += sg->dma_length;
-	}
-
-	if (sg_len != dma_len) {
-		printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
-		       sg_len, dma_len);
-		return -1;
-	}
-
-	pgcount = 0;
-	for_each_sg(sglist, sg, nents, i) {
-		unsigned long start, end;
-
-		if (!sg->dma_length)
-			break;
-
-		start = sg->dma_address;
-		start = start & IO_PAGE_MASK;
-
-		end = sg->dma_address + sg->dma_length;
-		end = (end + (IO_PAGE_SIZE - 1)) & IO_PAGE_MASK;
-
-		pgcount += ((end - start) >> IO_PAGE_SHIFT);
-	}
-
-	if (pgcount != npages) {
-		printk("verify_lengths: Error, page count wrong, "
-		       "npages[%d] pgcount[%d]\n",
-		       npages, pgcount);
-		return -1;
-	}
-
-	/* This test passes... */
-	return 0;
-}
-
-static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte)
-{
-	struct scatterlist *sg = *__sg;
-	iopte_t *iopte = *__iopte;
-	u32 dlen = dma_sg->dma_length;
-	u32 daddr;
-	unsigned int sglen;
-	unsigned long sgaddr;
-
-	daddr = dma_sg->dma_address;
-	sglen = sg->length;
-	sgaddr = (unsigned long) sg_virt(sg);
-	while (dlen > 0) {
-		unsigned long paddr;
-
-		/* SG and DMA_SG must begin at the same sub-page boundary. */
-		if ((sgaddr & ~IO_PAGE_MASK) != (daddr & ~IO_PAGE_MASK)) {
-			printk("verify_one_map: Wrong start offset "
-			       "sg[%08lx] dma[%08x]\n",
-			       sgaddr, daddr);
-			nents = -1;
-			goto out;
-		}
-
-		/* Verify the IOPTE points to the right page. */
-		paddr = iopte_val(*iopte) & IOPTE_PAGE;
-		if ((paddr + PAGE_OFFSET) != (sgaddr & IO_PAGE_MASK)) {
-			printk("verify_one_map: IOPTE[%08lx] maps the "
-			       "wrong page, should be [%08lx]\n",
-			       iopte_val(*iopte), (sgaddr & IO_PAGE_MASK) - PAGE_OFFSET);
-			nents = -1;
-			goto out;
-		}
-
-		/* If this SG crosses a page, adjust to that next page
-		 * boundary and loop.
-		 */
-		if ((sgaddr & IO_PAGE_MASK) ^ ((sgaddr + sglen - 1) & IO_PAGE_MASK)) {
-			unsigned long next_page, diff;
-
-			next_page = (sgaddr + IO_PAGE_SIZE) & IO_PAGE_MASK;
-			diff = next_page - sgaddr;
-			sgaddr += diff;
-			daddr += diff;
-			sglen -= diff;
-			dlen -= diff;
-			if (dlen > 0)
-				iopte++;
-			continue;
-		}
-
-		/* SG wholly consumed within this page. */
-		daddr += sglen;
-		dlen -= sglen;
-
-		if (dlen > 0 && ((daddr & ~IO_PAGE_MASK) == 0))
-			iopte++;
-
-		sg = sg_next(sg);
-		if (--nents <= 0)
-			break;
-		sgaddr = (unsigned long) sg_virt(sg);
-		sglen = sg->length;
-	}
-	if (dlen < 0) {
-		/* Transfer overrun, big problems. */
-		printk("verify_one_map: Transfer overrun by %d bytes.\n",
-		       -dlen);
-		nents = -1;
-	} else {
-		/* Advance to next dma_sg implies that the next iopte will
-		 * begin it.
-		 */
-		iopte++;
-	}
-
-out:
-	*__sg = sg;
-	*__iopte = iopte;
-	return nents;
-}
-
-static int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
-{
-	struct scatterlist *dma_sg = sg;
-	struct scatterlist *orig_dma_sg = dma_sg;
-	int orig_nents = nents;
-
-	for (;;) {
-		nents = verify_one_map(dma_sg, &sg, nents, &iopte);
-		if (nents <= 0)
-			break;
-		dma_sg = sg_next(dma_sg);
-		if (dma_sg->dma_length == 0)
-			break;
-	}
-
-	if (nents > 0) {
-		printk("verify_maps: dma maps consumed by some sgs remain (%d)\n",
-		       nents);
-		return -1;
-	}
-
-	if (nents < 0) {
-		printk("verify_maps: Error, messed up mappings, "
-		       "at sg %d dma_sg %d\n",
-		       (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg));
-		return -1;
-	}
-
-	/* This test passes... */
-	return 0;
-}
-
-void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int npages)
-{
-	struct scatterlist *sg;
-
-	if (verify_lengths(sglist, nents, npages) < 0 ||
-	    verify_maps(sglist, nents, iopte) < 0) {
-		int i;
-
-		printk("verify_sglist: Crap, messed up mappings, dumping, iodma at ");
-		printk("%016lx.\n", sglist->dma_address & IO_PAGE_MASK);
-
-		for_each_sg(sglist, sg, nents, i) {
-			printk("sg(%d): page_addr(%p) off(%x) length(%x) "
-			       "dma_address[%016x] dma_length[%016x]\n",
-			       i,
-			       page_address(sg_page(sg)), sg->offset,
-			       sg->length,
-			       sg->dma_address, sg->dma_length);
-		}
-	}
-
-	/* Seems to be ok */
-}
-#endif
-
-unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
-{
-	struct scatterlist *dma_sg = sg;
-	unsigned long prev;
-	u32 dent_addr, dent_len;
-	unsigned int max_seg_size;
-
-	prev  = (unsigned long) sg_virt(sg);
-	prev += (unsigned long) (dent_len = sg->length);
-	dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
-	max_seg_size = dma_get_max_seg_size(dev);
-	while (--nents) {
-		unsigned long addr;
-
-		sg = sg_next(sg);
-		addr = (unsigned long) sg_virt(sg);
-		if (! VCONTIG(prev, addr) ||
-			dent_len + sg->length > max_seg_size) {
-			dma_sg->dma_address = dent_addr;
-			dma_sg->dma_length = dent_len;
-			dma_sg = sg_next(dma_sg);
-
-			dent_addr = ((dent_addr +
-				      dent_len +
-				      (IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT);
-			dent_addr <<= IO_PAGE_SHIFT;
-			dent_addr += addr & (IO_PAGE_SIZE - 1UL);
-			dent_len = 0;
-		}
-		dent_len += sg->length;
-		prev = addr + sg->length;
-	}
-	dma_sg->dma_address = dent_addr;
-	dma_sg->dma_length = dent_len;
-
-	if (dma_sg != sg) {
-		dma_sg = sg_next(dma_sg);
-		dma_sg->dma_length = 0;
-	}
-
-	return ((unsigned long) dent_addr +
-		(unsigned long) dent_len +
-		(IO_PAGE_SIZE - 1UL)) >> IO_PAGE_SHIFT;
-}
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index a90d046e..4b5cafa 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -30,6 +30,32 @@
  */
 #define IOMMU_PAGE_SHIFT		13
 
+#define SG_ENT_PHYS_ADDRESS(SG)	(__pa(sg_virt((SG))))
+
+static inline unsigned long iommu_num_pages(unsigned long vaddr,
+					    unsigned long slen)
+{
+	unsigned long npages;
+
+	npages = IO_PAGE_ALIGN(vaddr + slen) - (vaddr & IO_PAGE_MASK);
+	npages >>= IO_PAGE_SHIFT;
+
+	return npages;
+}
+
+static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
+{
+	unsigned long i, npages = 0;
+	struct scatterlist *sg;
+
+	for_each_sg(sglist, sg, nelems, i) {
+		unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
+		npages += iommu_num_pages(paddr, sg->length);
+	}
+
+	return npages;
+}
+
 /* You are _strongly_ advised to enable the following debugging code
  * any time you make changes to the sg code below, run it for a while
  * with filesystems mounted read-only before buying the farm... -DaveM
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 5ea2eab..61baf8d 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -365,113 +365,14 @@
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-#define SG_ENT_PHYS_ADDRESS(SG)	(__pa(sg_virt((SG))))
-
-static long fill_sg(long entry, struct device *dev,
-		    struct scatterlist *sg,
-		    int nused, int nelems, unsigned long prot)
-{
-	struct scatterlist *dma_sg = sg;
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-
-	iommu_batch_start(dev, prot, entry);
-
-	for (i = 0; i < nused; i++) {
-		unsigned long pteval = ~0UL;
-		u32 dma_npages;
-
-		dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
-			      dma_sg->dma_length +
-			      ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
-		do {
-			unsigned long offset;
-			signed int len;
-
-			/* If we are here, we know we have at least one
-			 * more page to map.  So walk forward until we
-			 * hit a page crossing, and begin creating new
-			 * mappings from that spot.
-			 */
-			for (;;) {
-				unsigned long tmp;
-
-				tmp = SG_ENT_PHYS_ADDRESS(sg);
-				len = sg->length;
-				if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = tmp & IO_PAGE_MASK;
-					offset = tmp & (IO_PAGE_SIZE - 1UL);
-					break;
-				}
-				if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
-					offset = 0UL;
-					len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
-					break;
-				}
-				sg = sg_next(sg);
-				nelems--;
-			}
-
-			pteval = (pteval & IOPTE_PAGE);
-			while (len > 0) {
-				long err;
-
-				err = iommu_batch_add(pteval);
-				if (unlikely(err < 0L))
-					goto iommu_map_failed;
-
-				pteval += IO_PAGE_SIZE;
-				len -= (IO_PAGE_SIZE - offset);
-				offset = 0;
-				dma_npages--;
-			}
-
-			pteval = (pteval & IOPTE_PAGE) + len;
-			sg = sg_next(sg);
-			nelems--;
-
-			/* Skip over any tail mappings we've fully mapped,
-			 * adjusting pteval along the way.  Stop when we
-			 * detect a page crossing event.
-			 */
-			while (nelems &&
-			       (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
-			       (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
-			       ((pteval ^
-				 (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
-				pteval += sg->length;
-				sg = sg_next(sg);
-				nelems--;
-			}
-			if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
-				pteval = ~0UL;
-		} while (dma_npages != 0);
-		dma_sg = sg_next(dma_sg);
-	}
-
-	if (unlikely(iommu_batch_end() < 0L))
-		goto iommu_map_failed;
-
-	local_irq_restore(flags);
-	return 0;
-
-iommu_map_failed:
-	local_irq_restore(flags);
-	return -1L;
-}
-
 static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 {
+	unsigned long flags, npages, i, prot;
+	struct scatterlist *sg;
 	struct iommu *iommu;
-	unsigned long flags, npages, prot;
-	u32 dma_base;
-	struct scatterlist *sgtmp;
 	long entry, err;
-	int used;
+	u32 dma_base;
 
 	/* Fast path single entry scatterlists. */
 	if (nelems == 1) {
@@ -489,10 +390,8 @@
 	if (unlikely(direction == DMA_NONE))
 		goto bad;
 
-	/* Step 1: Prepare scatter list. */
-	npages = prepare_sg(dev, sglist, nelems);
+	npages = calc_npages(sglist, nelems);
 
-	/* Step 2: Allocate a cluster and context, if necessary. */
 	spin_lock_irqsave(&iommu->lock, flags);
 	entry = arena_alloc(&iommu->arena, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
@@ -503,27 +402,45 @@
 	dma_base = iommu->page_table_map_base +
 		(entry << IO_PAGE_SHIFT);
 
-	/* Step 3: Normalize DMA addresses. */
-	used = nelems;
-
-	sgtmp = sglist;
-	while (used && sgtmp->dma_length) {
-		sgtmp->dma_address += dma_base;
-		sgtmp = sg_next(sgtmp);
-		used--;
-	}
-	used = nelems - used;
-
-	/* Step 4: Create the mappings. */
 	prot = HV_PCI_MAP_ATTR_READ;
 	if (direction != DMA_TO_DEVICE)
 		prot |= HV_PCI_MAP_ATTR_WRITE;
 
-	err = fill_sg(entry, dev, sglist, used, nelems, prot);
+	local_irq_save(flags);
+
+	iommu_batch_start(dev, prot, entry);
+
+	for_each_sg(sglist, sg, nelems, i) {
+		unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
+		unsigned long slen = sg->length;
+		unsigned long this_npages;
+
+		this_npages = iommu_num_pages(paddr, slen);
+
+		sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
+		sg->dma_length = slen;
+
+		paddr &= IO_PAGE_MASK;
+		while (this_npages--) {
+			err = iommu_batch_add(paddr);
+			if (unlikely(err < 0L)) {
+				local_irq_restore(flags);
+				goto iommu_map_failed;
+			}
+
+			paddr += IO_PAGE_SIZE;
+			dma_base += IO_PAGE_SIZE;
+		}
+	}
+
+	err = iommu_batch_end();
+
+	local_irq_restore(flags);
+
 	if (unlikely(err < 0L))
 		goto iommu_map_failed;
 
-	return used;
+	return nelems;
 
 bad:
 	if (printk_ratelimit())
@@ -541,12 +458,11 @@
 static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 {
+	unsigned long flags, npages;
 	struct pci_pbm_info *pbm;
-	struct iommu *iommu;
-	unsigned long flags, i, npages;
-	struct scatterlist *sg, *sgprv;
-	long entry;
 	u32 devhandle, bus_addr;
+	struct iommu *iommu;
+	long entry;
 
 	if (unlikely(direction == DMA_NONE)) {
 		if (printk_ratelimit())
@@ -558,16 +474,8 @@
 	devhandle = pbm->devhandle;
 	
 	bus_addr = sglist->dma_address & IO_PAGE_MASK;
-	sgprv = NULL;
-	for_each_sg(sglist, sg, nelems, i) {
-		if (sg->dma_length == 0)
-			break;
 
-		sgprv = sg;
-	}
-
-	npages = (IO_PAGE_ALIGN(sgprv->dma_address + sgprv->dma_length) -
-		  bus_addr) >> IO_PAGE_SHIFT;
+	npages = calc_npages(sglist, nelems);
 
 	entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c399449..a8052b7 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -46,8 +46,6 @@
 #include <asm/ldc.h>
 #include <asm/hypervisor.h>
 
-extern void calibrate_delay(void);
-
 int sparc64_multi_core __read_mostly;
 
 cpumask_t cpu_possible_map __read_mostly = CPU_MASK_NONE;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 60765e3..8649635 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -277,6 +277,7 @@
 EXPORT_SYMBOL(sys_geteuid);
 EXPORT_SYMBOL(sys_getuid);
 EXPORT_SYMBOL(sys_getegid);
+EXPORT_SYMBOL(sysctl_nr_open);
 EXPORT_SYMBOL(sys_getgid);
 EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(svr4_setcontext);
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index b805890..adc62f4 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -80,7 +80,8 @@
 	.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
 /*300*/	.word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
 	.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
-/*310*/	.word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
+/*310*/	.word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
+	.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime
 
 #endif /* CONFIG_COMPAT */
 
@@ -152,7 +153,8 @@
 	.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
 /*300*/	.word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
 	.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
-/*310*/	.word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
+/*310*/	.word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
+	.word sys_timerfd_settime, sys_timerfd_gettime
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -271,6 +273,7 @@
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys
 /*310*/	.word sunos_nosys, sunos_nosys, sunos_nosys
-	.word sunos_nosys, sunos_nosys
+	.word sunos_nosys, sunos_nosys, sunos_nosys
+	.word sunos_nosys
 
 #endif
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 4352ee4..d204f1a 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1707,6 +1707,11 @@
 	misc_deregister(&rtc_mini_dev);
 }
 
+int __devinit read_current_timer(unsigned long *timer_val)
+{
+	*timer_val = tick_ops->get_tick();
+	return 0;
+}
 
 module_init(rtc_mini_init);
 module_exit(rtc_mini_exit);
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 61be597..9311bfe 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -624,7 +624,7 @@
 	case 3: /* UL_GMEMLIM */
 		return current->signal->rlim[RLIMIT_DATA].rlim_cur;
 	case 4: /* UL_GDESLIM */
-		return NR_OPEN;
+		return sysctl_nr_open;
 	}
 	return -EINVAL;
 }
diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c
index a9d32ce..f53123c 100644
--- a/arch/sparc64/solaris/timod.c
+++ b/arch/sparc64/solaris/timod.c
@@ -859,7 +859,8 @@
 
 	SOLD("entry");
 	lock_kernel();
-	if(fd >= NR_OPEN) goto out;
+	if (fd >= sysctl_nr_open)
+		goto out;
 
 	fdt = files_fdtable(current->files);
 	filp = fdt->fd[fd];
@@ -927,7 +928,8 @@
 
 	SOLD("entry");
 	lock_kernel();
-	if(fd >= NR_OPEN) goto out;
+	if (fd >= sysctl_nr_open)
+		goto out;
 
 	fdt = files_fdtable(current->files);
 	filp = fdt->fd[fd];
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4348211..e6728bd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -415,7 +415,7 @@
 
 config HPET_EMULATE_RTC
 	def_bool y
-	depends on HPET_TIMER && (RTC=y || RTC=m)
+	depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
 
 # Mark as embedded because too many people got it wrong.
 # The code disables itself when not needed.
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d9313d9..f86a3c4 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -637,7 +637,7 @@
 }
 
 /* Make sure %fs is initialized properly in idle threads */
-struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs)
 {
 	memset(regs, 0, sizeof(struct pt_regs));
 	regs->fs = __KERNEL_PERCPU;
diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c
index 404a6a2..7139b02 100644
--- a/arch/x86/kernel/cpu/cyrix.c
+++ b/arch/x86/kernel/cpu/cyrix.c
@@ -83,8 +83,6 @@
  * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP
  */
 
-extern void calibrate_delay(void) __init;
-
 static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
 {
 	unsigned long flags;
diff --git a/arch/x86/kernel/smpboot_32.c b/arch/x86/kernel/smpboot_32.c
index 5787a0c..579b9b7 100644
--- a/arch/x86/kernel/smpboot_32.c
+++ b/arch/x86/kernel/smpboot_32.c
@@ -202,8 +202,6 @@
 	;
 }
 
-extern void calibrate_delay(void);
-
 static atomic_t init_deasserted;
 
 static void __cpuinit smp_callin(void)
diff --git a/arch/x86/lib/delay_32.c b/arch/x86/lib/delay_32.c
index aad9d95..4535e6d 100644
--- a/arch/x86/lib/delay_32.c
+++ b/arch/x86/lib/delay_32.c
@@ -12,8 +12,10 @@
 
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/timex.h>
 #include <linux/preempt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/processor.h>
 #include <asm/delay.h>
@@ -63,7 +65,7 @@
 	delay_fn = delay_tsc;
 }
 
-int read_current_timer(unsigned long *timer_val)
+int __devinit read_current_timer(unsigned long *timer_val)
 {
 	if (delay_fn == delay_tsc) {
 		rdtscl(*timer_val);
diff --git a/arch/x86/lib/delay_64.c b/arch/x86/lib/delay_64.c
index 45cdd3f..bbc6105 100644
--- a/arch/x86/lib/delay_64.c
+++ b/arch/x86/lib/delay_64.c
@@ -10,8 +10,10 @@
 
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/timex.h>
 #include <linux/preempt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/delay.h>
 #include <asm/msr.h>
@@ -20,7 +22,7 @@
 #include <asm/smp.h>
 #endif
 
-int read_current_timer(unsigned long *timer_value)
+int __devinit read_current_timer(unsigned long *timer_value)
 {
 	rdtscll(*timer_value);
 	return 0;
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
index dffa786..3cc8eb2 100644
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ b/arch/x86/mach-voyager/voyager_smp.c
@@ -444,8 +444,6 @@
 static void __init start_secondary(void *unused)
 {
 	__u8 cpuid = hard_smp_processor_id();
-	/* external functions not defined in the headers */
-	extern void calibrate_delay(void);
 
 	cpu_init();
 
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 60d29fe..8df1e842 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -204,7 +204,7 @@
 }
 
 #ifndef CONFIG_GENERIC_CALIBRATE_DELAY
-void __devinit calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
 {
 	loops_per_jiffy = CCOUNT_PER_JIFFY;
 	printk("Calibrating delay loop (skipped)... "
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 047e533..0f62822 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -35,7 +35,7 @@
  * @src: src page
  * @offset: offset in pages to start transaction
  * @len: length in bytes
- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
  * @depend_tx: memcpy depends on the result of this transaction
  * @cb_fn: function to call when the memcpy completes
  * @cb_param: parameter to pass to the callback routine
@@ -46,33 +46,29 @@
 	struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_param)
 {
-	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY,
+						      &dest, 1, &src, 1, len);
 	struct dma_device *device = chan ? chan->device : NULL;
-	int int_en = cb_fn ? 1 : 0;
-	struct dma_async_tx_descriptor *tx = device ?
-		device->device_prep_dma_memcpy(chan, len,
-		int_en) : NULL;
+	struct dma_async_tx_descriptor *tx = NULL;
 
-	if (tx) { /* run the memcpy asynchronously */
-		dma_addr_t addr;
-		enum dma_data_direction dir;
+	if (device) {
+		dma_addr_t dma_dest, dma_src;
+		unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
 
+		dma_dest = dma_map_page(device->dev, dest, dest_offset, len,
+					DMA_FROM_DEVICE);
+
+		dma_src = dma_map_page(device->dev, src, src_offset, len,
+				       DMA_TO_DEVICE);
+
+		tx = device->device_prep_dma_memcpy(chan, dma_dest, dma_src,
+						    len, dma_prep_flags);
+	}
+
+	if (tx) {
 		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
-
-		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-			DMA_NONE : DMA_FROM_DEVICE;
-
-		addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
-		tx->tx_set_dest(addr, tx, 0);
-
-		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-			DMA_NONE : DMA_TO_DEVICE;
-
-		addr = dma_map_page(device->dev, src, src_offset, len, dir);
-		tx->tx_set_src(addr, tx, 0);
-
 		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
-	} else { /* run the memcpy synchronously */
+	} else {
 		void *dest_buf, *src_buf;
 		pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
 
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
index 66ef635..09c0e836 100644
--- a/crypto/async_tx/async_memset.c
+++ b/crypto/async_tx/async_memset.c
@@ -35,7 +35,7 @@
  * @val: fill value
  * @offset: offset in pages to start transaction
  * @len: length in bytes
- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
  * @depend_tx: memset depends on the result of this transaction
  * @cb_fn: function to call when the memcpy completes
  * @cb_param: parameter to pass to the callback routine
@@ -46,24 +46,24 @@
 	struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_param)
 {
-	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET,
+						      &dest, 1, NULL, 0, len);
 	struct dma_device *device = chan ? chan->device : NULL;
-	int int_en = cb_fn ? 1 : 0;
-	struct dma_async_tx_descriptor *tx = device ?
-		device->device_prep_dma_memset(chan, val, len,
-			int_en) : NULL;
+	struct dma_async_tx_descriptor *tx = NULL;
 
-	if (tx) { /* run the memset asynchronously */
-		dma_addr_t dma_addr;
-		enum dma_data_direction dir;
+	if (device) {
+		dma_addr_t dma_dest;
+		unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
 
+		dma_dest = dma_map_page(device->dev, dest, offset, len,
+					DMA_FROM_DEVICE);
+
+		tx = device->device_prep_dma_memset(chan, dma_dest, val, len,
+						    dma_prep_flags);
+	}
+
+	if (tx) {
 		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
-		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-			DMA_NONE : DMA_FROM_DEVICE;
-
-		dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
-		tx->tx_set_dest(dma_addr, tx, 0);
-
 		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
 	} else { /* run the memset synchronously */
 		void *dest_buf;
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index bc18cbb..56288218 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -57,8 +57,7 @@
  */
 static spinlock_t async_tx_lock;
 
-static struct list_head
-async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
+static LIST_HEAD(async_tx_master_list);
 
 /* async_tx_issue_pending_all - start all transactions on all channels */
 void async_tx_issue_pending_all(void)
@@ -362,13 +361,13 @@
 }
 
 /**
- * async_tx_find_channel - find a channel to carry out the operation or let
+ * __async_tx_find_channel - find a channel to carry out the operation or let
  *	the transaction execute synchronously
  * @depend_tx: transaction dependency
  * @tx_type: transaction type
  */
 struct dma_chan *
-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
 	enum dma_transaction_type tx_type)
 {
 	/* see if we can keep the chain on one channel */
@@ -384,7 +383,7 @@
 	} else
 		return NULL;
 }
-EXPORT_SYMBOL_GPL(async_tx_find_channel);
+EXPORT_SYMBOL_GPL(__async_tx_find_channel);
 #else
 static int __init async_tx_init(void)
 {
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 2575f67..2259a4f 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -30,35 +30,51 @@
 #include <linux/raid/xor.h>
 #include <linux/async_tx.h>
 
-static void
-do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
+/* do_async_xor - dma map the pages and perform the xor with an engine.
+ * 	This routine is marked __always_inline so it can be compiled away
+ * 	when CONFIG_DMA_ENGINE=n
+ */
+static __always_inline struct dma_async_tx_descriptor *
+do_async_xor(struct dma_device *device,
 	struct dma_chan *chan, struct page *dest, struct page **src_list,
 	unsigned int offset, unsigned int src_cnt, size_t len,
 	enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_param)
 {
-	dma_addr_t dma_addr;
-	enum dma_data_direction dir;
+	dma_addr_t dma_dest;
+	dma_addr_t *dma_src = (dma_addr_t *) src_list;
+	struct dma_async_tx_descriptor *tx;
 	int i;
+	unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
 
 	pr_debug("%s: len: %zu\n", __FUNCTION__, len);
 
-	dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-		DMA_NONE : DMA_FROM_DEVICE;
+	dma_dest = dma_map_page(device->dev, dest, offset, len,
+				DMA_FROM_DEVICE);
 
-	dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
-	tx->tx_set_dest(dma_addr, tx, 0);
+	for (i = 0; i < src_cnt; i++)
+		dma_src[i] = dma_map_page(device->dev, src_list[i], offset,
+					  len, DMA_TO_DEVICE);
 
-	dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-		DMA_NONE : DMA_TO_DEVICE;
+	/* Since we have clobbered the src_list we are committed
+	 * to doing this asynchronously.  Drivers force forward progress
+	 * in case they can not provide a descriptor
+	 */
+	tx = device->device_prep_dma_xor(chan, dma_dest, dma_src, src_cnt, len,
+					 dma_prep_flags);
+	if (!tx) {
+		if (depend_tx)
+			dma_wait_for_async_tx(depend_tx);
 
-	for (i = 0; i < src_cnt; i++) {
-		dma_addr = dma_map_page(device->dev, src_list[i],
-			offset, len, dir);
-		tx->tx_set_src(dma_addr, tx, i);
+		while (!tx)
+			tx = device->device_prep_dma_xor(chan, dma_dest,
+							 dma_src, src_cnt, len,
+							 dma_prep_flags);
 	}
 
 	async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+
+	return tx;
 }
 
 static void
@@ -102,7 +118,7 @@
  * @src_cnt: number of source pages
  * @len: length in bytes
  * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
- *	ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ *	ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
  * @depend_tx: xor depends on the result of this transaction.
  * @cb_fn: function to call when the xor completes
  * @cb_param: parameter to pass to the callback routine
@@ -113,14 +129,16 @@
 	struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_param)
 {
-	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR,
+						      &dest, 1, src_list,
+						      src_cnt, len);
 	struct dma_device *device = chan ? chan->device : NULL;
 	struct dma_async_tx_descriptor *tx = NULL;
 	dma_async_tx_callback _cb_fn;
 	void *_cb_param;
 	unsigned long local_flags;
 	int xor_src_cnt;
-	int i = 0, src_off = 0, int_en;
+	int i = 0, src_off = 0;
 
 	BUG_ON(src_cnt <= 1);
 
@@ -140,20 +158,11 @@
 				_cb_param = cb_param;
 			}
 
-			int_en = _cb_fn ? 1 : 0;
-
-			tx = device->device_prep_dma_xor(
-				chan, xor_src_cnt, len, int_en);
-
-			if (tx) {
-				do_async_xor(tx, device, chan, dest,
-				&src_list[src_off], offset, xor_src_cnt, len,
-				local_flags, depend_tx, _cb_fn,
-				_cb_param);
-			} else /* fall through */
-				goto xor_sync;
+			tx = do_async_xor(device, chan, dest,
+					  &src_list[src_off], offset,
+					  xor_src_cnt, len, local_flags,
+					  depend_tx, _cb_fn, _cb_param);
 		} else { /* run the xor synchronously */
-xor_sync:
 			/* in the sync case the dest is an implied source
 			 * (assumes the dest is at the src_off index)
 			 */
@@ -242,7 +251,7 @@
  * @src_cnt: number of source pages
  * @len: length in bytes
  * @result: 0 if sum == 0 else non-zero
- * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
  * @depend_tx: xor depends on the result of this transaction.
  * @cb_fn: function to call when the xor completes
  * @cb_param: parameter to pass to the callback routine
@@ -254,29 +263,36 @@
 	struct dma_async_tx_descriptor *depend_tx,
 	dma_async_tx_callback cb_fn, void *cb_param)
 {
-	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
+	struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM,
+						      &dest, 1, src_list,
+						      src_cnt, len);
 	struct dma_device *device = chan ? chan->device : NULL;
-	int int_en = cb_fn ? 1 : 0;
-	struct dma_async_tx_descriptor *tx = device ?
-		device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
-			int_en) : NULL;
-	int i;
+	struct dma_async_tx_descriptor *tx = NULL;
 
 	BUG_ON(src_cnt <= 1);
 
-	if (tx) {
-		dma_addr_t dma_addr;
-		enum dma_data_direction dir;
+	if (device) {
+		dma_addr_t *dma_src = (dma_addr_t *) src_list;
+		unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
+		int i;
 
 		pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
 
-		dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
-			DMA_NONE : DMA_TO_DEVICE;
+		for (i = 0; i < src_cnt; i++)
+			dma_src[i] = dma_map_page(device->dev, src_list[i],
+						  offset, len, DMA_TO_DEVICE);
 
-		for (i = 0; i < src_cnt; i++) {
-			dma_addr = dma_map_page(device->dev, src_list[i],
-				offset, len, dir);
-			tx->tx_set_src(dma_addr, tx, i);
+		tx = device->device_prep_dma_zero_sum(chan, dma_src, src_cnt,
+						      len, result,
+						      dma_prep_flags);
+		if (!tx) {
+			if (depend_tx)
+				dma_wait_for_async_tx(depend_tx);
+
+			while (!tx)
+				tx = device->device_prep_dma_zero_sum(chan,
+					dma_src, src_cnt, len, result,
+					dma_prep_flags);
 		}
 
 		async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
@@ -311,6 +327,16 @@
 
 static int __init async_xor_init(void)
 {
+	#ifdef CONFIG_DMA_ENGINE
+	/* To conserve stack space the input src_list (array of page pointers)
+	 * is reused to hold the array of dma addresses passed to the driver.
+	 * This conversion is only possible when dma_addr_t is less than the
+	 * the size of a pointer.  HIGHMEM64G is known to violate this
+	 * assumption.
+	 */
+	BUILD_BUG_ON(sizeof(dma_addr_t) > sizeof(struct page *));
+	#endif
+
 	return 0;
 }
 
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 27c8d56..29e71bd 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -679,24 +679,20 @@
 
 	/* cross check port_map and cap.n_ports */
 	if (port_map) {
-		u32 tmp_port_map = port_map;
-		int n_ports = ahci_nr_ports(cap);
+		int map_ports = 0;
 
-		for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) {
-			if (tmp_port_map & (1 << i)) {
-				n_ports--;
-				tmp_port_map &= ~(1 << i);
-			}
-		}
+		for (i = 0; i < AHCI_MAX_PORTS; i++)
+			if (port_map & (1 << i))
+				map_ports++;
 
-		/* If n_ports and port_map are inconsistent, whine and
-		 * clear port_map and let it be generated from n_ports.
+		/* If PI has more ports than n_ports, whine, clear
+		 * port_map and let it be generated from n_ports.
 		 */
-		if (n_ports || tmp_port_map) {
+		if (map_ports > ahci_nr_ports(cap)) {
 			dev_printk(KERN_WARNING, &pdev->dev,
-				   "nr_ports (%u) and implemented port map "
-				   "(0x%x) don't match, using nr_ports\n",
-				   ahci_nr_ports(cap), port_map);
+				   "implemented port map (0x%x) contains more "
+				   "ports than nr_ports (%u), using nr_ports\n",
+				   port_map, ahci_nr_ports(cap));
 			port_map = 0;
 		}
 	}
@@ -2201,7 +2197,7 @@
 	struct device *dev = &pdev->dev;
 	struct ahci_host_priv *hpriv;
 	struct ata_host *host;
-	int i, rc;
+	int n_ports, i, rc;
 
 	VPRINTK("ENTER\n");
 
@@ -2255,7 +2251,14 @@
 	if (hpriv->cap & HOST_CAP_PMP)
 		pi.flags |= ATA_FLAG_PMP;
 
-	host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map));
+	/* CAP.NP sometimes indicate the index of the last enabled
+	 * port, at other times, that of the last possible port, so
+	 * determining the maximum port number requires looking at
+	 * both CAP.NP and port_map.
+	 */
+	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
 	if (!host)
 		return -ENOMEM;
 	host->iomap = pcim_iomap_table(pdev);
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 4b99ed0..9c2515f 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1603,7 +1603,8 @@
  *	Zero on success, or -ERRNO value.
  */
 
-static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit piix_init_one(struct pci_dev *pdev,
+				   const struct pci_device_id *ent)
 {
 	static int printed_version;
 	struct device *dev = &pdev->dev;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 361cf50..3011919 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4154,8 +4154,6 @@
 	/* NCQ is broken */
 	{ "Maxtor *",		"BANC*",	ATA_HORKAGE_NONCQ },
 	{ "Maxtor 7V300F0",	"VA111630",	ATA_HORKAGE_NONCQ },
-	{ "HITACHI HDS7250SASUN500G*", NULL,    ATA_HORKAGE_NONCQ },
-	{ "HITACHI HDS7225SBSUN250G*", NULL,    ATA_HORKAGE_NONCQ },
 	{ "ST380817AS",		"3.42",		ATA_HORKAGE_NONCQ },
 	{ "ST3160023AS",	"3.42",		ATA_HORKAGE_NONCQ },
 
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 938f48a..408da30 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 
 static int __devinit pata_of_platform_probe(struct of_device *ofdev,
 					    const struct of_device_id *match)
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index 224bb6c..aad7adc 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -19,7 +19,7 @@
 #include <linux/ata.h>
 #include <linux/libata.h>
 #include <linux/platform_device.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 
 #define DRV_NAME "pata_platform"
 #define DRV_VERSION "1.2"
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 922d7b2..efcb66b6 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -355,8 +355,8 @@
 			ata_port_printk(qc->ap, KERN_ERR,
 					"s/g len unaligned : 0x%x\n", sg_len);
 
-		if ((num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1)) &&
-		    (qc->n_iter + 1 != qc->n_elem)) {
+		if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) &&
+		    sg_next(sg) != NULL) {
 			VPRINTK("setting indirect prde\n");
 			prd_ptr_to_indirect_ext = prd;
 			prd->dba = cpu_to_le32(indirect_ext_segment_paddr);
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 3c1b5c90..080b836 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -69,8 +69,11 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -179,6 +182,8 @@
 
 	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
 	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
+	HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020,
+	HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024,
 	PORT0_ERR		= (1 << 0),	/* shift by port # */
 	PORT0_DONE		= (1 << 1),	/* shift by port # */
 	HC0_IRQ_PEND		= 0x1ff,	/* bits 0-8 = HC0's ports */
@@ -194,11 +199,13 @@
 	TWSI_INT		= (1 << 24),
 	HC_MAIN_RSVD		= (0x7f << 25),	/* bits 31-25 */
 	HC_MAIN_RSVD_5		= (0x1fff << 19), /* bits 31-19 */
+	HC_MAIN_RSVD_SOC 	= (0x3fffffb << 6),     /* bits 31-9, 7-6 */
 	HC_MAIN_MASKED_IRQS	= (TRAN_LO_DONE | TRAN_HI_DONE |
 				   PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
 				   HC_MAIN_RSVD),
 	HC_MAIN_MASKED_IRQS_5	= (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
 				   HC_MAIN_RSVD_5),
+	HC_MAIN_MASKED_IRQS_SOC = (PORTS_0_3_COAL_DONE | HC_MAIN_RSVD_SOC),
 
 	/* SATAHC registers */
 	HC_CFG_OFS		= 0,
@@ -368,6 +375,7 @@
 	chip_608x,
 	chip_6042,
 	chip_7042,
+	chip_soc,
 };
 
 /* Command ReQuest Block: 32B */
@@ -424,6 +432,10 @@
 	u32			hp_flags;
 	struct mv_port_signal	signal[8];
 	const struct mv_hw_ops	*ops;
+	int			n_ports;
+	void __iomem		*base;
+	void __iomem		*main_cause_reg_addr;
+	void __iomem		*main_mask_reg_addr;
 	u32			irq_cause_ofs;
 	u32			irq_mask_ofs;
 	u32			unmask_all_irqs;
@@ -482,6 +494,15 @@
 static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
 			unsigned int n_hc);
 static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
+static void mv_soc_enable_leds(struct mv_host_priv *hpriv,
+				      void __iomem *mmio);
+static void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx,
+				      void __iomem *mmio);
+static int mv_soc_reset_hc(struct mv_host_priv *hpriv,
+				  void __iomem *mmio, unsigned int n_hc);
+static void mv_soc_reset_flash(struct mv_host_priv *hpriv,
+				      void __iomem *mmio);
+static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio);
 static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
 static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 			     unsigned int port_no);
@@ -661,6 +682,12 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &mv_iie_ops,
 	},
+	{  /* chip_soc */
+		.flags = MV_COMMON_FLAGS | MV_FLAG_SOC,
+		.pio_mask = 0x1f,      /* pio0-4 */
+		.udma_mask = ATA_UDMA6,
+		.port_ops = &mv_iie_ops,
+	},
 };
 
 static const struct pci_device_id mv_pci_tbl[] = {
@@ -711,6 +738,15 @@
 	.reset_bus		= mv_reset_pci_bus,
 };
 
+static const struct mv_hw_ops mv_soc_ops = {
+	.phy_errata		= mv6_phy_errata,
+	.enable_leds		= mv_soc_enable_leds,
+	.read_preamp		= mv_soc_read_preamp,
+	.reset_hc		= mv_soc_reset_hc,
+	.reset_flash		= mv_soc_reset_flash,
+	.reset_bus		= mv_soc_reset_bus,
+};
+
 /*
  * Functions
  */
@@ -749,9 +785,15 @@
 		(mv_hardport_from_port(port) * MV_PORT_REG_SZ);
 }
 
+static inline void __iomem *mv_host_base(struct ata_host *host)
+{
+	struct mv_host_priv *hpriv = host->private_data;
+	return hpriv->base;
+}
+
 static inline void __iomem *mv_ap_base(struct ata_port *ap)
 {
-	return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no);
+	return mv_port_base(mv_host_base(ap->host), ap->port_no);
 }
 
 static inline int mv_get_hc_count(unsigned long port_flags)
@@ -1649,16 +1691,21 @@
  */
 static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
 {
-	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
+	struct mv_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->base;
 	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
 	u32 hc_irq_cause;
-	int port, port0;
+	int port, port0, last_port;
 
 	if (hc == 0)
 		port0 = 0;
 	else
 		port0 = MV_PORTS_PER_HC;
 
+	if (HAS_PCI(host))
+		last_port = port0 + MV_PORTS_PER_HC;
+	else
+		last_port = port0 + hpriv->n_ports;
 	/* we'll need the HC success int register in most cases */
 	hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
 	if (!hc_irq_cause)
@@ -1669,7 +1716,7 @@
 	VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
 		hc, relevant, hc_irq_cause);
 
-	for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
+	for (port = port0; port < port0 + last_port; port++) {
 		struct ata_port *ap = host->ports[port];
 		struct mv_port_priv *pp = ap->private_data;
 		int have_err_bits, hard_port, shift;
@@ -1764,13 +1811,15 @@
 static irqreturn_t mv_interrupt(int irq, void *dev_instance)
 {
 	struct ata_host *host = dev_instance;
+	struct mv_host_priv *hpriv = host->private_data;
 	unsigned int hc, handled = 0, n_hcs;
-	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
+	void __iomem *mmio = hpriv->base;
 	u32 irq_stat, irq_mask;
 
 	spin_lock(&host->lock);
-	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
-	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+
+	irq_stat = readl(hpriv->main_cause_reg_addr);
+	irq_mask = readl(hpriv->main_mask_reg_addr);
 
 	/* check the cases where we either have nothing pending or have read
 	 * a bogus register value which can indicate HW removal or PCI fault
@@ -1827,7 +1876,8 @@
 
 static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
 {
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	void __iomem *mmio = hpriv->base;
 	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
 	unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
@@ -1840,7 +1890,8 @@
 
 static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
 {
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	void __iomem *mmio = hpriv->base;
 	void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
 	unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
@@ -2178,6 +2229,93 @@
 	writel(m2, port_mmio + PHY_MODE2);
 }
 
+/* TODO: use the generic LED interface to configure the SATA Presence */
+/* & Acitivy LEDs on the board */
+static void mv_soc_enable_leds(struct mv_host_priv *hpriv,
+				      void __iomem *mmio)
+{
+	return;
+}
+
+static void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx,
+			   void __iomem *mmio)
+{
+	void __iomem *port_mmio;
+	u32 tmp;
+
+	port_mmio = mv_port_base(mmio, idx);
+	tmp = readl(port_mmio + PHY_MODE2);
+
+	hpriv->signal[idx].amps = tmp & 0x700;	/* bits 10:8 */
+	hpriv->signal[idx].pre = tmp & 0xe0;	/* bits 7:5 */
+}
+
+#undef ZERO
+#define ZERO(reg) writel(0, port_mmio + (reg))
+static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv,
+					void __iomem *mmio, unsigned int port)
+{
+	void __iomem *port_mmio = mv_port_base(mmio, port);
+
+	writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
+
+	mv_channel_reset(hpriv, mmio, port);
+
+	ZERO(0x028);		/* command */
+	writel(0x101f, port_mmio + EDMA_CFG_OFS);
+	ZERO(0x004);		/* timer */
+	ZERO(0x008);		/* irq err cause */
+	ZERO(0x00c);		/* irq err mask */
+	ZERO(0x010);		/* rq bah */
+	ZERO(0x014);		/* rq inp */
+	ZERO(0x018);		/* rq outp */
+	ZERO(0x01c);		/* respq bah */
+	ZERO(0x024);		/* respq outp */
+	ZERO(0x020);		/* respq inp */
+	ZERO(0x02c);		/* test control */
+	writel(0xbc, port_mmio + EDMA_IORDY_TMOUT);
+}
+
+#undef ZERO
+
+#define ZERO(reg) writel(0, hc_mmio + (reg))
+static void mv_soc_reset_one_hc(struct mv_host_priv *hpriv,
+				       void __iomem *mmio)
+{
+	void __iomem *hc_mmio = mv_hc_base(mmio, 0);
+
+	ZERO(0x00c);
+	ZERO(0x010);
+	ZERO(0x014);
+
+}
+
+#undef ZERO
+
+static int mv_soc_reset_hc(struct mv_host_priv *hpriv,
+				  void __iomem *mmio, unsigned int n_hc)
+{
+	unsigned int port;
+
+	for (port = 0; port < hpriv->n_ports; port++)
+		mv_soc_reset_hc_port(hpriv, mmio, port);
+
+	mv_soc_reset_one_hc(hpriv, mmio);
+
+	return 0;
+}
+
+static void mv_soc_reset_flash(struct mv_host_priv *hpriv,
+				      void __iomem *mmio)
+{
+	return;
+}
+
+static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio)
+{
+	return;
+}
+
 static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
 			     unsigned int port_no)
 {
@@ -2342,7 +2480,7 @@
 {
 	struct ata_port *ap = link->ap;
 	struct mv_host_priv *hpriv = ap->host->private_data;
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	void __iomem *mmio = hpriv->base;
 
 	mv_stop_dma(ap);
 
@@ -2383,7 +2521,7 @@
 
 static void mv_eh_freeze(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	struct mv_host_priv *hpriv = ap->host->private_data;
 	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
 	u32 tmp, mask;
 	unsigned int shift;
@@ -2397,13 +2535,14 @@
 	mask = 0x3 << shift;
 
 	/* disable assertion of portN err, done events */
-	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
-	writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
+	tmp = readl(hpriv->main_mask_reg_addr);
+	writelfl(tmp & ~mask, hpriv->main_mask_reg_addr);
 }
 
 static void mv_eh_thaw(struct ata_port *ap)
 {
-	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+	struct mv_host_priv *hpriv = ap->host->private_data;
+	void __iomem *mmio = hpriv->base;
 	unsigned int hc = (ap->port_no > 3) ? 1 : 0;
 	void __iomem *hc_mmio = mv_hc_base(mmio, hc);
 	void __iomem *port_mmio = mv_ap_base(ap);
@@ -2430,8 +2569,8 @@
 	writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
 
 	/* enable assertion of portN err, done events */
-	tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
-	writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
+	tmp = readl(hpriv->main_mask_reg_addr);
+	writelfl(tmp | mask, hpriv->main_mask_reg_addr);
 }
 
 /**
@@ -2598,9 +2737,13 @@
 			break;
 		}
 		break;
+	case chip_soc:
+		hpriv->ops = &mv_soc_ops;
+		hp_flags |= MV_HP_ERRATA_60X1C0;
+		break;
 
 	default:
-		dev_printk(KERN_ERR, &pdev->dev,
+		dev_printk(KERN_ERR, host->dev,
 			   "BUG: invalid board index %u\n", board_idx);
 		return 1;
 	}
@@ -2633,15 +2776,25 @@
 static int mv_init_host(struct ata_host *host, unsigned int board_idx)
 {
 	int rc = 0, n_hc, port, hc;
-	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
 	struct mv_host_priv *hpriv = host->private_data;
-
-	/* global interrupt mask */
-	writel(0, mmio + HC_MAIN_IRQ_MASK_OFS);
+	void __iomem *mmio = hpriv->base;
 
 	rc = mv_chip_id(host, board_idx);
 	if (rc)
-		goto done;
+	goto done;
+
+	if (HAS_PCI(host)) {
+		hpriv->main_cause_reg_addr = hpriv->base +
+		  HC_MAIN_IRQ_CAUSE_OFS;
+		hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS;
+	} else {
+		hpriv->main_cause_reg_addr = hpriv->base +
+		  HC_SOC_MAIN_IRQ_CAUSE_OFS;
+		hpriv->main_mask_reg_addr = hpriv->base +
+		  HC_SOC_MAIN_IRQ_MASK_OFS;
+	}
+	/* global interrupt mask */
+	writel(0, hpriv->main_mask_reg_addr);
 
 	n_hc = mv_get_hc_count(host->ports[0]->flags);
 
@@ -2672,13 +2825,15 @@
 	for (port = 0; port < host->n_ports; port++) {
 		struct ata_port *ap = host->ports[port];
 		void __iomem *port_mmio = mv_port_base(mmio, port);
-		unsigned int offset = port_mmio - mmio;
 
 		mv_port_init(&ap->ioaddr, port_mmio);
 
 #ifdef CONFIG_PCI
-		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
-		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
+		if (HAS_PCI(host)) {
+			unsigned int offset = port_mmio - mmio;
+			ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
+			ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
+		}
 #endif
 	}
 
@@ -2694,35 +2849,141 @@
 		writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
 	}
 
-	/* Clear any currently outstanding host interrupt conditions */
-	writelfl(0, mmio + hpriv->irq_cause_ofs);
+	if (HAS_PCI(host)) {
+		/* Clear any currently outstanding host interrupt conditions */
+		writelfl(0, mmio + hpriv->irq_cause_ofs);
 
-	/* and unmask interrupt generation for host regs */
-	writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+		/* and unmask interrupt generation for host regs */
+		writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
+		if (IS_GEN_I(hpriv))
+			writelfl(~HC_MAIN_MASKED_IRQS_5,
+				 hpriv->main_mask_reg_addr);
+		else
+			writelfl(~HC_MAIN_MASKED_IRQS,
+				 hpriv->main_mask_reg_addr);
 
-	if (IS_GEN_I(hpriv))
-		writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
-	else
-		writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
-
-	VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
-		"PCI int cause/mask=0x%08x/0x%08x\n",
-		readl(mmio + HC_MAIN_IRQ_CAUSE_OFS),
-		readl(mmio + HC_MAIN_IRQ_MASK_OFS),
-		readl(mmio + hpriv->irq_cause_ofs),
-		readl(mmio + hpriv->irq_mask_ofs));
-
+		VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
+			"PCI int cause/mask=0x%08x/0x%08x\n",
+			readl(hpriv->main_cause_reg_addr),
+			readl(hpriv->main_mask_reg_addr),
+			readl(mmio + hpriv->irq_cause_ofs),
+			readl(mmio + hpriv->irq_mask_ofs));
+	} else {
+		writelfl(~HC_MAIN_MASKED_IRQS_SOC,
+			 hpriv->main_mask_reg_addr);
+		VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
+			readl(hpriv->main_cause_reg_addr),
+			readl(hpriv->main_mask_reg_addr));
+	}
 done:
 	return rc;
 }
 
+/**
+ *      mv_platform_probe - handle a positive probe of an soc Marvell
+ *      host
+ *      @pdev: platform device found
+ *
+ *      LOCKING:
+ *      Inherited from caller.
+ */
+static int mv_platform_probe(struct platform_device *pdev)
+{
+	static int printed_version;
+	const struct mv_sata_platform_data *mv_platform_data;
+	const struct ata_port_info *ppi[] =
+	    { &mv_port_info[chip_soc], NULL };
+	struct ata_host *host;
+	struct mv_host_priv *hpriv;
+	struct resource *res;
+	int n_ports, rc;
+
+	if (!printed_version++)
+		dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
+
+	/*
+	 * Simple resource validation ..
+	 */
+	if (unlikely(pdev->num_resources != 2)) {
+		dev_err(&pdev->dev, "invalid number of resources\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Get the register base first
+	 */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -EINVAL;
+
+	/* allocate host */
+	mv_platform_data = pdev->dev.platform_data;
+	n_ports = mv_platform_data->n_ports;
+
+	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
+	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
+
+	if (!host || !hpriv)
+		return -ENOMEM;
+	host->private_data = hpriv;
+	hpriv->n_ports = n_ports;
+
+	host->iomap = NULL;
+	hpriv->base = ioremap(res->start, res->end - res->start + 1);
+	hpriv->base -= MV_SATAHC0_REG_BASE;
+
+	/* initialize adapter */
+	rc = mv_init_host(host, chip_soc);
+	if (rc)
+		return rc;
+
+	dev_printk(KERN_INFO, &pdev->dev,
+		   "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH,
+		   host->n_ports);
+
+	return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt,
+				 IRQF_SHARED, &mv6_sht);
+}
+
+/*
+ *
+ *      mv_platform_remove    -       unplug a platform interface
+ *      @pdev: platform device
+ *
+ *      A platform bus SATA device has been unplugged. Perform the needed
+ *      cleanup. Also called on module unload for any active devices.
+ */
+static int __devexit mv_platform_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct mv_host_priv *hpriv = host->private_data;
+	void __iomem *base = hpriv->base;
+
+	ata_host_detach(host);
+	iounmap(base);
+	return 0;
+}
+
+static struct platform_driver mv_platform_driver = {
+	.probe			= mv_platform_probe,
+	.remove			= __devexit_p(mv_platform_remove),
+	.driver			= {
+				   .name = DRV_NAME,
+				   .owner = THIS_MODULE,
+				  },
+};
+
+
 #ifdef CONFIG_PCI
-static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int mv_pci_init_one(struct pci_dev *pdev,
+			   const struct pci_device_id *ent);
+
 
 static struct pci_driver mv_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= mv_pci_tbl,
-	.probe			= mv_init_one,
+	.probe			= mv_pci_init_one,
 	.remove			= ata_pci_remove_one,
 };
 
@@ -2828,14 +3089,15 @@
 }
 
 /**
- *      mv_init_one - handle a positive probe of a Marvell host
+ *      mv_pci_init_one - handle a positive probe of a PCI Marvell host
  *      @pdev: PCI device found
  *      @ent: PCI device ID entry for the matched host
  *
  *      LOCKING:
  *      Inherited from caller.
  */
-static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int mv_pci_init_one(struct pci_dev *pdev,
+			   const struct pci_device_id *ent)
 {
 	static int printed_version;
 	unsigned int board_idx = (unsigned int)ent->driver_data;
@@ -2855,6 +3117,7 @@
 	if (!host || !hpriv)
 		return -ENOMEM;
 	host->private_data = hpriv;
+	hpriv->n_ports = n_ports;
 
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
@@ -2867,6 +3130,7 @@
 	if (rc)
 		return rc;
 	host->iomap = pcim_iomap_table(pdev);
+	hpriv->base = host->iomap[MV_PRIMARY_BAR];
 
 	rc = pci_go_64(pdev);
 	if (rc)
@@ -2895,11 +3159,22 @@
 }
 #endif
 
+static int mv_platform_probe(struct platform_device *pdev);
+static int __devexit mv_platform_remove(struct platform_device *pdev);
+
 static int __init mv_init(void)
 {
 	int rc = -ENODEV;
 #ifdef CONFIG_PCI
 	rc = pci_register_driver(&mv_pci_driver);
+	if (rc < 0)
+		return rc;
+#endif
+	rc = platform_driver_register(&mv_platform_driver);
+
+#ifdef CONFIG_PCI
+	if (rc < 0)
+		pci_unregister_driver(&mv_pci_driver);
 #endif
 	return rc;
 }
@@ -2909,6 +3184,7 @@
 #ifdef CONFIG_PCI
 	pci_unregister_driver(&mv_pci_driver);
 #endif
+	platform_driver_unregister(&mv_platform_driver);
 }
 
 MODULE_AUTHOR("Brett Russ");
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index bfe92a4..ed5473b 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -247,6 +247,7 @@
 	void __iomem		*ctl_block;
 	void __iomem		*gen_block;
 	void __iomem		*notifier_clear_block;
+	u64			adma_dma_mask;
 	u8			flags;
 	int			last_issue_ncq;
 };
@@ -715,9 +716,10 @@
 {
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
 	struct nv_adma_port_priv *pp = ap->private_data;
+	struct nv_adma_port_priv *port0, *port1;
+	struct scsi_device *sdev0, *sdev1;
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-	u64 bounce_limit;
-	unsigned long segment_boundary;
+	unsigned long segment_boundary, flags;
 	unsigned short sg_tablesize;
 	int rc;
 	int adma_enable;
@@ -729,6 +731,8 @@
 		/* Not a proper libata device, ignore */
 		return rc;
 
+	spin_lock_irqsave(ap->lock, flags);
+
 	if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) {
 		/*
 		 * NVIDIA reports that ADMA mode does not support ATAPI commands.
@@ -737,7 +741,6 @@
 		 * Restrict DMA parameters as required by the legacy interface
 		 * when an ATAPI device is connected.
 		 */
-		bounce_limit = ATA_DMA_MASK;
 		segment_boundary = ATA_DMA_BOUNDARY;
 		/* Subtract 1 since an extra entry may be needed for padding, see
 		   libata-scsi.c */
@@ -748,7 +751,6 @@
 		adma_enable = 0;
 		nv_adma_register_mode(ap);
 	} else {
-		bounce_limit = *ap->dev->dma_mask;
 		segment_boundary = NV_ADMA_DMA_BOUNDARY;
 		sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
 		adma_enable = 1;
@@ -774,12 +776,49 @@
 	if (current_reg != new_reg)
 		pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
 
-	blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
+	port0 = ap->host->ports[0]->private_data;
+	port1 = ap->host->ports[1]->private_data;
+	sdev0 = ap->host->ports[0]->link.device[0].sdev;
+	sdev1 = ap->host->ports[1]->link.device[0].sdev;
+	if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+	    (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+		/** We have to set the DMA mask to 32-bit if either port is in
+		    ATAPI mode, since they are on the same PCI device which is
+		    used for DMA mapping. If we set the mask we also need to set
+		    the bounce limit on both ports to ensure that the block
+		    layer doesn't feed addresses that cause DMA mapping to
+		    choke. If either SCSI device is not allocated yet, it's OK
+		    since that port will discover its correct setting when it
+		    does get allocated.
+		    Note: Setting 32-bit mask should not fail. */
+		if (sdev0)
+			blk_queue_bounce_limit(sdev0->request_queue,
+					       ATA_DMA_MASK);
+		if (sdev1)
+			blk_queue_bounce_limit(sdev1->request_queue,
+					       ATA_DMA_MASK);
+
+		pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	} else {
+		/** This shouldn't fail as it was set to this value before */
+		pci_set_dma_mask(pdev, pp->adma_dma_mask);
+		if (sdev0)
+			blk_queue_bounce_limit(sdev0->request_queue,
+					       pp->adma_dma_mask);
+		if (sdev1)
+			blk_queue_bounce_limit(sdev1->request_queue,
+					       pp->adma_dma_mask);
+	}
+
 	blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
 	blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize);
 	ata_port_printk(ap, KERN_INFO,
-		"bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
-		(unsigned long long)bounce_limit, segment_boundary, sg_tablesize);
+		"DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
+		(unsigned long long)*ap->host->dev->dma_mask,
+		segment_boundary, sg_tablesize);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
 	return rc;
 }
 
@@ -1140,10 +1179,20 @@
 	void *mem;
 	dma_addr_t mem_dma;
 	void __iomem *mmio;
+	struct pci_dev *pdev = to_pci_dev(dev);
 	u16 tmp;
 
 	VPRINTK("ENTER\n");
 
+	/* Ensure DMA mask is set to 32-bit before allocating legacy PRD and
+	   pad buffers */
+	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (rc)
+		return rc;
+	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (rc)
+		return rc;
+
 	rc = ata_port_start(ap);
 	if (rc)
 		return rc;
@@ -1159,6 +1208,15 @@
 	pp->notifier_clear_block = pp->gen_block +
 	       NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
 
+	/* Now that the legacy PRD and padding buffer are allocated we can
+	   safely raise the DMA mask to allocate the CPB/APRD table.
+	   These are allowed to fail since we store the value that ends up
+	   being used to set as the bounce limit in slave_config later if
+	   needed. */
+	pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	pp->adma_dma_mask = *dev->dma_mask;
+
 	mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
 				  &mem_dma, GFP_KERNEL);
 	if (!mem)
@@ -2417,12 +2475,6 @@
 	hpriv->type = type;
 	host->private_data = hpriv;
 
-	/* set 64bit dma masks, may fail */
-	if (type == ADMA) {
-		if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0)
-			pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-	}
-
 	/* request and iomap NV_MMIO_BAR */
 	rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME);
 	if (rc)
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 3ef072ff..30caa03 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -30,8 +30,6 @@
  *  Hardware documentation available under NDA.
  *
  *
- *  To-do list:
- *  - VT6421 PATA support
  *
  */
 
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index c5885f5..499b003 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -110,7 +110,7 @@
  *
  * Initialize and register the CPU device.
  */
-int __devinit register_cpu(struct cpu *cpu, int num)
+int __cpuinit register_cpu(struct cpu *cpu, int num)
 {
 	int error;
 	cpu->node_id = cpu_to_node(num);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 94268c7..4249950 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -90,7 +90,7 @@
 	unsigned	blocks;		/* total number of blocks */
 	unsigned	fdc_speed;	/* fdc_speed setting */
 	unsigned 	stretch;	/* track doubling ? */
-} disk_type[] = {
+} atari_disk_type[] = {
 	{ "d360",  9, 720, 0, 0},	/*  0: 360kB diskette */
 	{ "D360",  9, 720, 0, 1},	/*  1: 360kb in 720k or 1.2MB drive */
 	{ "D720",  9,1440, 0, 0},	/*  2: 720kb in 720k or 1.2MB drive */
@@ -658,7 +658,7 @@
 			return -EINVAL;
 		}
 		type = minor2disktype[type].index;
-		UDT = &disk_type[type];
+		UDT = &atari_disk_type[type];
 	}
 
 	if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) {
@@ -1064,7 +1064,7 @@
 	       searched for a non-existent sector! */
 	    !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) {
 		if (Probing) {
-			if (SUDT > disk_type) {
+			if (SUDT > atari_disk_type) {
 			    if (SUDT[-1].blocks > ReqBlock) {
 				/* try another disk type */
 				SUDT--;
@@ -1082,7 +1082,7 @@
 		} else {	
 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
 			if (SUD.autoprobe) {
-				SUDT = disk_type + StartDiskType[DriveType];
+				SUDT = atari_disk_type + StartDiskType[DriveType];
 				set_capacity(unit[SelectedDrive].disk,
 							SUDT->blocks);
 				Probing = 1;
@@ -1421,7 +1421,7 @@
 	if (type == 0) {
 		if (!UDT) {
 			Probing = 1;
-			UDT = disk_type + StartDiskType[DriveType];
+			UDT = atari_disk_type + StartDiskType[DriveType];
 			set_capacity(floppy->disk, UDT->blocks);
 			UD.autoprobe = 1;
 		}
@@ -1439,7 +1439,7 @@
 			goto repeat;
 		}
 		type = minor2disktype[type].index;
-		UDT = &disk_type[type];
+		UDT = &atari_disk_type[type];
 		set_capacity(floppy->disk, UDT->blocks);
 		UD.autoprobe = 0;
 	}
@@ -1505,7 +1505,7 @@
 			if (minor2disktype[type].drive_types > DriveType)
 				return -ENODEV;
 			type = minor2disktype[type].index;
-			dtp = &disk_type[type];
+			dtp = &atari_disk_type[type];
 			if (UD.flags & FTD_MSG)
 			    printk (KERN_ERR "floppy%d: found dtp %p name %s!\n",
 			        drive, dtp, dtp->name);
@@ -1576,7 +1576,7 @@
 				continue;
 			}
 			setidx = minor2disktype[settype].index;
-			dtp = &disk_type[setidx];
+			dtp = &atari_disk_type[setidx];
 
 			/* found matching entry ?? */
 			if (   dtp->blocks  == setprm.size 
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 855ce8e..9715be3 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -2630,12 +2630,14 @@
 			c->Request.CDB[8] = creq->nr_sectors & 0xff;
 			c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 		} else {
+			u32 upper32 = upper_32_bits(start_blk);
+
 			c->Request.CDBLen = 16;
 			c->Request.CDB[1]= 0;
-			c->Request.CDB[2]= (start_blk >> 56) & 0xff;	//MSB
-			c->Request.CDB[3]= (start_blk >> 48) & 0xff;
-			c->Request.CDB[4]= (start_blk >> 40) & 0xff;
-			c->Request.CDB[5]= (start_blk >> 32) & 0xff;
+			c->Request.CDB[2]= (upper32 >> 24) & 0xff;	//MSB
+			c->Request.CDB[3]= (upper32 >> 16) & 0xff;
+			c->Request.CDB[4]= (upper32 >>  8) & 0xff;
+			c->Request.CDB[5]= upper32 & 0xff;
 			c->Request.CDB[6]= (start_blk >> 24) & 0xff;
 			c->Request.CDB[7]= (start_blk >> 16) & 0xff;
 			c->Request.CDB[8]= (start_blk >>  8) & 0xff;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index b8af22e..91ebb00 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -973,6 +973,10 @@
 	lo->transfer = xfer->transfer;
 	lo->ioctl = xfer->ioctl;
 
+	if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
+	     (info->lo_flags & LO_FLAGS_AUTOCLEAR))
+		lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
+
 	lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
 	lo->lo_init[0] = info->lo_init[0];
 	lo->lo_init[1] = info->lo_init[1];
@@ -1331,6 +1335,10 @@
 
 	mutex_lock(&lo->lo_ctl_mutex);
 	--lo->lo_refcnt;
+
+	if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
+		loop_clr_fd(lo, inode->i_bdev);
+
 	mutex_unlock(&lo->lo_ctl_mutex);
 
 	return 0;
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 76096ca..8b9549a 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -660,7 +660,7 @@
 	pt_identify(tape);
 
 	err = -ENODEV;
-	if (!tape->flags & PT_MEDIA)
+	if (!(tape->flags & PT_MEDIA))
 		goto out;
 
 	err = -EROFS;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index e9de171..674cd66 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2212,11 +2212,11 @@
 		return ret;
 	}
 
-	if (!buf[6] & 0x40) {
+	if (!(buf[6] & 0x40)) {
 		printk(DRIVER_NAME": Disc type is not CD-RW\n");
 		return 1;
 	}
-	if (!buf[6] & 0x4) {
+	if (!(buf[6] & 0x4)) {
 		printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n");
 		return 1;
 	}
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 82f4eec..06e23be 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -56,6 +56,7 @@
 #include <linux/backing-dev.h>
 #include <linux/blkpg.h>
 #include <linux/writeback.h>
+#include <linux/log2.h>
 
 #include <asm/uaccess.h>
 
@@ -450,7 +451,7 @@
 	err = -ENOMEM;
 
 	if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
-			(rd_blocksize & (rd_blocksize-1))) {
+			!is_power_of_2(rd_blocksize)) {
 		printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
 		       rd_blocksize);
 		rd_blocksize = BLOCK_SIZE;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 47e5b40..db259e6 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1206,25 +1206,26 @@
 	return 0;
 }
 
-/* Admittedly, the logic below could be performed in a nicer way. */
 int cdrom_release(struct cdrom_device_info *cdi, struct file *fp)
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
 	int opened_for_data;
 
-	cdinfo(CD_CLOSE, "entering cdrom_release\n"); 
+	cdinfo(CD_CLOSE, "entering cdrom_release\n");
 
 	if (cdi->use_count > 0)
 		cdi->use_count--;
-	if (cdi->use_count == 0)
+
+	if (cdi->use_count == 0) {
 		cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
-	if (cdi->use_count == 0)
 		cdrom_dvd_rw_close_write(cdi);
-	if (cdi->use_count == 0 &&
-	    (cdo->capability & CDC_LOCK) && !keeplocked) {
-		cdinfo(CD_CLOSE, "Unlocking door!\n");
-		cdo->lock_door(cdi, 0);
+
+		if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+			cdinfo(CD_CLOSE, "Unlocking door!\n");
+			cdo->lock_door(cdi, 0);
+		}
 	}
+
 	opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
 		!(fp && fp->f_flags & O_NONBLOCK);
 
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4666295..85bf9b2 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -276,7 +276,7 @@
 
 config RISCOM8
 	tristate "SDL RISCom/8 card support"
-	depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP
+	depends on SERIAL_NONSTANDARD
 	help
 	  This is a driver for the SDL Communications RISCom/8 multiport card,
 	  which gives you many serial ports. You would need something like
@@ -765,7 +765,7 @@
 
 config SGI_DS1286
 	tristate "SGI DS1286 RTC support"
-	depends on SGI_IP22
+	depends on SGI_HAS_DS1286
 	help
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 480fae2..44160d5 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -93,7 +93,7 @@
 };
 
 /* dynamic list of hvc_struct instances */
-static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
+static LIST_HEAD(hvc_structs);
 
 /*
  * Protect the list of hvc_struct instances from inserts and removals during
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 3402def..786d518 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -306,7 +306,7 @@
 /* Required to back map a kref to its containing object */
 #define from_kref(k) container_of(k, struct hvcs_struct, kref)
 
-static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
+static LIST_HEAD(hvcs_structs);
 static DEFINE_SPINLOCK(hvcs_structs_lock);
 
 static void hvcs_unthrottle(struct tty_struct *tty);
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 868e39f..f7feae4 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -42,6 +42,8 @@
 	VIA_STRFILT_ENABLE	= (1 << 14),
 	VIA_RAWBITS_ENABLE	= (1 << 13),
 	VIA_RNG_ENABLE		= (1 << 6),
+	VIA_NOISESRC1		= (1 << 8),
+	VIA_NOISESRC2		= (1 << 9),
 	VIA_XSTORE_CNT_MASK	= 0x0F,
 
 	VIA_RNG_CHUNK_8		= 0x00,	/* 64 rand bits, 64 stored bits */
@@ -119,6 +121,7 @@
 
 static int via_rng_init(struct hwrng *rng)
 {
+	struct cpuinfo_x86 *c = &cpu_data(0);
 	u32 lo, hi, old_lo;
 
 	/* Control the RNG via MSR.  Tread lightly and pay very close
@@ -134,6 +137,17 @@
 	lo &= ~VIA_XSTORE_CNT_MASK;
 	lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
 	lo |= VIA_RNG_ENABLE;
+	lo |= VIA_NOISESRC1;
+
+	/* Enable secondary noise source on CPUs where it is present. */
+
+	/* Nehemiah stepping 8 and higher */
+	if ((c->x86_model == 9) && (c->x86_mask > 7))
+		lo |= VIA_NOISESRC2;
+
+	/* Esther */
+	if (c->x86_model >= 10)
+		lo |= VIA_NOISESRC2;
 
 	if (lo != old_lo)
 		wrmsr(MSR_VIA_RNG, lo, hi);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 30e5645..179223a 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -439,6 +439,13 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
 		},
 	},
+	{	/* UK Inspiron 6400  */
+		.ident = "Dell Inspiron 3",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MM061"),
+		},
+	},
 	{ }
 };
 
diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c
index 932264a..86e6538 100644
--- a/drivers/char/ip27-rtc.c
+++ b/drivers/char/ip27-rtc.c
@@ -46,8 +46,8 @@
 #include <asm/sn/sn0/hub.h>
 #include <asm/sn/sn_private.h>
 
-static int rtc_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, unsigned long arg);
+static long rtc_ioctl(struct file *filp, unsigned int cmd,
+			unsigned long arg);
 
 static int rtc_read_proc(char *page, char **start, off_t off,
                          int count, int *eof, void *data);
@@ -75,8 +75,7 @@
 static const unsigned char days_in_mo[] =
 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
-static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-		     unsigned long arg)
+static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 
 	struct rtc_time wtime;
@@ -197,7 +196,7 @@
 
 static const struct file_operations rtc_fops = {
 	.owner		= THIS_MODULE,
-	.ioctl		= rtc_ioctl,
+	.unlocked_ioctl	= rtc_ioctl,
 	.open		= rtc_open,
 	.release	= rtc_release,
 };
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 5dc1265..32b2b22 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -365,12 +365,12 @@
 };
 static DEFINE_MUTEX(ipmidriver_mutex);
 
-static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces);
+static LIST_HEAD(ipmi_interfaces);
 static DEFINE_MUTEX(ipmi_interfaces_mutex);
 
 /* List of watchers that want to know when smi's are added and
    deleted. */
-static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers);
+static LIST_HEAD(smi_watchers);
 static DEFINE_MUTEX(smi_watchers_mutex);
 
 
@@ -441,7 +441,7 @@
 int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
 {
 	ipmi_smi_t intf;
-	struct list_head to_deliver = LIST_HEAD_INIT(to_deliver);
+	LIST_HEAD(to_deliver);
 	struct watcher_entry *e, *e2;
 
 	mutex_lock(&smi_watchers_mutex);
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 81674d7..60ac642 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -312,7 +312,7 @@
 	if (copy_size > LP_BUFFER_SIZE)
 		copy_size = LP_BUFFER_SIZE;
 
-	if (down_interruptible (&lp_table[minor].port_mutex))
+	if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
 		return -EINTR;
 
 	if (copy_from_user (kbuf, buf, copy_size)) {
@@ -399,7 +399,7 @@
 		lp_release_parport (&lp_table[minor]);
 	}
 out_unlock:
-	up (&lp_table[minor].port_mutex);
+	mutex_unlock(&lp_table[minor].port_mutex);
 
  	return retv;
 }
@@ -421,7 +421,7 @@
 	if (count > LP_BUFFER_SIZE)
 		count = LP_BUFFER_SIZE;
 
-	if (down_interruptible (&lp_table[minor].port_mutex))
+	if (mutex_lock_interruptible(&lp_table[minor].port_mutex))
 		return -EINTR;
 
 	lp_claim_parport_or_block (&lp_table[minor]);
@@ -479,7 +479,7 @@
 	if (retval > 0 && copy_to_user (buf, kbuf, retval))
 		retval = -EFAULT;
 
-	up (&lp_table[minor].port_mutex);
+	mutex_unlock(&lp_table[minor].port_mutex);
 
 	return retval;
 }
@@ -888,7 +888,7 @@
 		lp_table[i].last_error = 0;
 		init_waitqueue_head (&lp_table[i].waitq);
 		init_waitqueue_head (&lp_table[i].dataq);
-		init_MUTEX (&lp_table[i].port_mutex);
+		mutex_init(&lp_table[i].port_mutex);
 		lp_table[i].timeout = 10 * HZ;
 	}
 
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index fd0abef..4742078 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -37,7 +37,6 @@
 
 
 #include <linux/module.h>
-#include <linux/autoconf.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 081c84c..bf1bee4 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -20,7 +20,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/autoconf.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 596c717..90c3969 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -695,17 +695,16 @@
 		return;
 	}
 	
-	if (tty->stopped && !tty->flow_stopped &&
-	    I_IXON(tty) && I_IXANY(tty)) {
-		start_tty(tty);
-		return;
-	}
-	
 	if (I_ISTRIP(tty))
 		c &= 0x7f;
 	if (I_IUCLC(tty) && L_IEXTEN(tty))
 		c=tolower(c);
 
+	if (tty->stopped && !tty->flow_stopped && I_IXON(tty) &&
+	    ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) ||
+	     c == INTR_CHAR(tty) || c == QUIT_CHAR(tty)))
+		start_tty(tty);
+
 	if (tty->closing) {
 		if (I_IXON(tty)) {
 			if (c == START_CHAR(tty))
@@ -769,7 +768,21 @@
 		signal = SIGTSTP;
 		if (c == SUSP_CHAR(tty)) {
 send_signal:
-			isig(signal, tty, 0);
+			/*
+			 * Echo character, and then send the signal.
+			 * Note that we do not use isig() here because we want
+			 * the order to be:
+			 * 1) flush, 2) echo, 3) signal
+			 */
+			if (!L_NOFLSH(tty)) {
+				n_tty_flush_buffer(tty);
+				if (tty->driver->flush_buffer)
+					tty->driver->flush_buffer(tty);
+			}
+			if (L_ECHO(tty))
+				echo_char(c, tty);
+			if (tty->pgrp)
+				kill_pgrp(tty->pgrp, signal, 1);
 			return;
 		}
 	}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 8caff0c..279ff50 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -57,6 +57,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ioctl.h>
+#include <linux/synclink.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -87,8 +88,6 @@
 
 #include <asm/uaccess.h>
 
-#include "linux/synclink.h"
-
 static MGSL_PARAMS default_params = {
 	MGSL_MODE_HDLC,			/* unsigned long mode */
 	0,				/* unsigned char loopback; */
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c511a83..f43c89f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1039,6 +1039,7 @@
 		p += bytes;
 
 		add_entropy_words(r, buf, (bytes + 3) / 4);
+		cond_resched();
 	}
 
 	return 0;
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 102ece4..d130b87 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -47,6 +47,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/tty_flip.h>
+#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 
@@ -81,6 +82,8 @@
 
 static struct tty_driver *riscom_driver;
 
+static DEFINE_SPINLOCK(riscom_lock);
+
 static struct riscom_board rc_board[RC_NBOARD] =  {
 	{
 		.base	= RC_IOBASE1,
@@ -217,13 +220,14 @@
 {
 	unsigned long flags;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	rc_out(bp, RC_CTOUT, 0);     	           /* Clear timeout             */
 	rc_wait_CCR(bp);			   /* Wait for CCR ready        */
 	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip          */
-	sti();
+	spin_unlock_irqrestore(&riscom_lock, flags);
 	msleep(50);				   /* Delay 0.05 sec            */
-	cli();
+	spin_lock_irqsave(&riscom_lock, flags);
 	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip      */
 	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits            */
 	rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr       */
@@ -234,7 +238,7 @@
 	rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
 	rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
 	
-	restore_flags(flags);
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 /* Main probing routine, also sets irq. */
@@ -812,9 +816,9 @@
 		}
 		port->xmit_buf = (unsigned char *) tmp;
 	}
-		
-	save_flags(flags); cli();
-		
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	if (port->tty) 
 		clear_bit(TTY_IO_ERROR, &port->tty->flags);
 		
@@ -825,7 +829,7 @@
 	rc_change_speed(bp, port);
 	port->flags |= ASYNC_INITIALIZED;
 		
-	restore_flags(flags);
+	spin_unlock_irqrestore(&riscom_lock, flags);
 	return 0;
 }
 
@@ -901,6 +905,7 @@
 	int    retval;
 	int    do_clocal = 0;
 	int    CD;
+	unsigned long flags;
 
 	/*
 	 * If the device is in the middle of being closed, then block
@@ -936,19 +941,26 @@
 	 */
 	retval = 0;
 	add_wait_queue(&port->open_wait, &wait);
-	cli();
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	if (!tty_hung_up_p(filp))
 		port->count--;
-	sti();
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
 	port->blocked_open++;
 	while (1) {
-		cli();
+		spin_lock_irqsave(&riscom_lock, flags);
+
 		rc_out(bp, CD180_CAR, port_No(port));
 		CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
 		rc_out(bp, CD180_MSVR, MSVR_RTS);
 		bp->DTR &= ~(1u << port_No(port));
 		rc_out(bp, RC_DTR, bp->DTR);
-		sti();
+
+		spin_unlock_irqrestore(&riscom_lock, flags);
+
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(port->flags & ASYNC_INITIALIZED)) {
@@ -1020,8 +1032,9 @@
 	
 	if (!port || rc_paranoia_check(port, tty->name, "close"))
 		return;
-	
-	save_flags(flags); cli();
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	if (tty_hung_up_p(filp))
 		goto out;
 	
@@ -1088,7 +1101,9 @@
 	}
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	wake_up_interruptible(&port->close_wait);
-out:	restore_flags(flags);
+
+out:
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static int rc_write(struct tty_struct * tty, 
@@ -1107,34 +1122,33 @@
 	if (!tty || !port->xmit_buf)
 		return 0;
 
-	save_flags(flags);
 	while (1) {
-		cli();		
+		spin_lock_irqsave(&riscom_lock, flags);
+
 		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 					  SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0) {
-			restore_flags(flags);
-			break;
-		}
+		if (c <= 0)
+			break;	/* lock continues to be held */
 
 		memcpy(port->xmit_buf + port->xmit_head, buf, c);
 		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 		port->xmit_cnt += c;
-		restore_flags(flags);
+
+		spin_unlock_irqrestore(&riscom_lock, flags);
 
 		buf += c;
 		count -= c;
 		total += c;
 	}
 
-	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
 		rc_out(bp, CD180_CAR, port_No(port));
 		rc_out(bp, CD180_IER, port->IER);
 	}
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 
 	return total;
 }
@@ -1150,7 +1164,7 @@
 	if (!tty || !port->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
 	
 	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
 		goto out;
@@ -1158,7 +1172,9 @@
 	port->xmit_buf[port->xmit_head++] = ch;
 	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
 	port->xmit_cnt++;
-out:	restore_flags(flags);
+
+out:
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static void rc_flush_chars(struct tty_struct * tty)
@@ -1173,11 +1189,13 @@
 	    !port->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->IER |= IER_TXRDY;
 	rc_out(port_Board(port), CD180_CAR, port_No(port));
 	rc_out(port_Board(port), CD180_IER, port->IER);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static int rc_write_room(struct tty_struct * tty)
@@ -1212,9 +1230,11 @@
 	if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 	
 	tty_wakeup(tty);
 }
@@ -1231,11 +1251,15 @@
 		return -ENODEV;
 
 	bp = port_Board(port);
-	save_flags(flags); cli();
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	rc_out(bp, CD180_CAR, port_No(port));
 	status = rc_in(bp, CD180_MSVR);
 	result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
 	result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
 		| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
 		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
@@ -1256,7 +1280,8 @@
 
 	bp = port_Board(port);
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	if (set & TIOCM_RTS)
 		port->MSVR |= MSVR_RTS;
 	if (set & TIOCM_DTR)
@@ -1270,7 +1295,9 @@
 	rc_out(bp, CD180_CAR, port_No(port));
 	rc_out(bp, CD180_MSVR, port->MSVR);
 	rc_out(bp, RC_DTR, bp->DTR);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
 	return 0;
 }
 
@@ -1279,7 +1306,8 @@
 	struct riscom_board *bp = port_Board(port);
 	unsigned long flags;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->break_length = RISCOM_TPS / HZ * length;
 	port->COR2 |= COR2_ETC;
 	port->IER  |= IER_TXRDY;
@@ -1289,7 +1317,8 @@
 	rc_wait_CCR(bp);
 	rc_out(bp, CD180_CCR, CCR_CORCHG2);
 	rc_wait_CCR(bp);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static inline int rc_set_serial_info(struct riscom_port * port,
@@ -1298,7 +1327,6 @@
 	struct serial_struct tmp;
 	struct riscom_board *bp = port_Board(port);
 	int change_speed;
-	unsigned long flags;
 	
 	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
 		return -EFAULT;
@@ -1332,9 +1360,11 @@
 		port->closing_wait = tmp.closing_wait;
 	}
 	if (change_speed)  {
-		save_flags(flags); cli();
+		unsigned long flags;
+
+		spin_lock_irqsave(&riscom_lock, flags);
 		rc_change_speed(bp, port);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&riscom_lock, flags);
 	}
 	return 0;
 }
@@ -1414,17 +1444,19 @@
 		return;
 	
 	bp = port_Board(port);
-	
-	save_flags(flags); cli();
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->MSVR &= ~MSVR_RTS;
 	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty))  {
+	if (I_IXOFF(tty)) {
 		rc_wait_CCR(bp);
 		rc_out(bp, CD180_CCR, CCR_SSCH2);
 		rc_wait_CCR(bp);
 	}
 	rc_out(bp, CD180_MSVR, port->MSVR);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static void rc_unthrottle(struct tty_struct * tty)
@@ -1438,7 +1470,8 @@
 	
 	bp = port_Board(port);
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->MSVR |= MSVR_RTS;
 	rc_out(bp, CD180_CAR, port_No(port));
 	if (I_IXOFF(tty))  {
@@ -1447,7 +1480,8 @@
 		rc_wait_CCR(bp);
 	}
 	rc_out(bp, CD180_MSVR, port->MSVR);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static void rc_stop(struct tty_struct * tty)
@@ -1461,11 +1495,13 @@
 	
 	bp = port_Board(port);
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	port->IER &= ~IER_TXRDY;
 	rc_out(bp, CD180_CAR, port_No(port));
 	rc_out(bp, CD180_IER, port->IER);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 static void rc_start(struct tty_struct * tty)
@@ -1479,13 +1515,15 @@
 	
 	bp = port_Board(port);
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY))  {
 		port->IER |= IER_TXRDY;
 		rc_out(bp, CD180_CAR, port_No(port));
 		rc_out(bp, CD180_IER, port->IER);
 	}
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 /*
@@ -1537,9 +1575,9 @@
 	    tty->termios->c_iflag == old_termios->c_iflag)
 		return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&riscom_lock, flags);
 	rc_change_speed(port_Board(port), port);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&riscom_lock, flags);
 
 	if ((old_termios->c_cflag & CRTSCTS) &&
 	    !(tty->termios->c_cflag & CRTSCTS)) {
@@ -1627,11 +1665,12 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&riscom_lock, flags);
+
 	tty_unregister_driver(riscom_driver);
 	put_tty_driver(riscom_driver);
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
 }
 
 #ifndef MODULE
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 3c86914..4ba3aec 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -653,7 +653,7 @@
 		port->gs.closing_wait = 30 * HZ;
 		port->gs.rd = &a2232_real_driver;
 #ifdef NEW_WRITE_LOCKING
-		init_MUTEX(&(port->gs.port_write_mutex));
+		mutex_init(&(port->gs.port_write_mutex));
 #endif
 		init_waitqueue_head(&port->gs.open_wait);
 		init_waitqueue_head(&port->gs.close_wait);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index d010ed9..ddc74d1 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -85,6 +85,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/ioctl.h>
+#include <linux/synclink.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -110,8 +111,6 @@
 
 #include <asm/uaccess.h>
 
-#include "linux/synclink.h"
-
 #define RCLRVALUE 0xffff
 
 static MGSL_PARAMS default_params = {
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 64e835f..1f954ac 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -73,6 +73,7 @@
 #include <linux/bitops.h>
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
+#include <linux/synclink.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -81,8 +82,6 @@
 #include <asm/types.h>
 #include <asm/uaccess.h>
 
-#include "linux/synclink.h"
-
 #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
 #define SYNCLINK_GENERIC_HDLC 1
 #else
@@ -2040,37 +2039,41 @@
 		tty_wakeup(tty);
 }
 
-static void dsr_change(struct slgt_info *info)
+static void dsr_change(struct slgt_info *info, unsigned short status)
 {
-	get_signals(info);
+	if (status & BIT3) {
+		info->signals |= SerialSignal_DSR;
+		info->input_signal_events.dsr_up++;
+	} else {
+		info->signals &= ~SerialSignal_DSR;
+		info->input_signal_events.dsr_down++;
+	}
 	DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
 	if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
 		slgt_irq_off(info, IRQ_DSR);
 		return;
 	}
 	info->icount.dsr++;
-	if (info->signals & SerialSignal_DSR)
-		info->input_signal_events.dsr_up++;
-	else
-		info->input_signal_events.dsr_down++;
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 	info->pending_bh |= BH_STATUS;
 }
 
-static void cts_change(struct slgt_info *info)
+static void cts_change(struct slgt_info *info, unsigned short status)
 {
-	get_signals(info);
+	if (status & BIT2) {
+		info->signals |= SerialSignal_CTS;
+		info->input_signal_events.cts_up++;
+	} else {
+		info->signals &= ~SerialSignal_CTS;
+		info->input_signal_events.cts_down++;
+	}
 	DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
 	if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
 		slgt_irq_off(info, IRQ_CTS);
 		return;
 	}
 	info->icount.cts++;
-	if (info->signals & SerialSignal_CTS)
-		info->input_signal_events.cts_up++;
-	else
-		info->input_signal_events.cts_down++;
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 	info->pending_bh |= BH_STATUS;
@@ -2091,20 +2094,21 @@
 	}
 }
 
-static void dcd_change(struct slgt_info *info)
+static void dcd_change(struct slgt_info *info, unsigned short status)
 {
-	get_signals(info);
+	if (status & BIT1) {
+		info->signals |= SerialSignal_DCD;
+		info->input_signal_events.dcd_up++;
+	} else {
+		info->signals &= ~SerialSignal_DCD;
+		info->input_signal_events.dcd_down++;
+	}
 	DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
 	if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
 		slgt_irq_off(info, IRQ_DCD);
 		return;
 	}
 	info->icount.dcd++;
-	if (info->signals & SerialSignal_DCD) {
-		info->input_signal_events.dcd_up++;
-	} else {
-		info->input_signal_events.dcd_down++;
-	}
 #if SYNCLINK_GENERIC_HDLC
 	if (info->netcount) {
 		if (info->signals & SerialSignal_DCD)
@@ -2127,20 +2131,21 @@
 	}
 }
 
-static void ri_change(struct slgt_info *info)
+static void ri_change(struct slgt_info *info, unsigned short status)
 {
-	get_signals(info);
+	if (status & BIT0) {
+		info->signals |= SerialSignal_RI;
+		info->input_signal_events.ri_up++;
+	} else {
+		info->signals &= ~SerialSignal_RI;
+		info->input_signal_events.ri_down++;
+	}
 	DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
 	if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
 		slgt_irq_off(info, IRQ_RI);
 		return;
 	}
-	info->icount.dcd++;
-	if (info->signals & SerialSignal_RI) {
-		info->input_signal_events.ri_up++;
-	} else {
-		info->input_signal_events.ri_down++;
-	}
+	info->icount.rng++;
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 	info->pending_bh |= BH_STATUS;
@@ -2191,13 +2196,13 @@
 	}
 
 	if (status & IRQ_DSR)
-		dsr_change(info);
+		dsr_change(info, status);
 	if (status & IRQ_CTS)
-		cts_change(info);
+		cts_change(info, status);
 	if (status & IRQ_DCD)
-		dcd_change(info);
+		dcd_change(info, status);
 	if (status & IRQ_RI)
-		ri_change(info);
+		ri_change(info, status);
 }
 
 static void isr_rdma(struct slgt_info *info)
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index c63013b..f3e7807 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -66,6 +66,7 @@
 #include <linux/termios.h>
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
+#include <linux/synclink.h>
 
 #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
 #define SYNCLINK_GENERIC_HDLC 1
@@ -80,8 +81,6 @@
 
 #include <asm/uaccess.h>
 
-#include "linux/synclink.h"
-
 static MGSL_PARAMS default_params = {
 	MGSL_MODE_HDLC,			/* unsigned long mode */
 	0,				/* unsigned char loopback; */
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index c88424a..a5d8bcb 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -1031,18 +1031,13 @@
 
 	spin_unlock(&driver_lock);
 
-	dev_set_drvdata(dev, NULL);
 	misc_deregister(&chip->vendor.miscdev);
-	kfree(chip->vendor.miscdev.name);
 
 	sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
 	tpm_bios_log_teardown(chip->bios_dir);
 
-	clear_bit(chip->dev_num, dev_mask);
-
-	kfree(chip);
-
-	put_device(dev);
+	/* write it this way to be explicit (chip->dev == dev) */
+	put_device(chip->dev);
 }
 EXPORT_SYMBOL_GPL(tpm_remove_hardware);
 
@@ -1083,6 +1078,26 @@
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
 /*
+ * Once all references to platform device are down to 0,
+ * release all allocated structures.
+ * In case vendor provided release function,
+ * call it too.
+ */
+static void tpm_dev_release(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+
+	if (chip->vendor.release)
+		chip->vendor.release(dev);
+
+	chip->release(dev);
+
+	clear_bit(chip->dev_num, dev_mask);
+	kfree(chip->vendor.miscdev.name);
+	kfree(chip);
+}
+
+/*
  * Called from tpm_<specific>.c probe function only for devices 
  * the driver has determined it should claim.  Prior to calling
  * this function the specific probe function has called pci_enable_device
@@ -1136,23 +1151,21 @@
 
 	chip->vendor.miscdev.parent = dev;
 	chip->dev = get_device(dev);
+	chip->release = dev->release;
+	dev->release = tpm_dev_release;
+	dev_set_drvdata(dev, chip);
 
 	if (misc_register(&chip->vendor.miscdev)) {
 		dev_err(chip->dev,
 			"unable to misc_register %s, minor %d\n",
 			chip->vendor.miscdev.name,
 			chip->vendor.miscdev.minor);
-		put_device(dev);
-		clear_bit(chip->dev_num, dev_mask);
-		kfree(chip);
-		kfree(devname);
+		put_device(chip->dev);
 		return NULL;
 	}
 
 	spin_lock(&driver_lock);
 
-	dev_set_drvdata(dev, chip);
-
 	list_add(&chip->list, &tpm_chip_list);
 
 	spin_unlock(&driver_lock);
@@ -1160,10 +1173,7 @@
 	if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
 		list_del(&chip->list);
 		misc_deregister(&chip->vendor.miscdev);
-		put_device(dev);
-		clear_bit(chip->dev_num, dev_mask);
-		kfree(chip);
-		kfree(devname);
+		put_device(chip->dev);
 		return NULL;
 	}
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index d15ccdd..e885148 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -74,6 +74,7 @@
 	int (*send) (struct tpm_chip *, u8 *, size_t);
 	void (*cancel) (struct tpm_chip *);
 	u8 (*status) (struct tpm_chip *);
+	void (*release) (struct device *);
 	struct miscdevice miscdev;
 	struct attribute_group *attr_group;
 	struct list_head list;
@@ -106,6 +107,7 @@
 	struct dentry **bios_dir;
 
 	struct list_head list;
+	void (*release) (struct device *);
 };
 
 #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 967002a..726ee8a 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -611,7 +611,7 @@
 	}
 }
 
-static struct pnp_driver tpm_inf_pnp = {
+static struct pnp_driver tpm_inf_pnp_driver = {
 	.name = "tpm_inf_pnp",
 	.driver = {
 		.owner = THIS_MODULE,
@@ -625,12 +625,12 @@
 
 static int __init init_inf(void)
 {
-	return pnp_register_driver(&tpm_inf_pnp);
+	return pnp_register_driver(&tpm_inf_pnp_driver);
 }
 
 static void __exit cleanup_inf(void)
 {
-	pnp_unregister_driver(&tpm_inf_pnp);
+	pnp_unregister_driver(&tpm_inf_pnp_driver);
 }
 
 module_init(init_inf);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index f36fecd..79c86c4 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -138,7 +138,7 @@
 extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
 extern int pty_limit;		/* Config limit on Unix98 ptys */
 static DEFINE_IDR(allocated_ptys);
-static DECLARE_MUTEX(allocated_ptys_lock);
+static DEFINE_MUTEX(allocated_ptys_lock);
 static int ptmx_open(struct inode *, struct file *);
 #endif
 
@@ -2571,9 +2571,9 @@
 #ifdef CONFIG_UNIX98_PTYS
 	/* Make this pty number available for reallocation */
 	if (devpts) {
-		down(&allocated_ptys_lock);
+		mutex_lock(&allocated_ptys_lock);
 		idr_remove(&allocated_ptys, idx);
-		up(&allocated_ptys_lock);
+		mutex_unlock(&allocated_ptys_lock);
 	}
 #endif
 
@@ -2737,24 +2737,24 @@
 	nonseekable_open(inode, filp);
 
 	/* find a device that is not in use. */
-	down(&allocated_ptys_lock);
+	mutex_lock(&allocated_ptys_lock);
 	if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
-		up(&allocated_ptys_lock);
+		mutex_unlock(&allocated_ptys_lock);
 		return -ENOMEM;
 	}
 	idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
 	if (idr_ret < 0) {
-		up(&allocated_ptys_lock);
+		mutex_unlock(&allocated_ptys_lock);
 		if (idr_ret == -EAGAIN)
 			return -ENOMEM;
 		return -EIO;
 	}
 	if (index >= pty_limit) {
 		idr_remove(&allocated_ptys, index);
-		up(&allocated_ptys_lock);
+		mutex_unlock(&allocated_ptys_lock);
 		return -EIO;
 	}
-	up(&allocated_ptys_lock);
+	mutex_unlock(&allocated_ptys_lock);
 
 	mutex_lock(&tty_mutex);
 	retval = init_dev(ptm_driver, index, &tty);
@@ -2781,9 +2781,9 @@
 	release_dev(filp);
 	return retval;
 out:
-	down(&allocated_ptys_lock);
+	mutex_lock(&allocated_ptys_lock);
 	idr_remove(&allocated_ptys, index);
-	up(&allocated_ptys_lock);
+	mutex_unlock(&allocated_ptys_lock);
 	return retval;
 }
 #endif
@@ -3721,7 +3721,6 @@
 	tty->buf.head = tty->buf.tail = NULL;
 	tty_buffer_init(tty);
 	INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
-	init_MUTEX(&tty->buf.pty_sem);
 	mutex_init(&tty->termios_mutex);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
@@ -4048,10 +4047,6 @@
 	}
 }
 
-#ifdef CONFIG_VT
-extern int vty_init(void);
-#endif
-
 static int __init tty_class_init(void)
 {
 	tty_class = class_create(THIS_MODULE, "tty");
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 7a5badf..367be91 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2400,13 +2400,15 @@
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned char c;
-	static unsigned long printing;
+	static DEFINE_SPINLOCK(printing_lock);
 	const ushort *start;
 	ushort cnt = 0;
 	ushort myx;
 
 	/* console busy or not yet initialized */
-	if (!printable || test_and_set_bit(0, &printing))
+	if (!printable)
+		return;
+	if (!spin_trylock(&printing_lock))
 		return;
 
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
@@ -2481,7 +2483,7 @@
 	notify_update(vc);
 
 quit:
-	clear_bit(0, &printing);
+	spin_unlock(&printing_lock);
 }
 
 static struct tty_driver *vt_console_device(struct console *c, int *index)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index c46b7c2..a703def 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -5,6 +5,7 @@
 menuconfig DMADEVICES
 	bool "DMA Engine support"
 	depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
+	depends on !HIGHMEM64G
 	help
 	  DMA engines can do asynchronous data transfers without
 	  involving the host CPU.  Currently, this framework can be
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index bcf52df..2996523 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -473,20 +473,22 @@
 {
 	struct dma_device *dev = chan->device;
 	struct dma_async_tx_descriptor *tx;
-	dma_addr_t addr;
+	dma_addr_t dma_dest, dma_src;
 	dma_cookie_t cookie;
 	int cpu;
 
-	tx = dev->device_prep_dma_memcpy(chan, len, 0);
-	if (!tx)
+	dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+	dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
+
+	if (!tx) {
+		dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+		dma_unmap_single(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
 		return -ENOMEM;
+	}
 
 	tx->ack = 1;
 	tx->callback = NULL;
-	addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
-	tx->tx_set_src(addr, tx, 0);
-	addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
-	tx->tx_set_dest(addr, tx, 0);
 	cookie = tx->tx_submit(tx);
 
 	cpu = get_cpu();
@@ -517,20 +519,22 @@
 {
 	struct dma_device *dev = chan->device;
 	struct dma_async_tx_descriptor *tx;
-	dma_addr_t addr;
+	dma_addr_t dma_dest, dma_src;
 	dma_cookie_t cookie;
 	int cpu;
 
-	tx = dev->device_prep_dma_memcpy(chan, len, 0);
-	if (!tx)
+	dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+	dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
+
+	if (!tx) {
+		dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
+		dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
 		return -ENOMEM;
+	}
 
 	tx->ack = 1;
 	tx->callback = NULL;
-	addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
-	tx->tx_set_src(addr, tx, 0);
-	addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
-	tx->tx_set_dest(addr, tx, 0);
 	cookie = tx->tx_submit(tx);
 
 	cpu = get_cpu();
@@ -563,20 +567,23 @@
 {
 	struct dma_device *dev = chan->device;
 	struct dma_async_tx_descriptor *tx;
-	dma_addr_t addr;
+	dma_addr_t dma_dest, dma_src;
 	dma_cookie_t cookie;
 	int cpu;
 
-	tx = dev->device_prep_dma_memcpy(chan, len, 0);
-	if (!tx)
+	dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+	dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
+				DMA_FROM_DEVICE);
+	tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0);
+
+	if (!tx) {
+		dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
+		dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
 		return -ENOMEM;
+	}
 
 	tx->ack = 1;
 	tx->callback = NULL;
-	addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
-	tx->tx_set_src(addr, tx, 0);
-	addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
-	tx->tx_set_dest(addr, tx, 0);
 	cookie = tx->tx_submit(tx);
 
 	cpu = get_cpu();
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index 45e7b46..dff38ac 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -159,20 +159,6 @@
 	return device->common.chancnt;
 }
 
-static void ioat_set_src(dma_addr_t addr,
-			 struct dma_async_tx_descriptor *tx,
-			 int index)
-{
-	tx_to_ioat_desc(tx)->src = addr;
-}
-
-static void ioat_set_dest(dma_addr_t addr,
-			  struct dma_async_tx_descriptor *tx,
-			  int index)
-{
-	tx_to_ioat_desc(tx)->dst = addr;
-}
-
 /**
  * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
  *                                 descriptors to hw
@@ -415,8 +401,6 @@
 
 	memset(desc, 0, sizeof(*desc));
 	dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
-	desc_sw->async_tx.tx_set_src = ioat_set_src;
-	desc_sw->async_tx.tx_set_dest = ioat_set_dest;
 	switch (ioat_chan->device->version) {
 	case IOAT_VER_1_2:
 		desc_sw->async_tx.tx_submit = ioat1_tx_submit;
@@ -714,8 +698,10 @@
 
 static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
 						struct dma_chan *chan,
+						dma_addr_t dma_dest,
+						dma_addr_t dma_src,
 						size_t len,
-						int int_en)
+						unsigned long flags)
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 	struct ioat_desc_sw *new;
@@ -726,6 +712,8 @@
 
 	if (new) {
 		new->len = len;
+		new->dst = dma_dest;
+		new->src = dma_src;
 		return &new->async_tx;
 	} else
 		return NULL;
@@ -733,8 +721,10 @@
 
 static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
 						struct dma_chan *chan,
+						dma_addr_t dma_dest,
+						dma_addr_t dma_src,
 						size_t len,
-						int int_en)
+						unsigned long flags)
 {
 	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
 	struct ioat_desc_sw *new;
@@ -749,6 +739,8 @@
 
 	if (new) {
 		new->len = len;
+		new->dst = dma_dest;
+		new->src = dma_src;
 		return &new->async_tx;
 	} else
 		return NULL;
@@ -1045,7 +1037,7 @@
 	u8 *dest;
 	struct dma_chan *dma_chan;
 	struct dma_async_tx_descriptor *tx;
-	dma_addr_t addr;
+	dma_addr_t dma_dest, dma_src;
 	dma_cookie_t cookie;
 	int err = 0;
 
@@ -1073,7 +1065,12 @@
 		goto out;
 	}
 
-	tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+	dma_src = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+				 DMA_TO_DEVICE);
+	dma_dest = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+				  DMA_FROM_DEVICE);
+	tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
+						   IOAT_TEST_SIZE, 0);
 	if (!tx) {
 		dev_err(&device->pdev->dev,
 			"Self-test prep failed, disabling\n");
@@ -1082,12 +1079,6 @@
 	}
 
 	async_tx_ack(tx);
-	addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
-			      DMA_TO_DEVICE);
-	tx->tx_set_src(addr, tx, 0);
-	addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
-			      DMA_FROM_DEVICE);
-	tx->tx_set_dest(addr, tx, 0);
 	tx->callback = ioat_dma_test_callback;
 	tx->callback_param = (void *)0x8086;
 	cookie = tx->tx_submit(tx);
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index e5c62b7..3986d54 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -284,7 +284,7 @@
 			int slots_per_op)
 {
 	struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
-	struct list_head chain = LIST_HEAD_INIT(chain);
+	LIST_HEAD(chain);
 	int slots_found, retry = 0;
 
 	/* start search from the last allocated descrtiptor
@@ -443,17 +443,6 @@
 	return cookie;
 }
 
-static void
-iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-	int index)
-{
-	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-	struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
-
-	/* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
-	iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
-}
-
 static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
 static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
 
@@ -486,7 +475,6 @@
 
 		dma_async_tx_descriptor_init(&slot->async_tx, chan);
 		slot->async_tx.tx_submit = iop_adma_tx_submit;
-		slot->async_tx.tx_set_dest = iop_adma_set_dest;
 		INIT_LIST_HEAD(&slot->chain_node);
 		INIT_LIST_HEAD(&slot->slot_node);
 		INIT_LIST_HEAD(&slot->async_tx.tx_list);
@@ -547,18 +535,9 @@
 	return sw_desc ? &sw_desc->async_tx : NULL;
 }
 
-static void
-iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-	int index)
-{
-	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-
-	iop_desc_set_memcpy_src_addr(grp_start, addr);
-}
-
 static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
+iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
+			 dma_addr_t dma_src, size_t len, unsigned long flags)
 {
 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
 	struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -576,11 +555,12 @@
 	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
 	if (sw_desc) {
 		grp_start = sw_desc->group_head;
-		iop_desc_init_memcpy(grp_start, int_en);
+		iop_desc_init_memcpy(grp_start, flags);
 		iop_desc_set_byte_count(grp_start, iop_chan, len);
+		iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
+		iop_desc_set_memcpy_src_addr(grp_start, dma_src);
 		sw_desc->unmap_src_cnt = 1;
 		sw_desc->unmap_len = len;
-		sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
 	}
 	spin_unlock_bh(&iop_chan->lock);
 
@@ -588,8 +568,8 @@
 }
 
 static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
-	int int_en)
+iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest,
+			 int value, size_t len, unsigned long flags)
 {
 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
 	struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -607,9 +587,10 @@
 	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
 	if (sw_desc) {
 		grp_start = sw_desc->group_head;
-		iop_desc_init_memset(grp_start, int_en);
+		iop_desc_init_memset(grp_start, flags);
 		iop_desc_set_byte_count(grp_start, iop_chan, len);
 		iop_desc_set_block_fill_val(grp_start, value);
+		iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
 		sw_desc->unmap_src_cnt = 1;
 		sw_desc->unmap_len = len;
 	}
@@ -618,19 +599,10 @@
 	return sw_desc ? &sw_desc->async_tx : NULL;
 }
 
-static void
-iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
-	int index)
-{
-	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-
-	iop_desc_set_xor_src_addr(grp_start, index, addr);
-}
-
 static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
-	int int_en)
+iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
+		      dma_addr_t *dma_src, unsigned int src_cnt, size_t len,
+		      unsigned long flags)
 {
 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
 	struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -641,39 +613,32 @@
 	BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
 
 	dev_dbg(iop_chan->device->common.dev,
-		"%s src_cnt: %d len: %u int_en: %d\n",
-		__FUNCTION__, src_cnt, len, int_en);
+		"%s src_cnt: %d len: %u flags: %lx\n",
+		__FUNCTION__, src_cnt, len, flags);
 
 	spin_lock_bh(&iop_chan->lock);
 	slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
 	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
 	if (sw_desc) {
 		grp_start = sw_desc->group_head;
-		iop_desc_init_xor(grp_start, src_cnt, int_en);
+		iop_desc_init_xor(grp_start, src_cnt, flags);
 		iop_desc_set_byte_count(grp_start, iop_chan, len);
+		iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
 		sw_desc->unmap_src_cnt = src_cnt;
 		sw_desc->unmap_len = len;
-		sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
+		while (src_cnt--)
+			iop_desc_set_xor_src_addr(grp_start, src_cnt,
+						  dma_src[src_cnt]);
 	}
 	spin_unlock_bh(&iop_chan->lock);
 
 	return sw_desc ? &sw_desc->async_tx : NULL;
 }
 
-static void
-iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
-				struct dma_async_tx_descriptor *tx,
-				int index)
-{
-	struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
-	struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
-
-	iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
-}
-
 static struct dma_async_tx_descriptor *
-iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
-	size_t len, u32 *result, int int_en)
+iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
+			   unsigned int src_cnt, size_t len, u32 *result,
+			   unsigned long flags)
 {
 	struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
 	struct iop_adma_desc_slot *sw_desc, *grp_start;
@@ -690,14 +655,16 @@
 	sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
 	if (sw_desc) {
 		grp_start = sw_desc->group_head;
-		iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
+		iop_desc_init_zero_sum(grp_start, src_cnt, flags);
 		iop_desc_set_zero_sum_byte_count(grp_start, len);
 		grp_start->xor_check_result = result;
 		pr_debug("\t%s: grp_start->xor_check_result: %p\n",
 			__FUNCTION__, grp_start->xor_check_result);
 		sw_desc->unmap_src_cnt = src_cnt;
 		sw_desc->unmap_len = len;
-		sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
+		while (src_cnt--)
+			iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
+						       dma_src[src_cnt]);
 	}
 	spin_unlock_bh(&iop_chan->lock);
 
@@ -882,13 +849,12 @@
 		goto out;
 	}
 
-	tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
 	dest_dma = dma_map_single(dma_chan->device->dev, dest,
 				IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
-	iop_adma_set_dest(dest_dma, tx, 0);
 	src_dma = dma_map_single(dma_chan->device->dev, src,
 				IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
-	iop_adma_memcpy_set_src(src_dma, tx, 0);
+	tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma,
+				      IOP_ADMA_TEST_SIZE, 1);
 
 	cookie = iop_adma_tx_submit(tx);
 	iop_adma_issue_pending(dma_chan);
@@ -929,6 +895,7 @@
 	struct page *dest;
 	struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
 	struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
+	dma_addr_t dma_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
 	dma_addr_t dma_addr, dest_dma;
 	struct dma_async_tx_descriptor *tx;
 	struct dma_chan *dma_chan;
@@ -981,17 +948,13 @@
 	}
 
 	/* test xor */
-	tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
-				PAGE_SIZE, 1);
 	dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
 				PAGE_SIZE, DMA_FROM_DEVICE);
-	iop_adma_set_dest(dest_dma, tx, 0);
-
-	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
-		dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
-			PAGE_SIZE, DMA_TO_DEVICE);
-		iop_adma_xor_set_src(dma_addr, tx, i);
-	}
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+		dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i],
+					   0, PAGE_SIZE, DMA_TO_DEVICE);
+	tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
+				   IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1);
 
 	cookie = iop_adma_tx_submit(tx);
 	iop_adma_issue_pending(dma_chan);
@@ -1032,13 +995,13 @@
 
 	zero_sum_result = 1;
 
-	tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
-		PAGE_SIZE, &zero_sum_result, 1);
-	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
-		dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
-			0, PAGE_SIZE, DMA_TO_DEVICE);
-		iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
-	}
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++)
+		dma_srcs[i] = dma_map_page(dma_chan->device->dev,
+					   zero_sum_srcs[i], 0, PAGE_SIZE,
+					   DMA_TO_DEVICE);
+	tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+					IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+					&zero_sum_result, 1);
 
 	cookie = iop_adma_tx_submit(tx);
 	iop_adma_issue_pending(dma_chan);
@@ -1060,10 +1023,9 @@
 	}
 
 	/* test memset */
-	tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
 	dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
 			PAGE_SIZE, DMA_FROM_DEVICE);
-	iop_adma_set_dest(dma_addr, tx, 0);
+	tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1);
 
 	cookie = iop_adma_tx_submit(tx);
 	iop_adma_issue_pending(dma_chan);
@@ -1089,13 +1051,13 @@
 
 	/* test for non-zero parity sum */
 	zero_sum_result = 0;
-	tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
-		PAGE_SIZE, &zero_sum_result, 1);
-	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
-		dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
-			0, PAGE_SIZE, DMA_TO_DEVICE);
-		iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
-	}
+	for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++)
+		dma_srcs[i] = dma_map_page(dma_chan->device->dev,
+					   zero_sum_srcs[i], 0, PAGE_SIZE,
+					   DMA_TO_DEVICE);
+	tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs,
+					IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE,
+					&zero_sum_result, 1);
 
 	cookie = iop_adma_tx_submit(tx);
 	iop_adma_issue_pending(dma_chan);
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 18cdcb3..1636806 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -658,4 +658,5 @@
 MODULE_VERSION(DRIVER_VERSION);
 MODULE_AUTHOR("Dell Inc.");
 MODULE_LICENSE("GPL");
-
+/* Any System or BIOS claiming to be by Dell */
+MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*");
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index 313c99c..e880d6c 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/dmi.h>
 #include <linux/device.h>
-#include <linux/autoconf.h>
 
 struct dmi_device_attribute{
 	struct device_attribute dev_attr;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 74fac0f..bbd2834 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -27,15 +27,16 @@
 
 comment "I2C GPIO expanders:"
 
-config GPIO_PCA9539
-	tristate "PCA9539 16-bit I/O port"
+config GPIO_PCA953X
+	tristate "PCA953x I/O ports"
 	depends on I2C
 	help
-	  Say yes here to support the PCA9539 16-bit I/O port. These
-	  parts are made by NXP and TI.
+	  Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit),
+	  PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539
+	  (16-bit) I/O ports. These parts are made by NXP and TI.
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called pca9539.
+	  will be called pca953x.
 
 config GPIO_PCF857X
 	tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 470ecd6..fdde992 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -5,5 +5,5 @@
 obj-$(CONFIG_HAVE_GPIO_LIB)	+= gpiolib.o
 
 obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
-obj-$(CONFIG_GPIO_PCA9539)	+= pca9539.o
+obj-$(CONFIG_GPIO_PCA953X)	+= pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca9539.c
deleted file mode 100644
index 3e85c92..0000000
--- a/drivers/gpio/pca9539.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- *  pca9539.c - 16-bit I/O port with interrupt and reset
- *
- *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
- *  Copyright (C) 2007 Marvell International Ltd.
- *
- *  Derived from drivers/i2c/chips/pca9539.c
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/i2c.h>
-#include <linux/i2c/pca9539.h>
-
-#include <asm/gpio.h>
-
-
-#define NR_PCA9539_GPIOS	16
-
-#define PCA9539_INPUT		0
-#define PCA9539_OUTPUT		2
-#define PCA9539_INVERT		4
-#define PCA9539_DIRECTION	6
-
-struct pca9539_chip {
-	unsigned gpio_start;
-	uint16_t reg_output;
-	uint16_t reg_direction;
-
-	struct i2c_client *client;
-	struct gpio_chip gpio_chip;
-};
-
-/* NOTE:  we can't currently rely on fault codes to come from SMBus
- * calls, so we map all errors to EIO here and return zero otherwise.
- */
-static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val)
-{
-	if (i2c_smbus_write_word_data(chip->client, reg, val) < 0)
-		return -EIO;
-	else
-		return 0;
-}
-
-static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val)
-{
-	int ret;
-
-	ret = i2c_smbus_read_word_data(chip->client, reg);
-	if (ret < 0) {
-		dev_err(&chip->client->dev, "failed reading register\n");
-		return -EIO;
-	}
-
-	*val = (uint16_t)ret;
-	return 0;
-}
-
-static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off)
-{
-	struct pca9539_chip *chip;
-	uint16_t reg_val;
-	int ret;
-
-	chip = container_of(gc, struct pca9539_chip, gpio_chip);
-
-	reg_val = chip->reg_direction | (1u << off);
-	ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
-	if (ret)
-		return ret;
-
-	chip->reg_direction = reg_val;
-	return 0;
-}
-
-static int pca9539_gpio_direction_output(struct gpio_chip *gc,
-		unsigned off, int val)
-{
-	struct pca9539_chip *chip;
-	uint16_t reg_val;
-	int ret;
-
-	chip = container_of(gc, struct pca9539_chip, gpio_chip);
-
-	/* set output level */
-	if (val)
-		reg_val = chip->reg_output | (1u << off);
-	else
-		reg_val = chip->reg_output & ~(1u << off);
-
-	ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
-	if (ret)
-		return ret;
-
-	chip->reg_output = reg_val;
-
-	/* then direction */
-	reg_val = chip->reg_direction & ~(1u << off);
-	ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
-	if (ret)
-		return ret;
-
-	chip->reg_direction = reg_val;
-	return 0;
-}
-
-static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
-{
-	struct pca9539_chip *chip;
-	uint16_t reg_val;
-	int ret;
-
-	chip = container_of(gc, struct pca9539_chip, gpio_chip);
-
-	ret = pca9539_read_reg(chip, PCA9539_INPUT, &reg_val);
-	if (ret < 0) {
-		/* NOTE:  diagnostic already emitted; that's all we should
-		 * do unless gpio_*_value_cansleep() calls become different
-		 * from their nonsleeping siblings (and report faults).
-		 */
-		return 0;
-	}
-
-	return (reg_val & (1u << off)) ? 1 : 0;
-}
-
-static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
-{
-	struct pca9539_chip *chip;
-	uint16_t reg_val;
-	int ret;
-
-	chip = container_of(gc, struct pca9539_chip, gpio_chip);
-
-	if (val)
-		reg_val = chip->reg_output | (1u << off);
-	else
-		reg_val = chip->reg_output & ~(1u << off);
-
-	ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
-	if (ret)
-		return;
-
-	chip->reg_output = reg_val;
-}
-
-static int pca9539_init_gpio(struct pca9539_chip *chip)
-{
-	struct gpio_chip *gc;
-
-	gc = &chip->gpio_chip;
-
-	gc->direction_input  = pca9539_gpio_direction_input;
-	gc->direction_output = pca9539_gpio_direction_output;
-	gc->get = pca9539_gpio_get_value;
-	gc->set = pca9539_gpio_set_value;
-
-	gc->base = chip->gpio_start;
-	gc->ngpio = NR_PCA9539_GPIOS;
-	gc->label = "pca9539";
-
-	return gpiochip_add(gc);
-}
-
-static int __devinit pca9539_probe(struct i2c_client *client)
-{
-	struct pca9539_platform_data *pdata;
-	struct pca9539_chip *chip;
-	int ret;
-
-	pdata = client->dev.platform_data;
-	if (pdata == NULL)
-		return -ENODEV;
-
-	chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-
-	chip->client = client;
-
-	chip->gpio_start = pdata->gpio_base;
-
-	/* initialize cached registers from their original values.
-	 * we can't share this chip with another i2c master.
-	 */
-	ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output);
-	if (ret)
-		goto out_failed;
-
-	ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction);
-	if (ret)
-		goto out_failed;
-
-	/* set platform specific polarity inversion */
-	ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert);
-	if (ret)
-		goto out_failed;
-
-	ret = pca9539_init_gpio(chip);
-	if (ret)
-		goto out_failed;
-
-	if (pdata->setup) {
-		ret = pdata->setup(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0)
-			dev_warn(&client->dev, "setup failed, %d\n", ret);
-	}
-
-	i2c_set_clientdata(client, chip);
-	return 0;
-
-out_failed:
-	kfree(chip);
-	return ret;
-}
-
-static int pca9539_remove(struct i2c_client *client)
-{
-	struct pca9539_platform_data *pdata = client->dev.platform_data;
-	struct pca9539_chip *chip = i2c_get_clientdata(client);
-	int ret = 0;
-
-	if (pdata->teardown) {
-		ret = pdata->teardown(client, chip->gpio_chip.base,
-				chip->gpio_chip.ngpio, pdata->context);
-		if (ret < 0) {
-			dev_err(&client->dev, "%s failed, %d\n",
-					"teardown", ret);
-			return ret;
-		}
-	}
-
-	ret = gpiochip_remove(&chip->gpio_chip);
-	if (ret) {
-		dev_err(&client->dev, "%s failed, %d\n",
-				"gpiochip_remove()", ret);
-		return ret;
-	}
-
-	kfree(chip);
-	return 0;
-}
-
-static struct i2c_driver pca9539_driver = {
-	.driver = {
-		.name	= "pca9539",
-	},
-	.probe		= pca9539_probe,
-	.remove		= pca9539_remove,
-};
-
-static int __init pca9539_init(void)
-{
-	return i2c_add_driver(&pca9539_driver);
-}
-module_init(pca9539_init);
-
-static void __exit pca9539_exit(void)
-{
-	i2c_del_driver(&pca9539_driver);
-}
-module_exit(pca9539_exit);
-
-MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("GPIO expander driver for PCA9539");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
new file mode 100644
index 0000000..92583cd
--- /dev/null
+++ b/drivers/gpio/pca953x.c
@@ -0,0 +1,308 @@
+/*
+ *  pca953x.c - 4/8/16 bit I/O ports
+ *
+ *  Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+ *  Copyright (C) 2007 Marvell International Ltd.
+ *
+ *  Derived from drivers/i2c/chips/pca9539.c
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/i2c/pca953x.h>
+
+#include <asm/gpio.h>
+
+#define PCA953X_INPUT          0
+#define PCA953X_OUTPUT         1
+#define PCA953X_INVERT         2
+#define PCA953X_DIRECTION      3
+
+/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
+struct pca953x_desc {
+	char		name[I2C_NAME_SIZE];
+	unsigned long	driver_data;
+};
+
+static const struct pca953x_desc pca953x_descs[] = {
+	{ "pca9534", 8, },
+	{ "pca9535", 16, },
+	{ "pca9536", 4, },
+	{ "pca9537", 4, },
+	{ "pca9538", 8, },
+	{ "pca9539", 16, },
+	/* REVISIT several pca955x parts should work here too */
+};
+
+struct pca953x_chip {
+	unsigned gpio_start;
+	uint16_t reg_output;
+	uint16_t reg_direction;
+
+	struct i2c_client *client;
+	struct gpio_chip gpio_chip;
+};
+
+/* NOTE:  we can't currently rely on fault codes to come from SMBus
+ * calls, so we map all errors to EIO here and return zero otherwise.
+ */
+static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
+{
+	int ret;
+
+	if (chip->gpio_chip.ngpio <= 8)
+		ret = i2c_smbus_write_byte_data(chip->client, reg, val);
+	else
+		ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
+
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "failed writing register\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val)
+{
+	int ret;
+
+	if (chip->gpio_chip.ngpio <= 8)
+		ret = i2c_smbus_read_byte_data(chip->client, reg);
+	else
+		ret = i2c_smbus_read_word_data(chip->client, reg << 1);
+
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "failed reading register\n");
+		return -EIO;
+	}
+
+	*val = (uint16_t)ret;
+	return 0;
+}
+
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	reg_val = chip->reg_direction | (1u << off);
+	ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
+	if (ret)
+		return ret;
+
+	chip->reg_direction = reg_val;
+	return 0;
+}
+
+static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+		unsigned off, int val)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	/* set output level */
+	if (val)
+		reg_val = chip->reg_output | (1u << off);
+	else
+		reg_val = chip->reg_output & ~(1u << off);
+
+	ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
+	if (ret)
+		return ret;
+
+	chip->reg_output = reg_val;
+
+	/* then direction */
+	reg_val = chip->reg_direction & ~(1u << off);
+	ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
+	if (ret)
+		return ret;
+
+	chip->reg_direction = reg_val;
+	return 0;
+}
+
+static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
+	if (ret < 0) {
+		/* NOTE:  diagnostic already emitted; that's all we should
+		 * do unless gpio_*_value_cansleep() calls become different
+		 * from their nonsleeping siblings (and report faults).
+		 */
+		return 0;
+	}
+
+	return (reg_val & (1u << off)) ? 1 : 0;
+}
+
+static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+	struct pca953x_chip *chip;
+	uint16_t reg_val;
+	int ret;
+
+	chip = container_of(gc, struct pca953x_chip, gpio_chip);
+
+	if (val)
+		reg_val = chip->reg_output | (1u << off);
+	else
+		reg_val = chip->reg_output & ~(1u << off);
+
+	ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
+	if (ret)
+		return;
+
+	chip->reg_output = reg_val;
+}
+
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+{
+	struct gpio_chip *gc;
+
+	gc = &chip->gpio_chip;
+
+	gc->direction_input  = pca953x_gpio_direction_input;
+	gc->direction_output = pca953x_gpio_direction_output;
+	gc->get = pca953x_gpio_get_value;
+	gc->set = pca953x_gpio_set_value;
+
+	gc->base = chip->gpio_start;
+	gc->ngpio = gpios;
+	gc->label = chip->client->name;
+}
+
+static int __devinit pca953x_probe(struct i2c_client *client)
+{
+	struct pca953x_platform_data *pdata;
+	struct pca953x_chip *chip;
+	int ret, i;
+	const struct pca953x_desc *id = NULL;
+
+	pdata = client->dev.platform_data;
+	if (pdata == NULL)
+		return -ENODEV;
+
+	/* this loop vanishes when we get i2c_device_id */
+	for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
+		if (!strcmp(pca953x_descs[i].name, client->name)) {
+			id = pca953x_descs + i;
+			break;
+		}
+	if (!id)
+		return -ENODEV;
+
+	chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	chip->client = client;
+
+	chip->gpio_start = pdata->gpio_base;
+
+	/* initialize cached registers from their original values.
+	 * we can't share this chip with another i2c master.
+	 */
+	pca953x_setup_gpio(chip, id->driver_data);
+
+	ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+	if (ret)
+		goto out_failed;
+
+	ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
+	if (ret)
+		goto out_failed;
+
+	/* set platform specific polarity inversion */
+	ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
+	if (ret)
+		goto out_failed;
+
+
+	ret = gpiochip_add(&chip->gpio_chip);
+	if (ret)
+		goto out_failed;
+
+	if (pdata->setup) {
+		ret = pdata->setup(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0)
+			dev_warn(&client->dev, "setup failed, %d\n", ret);
+	}
+
+	i2c_set_clientdata(client, chip);
+	return 0;
+
+out_failed:
+	kfree(chip);
+	return ret;
+}
+
+static int pca953x_remove(struct i2c_client *client)
+{
+	struct pca953x_platform_data *pdata = client->dev.platform_data;
+	struct pca953x_chip *chip = i2c_get_clientdata(client);
+	int ret = 0;
+
+	if (pdata->teardown) {
+		ret = pdata->teardown(client, chip->gpio_chip.base,
+				chip->gpio_chip.ngpio, pdata->context);
+		if (ret < 0) {
+			dev_err(&client->dev, "%s failed, %d\n",
+					"teardown", ret);
+			return ret;
+		}
+	}
+
+	ret = gpiochip_remove(&chip->gpio_chip);
+	if (ret) {
+		dev_err(&client->dev, "%s failed, %d\n",
+				"gpiochip_remove()", ret);
+		return ret;
+	}
+
+	kfree(chip);
+	return 0;
+}
+
+static struct i2c_driver pca953x_driver = {
+	.driver = {
+		.name	= "pca953x",
+	},
+	.probe		= pca953x_probe,
+	.remove		= pca953x_remove,
+};
+
+static int __init pca953x_init(void)
+{
+	return i2c_add_driver(&pca953x_driver);
+}
+module_init(pca953x_init);
+
+static void __exit pca953x_exit(void)
+{
+	i2c_del_driver(&pca953x_driver);
+}
+module_exit(pca953x_exit);
+
+MODULE_AUTHOR("eric miao <eric.miao@marvell.com>");
+MODULE_DESCRIPTION("GPIO expander driver for PCA953x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index fd0ef82..6daea89 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1049,7 +1049,7 @@
 	 */
 	if (!match || match->irq != hwif->irq) {
 		int sa = 0;
-#if defined(__mc68000__) || defined(CONFIG_APUS)
+#if defined(__mc68000__)
 		sa = IRQF_SHARED;
 #endif /* __mc68000__ || CONFIG_APUS */
 
@@ -1072,7 +1072,7 @@
 			hwif->rqsize = 65536;
 	}
 
-#if !defined(__mc68000__) && !defined(CONFIG_APUS)
+#if !defined(__mc68000__)
 	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET],
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
@@ -1080,7 +1080,7 @@
 #else
 	printk("%s at 0x%08lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
-#endif /* __mc68000__ && CONFIG_APUS */
+#endif /* __mc68000__ */
 	if (match)
 		printk(" (%sed with %s)",
 			hwif->sharing_irq ? "shar" : "serializ", match->name);
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index 26c82ce..688fcae 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -17,7 +17,7 @@
 #include <linux/ide.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#include <linux/pata_platform.h>
+#include <linux/ata_platform.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 2ae6c60..28ae15e 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -109,7 +109,7 @@
 static irqreturn_t action_button_handler(int irq, void *dev_id)
 {
 	int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1;
-	struct input_dev *dev = (struct input_dev *) dev_id;
+	struct input_dev *dev = dev_id;
 
 	input_report_key(dev, KEY_ENTER, down);
 	input_sync(dev);
@@ -120,7 +120,7 @@
 static irqreturn_t npower_button_handler(int irq, void *dev_id)
 {
 	int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1;
-	struct input_dev *dev = (struct input_dev *) dev_id;
+	struct input_dev *dev = dev_id;
 
 	/*
 	 * This interrupt is only called when we release the key. So we have
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c
index ee2b0b9..8325022 100644
--- a/drivers/isdn/act2000/module.c
+++ b/drivers/isdn/act2000/module.c
@@ -310,7 +310,7 @@
 			}
 			break;
 		case ISDN_CMD_DIAL:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
@@ -339,7 +339,7 @@
 			}
 			return ret;
 		case ISDN_CMD_ACCEPTD:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
@@ -347,11 +347,11 @@
 				actcapi_select_b2_protocol_req(card, chan);
 			return 0;
 		case ISDN_CMD_ACCEPTB:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			return 0;
 		case ISDN_CMD_HANGUP:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
@@ -366,7 +366,7 @@
 			}
 			return 0;
 		case ISDN_CMD_SETEAZ:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
@@ -386,7 +386,7 @@
 			actcapi_listen_req(card);
 			return 0;
 		case ISDN_CMD_CLREAZ:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
@@ -394,14 +394,14 @@
 			actcapi_listen_req(card);
 			return 0;
 		case ISDN_CMD_SETL2:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
 			chan->l2prot = (c->arg >> 8);
 			return 0;
 		case ISDN_CMD_SETL3:
-			if (!card->flags & ACT2000_FLAGS_RUNNING)
+			if (!(card->flags & ACT2000_FLAGS_RUNNING))
 				return -ENODEV;
 			if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) {
 				printk(KERN_WARNING "L3 protocol unknown\n");
@@ -524,7 +524,7 @@
         act2000_card *card = act2000_findcard(id);
 
         if (card) {
-                if (!card->flags & ACT2000_FLAGS_RUNNING)
+                if (!(card->flags & ACT2000_FLAGS_RUNNING))
                         return -ENODEV;
                 return (len);
         }
@@ -539,7 +539,7 @@
         act2000_card *card = act2000_findcard(id);
 	
         if (card) {
-                if (!card->flags & ACT2000_FLAGS_RUNNING)
+                if (!(card->flags & ACT2000_FLAGS_RUNNING))
                         return -ENODEV;
                 return (act2000_readstatus(buf, len, card));
         }
@@ -554,7 +554,7 @@
         act2000_card *card = act2000_findcard(id);
 	
         if (card) {
-                if (!card->flags & ACT2000_FLAGS_RUNNING)
+                if (!(card->flags & ACT2000_FLAGS_RUNNING))
                         return -ENODEV;
 		return (act2000_sendbuf(card, channel, ack, skb));
         }
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c
index 00a3be5..091deb9 100644
--- a/drivers/isdn/gigaset/asyncdata.c
+++ b/drivers/isdn/gigaset/asyncdata.c
@@ -350,8 +350,8 @@
 	unsigned char *src, c;
 	int procbytes;
 
-	head = atomic_read(&inbuf->head);
-	tail = atomic_read(&inbuf->tail);
+	head = inbuf->head;
+	tail = inbuf->tail;
 	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 
 	if (head != tail) {
@@ -361,7 +361,7 @@
 		gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
 
 		while (numbytes) {
-			if (atomic_read(&cs->mstate) == MS_LOCKED) {
+			if (cs->mstate == MS_LOCKED) {
 				procbytes = lock_loop(src, numbytes, inbuf);
 				src += procbytes;
 				numbytes -= procbytes;
@@ -436,7 +436,7 @@
 		}
 
 		gig_dbg(DEBUG_INTR, "setting head to %u", head);
-		atomic_set(&inbuf->head, head);
+		inbuf->head = head;
 	}
 }
 EXPORT_SYMBOL_GPL(gigaset_m10x_input);
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index af76482..5255b5e 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -73,6 +73,14 @@
 /* Function will be called if the device is unplugged */
 static void gigaset_disconnect(struct usb_interface *interface);
 
+/* functions called before/after suspend */
+static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
+static int gigaset_resume(struct usb_interface *intf);
+
+/* functions called before/after device reset */
+static int gigaset_pre_reset(struct usb_interface *intf);
+static int gigaset_post_reset(struct usb_interface *intf);
+
 static int atread_submit(struct cardstate *, int);
 static void stopurbs(struct bas_bc_state *);
 static int req_submit(struct bc_state *, int, int, int);
@@ -105,8 +113,9 @@
 	unsigned char		int_in_buf[3];
 
 	spinlock_t		lock;		/* locks all following */
-	atomic_t		basstate;	/* bitmap (BS_*) */
+	int			basstate;	/* bitmap (BS_*) */
 	int			pending;	/* uncompleted base request */
+	wait_queue_head_t	waitqueue;
 	int			rcvbuf_size;	/* size of AT receive buffer */
 						/* 0: no receive in progress */
 	int			retry_cmd_in;	/* receive req retry count */
@@ -121,10 +130,10 @@
 #define BS_ATTIMER	0x020	/* waiting for HD_READY_SEND_ATDATA */
 #define BS_ATRDPEND	0x040	/* urb_cmd_in in use */
 #define BS_ATWRPEND	0x080	/* urb_cmd_out in use */
+#define BS_SUSPEND	0x100	/* USB port suspended */
 
 
 static struct gigaset_driver *driver = NULL;
-static struct cardstate *cardstate = NULL;
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver gigaset_usb_driver = {
@@ -132,6 +141,11 @@
 	.probe =        gigaset_probe,
 	.disconnect =   gigaset_disconnect,
 	.id_table =     gigaset_table,
+	.suspend =	gigaset_suspend,
+	.resume =	gigaset_resume,
+	.reset_resume =	gigaset_post_reset,
+	.pre_reset =	gigaset_pre_reset,
+	.post_reset =	gigaset_post_reset,
 };
 
 /* get message text for usb_submit_urb return code
@@ -248,12 +262,12 @@
 	if (urb) {
 		gig_dbg(level,
 			"  dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, "
-			"status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,",
+			"hcpriv=0x%08lx, transfer_flags=0x%x,",
 			(unsigned long) urb->dev,
 			usb_pipetype_str(urb->pipe),
 			usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe),
 			usb_pipein(urb->pipe) ? "in" : "out",
-			urb->status, (unsigned long) urb->hcpriv,
+			(unsigned long) urb->hcpriv,
 			urb->transfer_flags);
 		gig_dbg(level,
 			"  transfer_buffer=0x%08lx[%d], actual_length=%d, "
@@ -355,27 +369,27 @@
 	case 0:
 		break;
 	case HD_OPEN_ATCHANNEL:
-		if (atomic_read(&ucs->basstate) & BS_ATOPEN)
+		if (ucs->basstate & BS_ATOPEN)
 			ucs->pending = 0;
 		break;
 	case HD_OPEN_B1CHANNEL:
-		if (atomic_read(&ucs->basstate) & BS_B1OPEN)
+		if (ucs->basstate & BS_B1OPEN)
 			ucs->pending = 0;
 		break;
 	case HD_OPEN_B2CHANNEL:
-		if (atomic_read(&ucs->basstate) & BS_B2OPEN)
+		if (ucs->basstate & BS_B2OPEN)
 			ucs->pending = 0;
 		break;
 	case HD_CLOSE_ATCHANNEL:
-		if (!(atomic_read(&ucs->basstate) & BS_ATOPEN))
+		if (!(ucs->basstate & BS_ATOPEN))
 			ucs->pending = 0;
 		break;
 	case HD_CLOSE_B1CHANNEL:
-		if (!(atomic_read(&ucs->basstate) & BS_B1OPEN))
+		if (!(ucs->basstate & BS_B1OPEN))
 			ucs->pending = 0;
 		break;
 	case HD_CLOSE_B2CHANNEL:
-		if (!(atomic_read(&ucs->basstate) & BS_B2OPEN))
+		if (!(ucs->basstate & BS_B2OPEN))
 			ucs->pending = 0;
 		break;
 	case HD_DEVICE_INIT_ACK:		/* no reply expected */
@@ -441,8 +455,8 @@
 	int state;
 
 	spin_lock_irqsave(&ucs->lock, flags);
-	state = atomic_read(&ucs->basstate);
-	atomic_set(&ucs->basstate, (state & ~clear) | set);
+	state = ucs->basstate;
+	ucs->basstate = (state & ~clear) | set;
 	spin_unlock_irqrestore(&ucs->lock, flags);
 	return state;
 }
@@ -459,11 +473,13 @@
 	struct inbuf_t *inbuf = urb->context;
 	struct cardstate *cs = inbuf->cs;
 	struct bas_cardstate *ucs = cs->hw.bas;
+	int status = urb->status;
 	int have_data = 0;
 	unsigned numbytes;
 	int rc;
 
 	update_basstate(ucs, 0, BS_ATRDPEND);
+	wake_up(&ucs->waitqueue);
 
 	if (!ucs->rcvbuf_size) {
 		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
@@ -472,7 +488,7 @@
 
 	del_timer(&ucs->timer_cmd_in);
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:				/* normal completion */
 		numbytes = urb->actual_length;
 		if (unlikely(numbytes != ucs->rcvbuf_size)) {
@@ -506,12 +522,12 @@
 	case -ESHUTDOWN:		/* device shut down */
 		/* no action necessary */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		break;
 
 	default:			/* severe trouble */
 		dev_warn(cs->dev, "control read: %s\n",
-			 get_usb_statmsg(urb->status));
+			 get_usb_statmsg(status));
 		if (ucs->retry_cmd_in++ < BAS_RETRY) {
 			dev_notice(cs->dev, "control read: retry %d\n",
 				   ucs->retry_cmd_in);
@@ -550,17 +566,28 @@
 static int atread_submit(struct cardstate *cs, int timeout)
 {
 	struct bas_cardstate *ucs = cs->hw.bas;
+	int basstate;
 	int ret;
 
 	gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)",
 		ucs->rcvbuf_size);
 
-	if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) {
+	basstate = update_basstate(ucs, BS_ATRDPEND, 0);
+	if (basstate & BS_ATRDPEND) {
 		dev_err(cs->dev,
 			"could not submit HD_READ_ATMESSAGE: URB busy\n");
 		return -EBUSY;
 	}
 
+	if (basstate & BS_SUSPEND) {
+		dev_notice(cs->dev,
+			   "HD_READ_ATMESSAGE not submitted, "
+			   "suspend in progress\n");
+		update_basstate(ucs, 0, BS_ATRDPEND);
+		/* treat like disconnect */
+		return -ENODEV;
+	}
+
 	ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ;
 	ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE;
 	ucs->dr_cmd_in.wValue = 0;
@@ -601,12 +628,13 @@
 	struct cardstate *cs = urb->context;
 	struct bas_cardstate *ucs = cs->hw.bas;
 	struct bc_state *bcs;
+	int status = urb->status;
 	unsigned long flags;
 	int rc;
 	unsigned l;
 	int channel;
 
-	switch (urb->status) {
+	switch (status) {
 	case 0:			/* success */
 		break;
 	case -ENOENT:			/* cancelled */
@@ -614,7 +642,7 @@
 	case -EINPROGRESS:		/* pending */
 		/* ignore silently */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		return;
 	case -ENODEV:			/* device removed */
 	case -ESHUTDOWN:		/* device shut down */
@@ -623,7 +651,7 @@
 		return;
 	default:		/* severe trouble */
 		dev_warn(cs->dev, "interrupt read: %s\n",
-			 get_usb_statmsg(urb->status));
+			 get_usb_statmsg(status));
 		//FIXME corrective action? resubmission always ok?
 		goto resubmit;
 	}
@@ -745,6 +773,7 @@
 	}
 
 	check_pending(ucs);
+	wake_up(&ucs->waitqueue);
 
 resubmit:
 	rc = usb_submit_urb(urb, GFP_ATOMIC);
@@ -766,17 +795,18 @@
 {
 	struct bc_state *bcs;
 	struct bas_bc_state *ubc;
+	int status = urb->status;
 	unsigned long flags;
 	int i, rc;
 
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT ||
-		     urb->status == -ECONNRESET ||
-		     urb->status == -EINPROGRESS ||
-		     urb->status == -ENODEV ||
-		     urb->status == -ESHUTDOWN)) {
+	if (unlikely(status == -ENOENT ||
+		     status == -ECONNRESET ||
+		     status == -EINPROGRESS ||
+		     status == -ENODEV ||
+		     status == -ESHUTDOWN)) {
 		gig_dbg(DEBUG_ISO, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		return;
 	}
 
@@ -787,10 +817,11 @@
 	if (likely(ubc->isoindone == NULL)) {
 		/* pass URB to tasklet */
 		ubc->isoindone = urb;
+		ubc->isoinstatus = status;
 		tasklet_schedule(&ubc->rcvd_tasklet);
 	} else {
 		/* tasklet still busy, drop data and resubmit URB */
-		ubc->loststatus = urb->status;
+		ubc->loststatus = status;
 		for (i = 0; i < BAS_NUMFRAMES; i++) {
 			ubc->isoinlost += urb->iso_frame_desc[i].actual_length;
 			if (unlikely(urb->iso_frame_desc[i].status != 0 &&
@@ -800,7 +831,7 @@
 			urb->iso_frame_desc[i].status = 0;
 			urb->iso_frame_desc[i].actual_length = 0;
 		}
-		if (likely(atomic_read(&ubc->running))) {
+		if (likely(ubc->running)) {
 			/* urb->dev is clobbered by USB subsystem */
 			urb->dev = bcs->cs->hw.bas->udev;
 			urb->transfer_flags = URB_ISO_ASAP;
@@ -831,22 +862,24 @@
 {
 	struct isow_urbctx_t *ucx;
 	struct bas_bc_state *ubc;
+	int status = urb->status;
 	unsigned long flags;
 
 	/* status codes not worth bothering the tasklet with */
-	if (unlikely(urb->status == -ENOENT ||
-		     urb->status == -ECONNRESET ||
-		     urb->status == -EINPROGRESS ||
-		     urb->status == -ENODEV ||
-		     urb->status == -ESHUTDOWN)) {
+	if (unlikely(status == -ENOENT ||
+		     status == -ECONNRESET ||
+		     status == -EINPROGRESS ||
+		     status == -ENODEV ||
+		     status == -ESHUTDOWN)) {
 		gig_dbg(DEBUG_ISO, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		return;
 	}
 
 	/* pass URB context to tasklet */
 	ucx = urb->context;
 	ubc = ucx->bcs->hw.bas;
+	ucx->status = status;
 
 	spin_lock_irqsave(&ubc->isooutlock, flags);
 	ubc->isooutovfl = ubc->isooutdone;
@@ -875,7 +908,7 @@
 		bcs->inputstate |= INS_flag_hunt;
 
 	/* submit all isochronous input URBs */
-	atomic_set(&ubc->running, 1);
+	ubc->running = 1;
 	for (k = 0; k < BAS_INURBS; k++) {
 		urb = ubc->isoinurbs[k];
 		if (!urb) {
@@ -932,15 +965,15 @@
 		ubc->isoouturbs[k].limit = -1;
 	}
 
-	/* submit two URBs, keep third one */
-	for (k = 0; k < 2; ++k) {
+	/* keep one URB free, submit the others */
+	for (k = 0; k < BAS_OUTURBS-1; ++k) {
 		dump_urb(DEBUG_ISO, "Initial isoc write", urb);
 		rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC);
 		if (rc != 0)
 			goto error;
 	}
 	dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb);
-	ubc->isooutfree = &ubc->isoouturbs[2];
+	ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1];
 	ubc->isooutdone = ubc->isooutovfl = NULL;
 	return 0;
  error:
@@ -958,7 +991,7 @@
 {
 	int k, rc;
 
-	atomic_set(&ubc->running, 0);
+	ubc->running = 0;
 
 	for (k = 0; k < BAS_INURBS; ++k) {
 		rc = usb_unlink_urb(ubc->isoinurbs[k]);
@@ -1034,7 +1067,7 @@
 			}
 			break;
 		}
-		ucx->limit = atomic_read(&ubc->isooutbuf->nextread);
+		ucx->limit = ubc->isooutbuf->nextread;
 		ifd->status = 0;
 		ifd->actual_length = 0;
 	}
@@ -1070,6 +1103,7 @@
 	struct cardstate *cs = bcs->cs;
 	struct isow_urbctx_t *done, *next, *ovfl;
 	struct urb *urb;
+	int status;
 	struct usb_iso_packet_descriptor *ifd;
 	int offset;
 	unsigned long flags;
@@ -1080,7 +1114,7 @@
 
 	/* loop while completed URBs arrive in time */
 	for (;;) {
-		if (unlikely(!(atomic_read(&ubc->running)))) {
+		if (unlikely(!(ubc->running))) {
 			gig_dbg(DEBUG_ISO, "%s: not running", __func__);
 			return;
 		}
@@ -1126,7 +1160,8 @@
 
 		/* process completed URB */
 		urb = done->urb;
-		switch (urb->status) {
+		status = done->status;
+		switch (status) {
 		case -EXDEV:			/* partial completion */
 			gig_dbg(DEBUG_ISO, "%s: URB partially completed",
 				__func__);
@@ -1179,12 +1214,12 @@
 			break;
 		default:			/* severe trouble */
 			dev_warn(cs->dev, "isochronous write: %s\n",
-				 get_usb_statmsg(urb->status));
+				 get_usb_statmsg(status));
 		}
 
 		/* mark the write buffer area covered by this URB as free */
 		if (done->limit >= 0)
-			atomic_set(&ubc->isooutbuf->read, done->limit);
+			ubc->isooutbuf->read = done->limit;
 
 		/* mark URB as free */
 		spin_lock_irqsave(&ubc->isooutlock, flags);
@@ -1233,6 +1268,7 @@
 	struct bas_bc_state *ubc = bcs->hw.bas;
 	struct cardstate *cs = bcs->cs;
 	struct urb *urb;
+	int status;
 	char *rcvbuf;
 	unsigned long flags;
 	int totleft, numbytes, offset, frame, rc;
@@ -1245,6 +1281,7 @@
 			spin_unlock_irqrestore(&ubc->isoinlock, flags);
 			return;
 		}
+		status = ubc->isoinstatus;
 		ubc->isoindone = NULL;
 		if (unlikely(ubc->loststatus != -EINPROGRESS)) {
 			dev_warn(cs->dev,
@@ -1256,15 +1293,15 @@
 		}
 		spin_unlock_irqrestore(&ubc->isoinlock, flags);
 
-		if (unlikely(!(atomic_read(&ubc->running)))) {
+		if (unlikely(!(ubc->running))) {
 			gig_dbg(DEBUG_ISO,
 				"%s: channel not running, "
 				"dropped URB with status: %s",
-				__func__, get_usb_statmsg(urb->status));
+				__func__, get_usb_statmsg(status));
 			return;
 		}
 
-		switch (urb->status) {
+		switch (status) {
 		case 0:				/* normal completion */
 			break;
 		case -EXDEV:			/* inspect individual frames
@@ -1276,7 +1313,7 @@
 		case -ECONNRESET:
 		case -EINPROGRESS:
 			gig_dbg(DEBUG_ISO, "%s: %s",
-				__func__, get_usb_statmsg(urb->status));
+				__func__, get_usb_statmsg(status));
 			continue;		/* -> skip */
 		case -EPIPE:
 			dev_err(cs->dev, "isochronous read stalled\n");
@@ -1284,7 +1321,7 @@
 			continue;		/* -> skip */
 		default:			/* severe trouble */
 			dev_warn(cs->dev, "isochronous read: %s\n",
-				 get_usb_statmsg(urb->status));
+				 get_usb_statmsg(status));
 			goto error;
 		}
 
@@ -1406,6 +1443,8 @@
 		dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n",
 			 pending);
 	}
+
+	wake_up(&ucs->waitqueue);
 }
 
 /* write_ctrl_callback
@@ -1418,11 +1457,12 @@
 static void write_ctrl_callback(struct urb *urb)
 {
 	struct bas_cardstate *ucs = urb->context;
+	int status = urb->status;
 	int rc;
 	unsigned long flags;
 
 	/* check status */
-	switch (urb->status) {
+	switch (status) {
 	case 0:					/* normal completion */
 		spin_lock_irqsave(&ucs->lock, flags);
 		switch (ucs->pending) {
@@ -1441,20 +1481,22 @@
 	case -ESHUTDOWN:		/* device shut down */
 		/* ignore silently */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		break;
 
 	default:				/* any failure */
-		if (++ucs->retry_ctrl > BAS_RETRY) {
+		/* don't retry if suspend requested */
+		if (++ucs->retry_ctrl > BAS_RETRY ||
+		    (ucs->basstate & BS_SUSPEND)) {
 			dev_err(&ucs->interface->dev,
 				"control request 0x%02x failed: %s\n",
 				ucs->dr_ctrl.bRequest,
-				get_usb_statmsg(urb->status));
+				get_usb_statmsg(status));
 			break;		/* give up */
 		}
 		dev_notice(&ucs->interface->dev,
 			   "control request 0x%02x: %s, retry %d\n",
-			   ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status),
+			   ucs->dr_ctrl.bRequest, get_usb_statmsg(status),
 			   ucs->retry_ctrl);
 		/* urb->dev is clobbered by USB subsystem */
 		urb->dev = ucs->udev;
@@ -1474,6 +1516,7 @@
 	del_timer(&ucs->timer_ctrl);
 	ucs->pending = 0;
 	spin_unlock_irqrestore(&ucs->lock, flags);
+	wake_up(&ucs->waitqueue);
 }
 
 /* req_submit
@@ -1548,37 +1591,46 @@
  */
 static int gigaset_init_bchannel(struct bc_state *bcs)
 {
+	struct cardstate *cs = bcs->cs;
 	int req, ret;
 	unsigned long flags;
 
-	spin_lock_irqsave(&bcs->cs->lock, flags);
-	if (unlikely(!bcs->cs->connected)) {
+	spin_lock_irqsave(&cs->lock, flags);
+	if (unlikely(!cs->connected)) {
 		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
-		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return -ENODEV;
 	}
 
+	if (cs->hw.bas->basstate & BS_SUSPEND) {
+		dev_notice(cs->dev,
+			   "not starting isochronous I/O, "
+			   "suspend in progress\n");
+		spin_unlock_irqrestore(&cs->lock, flags);
+		return -EHOSTUNREACH;
+	}
+
 	if ((ret = starturbs(bcs)) < 0) {
-		dev_err(bcs->cs->dev,
+		dev_err(cs->dev,
 			"could not start isochronous I/O for channel B%d: %s\n",
 			bcs->channel + 1,
 			ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret));
 		if (ret != -ENODEV)
 			error_hangup(bcs);
-		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		spin_unlock_irqrestore(&cs->lock, flags);
 		return ret;
 	}
 
 	req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
-		dev_err(bcs->cs->dev, "could not open channel B%d\n",
+		dev_err(cs->dev, "could not open channel B%d\n",
 			bcs->channel + 1);
 		stopurbs(bcs->hw.bas);
 		if (ret != -ENODEV)
 			error_hangup(bcs);
 	}
 
-	spin_unlock_irqrestore(&bcs->cs->lock, flags);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return ret;
 }
 
@@ -1594,20 +1646,20 @@
  */
 static int gigaset_close_bchannel(struct bc_state *bcs)
 {
+	struct cardstate *cs = bcs->cs;
 	int req, ret;
 	unsigned long flags;
 
-	spin_lock_irqsave(&bcs->cs->lock, flags);
-	if (unlikely(!bcs->cs->connected)) {
-		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+	spin_lock_irqsave(&cs->lock, flags);
+	if (unlikely(!cs->connected)) {
+		spin_unlock_irqrestore(&cs->lock, flags);
 		gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__);
 		return -ENODEV;
 	}
 
-	if (!(atomic_read(&bcs->cs->hw.bas->basstate) &
-	      (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
+	if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) {
 		/* channel not running: just signal common.c */
-		spin_unlock_irqrestore(&bcs->cs->lock, flags);
+		spin_unlock_irqrestore(&cs->lock, flags);
 		gigaset_bchannel_down(bcs);
 		return 0;
 	}
@@ -1615,10 +1667,10 @@
 	/* channel running: tell device to close it */
 	req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
 	if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
-		dev_err(bcs->cs->dev, "closing channel B%d failed\n",
+		dev_err(cs->dev, "closing channel B%d failed\n",
 			bcs->channel + 1);
 
-	spin_unlock_irqrestore(&bcs->cs->lock, flags);
+	spin_unlock_irqrestore(&cs->lock, flags);
 	return ret;
 }
 
@@ -1665,12 +1717,14 @@
 {
 	struct cardstate *cs = urb->context;
 	struct bas_cardstate *ucs = cs->hw.bas;
+	int status = urb->status;
 	unsigned long flags;
 
 	update_basstate(ucs, 0, BS_ATWRPEND);
+	wake_up(&ucs->waitqueue);
 
 	/* check status */
-	switch (urb->status) {
+	switch (status) {
 	case 0:					/* normal completion */
 		break;
 	case -ENOENT:			/* cancelled */
@@ -1680,26 +1734,33 @@
 	case -ESHUTDOWN:		/* device shut down */
 		/* ignore silently */
 		gig_dbg(DEBUG_USBREQ, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
+			__func__, get_usb_statmsg(status));
 		return;
 	default:				/* any failure */
 		if (++ucs->retry_cmd_out > BAS_RETRY) {
 			dev_warn(cs->dev,
 				 "command write: %s, "
 				 "giving up after %d retries\n",
-				 get_usb_statmsg(urb->status),
+				 get_usb_statmsg(status),
 				 ucs->retry_cmd_out);
 			break;
 		}
+		if (ucs->basstate & BS_SUSPEND) {
+			dev_warn(cs->dev,
+				 "command write: %s, "
+				 "won't retry - suspend requested\n",
+				 get_usb_statmsg(status));
+			break;
+		}
 		if (cs->cmdbuf == NULL) {
 			dev_warn(cs->dev,
 				 "command write: %s, "
 				 "cannot retry - cmdbuf gone\n",
-				 get_usb_statmsg(urb->status));
+				 get_usb_statmsg(status));
 			break;
 		}
 		dev_notice(cs->dev, "command write: %s, retry %d\n",
-			   get_usb_statmsg(urb->status), ucs->retry_cmd_out);
+			   get_usb_statmsg(status), ucs->retry_cmd_out);
 		if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0)
 			/* resubmitted - bypass regular exit block */
 			return;
@@ -1799,8 +1860,14 @@
 	int rc;
 	int retval = 0;
 
+	/* check if suspend requested */
+	if (ucs->basstate & BS_SUSPEND) {
+		gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending");
+		return -EHOSTUNREACH;
+	}
+
 	/* check if AT channel is open */
-	if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) {
+	if (!(ucs->basstate & BS_ATOPEN)) {
 		gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open");
 		rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT);
 		if (rc < 0) {
@@ -1816,8 +1883,7 @@
 	/* try to send first command in queue */
 	spin_lock_irqsave(&cs->cmdlock, flags);
 
-	while ((cb = cs->cmdbuf) != NULL &&
-	       atomic_read(&ucs->basstate) & BS_ATREADY) {
+	while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) {
 		ucs->retry_cmd_out = 0;
 		rc = atwrite_submit(cs, cb->buf, cb->len);
 		if (unlikely(rc)) {
@@ -1855,7 +1921,7 @@
 	unsigned long flags;
 	int rc;
 
-	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
 			   "CMD Transmit", len, buf);
 
@@ -1970,7 +2036,7 @@
 		return 0;
 
 	/* kill URBs and tasklets before freeing - better safe than sorry */
-	atomic_set(&ubc->running, 0);
+	ubc->running = 0;
 	gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__);
 	for (i = 0; i < BAS_OUTURBS; ++i) {
 		usb_kill_urb(ubc->isoouturbs[i].urb);
@@ -2005,7 +2071,7 @@
 		return 0;
 	}
 
-	atomic_set(&ubc->running, 0);
+	ubc->running = 0;
 	atomic_set(&ubc->corrbytes, 0);
 	spin_lock_init(&ubc->isooutlock);
 	for (i = 0; i < BAS_OUTURBS; ++i) {
@@ -2050,7 +2116,7 @@
 {
 	struct bas_bc_state *ubc = bcs->hw.bas;
 
-	atomic_set(&bcs->hw.bas->running, 0);
+	bcs->hw.bas->running = 0;
 	atomic_set(&bcs->hw.bas->corrbytes, 0);
 	bcs->hw.bas->numsub = 0;
 	spin_lock_init(&ubc->isooutlock);
@@ -2081,10 +2147,11 @@
 	spin_lock_init(&ucs->lock);
 	ucs->pending = 0;
 
-	atomic_set(&ucs->basstate, 0);
+	ucs->basstate = 0;
 	init_timer(&ucs->timer_ctrl);
 	init_timer(&ucs->timer_atrdy);
 	init_timer(&ucs->timer_cmd_in);
+	init_waitqueue_head(&ucs->waitqueue);
 
 	return 1;
 }
@@ -2102,7 +2169,7 @@
 	int i, j;
 
 	gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__);
-	for (j = 0; j < 2; ++j) {
+	for (j = 0; j < BAS_CHANNELS; ++j) {
 		ubc = cs->bcs[j].hw.bas;
 		for (i = 0; i < BAS_OUTURBS; ++i) {
 			usb_kill_urb(ubc->isoouturbs[i].urb);
@@ -2179,11 +2246,11 @@
 		 __func__, le16_to_cpu(udev->descriptor.idVendor),
 		 le16_to_cpu(udev->descriptor.idProduct));
 
-	cs = gigaset_getunassignedcs(driver);
-	if (!cs) {
-		dev_err(&udev->dev, "no free cardstate\n");
+	/* allocate memory for our device state and intialize it */
+	cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode,
+			    GIGASET_MODULENAME);
+	if (!cs)
 		return -ENODEV;
-	}
 	ucs = cs->hw.bas;
 
 	/* save off device structure ptrs for later use */
@@ -2203,7 +2270,7 @@
 	    !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL)))
 		goto allocerr;
 
-	for (j = 0; j < 2; ++j) {
+	for (j = 0; j < BAS_CHANNELS; ++j) {
 		ubc = cs->bcs[j].hw.bas;
 		for (i = 0; i < BAS_OUTURBS; ++i)
 			if (!(ubc->isoouturbs[i].urb =
@@ -2237,7 +2304,7 @@
 
 	/* tell common part that the device is ready */
 	if (startmode == SM_LOCKED)
-		atomic_set(&cs->mstate, MS_LOCKED);
+		cs->mstate = MS_LOCKED;
 
 	/* save address of controller structure */
 	usb_set_intfdata(interface, cs);
@@ -2252,7 +2319,7 @@
 error:
 	freeurbs(cs);
 	usb_set_intfdata(interface, NULL);
-	gigaset_unassign(cs);
+	gigaset_freecs(cs);
 	return -ENODEV;
 }
 
@@ -2272,11 +2339,10 @@
 	dev_info(cs->dev, "disconnecting Gigaset base\n");
 
 	/* mark base as not ready, all channels disconnected */
-	atomic_set(&ucs->basstate, 0);
+	ucs->basstate = 0;
 
 	/* tell LL all channels are down */
-	//FIXME shouldn't gigaset_stop() do this?
-	for (j = 0; j < 2; ++j)
+	for (j = 0; j < BAS_CHANNELS; ++j)
 		gigaset_bchannel_down(cs->bcs + j);
 
 	/* stop driver (common part) */
@@ -2295,9 +2361,113 @@
 	ucs->interface = NULL;
 	ucs->udev = NULL;
 	cs->dev = NULL;
-	gigaset_unassign(cs);
+	gigaset_freecs(cs);
 }
 
+/* gigaset_suspend
+ * This function is called before the USB connection is suspended.
+ */
+static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct cardstate *cs = usb_get_intfdata(intf);
+	struct bas_cardstate *ucs = cs->hw.bas;
+	int rc;
+
+	/* set suspend flag; this stops AT command/response traffic */
+	if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) {
+		gig_dbg(DEBUG_SUSPEND, "already suspended");
+		return 0;
+	}
+
+	/* wait a bit for blocking conditions to go away */
+	rc = wait_event_timeout(ucs->waitqueue,
+			!(ucs->basstate &
+			  (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)),
+			BAS_TIMEOUT*HZ/10);
+	gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc);
+
+	/* check for conditions preventing suspend */
+	if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) {
+		dev_warn(cs->dev, "cannot suspend:\n");
+		if (ucs->basstate & BS_B1OPEN)
+			dev_warn(cs->dev, " B channel 1 open\n");
+		if (ucs->basstate & BS_B2OPEN)
+			dev_warn(cs->dev, " B channel 2 open\n");
+		if (ucs->basstate & BS_ATRDPEND)
+			dev_warn(cs->dev, " receiving AT reply\n");
+		if (ucs->basstate & BS_ATWRPEND)
+			dev_warn(cs->dev, " sending AT command\n");
+		update_basstate(ucs, 0, BS_SUSPEND);
+		return -EBUSY;
+	}
+
+	/* close AT channel if open */
+	if (ucs->basstate & BS_ATOPEN) {
+		gig_dbg(DEBUG_SUSPEND, "closing AT channel");
+		rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0);
+		if (rc) {
+			update_basstate(ucs, 0, BS_SUSPEND);
+			return rc;
+		}
+		wait_event_timeout(ucs->waitqueue, !ucs->pending,
+				   BAS_TIMEOUT*HZ/10);
+		/* in case of timeout, proceed anyway */
+	}
+
+	/* kill all URBs and timers that might still be pending */
+	usb_kill_urb(ucs->urb_ctrl);
+	usb_kill_urb(ucs->urb_int_in);
+	del_timer_sync(&ucs->timer_ctrl);
+
+	gig_dbg(DEBUG_SUSPEND, "suspend complete");
+	return 0;
+}
+
+/* gigaset_resume
+ * This function is called after the USB connection has been resumed.
+ */
+static int gigaset_resume(struct usb_interface *intf)
+{
+	struct cardstate *cs = usb_get_intfdata(intf);
+	struct bas_cardstate *ucs = cs->hw.bas;
+	int rc;
+
+	/* resubmit interrupt URB for spontaneous messages from base */
+	rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL);
+	if (rc) {
+		dev_err(cs->dev, "could not resubmit interrupt URB: %s\n",
+			get_usb_rcmsg(rc));
+		return rc;
+	}
+
+	/* clear suspend flag to reallow activity */
+	update_basstate(ucs, 0, BS_SUSPEND);
+
+	gig_dbg(DEBUG_SUSPEND, "resume complete");
+	return 0;
+}
+
+/* gigaset_pre_reset
+ * This function is called before the USB connection is reset.
+ */
+static int gigaset_pre_reset(struct usb_interface *intf)
+{
+	/* handle just like suspend */
+	return gigaset_suspend(intf, PMSG_ON);
+}
+
+/* gigaset_post_reset
+ * This function is called after the USB connection has been reset.
+ */
+static int gigaset_post_reset(struct usb_interface *intf)
+{
+	/* FIXME: send HD_DEVICE_INIT_ACK? */
+
+	/* resume operations */
+	return gigaset_resume(intf);
+}
+
+
 static const struct gigaset_ops gigops = {
 	gigaset_write_cmd,
 	gigaset_write_room,
@@ -2330,12 +2500,6 @@
 				       &gigops, THIS_MODULE)) == NULL)
 		goto error;
 
-	/* allocate memory for our device state and intialize it */
-	cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode,
-				   GIGASET_MODULENAME);
-	if (!cardstate)
-		goto error;
-
 	/* register this driver with the USB subsystem */
 	result = usb_register(&gigaset_usb_driver);
 	if (result < 0) {
@@ -2347,9 +2511,7 @@
 	info(DRIVER_DESC);
 	return 0;
 
-error:	if (cardstate)
-		gigaset_freecs(cardstate);
-	cardstate = NULL;
+error:
 	if (driver)
 		gigaset_freedriver(driver);
 	driver = NULL;
@@ -2361,43 +2523,50 @@
  */
 static void __exit bas_gigaset_exit(void)
 {
-	struct bas_cardstate *ucs = cardstate->hw.bas;
+	struct bas_cardstate *ucs;
+	int i;
 
 	gigaset_blockdriver(driver); /* => probe will fail
 				      * => no gigaset_start any more
 				      */
 
-	gigaset_shutdown(cardstate);
-	/* from now on, no isdn callback should be possible */
+	/* stop all connected devices */
+	for (i = 0; i < driver->minors; i++) {
+		if (gigaset_shutdown(driver->cs + i) < 0)
+			continue;		/* no device */
+		/* from now on, no isdn callback should be possible */
 
-	/* close all still open channels */
-	if (atomic_read(&ucs->basstate) & BS_B1OPEN) {
-		gig_dbg(DEBUG_INIT, "closing B1 channel");
-		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
-				HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0,
-				NULL, 0, BAS_TIMEOUT);
+		/* close all still open channels */
+		ucs = driver->cs[i].hw.bas;
+		if (ucs->basstate & BS_B1OPEN) {
+			gig_dbg(DEBUG_INIT, "closing B1 channel");
+			usb_control_msg(ucs->udev,
+					usb_sndctrlpipe(ucs->udev, 0),
+					HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ,
+					0, 0, NULL, 0, BAS_TIMEOUT);
+		}
+		if (ucs->basstate & BS_B2OPEN) {
+			gig_dbg(DEBUG_INIT, "closing B2 channel");
+			usb_control_msg(ucs->udev,
+					usb_sndctrlpipe(ucs->udev, 0),
+					HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ,
+					0, 0, NULL, 0, BAS_TIMEOUT);
+		}
+		if (ucs->basstate & BS_ATOPEN) {
+			gig_dbg(DEBUG_INIT, "closing AT channel");
+			usb_control_msg(ucs->udev,
+					usb_sndctrlpipe(ucs->udev, 0),
+					HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ,
+					0, 0, NULL, 0, BAS_TIMEOUT);
+		}
+		ucs->basstate = 0;
 	}
-	if (atomic_read(&ucs->basstate) & BS_B2OPEN) {
-		gig_dbg(DEBUG_INIT, "closing B2 channel");
-		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
-				HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0,
-				NULL, 0, BAS_TIMEOUT);
-	}
-	if (atomic_read(&ucs->basstate) & BS_ATOPEN) {
-		gig_dbg(DEBUG_INIT, "closing AT channel");
-		usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0),
-				HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0,
-				NULL, 0, BAS_TIMEOUT);
-	}
-	atomic_set(&ucs->basstate, 0);
 
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&gigaset_usb_driver);
 	/* this will call the disconnect-callback */
 	/* from now on, no disconnect/probe callback should be running */
 
-	gigaset_freecs(cardstate);
-	cardstate = NULL;
 	gigaset_freedriver(driver);
 	driver = NULL;
 }
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index acd4171..aacedec 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -31,7 +31,6 @@
 /* driver state flags */
 #define VALID_MINOR	0x01
 #define VALID_ID	0x02
-#define ASSIGNED	0x04
 
 void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
 			size_t len, const unsigned char *buf)
@@ -178,7 +177,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&bcs->cs->lock, flags);
-	if (bcs->use_count) {
+	if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) {
 		gig_dbg(DEBUG_ANY, "could not allocate channel %d",
 			bcs->channel);
 		spin_unlock_irqrestore(&bcs->cs->lock, flags);
@@ -203,6 +202,7 @@
 	}
 	--bcs->use_count;
 	bcs->busy = 0;
+	module_put(bcs->cs->driver->owner);
 	gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel);
 	spin_unlock_irqrestore(&bcs->cs->lock, flags);
 }
@@ -356,31 +356,28 @@
 {
 	unsigned long flags;
 	unsigned i;
+	struct cardstate *cs;
 	struct cardstate *ret = NULL;
 
 	spin_lock_irqsave(&drv->lock, flags);
+	if (drv->blocked)
+		goto exit;
 	for (i = 0; i < drv->minors; ++i) {
-		if (!(drv->flags[i] & VALID_MINOR)) {
-			if (try_module_get(drv->owner)) {
-				drv->flags[i] = VALID_MINOR;
-				ret = drv->cs + i;
-			}
+		cs = drv->cs + i;
+		if (!(cs->flags & VALID_MINOR)) {
+			cs->flags = VALID_MINOR;
+			ret = cs;
 			break;
 		}
 	}
+exit:
 	spin_unlock_irqrestore(&drv->lock, flags);
 	return ret;
 }
 
 static void free_cs(struct cardstate *cs)
 {
-	unsigned long flags;
-	struct gigaset_driver *drv = cs->driver;
-	spin_lock_irqsave(&drv->lock, flags);
-	if (drv->flags[cs->minor_index] & VALID_MINOR)
-		module_put(drv->owner);
-	drv->flags[cs->minor_index] = 0;
-	spin_unlock_irqrestore(&drv->lock, flags);
+	cs->flags = 0;
 }
 
 static void make_valid(struct cardstate *cs, unsigned mask)
@@ -388,7 +385,7 @@
 	unsigned long flags;
 	struct gigaset_driver *drv = cs->driver;
 	spin_lock_irqsave(&drv->lock, flags);
-	drv->flags[cs->minor_index] |= mask;
+	cs->flags |= mask;
 	spin_unlock_irqrestore(&drv->lock, flags);
 }
 
@@ -397,7 +394,7 @@
 	unsigned long flags;
 	struct gigaset_driver *drv = cs->driver;
 	spin_lock_irqsave(&drv->lock, flags);
-	drv->flags[cs->minor_index] &= ~mask;
+	cs->flags &= ~mask;
 	spin_unlock_irqrestore(&drv->lock, flags);
 }
 
@@ -501,11 +498,11 @@
 			       struct cardstate *cs, int inputstate)
 /* inbuf->read must be allocated before! */
 {
-	atomic_set(&inbuf->head, 0);
-	atomic_set(&inbuf->tail, 0);
+	inbuf->head = 0;
+	inbuf->tail = 0;
 	inbuf->cs = cs;
 	inbuf->bcs = bcs; /*base driver: NULL*/
-	inbuf->rcvbuf = NULL; //FIXME
+	inbuf->rcvbuf = NULL;
 	inbuf->inputstate = inputstate;
 }
 
@@ -521,8 +518,8 @@
 		return 0;
 
 	bytesleft = numbytes;
-	tail = atomic_read(&inbuf->tail);
-	head = atomic_read(&inbuf->head);
+	tail = inbuf->tail;
+	head = inbuf->head;
 	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 
 	while (bytesleft) {
@@ -546,7 +543,7 @@
 		src += n;
 	}
 	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
-	atomic_set(&inbuf->tail, tail);
+	inbuf->tail = tail;
 	return numbytes != bytesleft;
 }
 EXPORT_SYMBOL_GPL(gigaset_fill_inbuf);
@@ -668,7 +665,7 @@
 
 	tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
 		     (unsigned long) cs);
-	atomic_set(&cs->commands_pending, 0);
+	cs->commands_pending = 0;
 	cs->cur_at_seq = 0;
 	cs->gotfwver = -1;
 	cs->open_count = 0;
@@ -688,8 +685,8 @@
 	init_waitqueue_head(&cs->waitqueue);
 	cs->waiting = 0;
 
-	atomic_set(&cs->mode, M_UNKNOWN);
-	atomic_set(&cs->mstate, MS_UNINITIALIZED);
+	cs->mode = M_UNKNOWN;
+	cs->mstate = MS_UNINITIALIZED;
 
 	for (i = 0; i < channels; ++i) {
 		gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
@@ -806,8 +803,8 @@
 
 	spin_lock_irqsave(&cs->lock, flags);
 
-	atomic_set(&cs->mode, M_UNKNOWN);
-	atomic_set(&cs->mstate, MS_UNINITIALIZED);
+	cs->mode = M_UNKNOWN;
+	cs->mstate = MS_UNINITIALIZED;
 
 	clear_at_state(&cs->at_state);
 	dealloc_at_states(cs);
@@ -817,8 +814,8 @@
 	kfree(cs->inbuf->rcvbuf);
 	cs->inbuf->rcvbuf = NULL;
 	cs->inbuf->inputstate = INS_command;
-	atomic_set(&cs->inbuf->head, 0);
-	atomic_set(&cs->inbuf->tail, 0);
+	cs->inbuf->head = 0;
+	cs->inbuf->tail = 0;
 
 	cb = cs->cmdbuf;
 	while (cb) {
@@ -832,7 +829,7 @@
 	cs->gotfwver = -1;
 	cs->dle = 0;
 	cs->cur_at_seq = 0;
-	atomic_set(&cs->commands_pending, 0);
+	cs->commands_pending = 0;
 	cs->cbytes = 0;
 
 	spin_unlock_irqrestore(&cs->lock, flags);
@@ -862,7 +859,7 @@
 	cs->connected = 1;
 	spin_unlock_irqrestore(&cs->lock, flags);
 
-	if (atomic_read(&cs->mstate) != MS_LOCKED) {
+	if (cs->mstate != MS_LOCKED) {
 		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
 		cs->ops->baud_rate(cs, B115200);
 		cs->ops->set_line_ctrl(cs, CS8);
@@ -893,10 +890,17 @@
 }
 EXPORT_SYMBOL_GPL(gigaset_start);
 
-void gigaset_shutdown(struct cardstate *cs)
+/* gigaset_shutdown
+ * check if a device is associated to the cardstate structure and stop it
+ * return value: 0 if ok, -1 if no device was associated
+ */
+int gigaset_shutdown(struct cardstate *cs)
 {
 	mutex_lock(&cs->mutex);
 
+	if (!(cs->flags & VALID_MINOR))
+		return -1;
+
 	cs->waiting = 1;
 
 	if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
@@ -913,6 +917,7 @@
 
 exit:
 	mutex_unlock(&cs->mutex);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(gigaset_shutdown);
 
@@ -954,13 +959,11 @@
 	list_for_each_entry(drv, &drivers, list) {
 		spin_lock(&drv->lock);
 		for (i = 0; i < drv->minors; ++i) {
-			if (drv->flags[i] & VALID_ID) {
-				cs = drv->cs + i;
-				if (cs->myid == id)
-					ret = cs;
-			}
-			if (ret)
+			cs = drv->cs + i;
+			if ((cs->flags & VALID_ID) && cs->myid == id) {
+				ret = cs;
 				break;
+			}
 		}
 		spin_unlock(&drv->lock);
 		if (ret)
@@ -983,10 +986,9 @@
 		spin_lock(&drv->lock);
 		for (i = 0; i < drv->minors; ++i) {
 			gig_dbg(DEBUG_DRIVER, "  index %u", i);
-			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x",
-				drv->flags[i]);
 			cs = drv->cs + i;
 			gig_dbg(DEBUG_DRIVER, "    cardstate %p", cs);
+			gig_dbg(DEBUG_DRIVER, "    flags 0x%02x", cs->flags);
 			gig_dbg(DEBUG_DRIVER, "    minor_index %u",
 				cs->minor_index);
 			gig_dbg(DEBUG_DRIVER, "    driver %p", cs->driver);
@@ -1010,7 +1012,7 @@
 			continue;
 		index = minor - drv->minor;
 		spin_lock(&drv->lock);
-		if (drv->flags[index] & VALID_MINOR)
+		if (drv->cs[index].flags & VALID_MINOR)
 			ret = drv->cs + index;
 		spin_unlock(&drv->lock);
 		if (ret)
@@ -1038,7 +1040,6 @@
 	gigaset_if_freedriver(drv);
 
 	kfree(drv->cs);
-	kfree(drv->flags);
 	kfree(drv);
 }
 EXPORT_SYMBOL_GPL(gigaset_freedriver);
@@ -1080,12 +1081,8 @@
 	if (!drv->cs)
 		goto error;
 
-	drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL);
-	if (!drv->flags)
-		goto error;
-
 	for (i = 0; i < minors; ++i) {
-		drv->flags[i] = 0;
+		drv->cs[i].flags = 0;
 		drv->cs[i].driver = drv;
 		drv->cs[i].ops = drv->ops;
 		drv->cs[i].minor_index = i;
@@ -1106,53 +1103,9 @@
 }
 EXPORT_SYMBOL_GPL(gigaset_initdriver);
 
-/* For drivers without fixed assignment device<->cardstate (usb) */
-struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv)
-{
-	unsigned long flags;
-	struct cardstate *cs = NULL;
-	unsigned i;
-
-	spin_lock_irqsave(&drv->lock, flags);
-	if (drv->blocked)
-		goto exit;
-	for (i = 0; i < drv->minors; ++i) {
-		if ((drv->flags[i] & VALID_MINOR) &&
-		    !(drv->flags[i] & ASSIGNED)) {
-			drv->flags[i] |= ASSIGNED;
-			cs = drv->cs + i;
-			break;
-		}
-	}
-exit:
-	spin_unlock_irqrestore(&drv->lock, flags);
-	return cs;
-}
-EXPORT_SYMBOL_GPL(gigaset_getunassignedcs);
-
-void gigaset_unassign(struct cardstate *cs)
-{
-	unsigned long flags;
-	unsigned *minor_flags;
-	struct gigaset_driver *drv;
-
-	if (!cs)
-		return;
-	drv = cs->driver;
-	spin_lock_irqsave(&drv->lock, flags);
-	minor_flags = drv->flags + cs->minor_index;
-	if (*minor_flags & VALID_MINOR)
-		*minor_flags &= ~ASSIGNED;
-	spin_unlock_irqrestore(&drv->lock, flags);
-}
-EXPORT_SYMBOL_GPL(gigaset_unassign);
-
 void gigaset_blockdriver(struct gigaset_driver *drv)
 {
-	unsigned long flags;
-	spin_lock_irqsave(&drv->lock, flags);
 	drv->blocked = 1;
-	spin_unlock_irqrestore(&drv->lock, flags);
 }
 EXPORT_SYMBOL_GPL(gigaset_blockdriver);
 
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index cec1ef3..5cbf64d8 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -735,7 +735,7 @@
 	/* revert to selected idle mode */
 	if (!cs->cidmode) {
 		cs->at_state.pending_commands |= PC_UMMODE;
-		atomic_set(&cs->commands_pending, 1); //FIXME
+		cs->commands_pending = 1;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
 	}
 	spin_unlock_irqrestore(&cs->lock, flags);
@@ -793,15 +793,15 @@
 	struct at_state_t *at_state;
 
 	cs->at_state.pending_commands &= ~PC_INIT;
-	atomic_set(&cs->mode, mode);
-	atomic_set(&cs->mstate, MS_UNINITIALIZED);
+	cs->mode = mode;
+	cs->mstate = MS_UNINITIALIZED;
 	gigaset_free_channels(cs);
 	for (i = 0; i < cs->channels; ++i) {
 		at_state = &cs->bcs[i].at_state;
 		if (at_state->pending_commands & PC_CID) {
 			at_state->pending_commands &= ~PC_CID;
 			at_state->pending_commands |= PC_NOCID;
-			atomic_set(&cs->commands_pending, 1);
+			cs->commands_pending = 1;
 		}
 	}
 }
@@ -812,11 +812,11 @@
 		gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again");
 		return;
 	}
-	atomic_set(&cs->mstate, state);
-	atomic_set(&cs->mode, M_UNKNOWN);
+	cs->mstate = state;
+	cs->mode = M_UNKNOWN;
 	gigaset_block_channels(cs);
 	cs->at_state.pending_commands |= PC_INIT;
-	atomic_set(&cs->commands_pending, 1);
+	cs->commands_pending = 1;
 	gig_dbg(DEBUG_CMD, "Scheduling PC_INIT");
 }
 
@@ -953,13 +953,13 @@
 
 	at_state->pending_commands |= PC_CID;
 	gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
-	atomic_set(&cs->commands_pending, 1);
+	cs->commands_pending = 1;
 	return;
 
 error:
 	at_state->pending_commands |= PC_NOCID;
 	gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
-	atomic_set(&cs->commands_pending, 1);
+	cs->commands_pending = 1;
 	return;
 }
 
@@ -973,12 +973,12 @@
 	if (retval == 0) {
 		at_state->pending_commands |= PC_ACCEPT;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 	} else {
-		//FIXME
+		/* error reset */
 		at_state->pending_commands |= PC_HUP;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 	}
 }
 
@@ -986,7 +986,7 @@
 {
 	gigaset_free_channels(cs);
 
-	if (atomic_read(&cs->mstate) != MS_LOCKED)
+	if (cs->mstate != MS_LOCKED)
 		schedule_init(cs, MS_INIT);
 
 	cs->isdn_up = 1;
@@ -1000,9 +1000,9 @@
 
 static void finish_shutdown(struct cardstate *cs)
 {
-	if (atomic_read(&cs->mstate) != MS_LOCKED) {
-		atomic_set(&cs->mstate, MS_UNINITIALIZED);
-		atomic_set(&cs->mode, M_UNKNOWN);
+	if (cs->mstate != MS_LOCKED) {
+		cs->mstate = MS_UNINITIALIZED;
+		cs->mode = M_UNKNOWN;
 	}
 
 	/* Tell the LL that the device is not available .. */
@@ -1022,10 +1022,10 @@
 {
 	gigaset_block_channels(cs);
 
-	if (atomic_read(&cs->mstate) == MS_READY) {
-		atomic_set(&cs->mstate, MS_SHUTDOWN);
+	if (cs->mstate == MS_READY) {
+		cs->mstate = MS_SHUTDOWN;
 		cs->at_state.pending_commands |= PC_SHUTDOWN;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN");
 	} else
 		finish_shutdown(cs);
@@ -1120,7 +1120,7 @@
 		 * In fact it doesn't.
 		 */
 		at_state->pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		break;
 	}
 }
@@ -1130,7 +1130,7 @@
 	int mode;
 	int i;
 
-	switch (atomic_read(&cs->mstate)) {
+	switch (cs->mstate) {
 	case MS_UNINITIALIZED:
 	case MS_READY:
 		if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) ||
@@ -1152,20 +1152,20 @@
 		return -EBUSY;
 	}
 
-	mode = atomic_read(&cs->mode);
-	atomic_set(&cs->mstate, MS_LOCKED);
-	atomic_set(&cs->mode, M_UNKNOWN);
+	mode = cs->mode;
+	cs->mstate = MS_LOCKED;
+	cs->mode = M_UNKNOWN;
 
 	return mode;
 }
 
 static int do_unlock(struct cardstate *cs)
 {
-	if (atomic_read(&cs->mstate) != MS_LOCKED)
+	if (cs->mstate != MS_LOCKED)
 		return -EINVAL;
 
-	atomic_set(&cs->mstate, MS_UNINITIALIZED);
-	atomic_set(&cs->mode, M_UNKNOWN);
+	cs->mstate = MS_UNINITIALIZED;
+	cs->mode = M_UNKNOWN;
 	gigaset_free_channels(cs);
 	if (cs->connected)
 		schedule_init(cs, MS_INIT);
@@ -1198,17 +1198,17 @@
 	case ACT_INIT:
 		cs->at_state.pending_commands &= ~PC_INIT;
 		cs->cur_at_seq = SEQ_NONE;
-		atomic_set(&cs->mode, M_UNIMODEM);
+		cs->mode = M_UNIMODEM;
 		spin_lock_irqsave(&cs->lock, flags);
 		if (!cs->cidmode) {
 			spin_unlock_irqrestore(&cs->lock, flags);
 			gigaset_free_channels(cs);
-			atomic_set(&cs->mstate, MS_READY);
+			cs->mstate = MS_READY;
 			break;
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
 		cs->at_state.pending_commands |= PC_CIDMODE;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
 		break;
 	case ACT_FAILINIT:
@@ -1234,22 +1234,20 @@
 			| INS_command;
 		break;
 	case ACT_CMODESET:
-		if (atomic_read(&cs->mstate) == MS_INIT ||
-		    atomic_read(&cs->mstate) == MS_RECOVER) {
+		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
 			gigaset_free_channels(cs);
-			atomic_set(&cs->mstate, MS_READY);
+			cs->mstate = MS_READY;
 		}
-		atomic_set(&cs->mode, M_CID);
+		cs->mode = M_CID;
 		cs->cur_at_seq = SEQ_NONE;
 		break;
 	case ACT_UMODESET:
-		atomic_set(&cs->mode, M_UNIMODEM);
+		cs->mode = M_UNIMODEM;
 		cs->cur_at_seq = SEQ_NONE;
 		break;
 	case ACT_FAILCMODE:
 		cs->cur_at_seq = SEQ_NONE;
-		if (atomic_read(&cs->mstate) == MS_INIT ||
-		    atomic_read(&cs->mstate) == MS_RECOVER) {
+		if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) {
 			init_failed(cs, M_UNKNOWN);
 			break;
 		}
@@ -1307,7 +1305,7 @@
 	case ACT_CONNECT:
 		if (cs->onechannel) {
 			at_state->pending_commands |= PC_DLE1;
-			atomic_set(&cs->commands_pending, 1);
+			cs->commands_pending = 1;
 			break;
 		}
 		bcs->chstate |= CHS_D_UP;
@@ -1333,7 +1331,7 @@
 			 * DLE only used for M10x with one B channel.
 			 */
 			at_state->pending_commands |= PC_DLE0;
-			atomic_set(&cs->commands_pending, 1);
+			cs->commands_pending = 1;
 		} else
 			disconnect(p_at_state);
 		break;
@@ -1369,7 +1367,7 @@
 			 "Could not enter DLE mode. Trying to hang up.\n");
 		channel = cs->curchannel;
 		cs->bcs[channel].at_state.pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		break;
 
 	case ACT_CID: /* got cid; start dialing */
@@ -1379,7 +1377,7 @@
 			cs->bcs[channel].at_state.cid = ev->parameter;
 			cs->bcs[channel].at_state.pending_commands |=
 				PC_DIAL;
-			atomic_set(&cs->commands_pending, 1);
+			cs->commands_pending = 1;
 			break;
 		}
 		/* fall through */
@@ -1411,14 +1409,14 @@
 	case ACT_ABORTDIAL:	/* error/timeout during dial preparation */
 		cs->cur_at_seq = SEQ_NONE;
 		at_state->pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		break;
 
 	case ACT_REMOTEREJECT:	/* DISCONNECT_IND after dialling */
 	case ACT_CONNTIMEOUT:	/* timeout waiting for ZSAU=ACTIVE */
 	case ACT_REMOTEHUP:	/* DISCONNECT_IND with established connection */
 		at_state->pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		break;
 	case ACT_GETSTRING: /* warning: RING, ZDLE, ...
 			       are not handled properly anymore */
@@ -1515,7 +1513,7 @@
 		break;
 	case ACT_HUP:
 		at_state->pending_commands |= PC_HUP;
-		atomic_set(&cs->commands_pending, 1);
+		cs->commands_pending = 1;
 		gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
 		break;
 
@@ -1558,7 +1556,7 @@
 				cs->at_state.pending_commands |= PC_UMMODE;
 				gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE");
 			}
-			atomic_set(&cs->commands_pending, 1);
+			cs->commands_pending = 1;
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
 		cs->waiting = 0;
@@ -1741,7 +1739,7 @@
 	int sequence;
 	unsigned long flags;
 
-	atomic_set(&cs->commands_pending, 0);
+	cs->commands_pending = 0;
 
 	if (cs->cur_at_seq) {
 		gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy");
@@ -1779,7 +1777,7 @@
 				~(PC_DLE1 | PC_ACCEPT | PC_DIAL);
 			if (at_state->cid > 0)
 				at_state->pending_commands |= PC_HUP;
-			if (atomic_read(&cs->mstate) == MS_RECOVER) {
+			if (cs->mstate == MS_RECOVER) {
 				if (at_state->pending_commands & PC_CID) {
 					at_state->pending_commands |= PC_NOCID;
 					at_state->pending_commands &= ~PC_CID;
@@ -1793,7 +1791,7 @@
 	if (cs->at_state.pending_commands == PC_UMMODE
 	    && !cs->cidmode
 	    && list_empty(&cs->temp_at_states)
-	    && atomic_read(&cs->mode) == M_CID) {
+	    && cs->mode == M_CID) {
 		sequence = SEQ_UMMODE;
 		at_state = &cs->at_state;
 		for (i = 0; i < cs->channels; ++i) {
@@ -1860,7 +1858,7 @@
 	}
 	if (cs->at_state.pending_commands & PC_CIDMODE) {
 		cs->at_state.pending_commands &= ~PC_CIDMODE;
-		if (atomic_read(&cs->mode) == M_UNIMODEM) {
+		if (cs->mode == M_UNIMODEM) {
 			cs->retry_count = 1;
 			schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE);
 			return;
@@ -1886,11 +1884,11 @@
 			return;
 		}
 		if (bcs->at_state.pending_commands & PC_CID) {
-			switch (atomic_read(&cs->mode)) {
+			switch (cs->mode) {
 			case M_UNIMODEM:
 				cs->at_state.pending_commands |= PC_CIDMODE;
 				gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE");
-				atomic_set(&cs->commands_pending, 1);
+				cs->commands_pending = 1;
 				return;
 #ifdef GIG_MAYINITONDIAL
 			case M_UNKNOWN:
@@ -1926,7 +1924,7 @@
 	for (i = 0; i < 2 * MAX_EVENTS; ++i) {
 		tail = cs->ev_tail;
 		if (tail == head) {
-			if (!check_flags && !atomic_read(&cs->commands_pending))
+			if (!check_flags && !cs->commands_pending)
 				break;
 			check_flags = 0;
 			spin_unlock_irqrestore(&cs->ev_lock, flags);
@@ -1934,7 +1932,7 @@
 			spin_lock_irqsave(&cs->ev_lock, flags);
 			tail = cs->ev_tail;
 			if (tail == head) {
-				if (!atomic_read(&cs->commands_pending))
+				if (!cs->commands_pending)
 					break;
 				continue;
 			}
@@ -1971,7 +1969,7 @@
 	struct cardstate *cs = (struct cardstate *) data;
 
 	/* handle incoming data on control/common channel */
-	if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) {
+	if (cs->inbuf->head != cs->inbuf->tail) {
 		gig_dbg(DEBUG_INTR, "processing new data");
 		cs->ops->handle_input(cs->inbuf);
 	}
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 02bdaf2..f365993 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -70,22 +70,13 @@
 
 extern int gigaset_debuglevel;	/* "needs" cast to (enum debuglevel) */
 
-/* any combination of these can be given with the 'debug=' parameter to insmod,
- * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and
- * DEBUG_INTR.
- */
+/* debug flags, combine by adding/bitwise OR */
 enum debuglevel {
-	DEBUG_REG	  = 0x0002, /* serial port I/O register operations */
-	DEBUG_OPEN	  = 0x0004, /* open/close serial port */
-	DEBUG_INTR	  = 0x0008, /* interrupt processing */
-	DEBUG_INTR_DUMP	  = 0x0010, /* Activating hexdump debug output on
-				       interrupt requests, not available as
-				       run-time option */
+	DEBUG_INTR	  = 0x00008, /* interrupt processing */
 	DEBUG_CMD	  = 0x00020, /* sent/received LL commands */
 	DEBUG_STREAM	  = 0x00040, /* application data stream I/O events */
 	DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */
 	DEBUG_LLDATA	  = 0x00100, /* sent/received LL data */
-	DEBUG_INTR_0	  = 0x00200, /* serial port interrupt processing */
 	DEBUG_DRIVER	  = 0x00400, /* driver structure */
 	DEBUG_HDLC	  = 0x00800, /* M10x HDLC processing */
 	DEBUG_WRITE	  = 0x01000, /* M105 data write */
@@ -93,7 +84,7 @@
 	DEBUG_MCMD	  = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */
 	DEBUG_INIT	  = 0x08000, /* (de)allocation+initialization of data
 					structures */
-	DEBUG_LOCK	  = 0x10000, /* semaphore operations */
+	DEBUG_SUSPEND	  = 0x10000, /* suspend/resume processing */
 	DEBUG_OUTPUT	  = 0x20000, /* output to device */
 	DEBUG_ISO	  = 0x40000, /* isochronous transfers */
 	DEBUG_IF	  = 0x80000, /* character device operations */
@@ -191,6 +182,9 @@
 #define	HD_OPEN_ATCHANNEL		(0x28)		// 3070
 #define	HD_CLOSE_ATCHANNEL		(0x29)		// 3070
 
+/* number of B channels supported by base driver */
+#define BAS_CHANNELS	2
+
 /* USB frames for isochronous transfer */
 #define BAS_FRAMETIME	1	/* number of milliseconds between frames */
 #define BAS_NUMFRAMES	8	/* number of frames per URB */
@@ -313,7 +307,7 @@
 	struct bc_state		*bcs;
 	struct cardstate	*cs;
 	int			inputstate;
-	atomic_t		head, tail;
+	int			head, tail;
 	unsigned char		data[RBUFSIZE];
 };
 
@@ -335,9 +329,9 @@
  *   are also filled with that value
  */
 struct isowbuf_t {
-	atomic_t	read;
-	atomic_t	nextread;
-	atomic_t	write;
+	int		read;
+	int		nextread;
+	int		write;
 	atomic_t	writesem;
 	int		wbits;
 	unsigned char	data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD];
@@ -350,11 +344,13 @@
  * - urb: pointer to the URB itself
  * - bcs: pointer to the B Channel control structure
  * - limit: end of write buffer area covered by this URB
+ * - status: URB completion status
  */
 struct isow_urbctx_t {
 	struct urb *urb;
 	struct bc_state *bcs;
 	int limit;
+	int status;
 };
 
 /* AT state structure
@@ -439,14 +435,15 @@
 	unsigned minor_index;
 	struct device *dev;
 	struct device *tty_dev;
+	unsigned flags;
 
 	const struct gigaset_ops *ops;
 
 	/* Stuff to handle communication */
 	wait_queue_head_t waitqueue;
 	int waiting;
-	atomic_t mode;			/* see M_XXXX */
-	atomic_t mstate;		/* Modem state: see MS_XXXX */
+	int mode;			/* see M_XXXX */
+	int mstate;			/* Modem state: see MS_XXXX */
 					/* only changed by the event layer */
 	int cmd_result;
 
@@ -503,7 +500,7 @@
 					   processed */
 	int curchannel;			/* channel those commands are meant
 					   for */
-	atomic_t commands_pending;	/* flag(s) in xxx.commands_pending have
+	int commands_pending;		/* flag(s) in xxx.commands_pending have
 					   been set */
 	struct tasklet_struct event_tasklet;
 					/* tasklet for serializing AT commands.
@@ -543,7 +540,6 @@
 	unsigned minor;
 	unsigned minors;
 	struct cardstate *cs;
-	unsigned *flags;
 	int blocked;
 
 	const struct gigaset_ops *ops;
@@ -559,7 +555,7 @@
 
 struct bas_bc_state {
 	/* isochronous output state */
-	atomic_t	running;
+	int		running;
 	atomic_t	corrbytes;
 	spinlock_t	isooutlock;
 	struct isow_urbctx_t	isoouturbs[BAS_OUTURBS];
@@ -574,6 +570,7 @@
 	struct urb *isoinurbs[BAS_INURBS];
 	unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS];
 	struct urb *isoindone;		/* completed isoc read URB */
+	int isoinstatus;		/* status of completed URB */
 	int loststatus;			/* status of dropped URB */
 	unsigned isoinlost;		/* number of bytes lost */
 	/* state of bit unstuffing algorithm
@@ -770,10 +767,6 @@
 void gigaset_debugdrivers(void);
 struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty);
 struct cardstate *gigaset_get_cs_by_id(int id);
-
-/* For drivers without fixed assignment device<->cardstate (usb) */
-struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv);
-void gigaset_unassign(struct cardstate *cs);
 void gigaset_blockdriver(struct gigaset_driver *drv);
 
 /* Allocate and initialize card state. Calls hardware dependent
@@ -792,7 +785,7 @@
 void gigaset_stop(struct cardstate *cs);
 
 /* Tell common.c that the driver is being unloaded. */
-void gigaset_shutdown(struct cardstate *cs);
+int gigaset_shutdown(struct cardstate *cs);
 
 /* Tell common.c that an skb has been sent. */
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index eb50f3d..af195b0 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -28,12 +28,11 @@
 		return -EINVAL;
 
 	if (cmd < 0) {
-		*arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove?
+		*arg = cs->mstate == MS_LOCKED;
 		return 0;
 	}
 
-	if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED
-	    && cs->connected) {
+	if (!cmd && cs->mstate == MS_LOCKED && cs->connected) {
 		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
 		cs->ops->baud_rate(cs, B115200);
 		cs->ops->set_line_ctrl(cs, CS8);
@@ -104,7 +103,7 @@
 	if (*arg != 1)
 		return -EINVAL;
 
-	if (atomic_read(&cs->mstate) != MS_LOCKED)
+	if (cs->mstate != MS_LOCKED)
 		return -EBUSY;
 
 	if (!cs->connected) {
@@ -162,7 +161,7 @@
 	tty->driver_data = NULL;
 
 	cs = gigaset_get_cs_by_tty(tty);
-	if (!cs)
+	if (!cs || !try_module_get(cs->driver->owner))
 		return -ENODEV;
 
 	if (mutex_lock_interruptible(&cs->mutex))
@@ -208,6 +207,8 @@
 	}
 
 	mutex_unlock(&cs->mutex);
+
+	module_put(cs->driver->owner);
 }
 
 static int if_ioctl(struct tty_struct *tty, struct file *file,
@@ -364,7 +365,7 @@
 
 	if (!cs->open_count)
 		warn("%s: device not opened", __func__);
-	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+	else if (cs->mstate != MS_LOCKED) {
 		warn("can't write to unlocked device");
 		retval = -EBUSY;
 	} else if (!cs->connected) {
@@ -398,9 +399,9 @@
 
 	if (!cs->open_count)
 		warn("%s: device not opened", __func__);
-	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+	else if (cs->mstate != MS_LOCKED) {
 		warn("can't write to unlocked device");
-		retval = -EBUSY; //FIXME
+		retval = -EBUSY;
 	} else if (!cs->connected) {
 		gig_dbg(DEBUG_ANY, "can't write to unplugged device");
 		retval = -EBUSY; //FIXME
@@ -430,7 +431,7 @@
 
 	if (!cs->open_count)
 		warn("%s: device not opened", __func__);
-	else if (atomic_read(&cs->mstate) != MS_LOCKED) {
+	else if (cs->mstate != MS_LOCKED) {
 		warn("can't write to unlocked device");
 		retval = -EBUSY;
 	} else if (!cs->connected) {
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c
index e0505f2..e30a777 100644
--- a/drivers/isdn/gigaset/isocdata.c
+++ b/drivers/isdn/gigaset/isocdata.c
@@ -23,9 +23,9 @@
  */
 void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle)
 {
-	atomic_set(&iwb->read, 0);
-	atomic_set(&iwb->nextread, 0);
-	atomic_set(&iwb->write, 0);
+	iwb->read = 0;
+	iwb->nextread = 0;
+	iwb->write = 0;
 	atomic_set(&iwb->writesem, 1);
 	iwb->wbits = 0;
 	iwb->idle = idle;
@@ -39,8 +39,8 @@
 {
 	int read, write, freebytes;
 
-	read = atomic_read(&iwb->read);
-	write = atomic_read(&iwb->write);
+	read = iwb->read;
+	write = iwb->write;
 	if ((freebytes = read - write) > 0) {
 		/* no wraparound: need padding space within regular area */
 		return freebytes - BAS_OUTBUFPAD;
@@ -62,7 +62,7 @@
 	int read;
 	if (a == b)
 		return 0;
-	read = atomic_read(&iwb->read);
+	read = iwb->read;
 	if (a < b) {
 		if (a < read && read <= b)
 			return +1;
@@ -91,18 +91,18 @@
 #ifdef CONFIG_GIGASET_DEBUG
 	gig_dbg(DEBUG_ISO,
 		"%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
-		__func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits);
+		__func__, iwb->data[iwb->write], iwb->wbits);
 #endif
 	return 1;
 }
 
 /* finish writing
- * release the write semaphore and update the maximum buffer fill level
+ * release the write semaphore
  * returns the current write position
  */
 static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
 {
-	int write = atomic_read(&iwb->write);
+	int write = iwb->write;
 	atomic_inc(&iwb->writesem);
 	return write;
 }
@@ -116,7 +116,7 @@
  */
 static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
 {
-	int write = atomic_read(&iwb->write);
+	int write = iwb->write;
 	data <<= iwb->wbits;
 	data |= iwb->data[write];
 	nbits += iwb->wbits;
@@ -128,7 +128,7 @@
 	}
 	iwb->wbits = nbits;
 	iwb->data[write] = data & 0xff;
-	atomic_set(&iwb->write, write);
+	iwb->write = write;
 }
 
 /* put final flag on HDLC bitstream
@@ -142,7 +142,7 @@
 	/* add two flags, thus reliably covering one byte */
 	isowbuf_putbits(iwb, 0x7e7e, 8);
 	/* recover the idle flag byte */
-	write = atomic_read(&iwb->write);
+	write = iwb->write;
 	iwb->idle = iwb->data[write];
 	gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
 	/* mask extraneous bits in buffer */
@@ -160,8 +160,8 @@
 	int read, write, limit, src, dst;
 	unsigned char pbyte;
 
-	read = atomic_read(&iwb->nextread);
-	write = atomic_read(&iwb->write);
+	read = iwb->nextread;
+	write = iwb->write;
 	if (likely(read == write)) {
 		/* return idle frame */
 		return read < BAS_OUTBUFPAD ?
@@ -176,7 +176,7 @@
 		err("invalid size %d", size);
 		return -EINVAL;
 	}
-	src = atomic_read(&iwb->read);
+	src = iwb->read;
 	if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
 		     (read < src && limit >= src))) {
 		err("isoc write buffer frame reservation violated");
@@ -191,7 +191,8 @@
 			if (!isowbuf_startwrite(iwb))
 				return -EBUSY;
 			/* write position could have changed */
-			if (limit >= (write = atomic_read(&iwb->write))) {
+			write = iwb->write;
+			if (limit >= write) {
 				pbyte = iwb->data[write]; /* save
 							     partial byte */
 				limit = write + BAS_OUTBUFPAD;
@@ -213,7 +214,7 @@
 					__func__, pbyte, limit);
 				iwb->data[limit] = pbyte; /* restore
 							     partial byte */
-				atomic_set(&iwb->write, limit);
+				iwb->write = limit;
 			}
 			isowbuf_donewrite(iwb);
 		}
@@ -233,7 +234,7 @@
 			limit = src;
 		}
 	}
-	atomic_set(&iwb->nextread, limit);
+	iwb->nextread = limit;
 	return read;
 }
 
@@ -477,7 +478,7 @@
 	unsigned char c;
 
 	if (unlikely(count <= 0))
-		return atomic_read(&iwb->write); /* better ideas? */
+		return iwb->write;
 
 	if (isowbuf_freebytes(iwb) < count ||
 	    !isowbuf_startwrite(iwb)) {
@@ -486,13 +487,13 @@
 	}
 
 	gig_dbg(DEBUG_STREAM, "put %d bytes", count);
-	write = atomic_read(&iwb->write);
+	write = iwb->write;
 	do {
 		c = bitrev8(*in++);
 		iwb->data[write++] = c;
 		write %= BAS_OUTBUFSIZE;
 	} while (--count > 0);
-	atomic_set(&iwb->write, write);
+	iwb->write = write;
 	iwb->idle = c;
 
 	return isowbuf_donewrite(iwb);
@@ -947,8 +948,8 @@
 	unsigned tail, head, numbytes;
 	unsigned char *src;
 
-	head = atomic_read(&inbuf->head);
-	while (head != (tail = atomic_read(&inbuf->tail))) {
+	head = inbuf->head;
+	while (head != (tail = inbuf->tail)) {
 		gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
 		if (head > tail)
 			tail = RBUFSIZE;
@@ -956,7 +957,7 @@
 		numbytes = tail - head;
 		gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
 
-		if (atomic_read(&cs->mstate) == MS_LOCKED) {
+		if (cs->mstate == MS_LOCKED) {
 			gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
 					   numbytes, src);
 			gigaset_if_receive(inbuf->cs, src, numbytes);
@@ -970,7 +971,7 @@
 		if (head == RBUFSIZE)
 			head = 0;
 		gig_dbg(DEBUG_INTR, "setting head to %u", head);
-		atomic_set(&inbuf->head, head);
+		inbuf->head = head;
 	}
 }
 
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index ea44302..fceeb1d 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/tty.h>
 #include <linux/poll.h>
+#include <linux/completion.h>
 
 /* Version Information */
 #define DRIVER_AUTHOR "Tilman Schmidt"
@@ -48,7 +49,7 @@
 	struct platform_device	dev;
 	struct tty_struct	*tty;
 	atomic_t		refcnt;
-	struct mutex		dead_mutex;
+	struct completion	dead_cmp;
 };
 
 static struct platform_driver device_driver = {
@@ -240,7 +241,7 @@
 	struct cmdbuf_t *cb;
 	unsigned long flags;
 
-	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 	                     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
 	                   "CMD Transmit", len, buf);
 
@@ -498,7 +499,7 @@
 static void cs_put(struct cardstate *cs)
 {
 	if (atomic_dec_and_test(&cs->hw.ser->refcnt))
-		mutex_unlock(&cs->hw.ser->dead_mutex);
+		complete(&cs->hw.ser->dead_cmp);
 }
 
 /*
@@ -527,8 +528,8 @@
 
 	cs->dev = &cs->hw.ser->dev.dev;
 	cs->hw.ser->tty = tty;
-	mutex_init(&cs->hw.ser->dead_mutex);
 	atomic_set(&cs->hw.ser->refcnt, 1);
+	init_completion(&cs->hw.ser->dead_cmp);
 
 	tty->disc_data = cs;
 
@@ -536,14 +537,13 @@
 	 * startup system and notify the LL that we are ready to run
 	 */
 	if (startmode == SM_LOCKED)
-		atomic_set(&cs->mstate, MS_LOCKED);
+		cs->mstate = MS_LOCKED;
 	if (!gigaset_start(cs)) {
 		tasklet_kill(&cs->write_tasklet);
 		goto error;
 	}
 
 	gig_dbg(DEBUG_INIT, "Startup of HLL done");
-	mutex_lock(&cs->hw.ser->dead_mutex);
 	return 0;
 
 error:
@@ -577,7 +577,7 @@
 	else {
 		/* wait for running methods to finish */
 		if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
-			mutex_lock(&cs->hw.ser->dead_mutex);
+			wait_for_completion(&cs->hw.ser->dead_cmp);
 	}
 
 	/* stop operations */
@@ -714,8 +714,8 @@
 		return;
 	}
 
-	tail = atomic_read(&inbuf->tail);
-	head = atomic_read(&inbuf->head);
+	tail = inbuf->tail;
+	head = inbuf->head;
 	gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes",
 		head, tail, count);
 
@@ -742,7 +742,7 @@
 	}
 
 	gig_dbg(DEBUG_INTR, "setting tail to %u", tail);
-	atomic_set(&inbuf->tail, tail);
+	inbuf->tail = tail;
 
 	/* Everything was received .. Push data into handler */
 	gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c
index ca4bee1..77d20ab 100644
--- a/drivers/isdn/gigaset/usb-gigaset.c
+++ b/drivers/isdn/gigaset/usb-gigaset.c
@@ -104,12 +104,17 @@
  * flags per packet.
  */
 
+/* functions called if a device of this driver is connected/disconnected */
 static int gigaset_probe(struct usb_interface *interface,
 			 const struct usb_device_id *id);
 static void gigaset_disconnect(struct usb_interface *interface);
 
+/* functions called before/after suspend */
+static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
+static int gigaset_resume(struct usb_interface *intf);
+static int gigaset_pre_reset(struct usb_interface *intf);
+
 static struct gigaset_driver *driver = NULL;
-static struct cardstate *cardstate = NULL;
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver gigaset_usb_driver = {
@@ -117,12 +122,17 @@
 	.probe =	gigaset_probe,
 	.disconnect =	gigaset_disconnect,
 	.id_table =	gigaset_table,
+	.suspend =	gigaset_suspend,
+	.resume =	gigaset_resume,
+	.reset_resume =	gigaset_resume,
+	.pre_reset =	gigaset_pre_reset,
+	.post_reset =	gigaset_resume,
 };
 
 struct usb_cardstate {
 	struct usb_device	*udev;		/* usb device pointer */
 	struct usb_interface	*interface;	/* interface for this device */
-	atomic_t		busy;		/* bulk output in progress */
+	int			busy;		/* bulk output in progress */
 
 	/* Output buffer */
 	unsigned char		*bulk_out_buffer;
@@ -314,7 +324,7 @@
 
 	gig_dbg(DEBUG_OUTPUT, "modem_fill");
 
-	if (atomic_read(&cs->hw.usb->busy)) {
+	if (cs->hw.usb->busy) {
 		gig_dbg(DEBUG_OUTPUT, "modem_fill: busy");
 		return;
 	}
@@ -361,18 +371,13 @@
 {
 	struct inbuf_t *inbuf = urb->context;
 	struct cardstate *cs = inbuf->cs;
-	int resubmit = 0;
+	int status = urb->status;
 	int r;
 	unsigned numbytes;
 	unsigned char *src;
 	unsigned long flags;
 
-	if (!urb->status) {
-		if (!cs->connected) {
-			err("%s: disconnected", __func__); /* should never happen */
-			return;
-		}
-
+	if (!status) {
 		numbytes = urb->actual_length;
 
 		if (numbytes) {
@@ -389,28 +394,26 @@
 			}
 		} else
 			gig_dbg(DEBUG_INTR, "Received zero block length");
-		resubmit = 1;
 	} else {
 		/* The urb might have been killed. */
-		gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
-			__func__, urb->status);
-		if (urb->status != -ENOENT) { /* not killed */
-			if (!cs->connected) {
-				err("%s: disconnected", __func__); /* should never happen */
-				return;
-			}
-			resubmit = 1;
-		}
+		gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d",
+			__func__, status);
+		if (status == -ENOENT || status == -ESHUTDOWN)
+			/* killed or endpoint shutdown: don't resubmit */
+			return;
 	}
 
-	if (resubmit) {
-		spin_lock_irqsave(&cs->lock, flags);
-		r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV;
+	/* resubmit URB */
+	spin_lock_irqsave(&cs->lock, flags);
+	if (!cs->connected) {
 		spin_unlock_irqrestore(&cs->lock, flags);
-		if (r)
-			dev_err(cs->dev, "error %d when resubmitting urb.\n",
-				-r);
+		err("%s: disconnected", __func__);
+		return;
 	}
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	spin_unlock_irqrestore(&cs->lock, flags);
+	if (r)
+		dev_err(cs->dev, "error %d resubmitting URB\n", -r);
 }
 
 
@@ -418,19 +421,28 @@
 static void gigaset_write_bulk_callback(struct urb *urb)
 {
 	struct cardstate *cs = urb->context;
+	int status = urb->status;
 	unsigned long flags;
 
-	if (urb->status)
+	switch (status) {
+	case 0:			/* normal completion */
+		break;
+	case -ENOENT:		/* killed */
+		gig_dbg(DEBUG_ANY, "%s: killed", __func__);
+		cs->hw.usb->busy = 0;
+		return;
+	default:
 		dev_err(cs->dev, "bulk transfer failed (status %d)\n",
-			-urb->status);
+			-status);
 		/* That's all we can do. Communication problems
 		   are handled by timeouts or network protocols. */
+	}
 
 	spin_lock_irqsave(&cs->lock, flags);
 	if (!cs->connected) {
 		err("%s: not connected", __func__);
 	} else {
-		atomic_set(&cs->hw.usb->busy, 0);
+		cs->hw.usb->busy = 0;
 		tasklet_schedule(&cs->write_tasklet);
 	}
 	spin_unlock_irqrestore(&cs->lock, flags);
@@ -478,14 +490,14 @@
 
 			cb->offset += count;
 			cb->len -= count;
-			atomic_set(&ucs->busy, 1);
+			ucs->busy = 1;
 
 			spin_lock_irqsave(&cs->lock, flags);
 			status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV;
 			spin_unlock_irqrestore(&cs->lock, flags);
 
 			if (status) {
-				atomic_set(&ucs->busy, 0);
+				ucs->busy = 0;
 				err("could not submit urb (error %d)\n",
 				    -status);
 				cb->len = 0; /* skip urb => remove cb+wakeup
@@ -504,7 +516,7 @@
 	struct cmdbuf_t *cb;
 	unsigned long flags;
 
-	gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ?
+	gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
 			     DEBUG_TRANSCMD : DEBUG_LOCKCMD,
 			   "CMD Transmit", len, buf);
 
@@ -641,7 +653,7 @@
 	count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
 	skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
 	skb_pull(bcs->tx_skb, count);
-	atomic_set(&ucs->busy, 1);
+	ucs->busy = 1;
 	gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count);
 
 	spin_lock_irqsave(&cs->lock, flags);
@@ -659,7 +671,7 @@
 
 	if (ret) {
 		err("could not submit urb (error %d)\n", -ret);
-		atomic_set(&ucs->busy, 0);
+		ucs->busy = 0;
 	}
 
 	if (!bcs->tx_skb->len) {
@@ -680,53 +692,44 @@
 {
 	int retval;
 	struct usb_device *udev = interface_to_usbdev(interface);
-	unsigned int ifnum;
-	struct usb_host_interface *hostif;
+	struct usb_host_interface *hostif = interface->cur_altsetting;
 	struct cardstate *cs = NULL;
 	struct usb_cardstate *ucs = NULL;
 	struct usb_endpoint_descriptor *endpoint;
 	int buffer_size;
-	int alt;
 
-	gig_dbg(DEBUG_ANY,
-		"%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)",
-		__func__, le16_to_cpu(udev->descriptor.idVendor),
-		le16_to_cpu(udev->descriptor.idProduct));
-
-	retval = -ENODEV; //FIXME
+	gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__);
 
 	/* See if the device offered us matches what we can accept */
 	if ((le16_to_cpu(udev->descriptor.idVendor)  != USB_M105_VENDOR_ID) ||
-	    (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID))
-		return -ENODEV;
-
-	/* this starts to become ascii art... */
-	hostif = interface->cur_altsetting;
-	alt = hostif->desc.bAlternateSetting;
-	ifnum = hostif->desc.bInterfaceNumber; // FIXME ?
-
-	if (alt != 0 || ifnum != 0) {
-		dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt);
+	    (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) {
+		gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip",
+			le16_to_cpu(udev->descriptor.idVendor),
+			le16_to_cpu(udev->descriptor.idProduct));
 		return -ENODEV;
 	}
-
-	/* Reject application specific intefaces
-	 *
-	 */
+	if (hostif->desc.bInterfaceNumber != 0) {
+		gig_dbg(DEBUG_ANY, "interface %d not for me - skip",
+			hostif->desc.bInterfaceNumber);
+		return -ENODEV;
+	}
+	if (hostif->desc.bAlternateSetting != 0) {
+		dev_notice(&udev->dev, "unsupported altsetting %d - skip",
+			   hostif->desc.bAlternateSetting);
+		return -ENODEV;
+	}
 	if (hostif->desc.bInterfaceClass != 255) {
-		dev_info(&udev->dev,
-		"%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n",
-			 __func__, ifnum, hostif->desc.bInterfaceClass);
+		dev_notice(&udev->dev, "unsupported interface class %d - skip",
+			   hostif->desc.bInterfaceClass);
 		return -ENODEV;
 	}
 
 	dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
-	cs = gigaset_getunassignedcs(driver);
-	if (!cs) {
-		dev_warn(&udev->dev, "no free cardstate\n");
+	/* allocate memory for our device state and intialize it */
+	cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
+	if (!cs)
 		return -ENODEV;
-	}
 	ucs = cs->hw.usb;
 
 	/* save off device structure ptrs for later use */
@@ -759,7 +762,7 @@
 
 	endpoint = &hostif->endpoint[1].desc;
 
-	atomic_set(&ucs->busy, 0);
+	ucs->busy = 0;
 
 	ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!ucs->read_urb) {
@@ -792,7 +795,7 @@
 
 	/* tell common part that the device is ready */
 	if (startmode == SM_LOCKED)
-		atomic_set(&cs->mstate, MS_LOCKED);
+		cs->mstate = MS_LOCKED;
 
 	if (!gigaset_start(cs)) {
 		tasklet_kill(&cs->write_tasklet);
@@ -813,7 +816,7 @@
 	usb_put_dev(ucs->udev);
 	ucs->udev = NULL;
 	ucs->interface = NULL;
-	gigaset_unassign(cs);
+	gigaset_freecs(cs);
 	return retval;
 }
 
@@ -824,6 +827,9 @@
 
 	cs = usb_get_intfdata(interface);
 	ucs = cs->hw.usb;
+
+	dev_info(cs->dev, "disconnecting Gigaset USB adapter\n");
+
 	usb_kill_urb(ucs->read_urb);
 
 	gigaset_stop(cs);
@@ -831,7 +837,7 @@
 	usb_set_intfdata(interface, NULL);
 	tasklet_kill(&cs->write_tasklet);
 
-	usb_kill_urb(ucs->bulk_out_urb);	/* FIXME: only if active? */
+	usb_kill_urb(ucs->bulk_out_urb);
 
 	kfree(ucs->bulk_out_buffer);
 	usb_free_urb(ucs->bulk_out_urb);
@@ -844,7 +850,53 @@
 	ucs->interface = NULL;
 	ucs->udev = NULL;
 	cs->dev = NULL;
-	gigaset_unassign(cs);
+	gigaset_freecs(cs);
+}
+
+/* gigaset_suspend
+ * This function is called before the USB connection is suspended or reset.
+ */
+static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct cardstate *cs = usb_get_intfdata(intf);
+
+	/* stop activity */
+	cs->connected = 0;	/* prevent rescheduling */
+	usb_kill_urb(cs->hw.usb->read_urb);
+	tasklet_kill(&cs->write_tasklet);
+	usb_kill_urb(cs->hw.usb->bulk_out_urb);
+
+	gig_dbg(DEBUG_SUSPEND, "suspend complete");
+	return 0;
+}
+
+/* gigaset_resume
+ * This function is called after the USB connection has been resumed or reset.
+ */
+static int gigaset_resume(struct usb_interface *intf)
+{
+	struct cardstate *cs = usb_get_intfdata(intf);
+	int rc;
+
+	/* resubmit interrupt URB */
+	cs->connected = 1;
+	rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL);
+	if (rc) {
+		dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc);
+		return rc;
+	}
+
+	gig_dbg(DEBUG_SUSPEND, "resume complete");
+	return 0;
+}
+
+/* gigaset_pre_reset
+ * This function is called before the USB connection is reset.
+ */
+static int gigaset_pre_reset(struct usb_interface *intf)
+{
+	/* same as suspend */
+	return gigaset_suspend(intf, PMSG_ON);
 }
 
 static const struct gigaset_ops ops = {
@@ -880,11 +932,6 @@
 				       &ops, THIS_MODULE)) == NULL)
 		goto error;
 
-	/* allocate memory for our device state and intialize it */
-	cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
-	if (!cardstate)
-		goto error;
-
 	/* register this driver with the USB subsystem */
 	result = usb_register(&gigaset_usb_driver);
 	if (result < 0) {
@@ -897,9 +944,7 @@
 	info(DRIVER_DESC);
 	return 0;
 
-error:	if (cardstate)
-		gigaset_freecs(cardstate);
-	cardstate = NULL;
+error:
 	if (driver)
 		gigaset_freedriver(driver);
 	driver = NULL;
@@ -913,11 +958,16 @@
  */
 static void __exit usb_gigaset_exit(void)
 {
+	int i;
+
 	gigaset_blockdriver(driver); /* => probe will fail
 				      * => no gigaset_start any more
 				      */
 
-	gigaset_shutdown(cardstate);
+	/* stop all connected devices */
+	for (i = 0; i < driver->minors; i++)
+		gigaset_shutdown(driver->cs + i);
+
 	/* from now on, no isdn callback should be possible */
 
 	/* deregister this driver with the USB subsystem */
@@ -925,8 +975,6 @@
 	/* this will call the disconnect-callback */
 	/* from now on, no disconnect/probe callback should be running */
 
-	gigaset_freecs(cardstate);
-	cardstate = NULL;
 	gigaset_freedriver(driver);
 	driver = NULL;
 }
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index 0db9cc6..84318ec 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -1188,7 +1188,7 @@
 
     if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
         (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
-      dword rx_dma_magic;
+      dword uninitialized_var(rx_dma_magic);
       if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
         pC->xbuffer[0] = LLI;
         pC->xbuffer[1] = 8;
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c
index ffa2afa..1403a54 100644
--- a/drivers/isdn/hardware/eicon/diva.c
+++ b/drivers/isdn/hardware/eicon/diva.c
@@ -515,12 +515,11 @@
 
 irqreturn_t diva_os_irq_wrapper(int irq, void *context)
 {
-	diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context;
+	diva_os_xdi_adapter_t *a = context;
 	diva_xdi_clear_interrupts_proc_t clear_int_proc;
 
-	if (!a || !a->xdi_adapter.diva_isr_handler) {
+	if (!a || !a->xdi_adapter.diva_isr_handler)
 		return IRQ_NONE;
-	}
 
 	if ((clear_int_proc = a->clear_interrupts_proc)) {
 		(*clear_int_proc) (a);
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
index b9177ca..1ff98e7 100644
--- a/drivers/isdn/hardware/eicon/message.c
+++ b/drivers/isdn/hardware/eicon/message.c
@@ -9027,7 +9027,7 @@
    /* facility is a nested structure */
    /* FTY can be more than once      */
 
-  if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f )
+	if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f))
   {
     add_i[0] = (byte   *)"\x02\x02\x00"; /* use neither b nor d channel */
   }
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 035d158..0f1db1f 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -263,11 +263,7 @@
 		outl(idx, cs->hw.avm.cfg_reg + 4);
 		while (cnt < count) {
 #ifdef __powerpc__
-#ifdef CONFIG_APUS
-			*ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
-#else
 			*ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
-#endif /* CONFIG_APUS */
 #else
 			*ptr++ = inl(cs->hw.avm.isac);
 #endif /* __powerpc__ */
@@ -328,11 +324,7 @@
 	if (cs->subtyp == AVM_FRITZ_PCI) {
 		while (cnt<count) {
 #ifdef __powerpc__
-#ifdef CONFIG_APUS
-			out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
-#else
 			out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
-#endif /* CONFIG_APUS */
 #else
 			outl(*ptr++, cs->hw.avm.isac);
 #endif /* __powerpc__ */
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 9cb6e50..133eb18 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1917,7 +1917,6 @@
 		info->owner = THIS_MODULE;
 #endif
 		spin_lock_init(&info->readlock);
-		init_MUTEX(&info->write_sem);
 		sprintf(info->last_cause, "0000");
 		sprintf(info->last_num, "none");
 		info->last_dir = 0;
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c
index a943d07..f93de4a 100644
--- a/drivers/isdn/i4l/isdn_ttyfax.c
+++ b/drivers/isdn/i4l/isdn_ttyfax.c
@@ -834,7 +834,7 @@
 		char *rp = &f->resolution;
 
 		p[0] += 2;
-		if (!info->faxonline & 1)	/* not outgoing connection */
+		if (!(info->faxonline & 1))	/* not outgoing connection */
 			PARSE_ERROR1;
 
 		for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c
index 82d957b..bf7997a 100644
--- a/drivers/isdn/icn/icn.c
+++ b/drivers/isdn/icn/icn.c
@@ -1302,7 +1302,7 @@
 			}
 			break;
 		case ISDN_CMD_DIAL:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (card->leased)
 				break;
@@ -1328,7 +1328,7 @@
 			}
 			break;
 		case ISDN_CMD_ACCEPTD:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (c->arg < ICN_BCH) {
 				a = c->arg + 1;
@@ -1348,7 +1348,7 @@
 			}
 			break;
 		case ISDN_CMD_ACCEPTB:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (c->arg < ICN_BCH) {
 				a = c->arg + 1;
@@ -1366,7 +1366,7 @@
 			}
 			break;
 		case ISDN_CMD_HANGUP:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (c->arg < ICN_BCH) {
 				a = c->arg + 1;
@@ -1375,7 +1375,7 @@
 			}
 			break;
 		case ISDN_CMD_SETEAZ:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (card->leased)
 				break;
@@ -1391,7 +1391,7 @@
 			}
 			break;
 		case ISDN_CMD_CLREAZ:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if (card->leased)
 				break;
@@ -1405,7 +1405,7 @@
 			}
 			break;
 		case ISDN_CMD_SETL2:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			if ((c->arg & 255) < ICN_BCH) {
 				a = c->arg;
@@ -1424,7 +1424,7 @@
 			}
 			break;
 		case ISDN_CMD_SETL3:
-			if (!card->flags & ICN_FLAGS_RUNNING)
+			if (!(card->flags & ICN_FLAGS_RUNNING))
 				return -ENODEV;
 			return 0;
 		default:
@@ -1471,7 +1471,7 @@
 	icn_card *card = icn_findcard(id);
 
 	if (card) {
-		if (!card->flags & ICN_FLAGS_RUNNING)
+		if (!(card->flags & ICN_FLAGS_RUNNING))
 			return -ENODEV;
 		return (icn_writecmd(buf, len, 1, card));
 	}
@@ -1486,7 +1486,7 @@
 	icn_card *card = icn_findcard(id);
 
 	if (card) {
-		if (!card->flags & ICN_FLAGS_RUNNING)
+		if (!(card->flags & ICN_FLAGS_RUNNING))
 			return -ENODEV;
 		return (icn_readstatus(buf, len, card));
 	}
@@ -1501,7 +1501,7 @@
 	icn_card *card = icn_findcard(id);
 
 	if (card) {
-		if (!card->flags & ICN_FLAGS_RUNNING)
+		if (!(card->flags & ICN_FLAGS_RUNNING))
 			return -ENODEV;
 		return (icn_sendbuf(channel, ack, skb, card));
 	}
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
index bb92e3c..655ef9a 100644
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ b/drivers/isdn/isdnloop/isdnloop.c
@@ -1184,7 +1184,7 @@
 			}
 			break;
 		case ISDN_CMD_DIAL:
-			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 				return -ENODEV;
 			if (card->leased)
 				break;
@@ -1210,7 +1210,7 @@
 			}
 			break;
 		case ISDN_CMD_ACCEPTD:
-			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 				return -ENODEV;
 			if (c->arg < ISDNLOOP_BCH) {
 				a = c->arg + 1;
@@ -1238,7 +1238,7 @@
 			}
 			break;
 		case ISDN_CMD_ACCEPTB:
-			if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+			if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 				return -ENODEV;
 			if (c->arg < ISDNLOOP_BCH) {
 				a = c->arg + 1;
@@ -1264,7 +1264,7 @@
 				i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
 				break;
 		case ISDN_CMD_HANGUP:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+				if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 					return -ENODEV;
 				if (c->arg < ISDNLOOP_BCH) {
 					a = c->arg + 1;
@@ -1273,7 +1273,7 @@
 				}
 				break;
 		case ISDN_CMD_SETEAZ:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+				if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 					return -ENODEV;
 				if (card->leased)
 					break;
@@ -1303,7 +1303,7 @@
 				}
 				break;
 		case ISDN_CMD_SETL2:
-				if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+				if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 					return -ENODEV;
 				if ((c->arg & 255) < ISDNLOOP_BCH) {
 					a = c->arg;
@@ -1395,7 +1395,7 @@
 	isdnloop_card *card = isdnloop_findcard(id);
 
 	if (card) {
-		if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 			return -ENODEV;
 		return (isdnloop_readstatus(buf, len, card));
 	}
@@ -1410,7 +1410,7 @@
 	isdnloop_card *card = isdnloop_findcard(id);
 
 	if (card) {
-		if (!card->flags & ISDNLOOP_FLAGS_RUNNING)
+		if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
 			return -ENODEV;
 		/* ack request stored in skb scratch area */
 		*(skb->head) = ack;
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 1b1ef31..a0585fb 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -237,7 +237,7 @@
 	if (!page)
 		return ERR_PTR(-ENOMEM);
 
-	ITERATE_RDEV(mddev, rdev, tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (! test_bit(In_sync, &rdev->flags)
 		    || test_bit(Faulty, &rdev->flags))
 			continue;
@@ -261,7 +261,7 @@
 	struct list_head *tmp;
 	mddev_t *mddev = bitmap->mddev;
 
-	ITERATE_RDEV(mddev, rdev, tmp)
+	rdev_for_each(rdev, tmp, mddev)
 		if (test_bit(In_sync, &rdev->flags)
 		    && !test_bit(Faulty, &rdev->flags)) {
 			int size = PAGE_SIZE;
@@ -1348,16 +1348,40 @@
 	 */
 	sector_t sector = 0;
 	int blocks;
-	if (!bitmap) return;
+	if (!bitmap)
+		return;
 	while (sector < bitmap->mddev->resync_max_sectors) {
 		bitmap_end_sync(bitmap, sector, &blocks, 0);
-/*
-		if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
-					 (unsigned long long)sector, blocks);
-*/		sector += blocks;
+		sector += blocks;
 	}
 }
 
+void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector)
+{
+	sector_t s = 0;
+	int blocks;
+
+	if (!bitmap)
+		return;
+	if (sector == 0) {
+		bitmap->last_end_sync = jiffies;
+		return;
+	}
+	if (time_before(jiffies, (bitmap->last_end_sync
+				  + bitmap->daemon_sleep * HZ)))
+		return;
+	wait_event(bitmap->mddev->recovery_wait,
+		   atomic_read(&bitmap->mddev->recovery_active) == 0);
+
+	sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1);
+	s = 0;
+	while (s < sector && s < bitmap->mddev->resync_max_sectors) {
+		bitmap_end_sync(bitmap, s, &blocks, 0);
+		s += blocks;
+	}
+	bitmap->last_end_sync = jiffies;
+}
+
 static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
 {
 	/* For each chunk covered by any of these sectors, set the
@@ -1565,3 +1589,4 @@
 EXPORT_SYMBOL(bitmap_end_sync);
 EXPORT_SYMBOL(bitmap_unplug);
 EXPORT_SYMBOL(bitmap_close_sync);
+EXPORT_SYMBOL(bitmap_cond_end_sync);
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c
index cf2ddce3..d107ddc 100644
--- a/drivers/md/faulty.c
+++ b/drivers/md/faulty.c
@@ -294,7 +294,7 @@
 	}
 	conf->nfaults = 0;
 
-	ITERATE_RDEV(mddev, rdev, tmp)
+	rdev_for_each(rdev, tmp, mddev)
 		conf->rdev = rdev;
 
 	mddev->array_size = mddev->size;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 3dac1cf..0b85117 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -122,7 +122,7 @@
 	cnt = 0;
 	conf->array_size = 0;
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		int j = rdev->raid_disk;
 		dev_info_t *disk = conf->disks + j;
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c28a120..5fc326d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -195,7 +195,7 @@
  * Any code which breaks out of this loop while own
  * a reference to the current mddev and must mddev_put it.
  */
-#define ITERATE_MDDEV(mddev,tmp)					\
+#define for_each_mddev(mddev,tmp)					\
 									\
 	for (({ spin_lock(&all_mddevs_lock); 				\
 		tmp = all_mddevs.next;					\
@@ -275,6 +275,7 @@
 	spin_lock_init(&new->write_lock);
 	init_waitqueue_head(&new->sb_wait);
 	new->reshape_position = MaxSector;
+	new->resync_max = MaxSector;
 
 	new->queue = blk_alloc_queue(GFP_KERNEL);
 	if (!new->queue) {
@@ -310,7 +311,7 @@
 	mdk_rdev_t * rdev;
 	struct list_head *tmp;
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (rdev->desc_nr == nr)
 			return rdev;
 	}
@@ -322,7 +323,7 @@
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (rdev->bdev->bd_dev == dev)
 			return rdev;
 	}
@@ -773,12 +774,16 @@
 	__u64 ev1 = md_event(sb);
 
 	rdev->raid_disk = -1;
-	rdev->flags = 0;
+	clear_bit(Faulty, &rdev->flags);
+	clear_bit(In_sync, &rdev->flags);
+	clear_bit(WriteMostly, &rdev->flags);
+	clear_bit(BarriersNotsupp, &rdev->flags);
+
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 0;
 		mddev->minor_version = sb->minor_version;
 		mddev->patch_version = sb->patch_version;
-		mddev->persistent = ! sb->not_persistent;
+		mddev->external = 0;
 		mddev->chunk_size = sb->chunk_size;
 		mddev->ctime = sb->ctime;
 		mddev->utime = sb->utime;
@@ -904,7 +909,7 @@
 	sb->size  = mddev->size;
 	sb->raid_disks = mddev->raid_disks;
 	sb->md_minor = mddev->md_minor;
-	sb->not_persistent = !mddev->persistent;
+	sb->not_persistent = 0;
 	sb->utime = mddev->utime;
 	sb->state = 0;
 	sb->events_hi = (mddev->events>>32);
@@ -938,7 +943,7 @@
 		sb->state |= (1<<MD_SB_BITMAP_PRESENT);
 
 	sb->disks[0].state = (1<<MD_DISK_REMOVED);
-	ITERATE_RDEV(mddev,rdev2,tmp) {
+	rdev_for_each(rdev2, tmp, mddev) {
 		mdp_disk_t *d;
 		int desc_nr;
 		if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags)
@@ -1153,11 +1158,15 @@
 	__u64 ev1 = le64_to_cpu(sb->events);
 
 	rdev->raid_disk = -1;
-	rdev->flags = 0;
+	clear_bit(Faulty, &rdev->flags);
+	clear_bit(In_sync, &rdev->flags);
+	clear_bit(WriteMostly, &rdev->flags);
+	clear_bit(BarriersNotsupp, &rdev->flags);
+
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 1;
 		mddev->patch_version = 0;
-		mddev->persistent = 1;
+		mddev->external = 0;
 		mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
 		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
 		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
@@ -1286,7 +1295,7 @@
 	}
 
 	max_dev = 0;
-	ITERATE_RDEV(mddev,rdev2,tmp)
+	rdev_for_each(rdev2, tmp, mddev)
 		if (rdev2->desc_nr+1 > max_dev)
 			max_dev = rdev2->desc_nr+1;
 
@@ -1295,7 +1304,7 @@
 	for (i=0; i<max_dev;i++)
 		sb->dev_roles[i] = cpu_to_le16(0xfffe);
 	
-	ITERATE_RDEV(mddev,rdev2,tmp) {
+	rdev_for_each(rdev2, tmp, mddev) {
 		i = rdev2->desc_nr;
 		if (test_bit(Faulty, &rdev2->flags))
 			sb->dev_roles[i] = cpu_to_le16(0xfffe);
@@ -1333,8 +1342,8 @@
 	struct list_head *tmp, *tmp2;
 	mdk_rdev_t *rdev, *rdev2;
 
-	ITERATE_RDEV(mddev1,rdev,tmp)
-		ITERATE_RDEV(mddev2, rdev2, tmp2)
+	rdev_for_each(rdev, tmp, mddev1)
+		rdev_for_each(rdev2, tmp2, mddev2)
 			if (rdev->bdev->bd_contains ==
 			    rdev2->bdev->bd_contains)
 				return 1;
@@ -1401,7 +1410,7 @@
 		goto fail;
 	}
 	list_add(&rdev->same_set, &mddev->disks);
-	bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk);
+	bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
 	return 0;
 
  fail:
@@ -1410,10 +1419,11 @@
 	return err;
 }
 
-static void delayed_delete(struct work_struct *ws)
+static void md_delayed_delete(struct work_struct *ws)
 {
 	mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work);
 	kobject_del(&rdev->kobj);
+	kobject_put(&rdev->kobj);
 }
 
 static void unbind_rdev_from_array(mdk_rdev_t * rdev)
@@ -1432,7 +1442,8 @@
 	/* We need to delay this, otherwise we can deadlock when
 	 * writing to 'remove' to "dev/state"
 	 */
-	INIT_WORK(&rdev->del_work, delayed_delete);
+	INIT_WORK(&rdev->del_work, md_delayed_delete);
+	kobject_get(&rdev->kobj);
 	schedule_work(&rdev->del_work);
 }
 
@@ -1441,7 +1452,7 @@
  * otherwise reused by a RAID array (or any other kernel
  * subsystem), by bd_claiming the device.
  */
-static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
+static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
 {
 	int err = 0;
 	struct block_device *bdev;
@@ -1453,13 +1464,15 @@
 			__bdevname(dev, b));
 		return PTR_ERR(bdev);
 	}
-	err = bd_claim(bdev, rdev);
+	err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);
 	if (err) {
 		printk(KERN_ERR "md: could not bd_claim %s.\n",
 			bdevname(bdev, b));
 		blkdev_put(bdev);
 		return err;
 	}
+	if (!shared)
+		set_bit(AllReserved, &rdev->flags);
 	rdev->bdev = bdev;
 	return err;
 }
@@ -1503,7 +1516,7 @@
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (!rdev->mddev) {
 			MD_BUG();
 			continue;
@@ -1581,17 +1594,17 @@
 	printk("md:	**********************************\n");
 	printk("md:	* <COMPLETE RAID STATE PRINTOUT> *\n");
 	printk("md:	**********************************\n");
-	ITERATE_MDDEV(mddev,tmp) {
+	for_each_mddev(mddev, tmp) {
 
 		if (mddev->bitmap)
 			bitmap_print_sb(mddev->bitmap);
 		else
 			printk("%s: ", mdname(mddev));
-		ITERATE_RDEV(mddev,rdev,tmp2)
+		rdev_for_each(rdev, tmp2, mddev)
 			printk("<%s>", bdevname(rdev->bdev,b));
 		printk("\n");
 
-		ITERATE_RDEV(mddev,rdev,tmp2)
+		rdev_for_each(rdev, tmp2, mddev)
 			print_rdev(rdev);
 	}
 	printk("md:	**********************************\n");
@@ -1610,7 +1623,7 @@
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (rdev->sb_events == mddev->events ||
 		    (nospares &&
 		     rdev->raid_disk < 0 &&
@@ -1696,18 +1709,20 @@
 		MD_BUG();
 		mddev->events --;
 	}
-	sync_sbs(mddev, nospares);
 
 	/*
 	 * do not write anything to disk if using
 	 * nonpersistent superblocks
 	 */
 	if (!mddev->persistent) {
-		clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+		if (!mddev->external)
+			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+
 		spin_unlock_irq(&mddev->write_lock);
 		wake_up(&mddev->sb_wait);
 		return;
 	}
+	sync_sbs(mddev, nospares);
 	spin_unlock_irq(&mddev->write_lock);
 
 	dprintk(KERN_INFO 
@@ -1715,7 +1730,7 @@
 		mdname(mddev),mddev->in_sync);
 
 	bitmap_update_sb(mddev->bitmap);
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		char b[BDEVNAME_SIZE];
 		dprintk(KERN_INFO "md: ");
 		if (rdev->sb_loaded != 1)
@@ -1785,7 +1800,7 @@
 state_show(mdk_rdev_t *rdev, char *page)
 {
 	char *sep = "";
-	int len=0;
+	size_t len = 0;
 
 	if (test_bit(Faulty, &rdev->flags)) {
 		len+= sprintf(page+len, "%sfaulty",sep);
@@ -1887,20 +1902,45 @@
 slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 {
 	char *e;
+	int err;
+	char nm[20];
 	int slot = simple_strtoul(buf, &e, 10);
 	if (strncmp(buf, "none", 4)==0)
 		slot = -1;
 	else if (e==buf || (*e && *e!= '\n'))
 		return -EINVAL;
-	if (rdev->mddev->pers)
-		/* Cannot set slot in active array (yet) */
-		return -EBUSY;
-	if (slot >= rdev->mddev->raid_disks)
-		return -ENOSPC;
-	rdev->raid_disk = slot;
-	/* assume it is working */
-	rdev->flags = 0;
-	set_bit(In_sync, &rdev->flags);
+	if (rdev->mddev->pers) {
+		/* Setting 'slot' on an active array requires also
+		 * updating the 'rd%d' link, and communicating
+		 * with the personality with ->hot_*_disk.
+		 * For now we only support removing
+		 * failed/spare devices.  This normally happens automatically,
+		 * but not when the metadata is externally managed.
+		 */
+		if (slot != -1)
+			return -EBUSY;
+		if (rdev->raid_disk == -1)
+			return -EEXIST;
+		/* personality does all needed checks */
+		if (rdev->mddev->pers->hot_add_disk == NULL)
+			return -EINVAL;
+		err = rdev->mddev->pers->
+			hot_remove_disk(rdev->mddev, rdev->raid_disk);
+		if (err)
+			return err;
+		sprintf(nm, "rd%d", rdev->raid_disk);
+		sysfs_remove_link(&rdev->mddev->kobj, nm);
+		set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery);
+		md_wakeup_thread(rdev->mddev->thread);
+	} else {
+		if (slot >= rdev->mddev->raid_disks)
+			return -ENOSPC;
+		rdev->raid_disk = slot;
+		/* assume it is working */
+		clear_bit(Faulty, &rdev->flags);
+		clear_bit(WriteMostly, &rdev->flags);
+		set_bit(In_sync, &rdev->flags);
+	}
 	return len;
 }
 
@@ -1923,6 +1963,10 @@
 		return -EINVAL;
 	if (rdev->mddev->pers)
 		return -EBUSY;
+	if (rdev->size && rdev->mddev->external)
+		/* Must set offset before size, so overlap checks
+		 * can be sane */
+		return -EBUSY;
 	rdev->data_offset = offset;
 	return len;
 }
@@ -1936,16 +1980,69 @@
 	return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
 }
 
+static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
+{
+	/* check if two start/length pairs overlap */
+	if (s1+l1 <= s2)
+		return 0;
+	if (s2+l2 <= s1)
+		return 0;
+	return 1;
+}
+
 static ssize_t
 rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len)
 {
 	char *e;
 	unsigned long long size = simple_strtoull(buf, &e, 10);
+	unsigned long long oldsize = rdev->size;
 	if (e==buf || (*e && *e != '\n'))
 		return -EINVAL;
 	if (rdev->mddev->pers)
 		return -EBUSY;
 	rdev->size = size;
+	if (size > oldsize && rdev->mddev->external) {
+		/* need to check that all other rdevs with the same ->bdev
+		 * do not overlap.  We need to unlock the mddev to avoid
+		 * a deadlock.  We have already changed rdev->size, and if
+		 * we have to change it back, we will have the lock again.
+		 */
+		mddev_t *mddev;
+		int overlap = 0;
+		struct list_head *tmp, *tmp2;
+
+		mddev_unlock(rdev->mddev);
+		for_each_mddev(mddev, tmp) {
+			mdk_rdev_t *rdev2;
+
+			mddev_lock(mddev);
+			rdev_for_each(rdev2, tmp2, mddev)
+				if (test_bit(AllReserved, &rdev2->flags) ||
+				    (rdev->bdev == rdev2->bdev &&
+				     rdev != rdev2 &&
+				     overlaps(rdev->data_offset, rdev->size,
+					    rdev2->data_offset, rdev2->size))) {
+					overlap = 1;
+					break;
+				}
+			mddev_unlock(mddev);
+			if (overlap) {
+				mddev_put(mddev);
+				break;
+			}
+		}
+		mddev_lock(rdev->mddev);
+		if (overlap) {
+			/* Someone else could have slipped in a size
+			 * change here, but doing so is just silly.
+			 * We put oldsize back because we *know* it is
+			 * safe, and trust userspace not to race with
+			 * itself
+			 */
+			rdev->size = oldsize;
+			return -EBUSY;
+		}
+	}
 	if (size < rdev->mddev->size || rdev->mddev->size == 0)
 		rdev->mddev->size = size;
 	return len;
@@ -1980,12 +2077,18 @@
 {
 	struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr);
 	mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj);
+	int rv;
 
 	if (!entry->store)
 		return -EIO;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
-	return entry->store(rdev, page, length);
+	rv = mddev_lock(rdev->mddev);
+	if (!rv) {
+		rv = entry->store(rdev, page, length);
+		mddev_unlock(rdev->mddev);
+	}
+	return rv;
 }
 
 static void rdev_free(struct kobject *ko)
@@ -2029,7 +2132,7 @@
 	if ((err = alloc_disk_sb(rdev)))
 		goto abort_free;
 
-	err = lock_rdev(rdev, newdev);
+	err = lock_rdev(rdev, newdev, super_format == -2);
 	if (err)
 		goto abort_free;
 
@@ -2099,7 +2202,7 @@
 	char b[BDEVNAME_SIZE];
 
 	freshest = NULL;
-	ITERATE_RDEV(mddev,rdev,tmp)
+	rdev_for_each(rdev, tmp, mddev)
 		switch (super_types[mddev->major_version].
 			load_super(rdev, freshest, mddev->minor_version)) {
 		case 1:
@@ -2120,7 +2223,7 @@
 		validate_super(mddev, freshest);
 
 	i = 0;
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (rdev != freshest)
 			if (super_types[mddev->major_version].
 			    validate_super(mddev, rdev)) {
@@ -2215,7 +2318,7 @@
 static ssize_t
 level_store(mddev_t *mddev, const char *buf, size_t len)
 {
-	int rv = len;
+	ssize_t rv = len;
 	if (mddev->pers)
 		return -EBUSY;
 	if (len == 0)
@@ -2425,6 +2528,8 @@
 		case 0:
 			if (mddev->in_sync)
 				st = clean;
+			else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags))
+				st = write_pending;
 			else if (mddev->safemode)
 				st = active_idle;
 			else
@@ -2455,11 +2560,9 @@
 		break;
 	case clear:
 		/* stopping an active array */
-		if (mddev->pers) {
-			if (atomic_read(&mddev->active) > 1)
-				return -EBUSY;
-			err = do_md_stop(mddev, 0);
-		}
+		if (atomic_read(&mddev->active) > 1)
+			return -EBUSY;
+		err = do_md_stop(mddev, 0);
 		break;
 	case inactive:
 		/* stopping an active array */
@@ -2467,7 +2570,8 @@
 			if (atomic_read(&mddev->active) > 1)
 				return -EBUSY;
 			err = do_md_stop(mddev, 2);
-		}
+		} else
+			err = 0; /* already inactive */
 		break;
 	case suspended:
 		break; /* not supported yet */
@@ -2495,9 +2599,15 @@
 			restart_array(mddev);
 			spin_lock_irq(&mddev->write_lock);
 			if (atomic_read(&mddev->writes_pending) == 0) {
-				mddev->in_sync = 1;
-				set_bit(MD_CHANGE_CLEAN, &mddev->flags);
-			}
+				if (mddev->in_sync == 0) {
+					mddev->in_sync = 1;
+					if (mddev->persistent)
+						set_bit(MD_CHANGE_CLEAN,
+							&mddev->flags);
+				}
+				err = 0;
+			} else
+				err = -EBUSY;
 			spin_unlock_irq(&mddev->write_lock);
 		} else {
 			mddev->ro = 0;
@@ -2508,7 +2618,8 @@
 	case active:
 		if (mddev->pers) {
 			restart_array(mddev);
-			clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
+			if (mddev->external)
+				clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
 			wake_up(&mddev->sb_wait);
 			err = 0;
 		} else {
@@ -2574,7 +2685,9 @@
 			if (err < 0)
 				goto out;
 		}
-	} else
+	} else if (mddev->external)
+		rdev = md_import_device(dev, -2, -1);
+	else
 		rdev = md_import_device(dev, -1, -1);
 
 	if (IS_ERR(rdev))
@@ -2659,7 +2772,9 @@
 
 
 /* Metdata version.
- * This is either 'none' for arrays with externally managed metadata,
+ * This is one of
+ *   'none' for arrays with no metadata (good luck...)
+ *   'external' for arrays with externally managed metadata,
  * or N.M for internally known formats
  */
 static ssize_t
@@ -2668,6 +2783,8 @@
 	if (mddev->persistent)
 		return sprintf(page, "%d.%d\n",
 			       mddev->major_version, mddev->minor_version);
+	else if (mddev->external)
+		return sprintf(page, "external:%s\n", mddev->metadata_type);
 	else
 		return sprintf(page, "none\n");
 }
@@ -2682,6 +2799,21 @@
 
 	if (cmd_match(buf, "none")) {
 		mddev->persistent = 0;
+		mddev->external = 0;
+		mddev->major_version = 0;
+		mddev->minor_version = 90;
+		return len;
+	}
+	if (strncmp(buf, "external:", 9) == 0) {
+		size_t namelen = len-9;
+		if (namelen >= sizeof(mddev->metadata_type))
+			namelen = sizeof(mddev->metadata_type)-1;
+		strncpy(mddev->metadata_type, buf+9, namelen);
+		mddev->metadata_type[namelen] = 0;
+		if (namelen && mddev->metadata_type[namelen-1] == '\n')
+			mddev->metadata_type[--namelen] = 0;
+		mddev->persistent = 0;
+		mddev->external = 1;
 		mddev->major_version = 0;
 		mddev->minor_version = 90;
 		return len;
@@ -2698,6 +2830,7 @@
 	mddev->major_version = major;
 	mddev->minor_version = minor;
 	mddev->persistent = 1;
+	mddev->external = 0;
 	return len;
 }
 
@@ -2865,6 +2998,43 @@
 static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
 
 static ssize_t
+max_sync_show(mddev_t *mddev, char *page)
+{
+	if (mddev->resync_max == MaxSector)
+		return sprintf(page, "max\n");
+	else
+		return sprintf(page, "%llu\n",
+			       (unsigned long long)mddev->resync_max);
+}
+static ssize_t
+max_sync_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	if (strncmp(buf, "max", 3) == 0)
+		mddev->resync_max = MaxSector;
+	else {
+		char *ep;
+		unsigned long long max = simple_strtoull(buf, &ep, 10);
+		if (ep == buf || (*ep != 0 && *ep != '\n'))
+			return -EINVAL;
+		if (max < mddev->resync_max &&
+		    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+			return -EBUSY;
+
+		/* Must be a multiple of chunk_size */
+		if (mddev->chunk_size) {
+			if (max & (sector_t)((mddev->chunk_size>>9)-1))
+				return -EINVAL;
+		}
+		mddev->resync_max = max;
+	}
+	wake_up(&mddev->recovery_wait);
+	return len;
+}
+
+static struct md_sysfs_entry md_max_sync =
+__ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
+
+static ssize_t
 suspend_lo_show(mddev_t *mddev, char *page)
 {
 	return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
@@ -2974,6 +3144,7 @@
 	&md_sync_max.attr,
 	&md_sync_speed.attr,
 	&md_sync_completed.attr,
+	&md_max_sync.attr,
 	&md_suspend_lo.attr,
 	&md_suspend_hi.attr,
 	&md_bitmap.attr,
@@ -3118,8 +3289,11 @@
 	/*
 	 * Analyze all RAID superblock(s)
 	 */
-	if (!mddev->raid_disks)
+	if (!mddev->raid_disks) {
+		if (!mddev->persistent)
+			return -EINVAL;
 		analyze_sbs(mddev);
+	}
 
 	chunk_size = mddev->chunk_size;
 
@@ -3143,7 +3317,7 @@
 		}
 
 		/* devices must have minimum size of one chunk */
-		ITERATE_RDEV(mddev,rdev,tmp) {
+		rdev_for_each(rdev, tmp, mddev) {
 			if (test_bit(Faulty, &rdev->flags))
 				continue;
 			if (rdev->size < chunk_size / 1024) {
@@ -3170,7 +3344,7 @@
 	 * the only valid external interface is through the md
 	 * device.
 	 */
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		if (test_bit(Faulty, &rdev->flags))
 			continue;
 		sync_blockdev(rdev->bdev);
@@ -3236,8 +3410,8 @@
 		mdk_rdev_t *rdev2;
 		struct list_head *tmp2;
 		int warned = 0;
-		ITERATE_RDEV(mddev, rdev, tmp) {
-			ITERATE_RDEV(mddev, rdev2, tmp2) {
+		rdev_for_each(rdev, tmp, mddev) {
+			rdev_for_each(rdev2, tmp2, mddev) {
 				if (rdev < rdev2 &&
 				    rdev->bdev->bd_contains ==
 				    rdev2->bdev->bd_contains) {
@@ -3297,7 +3471,7 @@
 	mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
 	mddev->in_sync = 1;
 
-	ITERATE_RDEV(mddev,rdev,tmp)
+	rdev_for_each(rdev, tmp, mddev)
 		if (rdev->raid_disk >= 0) {
 			char nm[20];
 			sprintf(nm, "rd%d", rdev->raid_disk);
@@ -3330,7 +3504,7 @@
 	if (mddev->degraded && !mddev->sync_thread) {
 		struct list_head *rtmp;
 		int spares = 0;
-		ITERATE_RDEV(mddev,rdev,rtmp)
+		rdev_for_each(rdev, rtmp, mddev)
 			if (rdev->raid_disk >= 0 &&
 			    !test_bit(In_sync, &rdev->flags) &&
 			    !test_bit(Faulty, &rdev->flags))
@@ -3507,14 +3681,14 @@
 		}
 		mddev->bitmap_offset = 0;
 
-		ITERATE_RDEV(mddev,rdev,tmp)
+		rdev_for_each(rdev, tmp, mddev)
 			if (rdev->raid_disk >= 0) {
 				char nm[20];
 				sprintf(nm, "rd%d", rdev->raid_disk);
 				sysfs_remove_link(&mddev->kobj, nm);
 			}
 
-		/* make sure all delayed_delete calls have finished */
+		/* make sure all md_delayed_delete calls have finished */
 		flush_scheduled_work();
 
 		export_array(mddev);
@@ -3523,7 +3697,10 @@
 		mddev->size = 0;
 		mddev->raid_disks = 0;
 		mddev->recovery_cp = 0;
+		mddev->resync_max = MaxSector;
 		mddev->reshape_position = MaxSector;
+		mddev->external = 0;
+		mddev->persistent = 0;
 
 	} else if (mddev->pers)
 		printk(KERN_INFO "md: %s switched to read-only mode.\n",
@@ -3546,7 +3723,7 @@
 
 	printk(KERN_INFO "md: running: ");
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		char b[BDEVNAME_SIZE];
 		printk("<%s>", bdevname(rdev->bdev,b));
 	}
@@ -3589,7 +3766,7 @@
 		printk(KERN_INFO "md: considering %s ...\n",
 			bdevname(rdev0->bdev,b));
 		INIT_LIST_HEAD(&candidates);
-		ITERATE_RDEV_PENDING(rdev,tmp)
+		rdev_for_each_list(rdev, tmp, pending_raid_disks)
 			if (super_90_load(rdev, rdev0, 0) >= 0) {
 				printk(KERN_INFO "md:  adding %s ...\n",
 					bdevname(rdev->bdev,b));
@@ -3632,7 +3809,8 @@
 			mddev_unlock(mddev);
 		} else {
 			printk(KERN_INFO "md: created %s\n", mdname(mddev));
-			ITERATE_RDEV_GENERIC(candidates,rdev,tmp) {
+			mddev->persistent = 1;
+			rdev_for_each_list(rdev, tmp, candidates) {
 				list_del_init(&rdev->same_set);
 				if (bind_rdev_to_array(rdev, mddev))
 					export_rdev(rdev);
@@ -3643,7 +3821,7 @@
 		/* on success, candidates will be empty, on error
 		 * it won't...
 		 */
-		ITERATE_RDEV_GENERIC(candidates,rdev,tmp)
+		rdev_for_each_list(rdev, tmp, candidates)
 			export_rdev(rdev);
 		mddev_put(mddev);
 	}
@@ -3673,7 +3851,7 @@
 	struct list_head *tmp;
 
 	nr=working=active=failed=spare=0;
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		nr++;
 		if (test_bit(Faulty, &rdev->flags))
 			failed++;
@@ -3919,8 +4097,6 @@
 		else
 			rdev->raid_disk = -1;
 
-		rdev->flags = 0;
-
 		if (rdev->raid_disk < mddev->raid_disks)
 			if (info->state & (1<<MD_DISK_SYNC))
 				set_bit(In_sync, &rdev->flags);
@@ -4165,13 +4341,15 @@
 	else
 		mddev->recovery_cp = 0;
 	mddev->persistent    = ! info->not_persistent;
+	mddev->external	     = 0;
 
 	mddev->layout        = info->layout;
 	mddev->chunk_size    = info->chunk_size;
 
 	mddev->max_disks     = MD_SB_DISKS;
 
-	mddev->flags         = 0;
+	if (mddev->persistent)
+		mddev->flags         = 0;
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
 	mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
@@ -4213,7 +4391,7 @@
 	 */
 	if (mddev->sync_thread)
 		return -EBUSY;
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		sector_t avail;
 		avail = rdev->size * 2;
 
@@ -4471,9 +4649,10 @@
 	 */
 	/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
 	 * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */
-	if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
-			&& cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE
-	    		&& cmd != GET_BITMAP_FILE) {
+	if ((!mddev->raid_disks && !mddev->external)
+	    && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
+	    && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE
+	    && cmd != GET_BITMAP_FILE) {
 		err = -ENODEV;
 		goto abort_unlock;
 	}
@@ -4757,7 +4936,7 @@
 
 	seq_printf(seq, "unused devices: ");
 
-	ITERATE_RDEV_PENDING(rdev,tmp) {
+	rdev_for_each_list(rdev, tmp, pending_raid_disks) {
 		char b[BDEVNAME_SIZE];
 		i++;
 		seq_printf(seq, "%s ",
@@ -4953,7 +5132,7 @@
 		}
 
 		size = 0;
-		ITERATE_RDEV(mddev,rdev,tmp2) {
+		rdev_for_each(rdev, tmp2, mddev) {
 			char b[BDEVNAME_SIZE];
 			seq_printf(seq, " %s[%d]",
 				bdevname(rdev->bdev,b), rdev->desc_nr);
@@ -4982,7 +5161,10 @@
 					   mddev->major_version,
 					   mddev->minor_version);
 			}
-		} else
+		} else if (mddev->external)
+			seq_printf(seq, " super external:%s",
+				   mddev->metadata_type);
+		else
 			seq_printf(seq, " super non-persistent");
 
 		if (mddev->pers) {
@@ -5106,7 +5288,7 @@
 	long curr_events;
 
 	idle = 1;
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
 		curr_events = disk_stat_read(disk, sectors[0]) + 
 				disk_stat_read(disk, sectors[1]) - 
@@ -5283,7 +5465,7 @@
 			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 			goto skip;
 		}
-		ITERATE_MDDEV(mddev2,tmp) {
+		for_each_mddev(mddev2, tmp) {
 			if (mddev2 == mddev)
 				continue;
 			if (mddev2->curr_resync && 
@@ -5333,7 +5515,7 @@
 		/* recovery follows the physical size of devices */
 		max_sectors = mddev->size << 1;
 		j = MaxSector;
-		ITERATE_RDEV(mddev,rdev,rtmp)
+		rdev_for_each(rdev, rtmp, mddev)
 			if (rdev->raid_disk >= 0 &&
 			    !test_bit(Faulty, &rdev->flags) &&
 			    !test_bit(In_sync, &rdev->flags) &&
@@ -5381,8 +5563,16 @@
 		sector_t sectors;
 
 		skipped = 0;
+		if (j >= mddev->resync_max) {
+			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+			wait_event(mddev->recovery_wait,
+				   mddev->resync_max > j
+				   || kthread_should_stop());
+		}
+		if (kthread_should_stop())
+			goto interrupted;
 		sectors = mddev->pers->sync_request(mddev, j, &skipped,
-					    currspeed < speed_min(mddev));
+						  currspeed < speed_min(mddev));
 		if (sectors == 0) {
 			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
 			goto out;
@@ -5424,15 +5614,9 @@
 		}
 
 
-		if (kthread_should_stop()) {
-			/*
-			 * got a signal, exit.
-			 */
-			printk(KERN_INFO 
-				"md: md_do_sync() got signal ... exiting\n");
-			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-			goto out;
-		}
+		if (kthread_should_stop())
+			goto interrupted;
+
 
 		/*
 		 * this loop exits only if either when we are slower than
@@ -5484,7 +5668,7 @@
 		} else {
 			if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
 				mddev->curr_resync = MaxSector;
-			ITERATE_RDEV(mddev,rdev,rtmp)
+			rdev_for_each(rdev, rtmp, mddev)
 				if (rdev->raid_disk >= 0 &&
 				    !test_bit(Faulty, &rdev->flags) &&
 				    !test_bit(In_sync, &rdev->flags) &&
@@ -5496,9 +5680,22 @@
 
  skip:
 	mddev->curr_resync = 0;
+	mddev->resync_max = MaxSector;
+	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 	wake_up(&resync_wait);
 	set_bit(MD_RECOVERY_DONE, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
+	return;
+
+ interrupted:
+	/*
+	 * got a signal, exit.
+	 */
+	printk(KERN_INFO
+	       "md: md_do_sync() got signal ... exiting\n");
+	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+	goto out;
+
 }
 EXPORT_SYMBOL_GPL(md_do_sync);
 
@@ -5509,8 +5706,9 @@
 	struct list_head *rtmp;
 	int spares = 0;
 
-	ITERATE_RDEV(mddev,rdev,rtmp)
+	rdev_for_each(rdev, rtmp, mddev)
 		if (rdev->raid_disk >= 0 &&
+		    !mddev->external &&
 		    (test_bit(Faulty, &rdev->flags) ||
 		     ! test_bit(In_sync, &rdev->flags)) &&
 		    atomic_read(&rdev->nr_pending)==0) {
@@ -5524,7 +5722,7 @@
 		}
 
 	if (mddev->degraded) {
-		ITERATE_RDEV(mddev,rdev,rtmp)
+		rdev_for_each(rdev, rtmp, mddev)
 			if (rdev->raid_disk < 0
 			    && !test_bit(Faulty, &rdev->flags)) {
 				rdev->recovery_offset = 0;
@@ -5589,7 +5787,7 @@
 	}
 
 	if ( ! (
-		mddev->flags ||
+		(mddev->flags && !mddev->external) ||
 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
 		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
 		(mddev->safemode == 1) ||
@@ -5605,7 +5803,8 @@
 		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
 		    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
 			mddev->in_sync = 1;
-			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+			if (mddev->persistent)
+				set_bit(MD_CHANGE_CLEAN, &mddev->flags);
 		}
 		if (mddev->safemode == 1)
 			mddev->safemode = 0;
@@ -5637,7 +5836,7 @@
 			 * information must be scrapped
 			 */
 			if (!mddev->degraded)
-				ITERATE_RDEV(mddev,rdev,rtmp)
+				rdev_for_each(rdev, rtmp, mddev)
 					rdev->saved_raid_disk = -1;
 
 			mddev->recovery = 0;
@@ -5714,7 +5913,7 @@
 
 		printk(KERN_INFO "md: stopping all md devices.\n");
 
-		ITERATE_MDDEV(mddev,tmp)
+		for_each_mddev(mddev, tmp)
 			if (mddev_trylock(mddev)) {
 				do_md_stop (mddev, 1);
 				mddev_unlock(mddev);
@@ -5848,7 +6047,7 @@
 	unregister_reboot_notifier(&md_notifier);
 	unregister_sysctl_table(raid_table_header);
 	remove_proc_entry("mdstat", NULL);
-	ITERATE_MDDEV(mddev,tmp) {
+	for_each_mddev(mddev, tmp) {
 		struct gendisk *disk = mddev->gendisk;
 		if (!disk)
 			continue;
diff --git a/drivers/md/mktables.c b/drivers/md/mktables.c
index adef299..b61d576 100644
--- a/drivers/md/mktables.c
+++ b/drivers/md/mktables.c
@@ -1,13 +1,10 @@
-#ident "$Id: mktables.c,v 1.2 2002/12/12 22:41:27 hpa Exp $"
-/* ----------------------------------------------------------------------- *
+/* -*- linux-c -*- ------------------------------------------------------- *
  *
- *   Copyright 2002 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2002-2007 H. Peter Anvin - 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 Software Foundation, Inc., 53 Temple Place Ste 330,
- *   Bostom MA 02111-1307, USA; either version 2 of the License, or
- *   (at your option) any later version; incorporated herein by reference.
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
  *
  * ----------------------------------------------------------------------- */
 
@@ -26,100 +23,98 @@
 
 static uint8_t gfmul(uint8_t a, uint8_t b)
 {
-  uint8_t v = 0;
+	uint8_t v = 0;
 
-  while ( b ) {
-    if ( b & 1 ) v ^= a;
-    a = (a << 1) ^ (a & 0x80 ? 0x1d : 0);
-    b >>= 1;
-  }
-  return v;
+	while (b) {
+		if (b & 1)
+			v ^= a;
+		a = (a << 1) ^ (a & 0x80 ? 0x1d : 0);
+		b >>= 1;
+	}
+
+	return v;
 }
 
 static uint8_t gfpow(uint8_t a, int b)
 {
-  uint8_t v = 1;
+	uint8_t v = 1;
 
-  b %= 255;
-  if ( b < 0 )
-    b += 255;
+	b %= 255;
+	if (b < 0)
+		b += 255;
 
-  while ( b ) {
-    if ( b & 1 ) v = gfmul(v,a);
-    a = gfmul(a,a);
-    b >>= 1;
-  }
-  return v;
+	while (b) {
+		if (b & 1)
+			v = gfmul(v, a);
+		a = gfmul(a, a);
+		b >>= 1;
+	}
+
+	return v;
 }
 
 int main(int argc, char *argv[])
 {
-  int i, j, k;
-  uint8_t v;
-  uint8_t exptbl[256], invtbl[256];
+	int i, j, k;
+	uint8_t v;
+	uint8_t exptbl[256], invtbl[256];
 
-  printf("#include \"raid6.h\"\n");
+	printf("#include \"raid6.h\"\n");
 
-  /* Compute multiplication table */
-  printf("\nconst u8  __attribute__((aligned(256)))\n"
-	 "raid6_gfmul[256][256] =\n"
-	 "{\n");
-  for ( i = 0 ; i < 256 ; i++ ) {
-    printf("\t{\n");
-    for ( j = 0 ; j < 256 ; j += 8 ) {
-      printf("\t\t");
-      for ( k = 0 ; k < 8 ; k++ ) {
-	printf("0x%02x, ", gfmul(i,j+k));
-      }
-      printf("\n");
-    }
-    printf("\t},\n");
-  }
-  printf("};\n");
+	/* Compute multiplication table */
+	printf("\nconst u8  __attribute__((aligned(256)))\n"
+		"raid6_gfmul[256][256] =\n"
+		"{\n");
+	for (i = 0; i < 256; i++) {
+		printf("\t{\n");
+		for (j = 0; j < 256; j += 8) {
+			printf("\t\t");
+			for (k = 0; k < 8; k++)
+				printf("0x%02x,%c", gfmul(i, j + k),
+				       (k == 7) ? '\n' : ' ');
+		}
+		printf("\t},\n");
+	}
+	printf("};\n");
 
-  /* Compute power-of-2 table (exponent) */
-  v = 1;
-  printf("\nconst u8 __attribute__((aligned(256)))\n"
-	 "raid6_gfexp[256] =\n"
-	 "{\n");
-  for ( i = 0 ; i < 256 ; i += 8 ) {
-    printf("\t");
-    for ( j = 0 ; j < 8 ; j++ ) {
-      exptbl[i+j] = v;
-      printf("0x%02x, ", v);
-      v = gfmul(v,2);
-      if ( v == 1 ) v = 0;	/* For entry 255, not a real entry */
-    }
-    printf("\n");
-  }
-  printf("};\n");
+	/* Compute power-of-2 table (exponent) */
+	v = 1;
+	printf("\nconst u8 __attribute__((aligned(256)))\n"
+	       "raid6_gfexp[256] =\n" "{\n");
+	for (i = 0; i < 256; i += 8) {
+		printf("\t");
+		for (j = 0; j < 8; j++) {
+			exptbl[i + j] = v;
+			printf("0x%02x,%c", v, (j == 7) ? '\n' : ' ');
+			v = gfmul(v, 2);
+			if (v == 1)
+				v = 0;	/* For entry 255, not a real entry */
+		}
+	}
+	printf("};\n");
 
-  /* Compute inverse table x^-1 == x^254 */
-  printf("\nconst u8 __attribute__((aligned(256)))\n"
-	 "raid6_gfinv[256] =\n"
-	 "{\n");
-  for ( i = 0 ; i < 256 ; i += 8 ) {
-    printf("\t");
-    for ( j = 0 ; j < 8 ; j++ ) {
-      invtbl[i+j] = v = gfpow(i+j,254);
-      printf("0x%02x, ", v);
-    }
-    printf("\n");
-  }
-  printf("};\n");
+	/* Compute inverse table x^-1 == x^254 */
+	printf("\nconst u8 __attribute__((aligned(256)))\n"
+	       "raid6_gfinv[256] =\n" "{\n");
+	for (i = 0; i < 256; i += 8) {
+		printf("\t");
+		for (j = 0; j < 8; j++) {
+			invtbl[i + j] = v = gfpow(i + j, 254);
+			printf("0x%02x,%c", v, (j == 7) ? '\n' : ' ');
+		}
+	}
+	printf("};\n");
 
-  /* Compute inv(2^x + 1) (exponent-xor-inverse) table */
-  printf("\nconst u8 __attribute__((aligned(256)))\n"
-	 "raid6_gfexi[256] =\n"
-	 "{\n");
-  for ( i = 0 ; i < 256 ; i += 8 ) {
-    printf("\t");
-    for ( j = 0 ; j < 8 ; j++ ) {
-      printf("0x%02x, ", invtbl[exptbl[i+j]^1]);
-    }
-    printf("\n");
-  }
-  printf("};\n\n");
+	/* Compute inv(2^x + 1) (exponent-xor-inverse) table */
+	printf("\nconst u8 __attribute__((aligned(256)))\n"
+	       "raid6_gfexi[256] =\n" "{\n");
+	for (i = 0; i < 256; i += 8) {
+		printf("\t");
+		for (j = 0; j < 8; j++)
+			printf("0x%02x,%c", invtbl[exptbl[i + j] ^ 1],
+			       (j == 7) ? '\n' : ' ');
+	}
+	printf("};\n");
 
-  return 0;
+	return 0;
 }
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index eb631eb..3f299d8 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -436,7 +436,7 @@
 	}
 
 	conf->working_disks = 0;
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		disk_idx = rdev->raid_disk;
 		if (disk_idx < 0 ||
 		    disk_idx >= mddev->raid_disks)
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index f8e5917..818b482 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -72,11 +72,11 @@
 	 */
 	conf->nr_strip_zones = 0;
  
-	ITERATE_RDEV(mddev,rdev1,tmp1) {
+	rdev_for_each(rdev1, tmp1, mddev) {
 		printk("raid0: looking at %s\n",
 			bdevname(rdev1->bdev,b));
 		c = 0;
-		ITERATE_RDEV(mddev,rdev2,tmp2) {
+		rdev_for_each(rdev2, tmp2, mddev) {
 			printk("raid0:   comparing %s(%llu)",
 			       bdevname(rdev1->bdev,b),
 			       (unsigned long long)rdev1->size);
@@ -124,7 +124,7 @@
 	cnt = 0;
 	smallest = NULL;
 	zone->dev = conf->devlist;
-	ITERATE_RDEV(mddev, rdev1, tmp1) {
+	rdev_for_each(rdev1, tmp1, mddev) {
 		int j = rdev1->raid_disk;
 
 		if (j < 0 || j >= mddev->raid_disks) {
@@ -293,7 +293,7 @@
 
 	/* calculate array device size */
 	mddev->array_size = 0;
-	ITERATE_RDEV(mddev,rdev,tmp)
+	rdev_for_each(rdev, tmp, mddev)
 		mddev->array_size += rdev->size;
 
 	printk("raid0 : md_size is %llu blocks.\n", 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 4a69c41..5c7fef0 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1684,6 +1684,7 @@
 	if (!go_faster && conf->nr_waiting)
 		msleep_interruptible(1000);
 
+	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
 	raise_barrier(conf);
 
 	conf->next_resync = sector_nr;
@@ -1766,6 +1767,8 @@
 		return rv;
 	}
 
+	if (max_sector > mddev->resync_max)
+		max_sector = mddev->resync_max; /* Don't do IO beyond here */
 	nr_sectors = 0;
 	sync_blocks = 0;
 	do {
@@ -1884,7 +1887,7 @@
 	if (!conf->r1bio_pool)
 		goto out_no_mem;
 
-	ITERATE_RDEV(mddev, rdev, tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		disk_idx = rdev->raid_disk;
 		if (disk_idx >= mddev->raid_disks
 		    || disk_idx < 0)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 5cdcc93..017f581 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1657,6 +1657,9 @@
 		return (max_sector - sector_nr) + sectors_skipped;
 	}
 
+	if (max_sector > mddev->resync_max)
+		max_sector = mddev->resync_max; /* Don't do IO beyond here */
+
 	/* make sure whole request will fit in a chunk - if chunks
 	 * are meaningful
 	 */
@@ -1670,6 +1673,8 @@
 	if (!go_faster && conf->nr_waiting)
 		msleep_interruptible(1000);
 
+	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+
 	/* Again, very different code for resync and recovery.
 	 * Both must result in an r10bio with a list of bios that
 	 * have bi_end_io, bi_sector, bi_bdev set,
@@ -2021,7 +2026,7 @@
 		goto out_free_conf;
 	}
 
-	ITERATE_RDEV(mddev, rdev, tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		disk_idx = rdev->raid_disk;
 		if (disk_idx >= mddev->raid_disks
 		    || disk_idx < 0)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e8c8157..2d6f1a5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3159,7 +3159,8 @@
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->handle_list);
 		}
-	}
+	} else
+		blk_plug_device(conf->mddev->queue);
 }
 
 static void activate_bit_delay(raid5_conf_t *conf)
@@ -3549,7 +3550,8 @@
 				goto retry;
 			}
 			finish_wait(&conf->wait_for_overlap, &w);
-			handle_stripe(sh, NULL);
+			set_bit(STRIPE_HANDLE, &sh->state);
+			clear_bit(STRIPE_DELAYED, &sh->state);
 			release_stripe(sh);
 		} else {
 			/* cannot get stripe for read-ahead, just give-up */
@@ -3698,6 +3700,25 @@
 		release_stripe(sh);
 		first_sector += STRIPE_SECTORS;
 	}
+	/* If this takes us to the resync_max point where we have to pause,
+	 * then we need to write out the superblock.
+	 */
+	sector_nr += conf->chunk_size>>9;
+	if (sector_nr >= mddev->resync_max) {
+		/* Cannot proceed until we've updated the superblock... */
+		wait_event(conf->wait_for_overlap,
+			   atomic_read(&conf->reshape_stripes) == 0);
+		mddev->reshape_position = conf->expand_progress;
+		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		md_wakeup_thread(mddev->thread);
+		wait_event(mddev->sb_wait,
+			   !test_bit(MD_CHANGE_DEVS, &mddev->flags)
+			   || kthread_should_stop());
+		spin_lock_irq(&conf->device_lock);
+		conf->expand_lo = mddev->reshape_position;
+		spin_unlock_irq(&conf->device_lock);
+		wake_up(&conf->wait_for_overlap);
+	}
 	return conf->chunk_size>>9;
 }
 
@@ -3734,6 +3755,12 @@
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
 		return reshape_request(mddev, sector_nr, skipped);
 
+	/* No need to check resync_max as we never do more than one
+	 * stripe, and as resync_max will always be on a chunk boundary,
+	 * if the check in md_do_sync didn't fire, there is no chance
+	 * of overstepping resync_max here
+	 */
+
 	/* if there is too many failed drives and we are trying
 	 * to resync, then assert that we are finished, because there is
 	 * nothing we can do.
@@ -3753,6 +3780,9 @@
 		return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
 	}
 
+
+	bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+
 	pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks);
 	sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1);
 	if (sh == NULL) {
@@ -3864,7 +3894,7 @@
  * During the scan, completed stripes are saved for us by the interrupt
  * handler, so that they will not have to wait for our next wakeup.
  */
-static void raid5d (mddev_t *mddev)
+static void raid5d(mddev_t *mddev)
 {
 	struct stripe_head *sh;
 	raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -3889,12 +3919,6 @@
 			activate_bit_delay(conf);
 		}
 
-		if (list_empty(&conf->handle_list) &&
-		    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
-		    !blk_queue_plugged(mddev->queue) &&
-		    !list_empty(&conf->delayed_list))
-			raid5_activate_delayed(conf);
-
 		while ((bio = remove_bio_from_retry(conf))) {
 			int ok;
 			spin_unlock_irq(&conf->device_lock);
@@ -4108,7 +4132,7 @@
 
 	pr_debug("raid5: run(%s) called.\n", mdname(mddev));
 
-	ITERATE_RDEV(mddev,rdev,tmp) {
+	rdev_for_each(rdev, tmp, mddev) {
 		raid_disk = rdev->raid_disk;
 		if (raid_disk >= conf->raid_disks
 		    || raid_disk < 0)
@@ -4521,7 +4545,7 @@
 	if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 		return -EBUSY;
 
-	ITERATE_RDEV(mddev, rdev, rtmp)
+	rdev_for_each(rdev, rtmp, mddev)
 		if (rdev->raid_disk < 0 &&
 		    !test_bit(Faulty, &rdev->flags))
 			spares++;
@@ -4543,7 +4567,7 @@
 	/* Add some new drives, as many as will fit.
 	 * We know there are enough to make the newly sized array work.
 	 */
-	ITERATE_RDEV(mddev, rdev, rtmp)
+	rdev_for_each(rdev, rtmp, mddev)
 		if (rdev->raid_disk < 0 &&
 		    !test_bit(Faulty, &rdev->flags)) {
 			if (raid5_add_disk(mddev, rdev)) {
diff --git a/drivers/md/raid6test/test.c b/drivers/md/raid6test/test.c
index 0d5cd57..559cc41 100644
--- a/drivers/md/raid6test/test.c
+++ b/drivers/md/raid6test/test.c
@@ -1,12 +1,10 @@
 /* -*- linux-c -*- ------------------------------------------------------- *
  *
- *   Copyright 2002 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2002-2007 H. Peter Anvin - 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 Software Foundation, Inc., 53 Temple Place Ste 330,
- *   Bostom MA 02111-1307, USA; either version 2 of the License, or
- *   (at your option) any later version; incorporated herein by reference.
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
  *
  * ----------------------------------------------------------------------- */
 
@@ -30,67 +28,87 @@
 char data[NDISKS][PAGE_SIZE];
 char recovi[PAGE_SIZE], recovj[PAGE_SIZE];
 
-void makedata(void)
+static void makedata(void)
 {
 	int i, j;
 
-	for (  i = 0 ; i < NDISKS ; i++ ) {
-		for ( j = 0 ; j < PAGE_SIZE ; j++ ) {
+	for (i = 0; i < NDISKS; i++) {
+		for (j = 0; j < PAGE_SIZE; j++)
 			data[i][j] = rand();
-		}
+
 		dataptrs[i] = data[i];
 	}
 }
 
+static char disk_type(int d)
+{
+	switch (d) {
+	case NDISKS-2:
+		return 'P';
+	case NDISKS-1:
+		return 'Q';
+	default:
+		return 'D';
+	}
+}
+
+static int test_disks(int i, int j)
+{
+	int erra, errb;
+
+	memset(recovi, 0xf0, PAGE_SIZE);
+	memset(recovj, 0xba, PAGE_SIZE);
+
+	dataptrs[i] = recovi;
+	dataptrs[j] = recovj;
+
+	raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs);
+
+	erra = memcmp(data[i], recovi, PAGE_SIZE);
+	errb = memcmp(data[j], recovj, PAGE_SIZE);
+
+	if (i < NDISKS-2 && j == NDISKS-1) {
+		/* We don't implement the DQ failure scenario, since it's
+		   equivalent to a RAID-5 failure (XOR, then recompute Q) */
+		erra = errb = 0;
+	} else {
+		printf("algo=%-8s  faila=%3d(%c)  failb=%3d(%c)  %s\n",
+		       raid6_call.name,
+		       i, disk_type(i),
+		       j, disk_type(j),
+		       (!erra && !errb) ? "OK" :
+		       !erra ? "ERRB" :
+		       !errb ? "ERRA" : "ERRAB");
+	}
+
+	dataptrs[i] = data[i];
+	dataptrs[j] = data[j];
+
+	return erra || errb;
+}
+
 int main(int argc, char *argv[])
 {
-	const struct raid6_calls * const * algo;
+	const struct raid6_calls *const *algo;
 	int i, j;
-	int erra, errb;
+	int err = 0;
 
 	makedata();
 
-	for ( algo = raid6_algos ; *algo ; algo++ ) {
-		if ( !(*algo)->valid || (*algo)->valid() ) {
+	for (algo = raid6_algos; *algo; algo++) {
+		if (!(*algo)->valid || (*algo)->valid()) {
 			raid6_call = **algo;
 
 			/* Nuke syndromes */
 			memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE);
 
 			/* Generate assumed good syndrome */
-			raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, (void **)&dataptrs);
+			raid6_call.gen_syndrome(NDISKS, PAGE_SIZE,
+						(void **)&dataptrs);
 
-			for ( i = 0 ; i < NDISKS-1 ; i++ ) {
-				for ( j = i+1 ; j < NDISKS ; j++ ) {
-					memset(recovi, 0xf0, PAGE_SIZE);
-					memset(recovj, 0xba, PAGE_SIZE);
-
-					dataptrs[i] = recovi;
-					dataptrs[j] = recovj;
-
-					raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs);
-
-					erra = memcmp(data[i], recovi, PAGE_SIZE);
-					errb = memcmp(data[j], recovj, PAGE_SIZE);
-
-					if ( i < NDISKS-2 && j == NDISKS-1 ) {
-						/* We don't implement the DQ failure scenario, since it's
-						   equivalent to a RAID-5 failure (XOR, then recompute Q) */
-					} else {
-						printf("algo=%-8s  faila=%3d(%c)  failb=%3d(%c)  %s\n",
-						       raid6_call.name,
-						       i, (i==NDISKS-2)?'P':'D',
-						       j, (j==NDISKS-1)?'Q':(j==NDISKS-2)?'P':'D',
-						       (!erra && !errb) ? "OK" :
-						       !erra ? "ERRB" :
-						       !errb ? "ERRA" :
-						       "ERRAB");
-					}
-
-					dataptrs[i] = data[i];
-					dataptrs[j] = data[j];
-				}
-			}
+			for (i = 0; i < NDISKS-1; i++)
+				for (j = i+1; j < NDISKS; j++)
+					err += test_disks(i, j);
 		}
 		printf("\n");
 	}
@@ -99,5 +117,8 @@
 	/* Pick the best algorithm test */
 	raid6_select_algo();
 
-	return 0;
+	if (err)
+		printf("\n*** ERRORS FOUND ***\n");
+
+	return err;
 }
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 28ddd14..850b8c6 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -22,7 +22,6 @@
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
-obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
deleted file mode 100644
index 9fa5b70..0000000
--- a/drivers/media/video/tvmixer.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-#include <linux/kdev_t.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-
-
-#define DEV_MAX  4
-
-static int devnr = -1;
-module_param(devnr, int, 0644);
-
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/* ----------------------------------------------------------------------- */
-
-struct TVMIXER {
-	struct i2c_client *dev;
-	int minor;
-	int count;
-};
-
-static struct TVMIXER devices[DEV_MAX];
-
-static int tvmixer_adapters(struct i2c_adapter *adap);
-static int tvmixer_clients(struct i2c_client *client);
-
-/* ----------------------------------------------------------------------- */
-
-static int mix_to_v4l(int i)
-{
-	int r;
-
-	r = ((i & 0xff) * 65536 + 50) / 100;
-	if (r > 65535) r = 65535;
-	if (r <     0) r =     0;
-	return r;
-}
-
-static int v4l_to_mix(int i)
-{
-	int r;
-
-	r = (i * 100 + 32768) / 65536;
-	if (r > 100) r = 100;
-	if (r <   0) r =   0;
-	return r | (r << 8);
-}
-
-static int v4l_to_mix2(int l, int r)
-{
-	r = (r * 100 + 32768) / 65536;
-	if (r > 100) r = 100;
-	if (r <   0) r =   0;
-	l = (l * 100 + 32768) / 65536;
-	if (l > 100) l = 100;
-	if (l <   0) l =   0;
-	return (r << 8) | l;
-}
-
-static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct video_audio va;
-	int left,right,ret,val = 0;
-	struct TVMIXER *mix = file->private_data;
-	struct i2c_client *client = mix->dev;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-	if (NULL == client)
-		return -ENODEV;
-
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		strlcpy(info.id, "tv card", sizeof(info.id));
-		strlcpy(info.name, client->name, sizeof(info.name));
-		info.modify_counter = 42 /* FIXME */;
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		strlcpy(info.id, "tv card", sizeof(info.id));
-		strlcpy(info.name, client->name, sizeof(info.name));
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, p);
-
-	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
-		if (get_user(val, p))
-			return -EFAULT;
-
-	/* read state */
-	memset(&va,0,sizeof(va));
-	client->driver->command(client,VIDIOCGAUDIO,&va);
-
-	switch (cmd) {
-	case MIXER_READ(SOUND_MIXER_RECMASK):
-	case MIXER_READ(SOUND_MIXER_CAPS):
-	case MIXER_READ(SOUND_MIXER_RECSRC):
-	case MIXER_WRITE(SOUND_MIXER_RECSRC):
-		ret = 0;
-		break;
-
-	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = SOUND_MASK_VOLUME;
-		break;
-	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_VOLUME;
-		if (va.flags & VIDEO_AUDIO_BASS)
-			ret |= SOUND_MASK_BASS;
-		if (va.flags & VIDEO_AUDIO_TREBLE)
-			ret |= SOUND_MASK_TREBLE;
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_VOLUME):
-		left  = mix_to_v4l(val);
-		right = mix_to_v4l(val >> 8);
-		va.volume  = max(left,right);
-		va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1);
-		va.balance = (left<right) ? (65535-va.balance) : va.balance;
-		if (va.volume)
-			va.flags &= ~VIDEO_AUDIO_MUTE;
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth */
-	case MIXER_READ(SOUND_MIXER_VOLUME):
-		left  = (min(65536 - va.balance,32768) *
-			 va.volume) / 32768;
-		right = (min(va.balance,(u16)32768) *
-			 va.volume) / 32768;
-		ret = v4l_to_mix2(left,right);
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_BASS):
-		va.bass = mix_to_v4l(val);
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth  */
-	case MIXER_READ(SOUND_MIXER_BASS):
-		ret = v4l_to_mix(va.bass);
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_TREBLE):
-		va.treble = mix_to_v4l(val);
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth */
-	case MIXER_READ(SOUND_MIXER_TREBLE):
-		ret = v4l_to_mix(va.treble);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (put_user(ret, p))
-		return -EFAULT;
-	return 0;
-}
-
-static int tvmixer_open(struct inode *inode, struct file *file)
-{
-	int i, minor = iminor(inode);
-	struct TVMIXER *mix = NULL;
-	struct i2c_client *client = NULL;
-
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].minor == minor) {
-			mix = devices+i;
-			client = mix->dev;
-			break;
-		}
-	}
-
-	if (NULL == client)
-		return -ENODEV;
-
-	/* lock bttv in memory while the mixer is in use  */
-	file->private_data = mix;
-	if (client->adapter->owner)
-		try_module_get(client->adapter->owner);
-	return 0;
-}
-
-static int tvmixer_release(struct inode *inode, struct file *file)
-{
-	struct TVMIXER *mix = file->private_data;
-	struct i2c_client *client;
-
-	client = mix->dev;
-	if (NULL == client) {
-		return -ENODEV;
-	}
-
-	module_put(client->adapter->owner);
-	return 0;
-}
-
-static struct i2c_driver driver = {
-	.driver = {
-		.name    = "tvmixer",
-	},
-	.id              = I2C_DRIVERID_TVMIXER,
-	.detach_adapter  = tvmixer_adapters,
-	.attach_adapter  = tvmixer_adapters,
-	.detach_client   = tvmixer_clients,
-};
-
-static const struct file_operations tvmixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek         = no_llseek,
-	.ioctl          = tvmixer_ioctl,
-	.open           = tvmixer_open,
-	.release        = tvmixer_release,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static int tvmixer_adapters(struct i2c_adapter *adap)
-{
-	struct i2c_client *client;
-
-	list_for_each_entry(client, &adap->clients, list)
-		tvmixer_clients(client);
-	return 0;
-}
-
-static int tvmixer_clients(struct i2c_client *client)
-{
-	struct video_audio va;
-	int i,minor;
-
-	if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
-		return -1;
-
-	/* unregister ?? */
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].dev == client) {
-			/* unregister */
-			unregister_sound_mixer(devices[i].minor);
-			devices[i].dev = NULL;
-			devices[i].minor = -1;
-			printk("tvmixer: %s unregistered (#1)\n",
-			       client->name);
-			return 0;
-		}
-	}
-
-	/* look for a free slot */
-	for (i = 0; i < DEV_MAX; i++)
-		if (NULL == devices[i].dev)
-			break;
-	if (i == DEV_MAX) {
-		printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
-		return -1;
-	}
-
-	/* audio chip with mixer ??? */
-	if (NULL == client->driver->command)
-		return -1;
-	memset(&va,0,sizeof(va));
-	if (0 != client->driver->command(client,VIDIOCGAUDIO,&va))
-		return -1;
-	if (0 == (va.flags & VIDEO_AUDIO_VOLUME))
-		return -1;
-
-	/* everything is fine, register */
-	if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
-		printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
-		return -1;
-	}
-
-	devices[i].minor = minor;
-	devices[i].count = 0;
-	devices[i].dev   = client;
-	printk("tvmixer: %s (%s) registered with minor %d\n",
-	       client->name,client->adapter->name,minor);
-
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int __init tvmixer_init_module(void)
-{
-	int i;
-
-	for (i = 0; i < DEV_MAX; i++)
-		devices[i].minor = -1;
-
-	return i2c_add_driver(&driver);
-}
-
-static void __exit tvmixer_cleanup_module(void)
-{
-	int i;
-
-	i2c_del_driver(&driver);
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].minor != -1) {
-			unregister_sound_mixer(devices[i].minor);
-			printk("tvmixer: %s unregistered (#2)\n",
-			       devices[i].dev->name);
-		}
-	}
-}
-
-module_init(tvmixer_init_module);
-module_exit(tvmixer_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 7dce318..0846c33 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -33,7 +33,6 @@
  *  Sam Lin        - GPS support
  */
 
-#include <linux/autoconf.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c
index c8d62c2..1cfd7f3 100644
--- a/drivers/misc/fujitsu-laptop.c
+++ b/drivers/misc/fujitsu-laptop.c
@@ -50,7 +50,6 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
-#include <linux/autoconf.h>
 
 #define FUJITSU_DRIVER_VERSION "0.3"
 
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 552b795..c884730 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -129,27 +129,28 @@
 MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\
 				"crash point is to be hit to trigger action");
 
-unsigned int jp_do_irq(unsigned int irq)
+static unsigned int jp_do_irq(unsigned int irq)
 {
 	lkdtm_handler();
 	jprobe_return();
 	return 0;
 }
 
-irqreturn_t jp_handle_irq_event(unsigned int irq, struct irqaction *action)
+static irqreturn_t jp_handle_irq_event(unsigned int irq,
+				       struct irqaction *action)
 {
 	lkdtm_handler();
 	jprobe_return();
 	return 0;
 }
 
-void jp_tasklet_action(struct softirq_action *a)
+static void jp_tasklet_action(struct softirq_action *a)
 {
 	lkdtm_handler();
 	jprobe_return();
 }
 
-void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
+static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
 {
 	lkdtm_handler();
 	jprobe_return();
@@ -157,23 +158,24 @@
 
 struct scan_control;
 
-unsigned long jp_shrink_inactive_list(unsigned long max_scan,
-				struct zone *zone, struct scan_control *sc)
+static unsigned long jp_shrink_inactive_list(unsigned long max_scan,
+					     struct zone *zone,
+					     struct scan_control *sc)
 {
 	lkdtm_handler();
 	jprobe_return();
 	return 0;
 }
 
-int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
-				const enum hrtimer_mode mode)
+static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim,
+			    const enum hrtimer_mode mode)
 {
 	lkdtm_handler();
 	jprobe_return();
 	return 0;
 }
 
-int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
+static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd)
 {
 	lkdtm_handler();
 	jprobe_return();
@@ -270,7 +272,7 @@
 	}
 }
 
-int lkdtm_module_init(void)
+static int __init lkdtm_module_init(void)
 {
 	int ret;
 
@@ -331,7 +333,7 @@
 	return 0;
 }
 
-void lkdtm_module_exit(void)
+static void __exit lkdtm_module_exit(void)
 {
         unregister_jprobe(&lkdtm);
         printk(KERN_INFO "lkdtm : Crash point unregistered\n");
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 83679c7..de898c6 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -58,7 +58,6 @@
 #include <linux/dmi.h>
 #include <linux/backlight.h>
 #include <linux/platform_device.h>
-#include <linux/autoconf.h>
 
 #define MSI_DRIVER_VERSION "0.5"
 
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index cd221fd..7fa61e9 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -25,7 +25,7 @@
 #include <asm/atomic.h>
 #include <asm/io.h>
 
-#define PHANTOM_VERSION		"n0.9.7"
+#define PHANTOM_VERSION		"n0.9.8"
 
 #define PHANTOM_MAX_MINORS	8
 
@@ -456,8 +456,9 @@
 #endif
 
 static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
-		.class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
+	{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
+	  .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
+	  .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index be4b994..eeaaa9d 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -4,7 +4,7 @@
  * block2mtd.c - create an mtd from a block device
  *
  * Copyright (C) 2001,2002	Simon Evans <spse@secret.org.uk>
- * Copyright (C) 2004-2006	Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (C) 2004-2006	Joern Engel <joern@wh.fh-wedel.de>
  *
  * Licence: GPL
  */
@@ -485,5 +485,5 @@
 module_exit(block2mtd_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Simon Evans <spse@secret.org.uk> and others");
+MODULE_AUTHOR("Joern Engel <joern@lazybastard.org>");
 MODULE_DESCRIPTION("Emulate an MTD using a block device");
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 56cc1ca..180298b 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -2,7 +2,7 @@
  * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $
  *
  * Copyright (c) ????		Jochen Schäuble <psionic@psionic.de>
- * Copyright (c) 2003-2004	Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (c) 2003-2004	Joern Engel <joern@wh.fh-wedel.de>
  *
  * Usage:
  *
@@ -299,5 +299,5 @@
 module_exit(cleanup_phram);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
+MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>");
 MODULE_DESCRIPTION("MTD driver for physical RAM");
diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c
index d884f2b..2a8fde9 100644
--- a/drivers/mtd/maps/mtx-1_flash.c
+++ b/drivers/mtd/maps/mtx-1_flash.c
@@ -4,7 +4,7 @@
  * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $
  *
  * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz>
- * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de>
+ * (C) 2005 Joern Engel <joern@wohnheim.fh-wedel.de>
  *
  */
 
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 3634223..d4843d0 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -323,8 +323,8 @@
 	NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR		0x0001
 #define NVREG_MIISTAT_LINKCHANGE	0x0008
-#define NVREG_MIISTAT_MASK		0x000f
-#define NVREG_MIISTAT_MASK2		0x000f
+#define NVREG_MIISTAT_MASK_RW		0x0007
+#define NVREG_MIISTAT_MASK_ALL		0x000f
 	NvRegMIIMask = 0x184,
 #define NVREG_MII_LINKCHANGE		0x0008
 
@@ -624,6 +624,9 @@
 #define NV_MSI_X_VECTOR_TX    0x1
 #define NV_MSI_X_VECTOR_OTHER 0x2
 
+#define NV_RESTART_TX         0x1
+#define NV_RESTART_RX         0x2
+
 /* statistics */
 struct nv_ethtool_str {
 	char name[ETH_GSTRING_LEN];
@@ -1061,7 +1064,7 @@
 	u32 reg;
 	int retval;
 
-	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_MASK_RW, base + NvRegMIIStatus);
 
 	reg = readl(base + NvRegMIIControl);
 	if (reg & NVREG_MIICTL_INUSE) {
@@ -1432,16 +1435,30 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 temp1, temp2, temp3;
 
 	dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
+
 	writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
+
+	/* save registers since they will be cleared on reset */
+	temp1 = readl(base + NvRegMacAddrA);
+	temp2 = readl(base + NvRegMacAddrB);
+	temp3 = readl(base + NvRegTransmitPoll);
+
 	writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset);
 	pci_push(base);
 	udelay(NV_MAC_RESET_DELAY);
 	writel(0, base + NvRegMacReset);
 	pci_push(base);
 	udelay(NV_MAC_RESET_DELAY);
+
+	/* restore saved registers */
+	writel(temp1, base + NvRegMacAddrA);
+	writel(temp2, base + NvRegMacAddrB);
+	writel(temp3, base + NvRegTransmitPoll);
+
 	writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
 	pci_push(base);
 }
@@ -2767,6 +2784,7 @@
 	int mii_status;
 	int retval = 0;
 	u32 control_1000, status_1000, phyreg, pause_flags, txreg;
+	u32 txrxFlags = 0;
 
 	/* BMSR_LSTATUS is latched, read it twice:
 	 * we want the current value.
@@ -2862,6 +2880,16 @@
 	np->duplex = newdup;
 	np->linkspeed = newls;
 
+	/* The transmitter and receiver must be restarted for safe update */
+	if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) {
+		txrxFlags |= NV_RESTART_TX;
+		nv_stop_tx(dev);
+	}
+	if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
+		txrxFlags |= NV_RESTART_RX;
+		nv_stop_rx(dev);
+	}
+
 	if (np->gigabit == PHY_GIGABIT) {
 		phyreg = readl(base + NvRegRandomSeed);
 		phyreg &= ~(0x3FF00);
@@ -2950,6 +2978,11 @@
 	}
 	nv_update_pause(dev, pause_flags);
 
+	if (txrxFlags & NV_RESTART_TX)
+		nv_start_tx(dev);
+	if (txrxFlags & NV_RESTART_RX)
+		nv_start_rx(dev);
+
 	return retval;
 }
 
@@ -2976,7 +3009,7 @@
 	u32 miistat;
 
 	miistat = readl(base + NvRegMIIStatus);
-	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus);
 	dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat);
 
 	if (miistat & (NVREG_MIISTAT_LINKCHANGE))
@@ -4851,7 +4884,7 @@
 
 	writel(0, base + NvRegMIIMask);
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
-	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
 
 	writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
 	writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
@@ -4889,7 +4922,7 @@
 
 	nv_disable_hw_interrupts(dev, np->irqmask);
 	pci_push(base);
-	writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
 	pci_push(base);
 
@@ -4912,7 +4945,7 @@
 	{
 		u32 miistat;
 		miistat = readl(base + NvRegMIIStatus);
-		writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+		writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
 		dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
 	}
 	/* set linkspeed to invalid value, thus force nv_update_linkspeed
@@ -5280,7 +5313,7 @@
 		phystate &= ~NVREG_ADAPTCTL_RUNNING;
 		writel(phystate, base + NvRegAdapterControl);
 	}
-	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
+	writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
 
 	if (id->driver_data & DEV_HAS_MGMT_UNIT) {
 		/* management unit running on the mac? */
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 100bf41..6a647d9 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -127,7 +127,7 @@
 	struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
 	unsigned int timeout = PHY_INIT_TIMEOUT;
 
-	spin_lock_bh(&bus->mdio_lock);
+	mutex_lock(&bus->mdio_lock);
 
 	/* Reset the management interface */
 	gfar_write(&regs->miimcfg, MIIMCFG_RESET);
@@ -140,7 +140,7 @@
 			timeout--)
 		cpu_relax();
 
-	spin_unlock_bh(&bus->mdio_lock);
+	mutex_unlock(&bus->mdio_lock);
 
 	if(timeout <= 0) {
 		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 419861c..58d3bb6 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -1020,7 +1020,7 @@
 	.get_link = veth_get_link,
 };
 
-static struct net_device * __init veth_probe_one(int vlan,
+static struct net_device *veth_probe_one(int vlan,
 		struct vio_dev *vio_dev)
 {
 	struct net_device *dev;
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index a021a6e..d0bf206 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -136,8 +136,6 @@
 	u16 head;
 	u16 tail;
 
-	/* To protect race between sender and clean_tx_irq */
-	spinlock_t tx_lock;
 
 	struct ixgbe_queue_stats stats;
 
@@ -174,7 +172,6 @@
 	struct vlan_group *vlgrp;
 	u16 bd_number;
 	u16 rx_buf_len;
-	atomic_t irq_sem;
 	struct work_struct reset_task;
 
 	/* TX */
@@ -244,6 +241,7 @@
 
 extern int ixgbe_up(struct ixgbe_adapter *adapter);
 extern void ixgbe_down(struct ixgbe_adapter *adapter);
+extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter);
 extern void ixgbe_reset(struct ixgbe_adapter *adapter);
 extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
 extern void ixgbe_set_ethtool_ops(struct net_device *netdev);
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 3635344..a119cbd 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -103,21 +103,41 @@
 			      struct ethtool_cmd *ecmd)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 link_speed = 0;
+	bool link_up;
 
-	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
-	ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
-	ecmd->port = PORT_FIBRE;
+	ecmd->supported = SUPPORTED_10000baseT_Full;
+	ecmd->autoneg = AUTONEG_ENABLE;
 	ecmd->transceiver = XCVR_EXTERNAL;
+	if (hw->phy.media_type == ixgbe_media_type_copper) {
+		ecmd->supported |= (SUPPORTED_1000baseT_Full |
+				    SUPPORTED_TP | SUPPORTED_Autoneg);
 
-	if (netif_carrier_ok(adapter->netdev)) {
-		ecmd->speed = SPEED_10000;
+		ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg);
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+			ecmd->advertising |= ADVERTISED_10000baseT_Full;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+			ecmd->advertising |= ADVERTISED_1000baseT_Full;
+
+		ecmd->port = PORT_TP;
+	} else {
+		ecmd->supported |= SUPPORTED_FIBRE;
+		ecmd->advertising = (ADVERTISED_10000baseT_Full |
+				     ADVERTISED_FIBRE);
+		ecmd->port = PORT_FIBRE;
+	}
+
+	adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up);
+	if (link_up) {
+		ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
+				SPEED_10000 : SPEED_1000;
 		ecmd->duplex = DUPLEX_FULL;
 	} else {
 		ecmd->speed = -1;
 		ecmd->duplex = -1;
 	}
 
-	ecmd->autoneg = AUTONEG_DISABLE;
 	return 0;
 }
 
@@ -125,17 +145,17 @@
 			      struct ethtool_cmd *ecmd)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (ecmd->autoneg == AUTONEG_ENABLE ||
-	    ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
-		return -EINVAL;
-
-	if (netif_running(adapter->netdev)) {
-		ixgbe_down(adapter);
-		ixgbe_reset(adapter);
-		ixgbe_up(adapter);
-	} else {
-		ixgbe_reset(adapter);
+	switch (hw->phy.media_type) {
+	case ixgbe_media_type_fiber:
+		if ((ecmd->autoneg == AUTONEG_ENABLE) ||
+		    (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
+			return -EINVAL;
+		/* in this case we currently only support 10Gb/FULL */
+		break;
+	default:
+		break;
 	}
 
 	return 0;
@@ -147,7 +167,7 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	pause->autoneg = AUTONEG_DISABLE;
+	pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0);
 
 	if (hw->fc.type == ixgbe_fc_rx_pause) {
 		pause->rx_pause = 1;
@@ -165,10 +185,8 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 
-	if (pause->autoneg == AUTONEG_ENABLE)
-		return -EINVAL;
-
-	if (pause->rx_pause && pause->tx_pause)
+	if ((pause->autoneg == AUTONEG_ENABLE) ||
+	    (pause->rx_pause && pause->tx_pause))
 		hw->fc.type = ixgbe_fc_full;
 	else if (pause->rx_pause && !pause->tx_pause)
 		hw->fc.type = ixgbe_fc_rx_pause;
@@ -176,15 +194,15 @@
 		hw->fc.type = ixgbe_fc_tx_pause;
 	else if (!pause->rx_pause && !pause->tx_pause)
 		hw->fc.type = ixgbe_fc_none;
+	else
+		return -EINVAL;
 
 	hw->fc.original_type = hw->fc.type;
 
-	if (netif_running(adapter->netdev)) {
-		ixgbe_down(adapter);
-		ixgbe_up(adapter);
-	} else {
+	if (netif_running(netdev))
+		ixgbe_reinit_locked(adapter);
+	else
 		ixgbe_reset(adapter);
-	}
 
 	return 0;
 }
@@ -203,12 +221,10 @@
 	else
 		adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED;
 
-	if (netif_running(netdev)) {
-		ixgbe_down(adapter);
-		ixgbe_up(adapter);
-	} else {
+	if (netif_running(netdev))
+		ixgbe_reinit_locked(adapter);
+	else
 		ixgbe_reset(adapter);
-	}
 
 	return 0;
 }
@@ -662,7 +678,10 @@
 		return 0;
 	}
 
-	if (netif_running(adapter->netdev))
+	while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
+		msleep(1);
+
+	if (netif_running(netdev))
 		ixgbe_down(adapter);
 
 	/*
@@ -733,6 +752,7 @@
 	if (netif_running(adapter->netdev))
 		ixgbe_up(adapter);
 
+	clear_bit(__IXGBE_RESETTING, &adapter->state);
 	return err;
 }
 
@@ -820,11 +840,8 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	if (netif_running(netdev)) {
-		ixgbe_down(adapter);
-		ixgbe_reset(adapter);
-		ixgbe_up(adapter);
-	}
+	if (netif_running(netdev))
+		ixgbe_reinit_locked(adapter);
 
 	return 0;
 }
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 3732dd6..ead49e5 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -87,6 +87,25 @@
 
 #define DEFAULT_DEBUG_LEVEL_SHIFT 3
 
+static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter)
+{
+	u32 ctrl_ext;
+
+	/* Let firmware take over control of h/w */
+	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
+			ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
+}
+
+static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter)
+{
+	u32 ctrl_ext;
+
+	/* Let firmware know the driver has taken over */
+	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
+			ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
+}
 
 #ifdef DEBUG
 /**
@@ -165,6 +184,15 @@
 	return false;
 }
 
+#define IXGBE_MAX_TXD_PWR	14
+#define IXGBE_MAX_DATA_PER_TXD	(1 << IXGBE_MAX_TXD_PWR)
+
+/* Tx Descriptors needed, worst case */
+#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
+			 (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
+#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
+	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1)	/* for context */
+
 /**
  * ixgbe_clean_tx_irq - Reclaim resources after transmit completes
  * @adapter: board private structure
@@ -177,18 +205,34 @@
 	struct ixgbe_tx_buffer *tx_buffer_info;
 	unsigned int i, eop;
 	bool cleaned = false;
-	int count = 0;
+	unsigned int total_tx_bytes = 0, total_tx_packets = 0;
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->tx_buffer_info[i].next_to_watch;
 	eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
 	while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) {
-		for (cleaned = false; !cleaned;) {
+		cleaned = false;
+		while (!cleaned) {
 			tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i);
 			tx_buffer_info = &tx_ring->tx_buffer_info[i];
 			cleaned = (i == eop);
 
 			tx_ring->stats.bytes += tx_buffer_info->length;
+			if (cleaned) {
+				struct sk_buff *skb = tx_buffer_info->skb;
+#ifdef NETIF_F_TSO
+				unsigned int segs, bytecount;
+				segs = skb_shinfo(skb)->gso_segs ?: 1;
+				/* multiply data chunks by size of headers */
+				bytecount = ((segs - 1) * skb_headlen(skb)) +
+					    skb->len;
+				total_tx_packets += segs;
+				total_tx_bytes += bytecount;
+#else
+				total_tx_packets++;
+				total_tx_bytes += skb->len;
+#endif
+			}
 			ixgbe_unmap_and_free_tx_resource(adapter,
 							 tx_buffer_info);
 			tx_desc->wb.status = 0;
@@ -204,29 +248,36 @@
 		eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
 
 		/* weight of a sort for tx, avoid endless transmit cleanup */
-		if (count++ >= tx_ring->work_limit)
+		if (total_tx_packets >= tx_ring->work_limit)
 			break;
 	}
 
 	tx_ring->next_to_clean = i;
 
-#define TX_WAKE_THRESHOLD 32
-	spin_lock(&tx_ring->tx_lock);
-
-	if (cleaned && netif_carrier_ok(netdev) &&
-	    (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD) &&
-	    !test_bit(__IXGBE_DOWN, &adapter->state))
-		netif_wake_queue(netdev);
-
-	spin_unlock(&tx_ring->tx_lock);
+#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
+	if (total_tx_packets && netif_carrier_ok(netdev) &&
+	    (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
+		/* Make sure that anybody stopping the queue after this
+		 * sees the new next_to_clean.
+		 */
+		smp_mb();
+		if (netif_queue_stopped(netdev) &&
+		    !test_bit(__IXGBE_DOWN, &adapter->state)) {
+			netif_wake_queue(netdev);
+			adapter->restart_queue++;
+		}
+	}
 
 	if (adapter->detect_tx_hung)
 		if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc))
 			netif_stop_queue(netdev);
 
-	if (count >= tx_ring->work_limit)
+	if (total_tx_packets >= tx_ring->work_limit)
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value);
 
+	adapter->net_stats.tx_bytes += total_tx_bytes;
+	adapter->net_stats.tx_packets += total_tx_packets;
+	cleaned = total_tx_packets ? true : false;
 	return cleaned;
 }
 
@@ -255,25 +306,40 @@
 	}
 }
 
+/**
+ * ixgbe_rx_checksum - indicate in skb if hw indicated a good cksum
+ * @adapter: address of board private structure
+ * @status_err: hardware indication of status of receive
+ * @skb: skb currently being received and modified
+ **/
 static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
 					 u32 status_err,
 					 struct sk_buff *skb)
 {
 	skb->ip_summed = CHECKSUM_NONE;
 
-	/* Ignore Checksum bit is set */
+	/* Ignore Checksum bit is set, or rx csum disabled */
 	if ((status_err & IXGBE_RXD_STAT_IXSM) ||
-		     !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
+	    !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED))
 		return;
-	/* TCP/UDP checksum error bit is set */
-	if (status_err & (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE)) {
-		/* let the stack verify checksum errors */
+
+	/* if IP and error */
+	if ((status_err & IXGBE_RXD_STAT_IPCS) &&
+	    (status_err & IXGBE_RXDADV_ERR_IPE)) {
 		adapter->hw_csum_rx_error++;
 		return;
 	}
+
+	if (!(status_err & IXGBE_RXD_STAT_L4CS))
+		return;
+
+	if (status_err & IXGBE_RXDADV_ERR_TCPE) {
+		adapter->hw_csum_rx_error++;
+		return;
+	}
+
 	/* It must be a TCP or UDP packet with a valid checksum */
-	if (status_err & (IXGBE_RXD_STAT_L4CS | IXGBE_RXD_STAT_UDPCS))
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
 	adapter->hw_csum_rx_good++;
 }
 
@@ -379,6 +445,7 @@
 	u16 hdr_info, vlan_tag;
 	bool is_vlan, cleaned = false;
 	int cleaned_count = 0;
+	unsigned int total_rx_bytes = 0, total_rx_packets = 0;
 
 	i = rx_ring->next_to_clean;
 	upper_len = 0;
@@ -458,6 +525,11 @@
 		}
 
 		ixgbe_rx_checksum(adapter, staterr, skb);
+
+		/* probably a little skewed due to removing CRC */
+		total_rx_bytes += skb->len;
+		total_rx_packets++;
+
 		skb->protocol = eth_type_trans(skb, netdev);
 		ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag);
 		netdev->last_rx = jiffies;
@@ -486,6 +558,9 @@
 	if (cleaned_count)
 		ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count);
 
+	adapter->net_stats.rx_bytes += total_rx_bytes;
+	adapter->net_stats.rx_packets += total_rx_packets;
+
 	return cleaned;
 }
 
@@ -535,7 +610,9 @@
 		if (!test_bit(__IXGBE_DOWN, &adapter->state))
 			mod_timer(&adapter->watchdog_timer, jiffies);
 	}
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
+
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
 
 	return IRQ_HANDLED;
 }
@@ -713,7 +790,6 @@
 	if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
 		/* Disable interrupts and register for poll. The flush of the
 		 * posted write is intentionally left out. */
-		atomic_inc(&adapter->irq_sem);
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
 		__netif_rx_schedule(netdev, &adapter->napi);
 	}
@@ -801,7 +877,6 @@
  **/
 static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
 {
-	atomic_inc(&adapter->irq_sem);
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0);
 	IXGBE_WRITE_FLUSH(&adapter->hw);
 	synchronize_irq(adapter->pdev->irq);
@@ -813,15 +888,13 @@
  **/
 static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
 {
-	if (atomic_dec_and_test(&adapter->irq_sem)) {
-		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
-			IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
-					(IXGBE_EIMS_ENABLE_MASK &
-					 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
-				IXGBE_EIMS_ENABLE_MASK);
-		IXGBE_WRITE_FLUSH(&adapter->hw);
-	}
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC,
+				(IXGBE_EIMS_ENABLE_MASK &
+				 ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC)));
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS,
+			IXGBE_EIMS_ENABLE_MASK);
+	IXGBE_WRITE_FLUSH(&adapter->hw);
 }
 
 /**
@@ -1040,7 +1113,8 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	u32 ctrl;
 
-	ixgbe_irq_disable(adapter);
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		ixgbe_irq_disable(adapter);
 	adapter->vlgrp = grp;
 
 	if (grp) {
@@ -1051,7 +1125,8 @@
 		IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
 	}
 
-	ixgbe_irq_enable(adapter);
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		ixgbe_irq_enable(adapter);
 }
 
 static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
@@ -1066,9 +1141,13 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	ixgbe_irq_disable(adapter);
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		ixgbe_irq_disable(adapter);
+
 	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-	ixgbe_irq_enable(adapter);
+
+	if (!test_bit(__IXGBE_DOWN, &adapter->state))
+		ixgbe_irq_enable(adapter);
 
 	/* remove VID from filter table */
 	ixgbe_set_vfta(&adapter->hw, vid, 0, false);
@@ -1170,6 +1249,8 @@
 	u32 txdctl, rxdctl, mhadd;
 	int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
+	ixgbe_get_hw_control(adapter);
+
 	if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED |
 			      IXGBE_FLAG_MSI_ENABLED)) {
 		if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
@@ -1224,6 +1305,16 @@
 	return 0;
 }
 
+void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
+{
+	WARN_ON(in_interrupt());
+	while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
+		msleep(1);
+	ixgbe_down(adapter);
+	ixgbe_up(adapter);
+	clear_bit(__IXGBE_RESETTING, &adapter->state);
+}
+
 int ixgbe_up(struct ixgbe_adapter *adapter)
 {
 	/* hardware has been reset, we need to reload some things */
@@ -1408,7 +1499,6 @@
 	msleep(10);
 
 	napi_disable(&adapter->napi);
-	atomic_set(&adapter->irq_sem, 0);
 
 	ixgbe_irq_disable(adapter);
 
@@ -1447,6 +1537,8 @@
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 	pci_enable_wake(pdev, PCI_D3cold, 0);
 
+	ixgbe_release_hw_control(adapter);
+
 	pci_disable_device(pdev);
 
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1481,7 +1573,8 @@
 	/* If budget not fully consumed, exit the polling mode */
 	if (work_done < budget) {
 		netif_rx_complete(netdev, napi);
-		ixgbe_irq_enable(adapter);
+		if (!test_bit(__IXGBE_DOWN, &adapter->state))
+			ixgbe_irq_enable(adapter);
 	}
 
 	return work_done;
@@ -1506,8 +1599,7 @@
 
 	adapter->tx_timeout_count++;
 
-	ixgbe_down(adapter);
-	ixgbe_up(adapter);
+	ixgbe_reinit_locked(adapter);
 }
 
 /**
@@ -1590,7 +1682,6 @@
 		return -ENOMEM;
 	}
 
-	atomic_set(&adapter->irq_sem, 1);
 	set_bit(__IXGBE_DOWN, &adapter->state);
 
 	return 0;
@@ -1634,7 +1725,6 @@
 	txdr->next_to_use = 0;
 	txdr->next_to_clean = 0;
 	txdr->work_limit = txdr->count;
-	spin_lock_init(&txdr->tx_lock);
 
 	return 0;
 }
@@ -1828,10 +1918,8 @@
 
 	netdev->mtu = new_mtu;
 
-	if (netif_running(netdev)) {
-		ixgbe_down(adapter);
-		ixgbe_up(adapter);
-	}
+	if (netif_running(netdev))
+		ixgbe_reinit_locked(adapter);
 
 	return 0;
 }
@@ -1852,14 +1940,8 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int err;
-	u32 ctrl_ext;
 	u32 num_rx_queues = adapter->num_rx_queues;
 
-	/* Let firmware know the driver has taken over */
-	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
-			ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);
-
 try_intr_reinit:
 	/* allocate transmit descriptors */
 	err = ixgbe_setup_all_tx_resources(adapter);
@@ -1910,6 +1992,7 @@
 	return 0;
 
 err_up:
+	ixgbe_release_hw_control(adapter);
 	ixgbe_free_irq(adapter);
 err_req_irq:
 	ixgbe_free_all_rx_resources(adapter);
@@ -1935,7 +2018,6 @@
 static int ixgbe_close(struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u32 ctrl_ext;
 
 	ixgbe_down(adapter);
 	ixgbe_free_irq(adapter);
@@ -1943,9 +2025,7 @@
 	ixgbe_free_all_tx_resources(adapter);
 	ixgbe_free_all_rx_resources(adapter);
 
-	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT,
-			ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD);
+	ixgbe_release_hw_control(adapter);
 
 	return 0;
 }
@@ -1957,22 +2037,26 @@
 void ixgbe_update_stats(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u64 good_rx, missed_rx, bprc;
+	u64 total_mpc = 0;
+	u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot;
 
 	adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS);
-	good_rx = IXGBE_READ_REG(hw, IXGBE_GPRC);
-	missed_rx = IXGBE_READ_REG(hw, IXGBE_MPC(0));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(1));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(2));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(3));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(4));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(5));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(6));
-	missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(7));
-	adapter->stats.gprc += (good_rx - missed_rx);
+	for (i = 0; i < 8; i++) {
+		/* for packet buffers not used, the register should read 0 */
+		mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i));
+		missed_rx += mpc;
+		adapter->stats.mpc[i] += mpc;
+		total_mpc += adapter->stats.mpc[i];
+		adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+	}
+	adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
+	/* work around hardware counting issue */
+	adapter->stats.gprc -= missed_rx;
 
-	adapter->stats.mpc[0] += missed_rx;
+	/* 82598 hardware only has a 32 bit counter in the high register */
 	adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH);
+	adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
+	adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
 	bprc = IXGBE_READ_REG(hw, IXGBE_BPRC);
 	adapter->stats.bprc += bprc;
 	adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC);
@@ -1984,35 +2068,37 @@
 	adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511);
 	adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
 	adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
-
 	adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
 	adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC);
-	adapter->stats.lxontxc += IXGBE_READ_REG(hw, IXGBE_LXONTXC);
 	adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
-	adapter->stats.lxofftxc += IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
+	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
+	adapter->stats.lxontxc += lxon;
+	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
+	adapter->stats.lxofftxc += lxoff;
 	adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
 	adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC);
-	adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH);
-	adapter->stats.rnbc[0] += IXGBE_READ_REG(hw, IXGBE_RNBC(0));
+	adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+	/*
+	 * 82598 errata - tx of flow control packets is included in tx counters
+	 */
+	xon_off_tot = lxon + lxoff;
+	adapter->stats.gptc -= xon_off_tot;
+	adapter->stats.mptc -= xon_off_tot;
+	adapter->stats.gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN));
 	adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
 	adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
 	adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC);
-	adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH);
 	adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR);
 	adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+	adapter->stats.ptc64 -= xon_off_tot;
 	adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127);
 	adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255);
 	adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511);
 	adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023);
 	adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522);
-	adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
 	adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC);
 
 	/* Fill out the OS statistics structure */
-	adapter->net_stats.rx_packets = adapter->stats.gprc;
-	adapter->net_stats.tx_packets = adapter->stats.gptc;
-	adapter->net_stats.rx_bytes = adapter->stats.gorc;
-	adapter->net_stats.tx_bytes = adapter->stats.gotc;
 	adapter->net_stats.multicast = adapter->stats.mprc;
 
 	/* Rx Errors */
@@ -2021,8 +2107,7 @@
 	adapter->net_stats.rx_dropped = 0;
 	adapter->net_stats.rx_length_errors = adapter->stats.rlec;
 	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
-	adapter->net_stats.rx_missed_errors = adapter->stats.mpc[0];
-
+	adapter->net_stats.rx_missed_errors = total_mpc;
 }
 
 /**
@@ -2076,15 +2161,6 @@
 			  round_jiffies(jiffies + 2 * HZ));
 }
 
-#define IXGBE_MAX_TXD_PWR	14
-#define IXGBE_MAX_DATA_PER_TXD	(1 << IXGBE_MAX_TXD_PWR)
-
-/* Tx Descriptors needed, worst case */
-#define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \
-			 (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
-#define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \
-	MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1)	/* for context */
-
 static int ixgbe_tso(struct ixgbe_adapter *adapter,
 			 struct ixgbe_ring *tx_ring, struct sk_buff *skb,
 			 u32 tx_flags, u8 *hdr_len)
@@ -2356,6 +2432,37 @@
 	writel(i, adapter->hw.hw_addr + tx_ring->tail);
 }
 
+static int __ixgbe_maybe_stop_tx(struct net_device *netdev,
+				 struct ixgbe_ring *tx_ring, int size)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+	netif_stop_queue(netdev);
+	/* Herbert's original patch had:
+	 *  smp_mb__after_netif_stop_queue();
+	 * but since that doesn't exist yet, just open code it. */
+	smp_mb();
+
+	/* We need to check again in a case another CPU has just
+	 * made room available. */
+	if (likely(IXGBE_DESC_UNUSED(tx_ring) < size))
+		return -EBUSY;
+
+	/* A reprieve! - use start_queue because it doesn't call schedule */
+	netif_wake_queue(netdev);
+	++adapter->restart_queue;
+	return 0;
+}
+
+static int ixgbe_maybe_stop_tx(struct net_device *netdev,
+			       struct ixgbe_ring *tx_ring, int size)
+{
+	if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size))
+		return 0;
+	return __ixgbe_maybe_stop_tx(netdev, tx_ring, size);
+}
+
+
 static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -2363,7 +2470,6 @@
 	unsigned int len = skb->len;
 	unsigned int first;
 	unsigned int tx_flags = 0;
-	unsigned long flags = 0;
 	u8 hdr_len;
 	int tso;
 	unsigned int mss = 0;
@@ -2389,14 +2495,10 @@
 	for (f = 0; f < nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
 
-	spin_lock_irqsave(&tx_ring->tx_lock, flags);
-	if (IXGBE_DESC_UNUSED(tx_ring) < (count + 2)) {
+	if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) {
 		adapter->tx_busy++;
-		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
-	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
 	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT);
@@ -2423,11 +2525,7 @@
 
 	netdev->trans_start = jiffies;
 
-	spin_lock_irqsave(&tx_ring->tx_lock, flags);
-	/* Make sure there is space in the ring for the next send. */
-	if (IXGBE_DESC_UNUSED(tx_ring) < DESC_NEEDED)
-		netif_stop_queue(netdev);
-	spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
+	ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED);
 
 	return NETDEV_TX_OK;
 }
@@ -2697,6 +2795,7 @@
 	return 0;
 
 err_register:
+	ixgbe_release_hw_control(adapter);
 err_hw_init:
 err_sw_init:
 err_eeprom:
@@ -2732,6 +2831,8 @@
 
 	unregister_netdev(netdev);
 
+	ixgbe_release_hw_control(adapter);
+
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
 
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 651c269..b528ce7 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1652,6 +1652,11 @@
 	}
 }
 
+static inline __be16 sum16_as_be(__sum16 sum)
+{
+	return (__force __be16)sum;
+}
+
 /**
  * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw
  *
@@ -1689,7 +1694,7 @@
 	desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE);
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		BUG_ON(skb->protocol != ETH_P_IP);
+		BUG_ON(skb->protocol != htons(ETH_P_IP));
 
 		cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
 			   ETH_GEN_IP_V_4_CHECKSUM  |
@@ -1698,10 +1703,10 @@
 		switch (ip_hdr(skb)->protocol) {
 		case IPPROTO_UDP:
 			cmd_sts |= ETH_UDP_FRAME;
-			desc->l4i_chk = udp_hdr(skb)->check;
+			desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check));
 			break;
 		case IPPROTO_TCP:
-			desc->l4i_chk = tcp_hdr(skb)->check;
+			desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check));
 			break;
 		default:
 			BUG();
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 1b51bb6..5aa0a80 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -2468,9 +2468,10 @@
 
 out:
 	return err;
-
+#ifdef CONFIG_PROC_FS
 out_unregister_pppox_proto:
 	unregister_pppox_proto(PX_PROTO_OL2TP);
+#endif
 out_unregister_pppol2tp_proto:
 	proto_unregister(&pppol2tp_sk_proto);
 	goto out;
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index dc06236..9a62959 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -857,7 +857,7 @@
 	sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 
 	/* On chips without ram buffer, pause is controled by MAC level */
-	if (sky2_read8(hw, B2_E_0) == 0) {
+	if (!(hw->flags & SKY2_HW_RAM_BUFFER)) {
 		sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
 		sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
 
@@ -1194,7 +1194,7 @@
 	struct sk_buff *skb;
 	int i;
 
-	if (sky2->hw->flags & SKY2_HW_FIFO_HANG_CHECK) {
+	if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) {
 		unsigned char *start;
 		/*
 		 * Workaround for a bug in FIFO that cause hang
@@ -1387,6 +1387,7 @@
 	if (ramsize > 0) {
 		u32 rxspace;
 
+		hw->flags |= SKY2_HW_RAM_BUFFER;
 		pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
 		if (ramsize < 16)
 			rxspace = ramsize / 2;
@@ -2026,7 +2027,7 @@
 
 	synchronize_irq(hw->pdev->irq);
 
-	if (sky2_read8(hw, B2_E_0) == 0)
+	if (!(hw->flags & SKY2_HW_RAM_BUFFER))
 		sky2_set_tx_stfwd(hw, port);
 
 	ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2566,7 +2567,7 @@
 			++active;
 
 			/* For chips with Rx FIFO, check if stuck */
-			if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) &&
+			if ((hw->flags & SKY2_HW_RAM_BUFFER) &&
 			     sky2_rx_hung(dev)) {
 				pr_info(PFX "%s: receiver hang detected\n",
 					dev->name);
@@ -2722,11 +2723,7 @@
 
 	switch(hw->chip_id) {
 	case CHIP_ID_YUKON_XL:
-		hw->flags = SKY2_HW_GIGABIT
-			| SKY2_HW_NEWER_PHY;
-		if (hw->chip_rev < 3)
-			hw->flags |= SKY2_HW_FIFO_HANG_CHECK;
-
+		hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY;
 		break;
 
 	case CHIP_ID_YUKON_EC_U:
@@ -2752,7 +2749,7 @@
 			dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
 			return -EOPNOTSUPP;
 		}
-		hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK;
+		hw->flags = SKY2_HW_GIGABIT;
 		break;
 
 	case CHIP_ID_YUKON_FE:
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 2bced1a..5ab5c1c 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2045,7 +2045,7 @@
 #define SKY2_HW_FIBRE_PHY	0x00000002
 #define SKY2_HW_GIGABIT		0x00000004
 #define SKY2_HW_NEWER_PHY	0x00000008
-#define SKY2_HW_FIFO_HANG_CHECK	0x00000010
+#define SKY2_HW_RAM_BUFFER	0x00000010
 #define SKY2_HW_NEW_LE		0x00000020	/* new LSOv2 format */
 #define SKY2_HW_AUTO_TX_SUM	0x00000040	/* new IP decode for Tx */
 #define SKY2_HW_ADV_POWER_CTL	0x00000080	/* additional PHY power regs */
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index c99ce74..3af5b92 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -465,7 +465,7 @@
 
 static int __init tlan_probe(void)
 {
-	static int	pad_allocated;
+	int rc = -ENODEV;
 
 	printk(KERN_INFO "%s", tlan_banner);
 
@@ -473,17 +473,22 @@
 
 	if (TLanPadBuffer == NULL) {
 		printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto err_out;
 	}
 
 	memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE);
-	pad_allocated = 1;
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");
 
 	/* Use new style PCI probing. Now the kernel will
 	   do most of this for us */
-	pci_register_driver(&tlan_driver);
+	rc = pci_register_driver(&tlan_driver);
+
+	if (rc != 0) {
+		printk(KERN_ERR "TLAN: Could not register pci driver.\n");
+		goto err_out_pci_free;
+	}
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");
 	TLan_EisaProbe();
@@ -493,11 +498,17 @@
 		 tlan_have_pci, tlan_have_eisa);
 
 	if (TLanDevicesInstalled == 0) {
-		pci_unregister_driver(&tlan_driver);
-		pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto  err_out_pci_unreg;
 	}
 	return 0;
+
+err_out_pci_unreg:
+	pci_unregister_driver(&tlan_driver);
+err_out_pci_free:
+	pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA);
+err_out:
+	return rc;
 }
 
 
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 8fc7274..6b93d016 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -441,7 +441,7 @@
 	spin_unlock_irqrestore(&card->lock,flags);
 	trigger_transmit(card);
 
-	return -EIO;
+	return NETDEV_TX_BUSY;
 }
 
 
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
index e3ba14a..c69e654 100644
--- a/drivers/net/ucc_geth_mii.c
+++ b/drivers/net/ucc_geth_mii.c
@@ -109,7 +109,7 @@
 	struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv;
 	unsigned int timeout = PHY_INIT_TIMEOUT;
 
-	spin_lock_bh(&bus->mdio_lock);
+	mutex_lock(&bus->mdio_lock);
 
 	/* Reset the management interface */
 	out_be32(&regs->miimcfg, MIIMCFG_RESET_MANAGEMENT);
@@ -121,7 +121,7 @@
 	while ((in_be32(&regs->miimind) & MIIMIND_BUSY) && timeout--)
 		cpu_relax();
 
-	spin_unlock_bh(&bus->mdio_lock);
+	mutex_unlock(&bus->mdio_lock);
 
 	if (timeout <= 0) {
 		printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e66de0c..fdc2367 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -302,10 +302,12 @@
 
 	/* If all buffers were filled by other side before we napi_enabled, we
 	 * won't get another interrupt, so process any outstanding packets
-	 * now.  virtnet_poll wants re-enable the queue, so we disable here. */
-	vi->rvq->vq_ops->disable_cb(vi->rvq);
-	netif_rx_schedule(vi->dev, &vi->napi);
-
+	 * now.  virtnet_poll wants re-enable the queue, so we disable here.
+	 * We synchronize against interrupts via NAPI_STATE_SCHED */
+	if (netif_rx_schedule_prep(dev, &vi->napi)) {
+		vi->rvq->vq_ops->disable_cb(vi->rvq);
+		__netif_rx_schedule(dev, &vi->napi);
+	}
 	return 0;
 }
 
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index d553e6f..39951d0 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -1,7 +1,7 @@
 /*
  * Generic HDLC support routines for Linux
  *
- * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -39,7 +39,7 @@
 #include <net/net_namespace.h>
 
 
-static const char* version = "HDLC support module revision 1.21";
+static const char* version = "HDLC support module revision 1.22";
 
 #undef DEBUG_LINK
 
@@ -66,19 +66,15 @@
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
 		    struct packet_type *p, struct net_device *orig_dev)
 {
-	struct hdlc_device_desc *desc = dev_to_desc(dev);
+	struct hdlc_device *hdlc = dev_to_hdlc(dev);
 
 	if (dev->nd_net != &init_net) {
 		kfree_skb(skb);
 		return 0;
 	}
 
-	if (desc->netif_rx)
-		return desc->netif_rx(skb);
-
-	desc->stats.rx_dropped++; /* Shouldn't happen */
-	dev_kfree_skb(skb);
-	return NET_RX_DROP;
+	BUG_ON(!hdlc->proto->netif_rx);
+	return hdlc->proto->netif_rx(skb);
 }
 
 
@@ -87,7 +83,7 @@
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	if (hdlc->proto->start)
-		return hdlc->proto->start(dev);
+		hdlc->proto->start(dev);
 }
 
 
@@ -96,7 +92,7 @@
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	if (hdlc->proto->stop)
-		return hdlc->proto->stop(dev);
+		hdlc->proto->stop(dev);
 }
 
 
@@ -263,8 +259,7 @@
 struct net_device *alloc_hdlcdev(void *priv)
 {
 	struct net_device *dev;
-	dev = alloc_netdev(sizeof(struct hdlc_device_desc) +
-			   sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+	dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", hdlc_setup);
 	if (dev)
 		dev_to_hdlc(dev)->priv = priv;
 	return dev;
@@ -281,7 +276,7 @@
 
 
 int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
-			 int (*rx)(struct sk_buff *skb), size_t size)
+			 size_t size)
 {
 	detach_hdlc_protocol(dev);
 
@@ -297,7 +292,6 @@
 			return -ENOBUFS;
 		}
 	dev_to_hdlc(dev)->proto = proto;
-	dev_to_desc(dev)->netif_rx = rx;
 	return 0;
 }
 
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 038a6e7..7133c68 100644
--- a/drivers/net/wan/hdlc_cisco.c
+++ b/drivers/net/wan/hdlc_cisco.c
@@ -250,7 +250,7 @@
 	return NET_RX_DROP;
 
  rx_error:
-	dev_to_desc(dev)->stats.rx_errors++; /* Mark error */
+	dev_to_hdlc(dev)->stats.rx_errors++; /* Mark error */
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
@@ -314,6 +314,7 @@
 	.stop		= cisco_stop,
 	.type_trans	= cisco_type_trans,
 	.ioctl		= cisco_ioctl,
+	.netif_rx	= cisco_rx,
 	.module		= THIS_MODULE,
 };
 
@@ -360,7 +361,7 @@
 		if (result)
 			return result;
 
-		result = attach_hdlc_protocol(dev, &proto, cisco_rx,
+		result = attach_hdlc_protocol(dev, &proto,
 					      sizeof(struct cisco_state));
 		if (result)
 			return result;
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 071a64c..c4ab032 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -42,7 +42,6 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/pkt_sched.h>
-#include <linux/random.h>
 #include <linux/inetdevice.h>
 #include <linux/lapb.h>
 #include <linux/rtnetlink.h>
@@ -136,6 +135,10 @@
 	}state;
 }pvc_device;
 
+struct pvc_desc {
+	struct net_device_stats stats;
+	pvc_device *pvc;
+};
 
 struct frad_state {
 	fr_proto settings;
@@ -171,17 +174,20 @@
 }
 
 
-static inline struct frad_state * state(hdlc_device *hdlc)
+static inline struct frad_state* state(hdlc_device *hdlc)
 {
 	return(struct frad_state *)(hdlc->state);
 }
 
-
-static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+static inline struct pvc_desc* pvcdev_to_desc(struct net_device *dev)
 {
 	return dev->priv;
 }
 
+static inline struct net_device_stats* pvc_get_stats(struct net_device *dev)
+{
+	return &pvcdev_to_desc(dev)->stats;
+}
 
 static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 {
@@ -351,7 +357,7 @@
 
 static int pvc_open(struct net_device *dev)
 {
-	pvc_device *pvc = dev_to_pvc(dev);
+	pvc_device *pvc = pvcdev_to_desc(dev)->pvc;
 
 	if ((pvc->frad->flags & IFF_UP) == 0)
 		return -EIO;  /* Frad must be UP in order to activate PVC */
@@ -371,7 +377,7 @@
 
 static int pvc_close(struct net_device *dev)
 {
-	pvc_device *pvc = dev_to_pvc(dev);
+	pvc_device *pvc = pvcdev_to_desc(dev)->pvc;
 
 	if (--pvc->open_count == 0) {
 		hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
@@ -390,7 +396,7 @@
 
 static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	pvc_device *pvc = dev_to_pvc(dev);
+	pvc_device *pvc = pvcdev_to_desc(dev)->pvc;
 	fr_proto_pvc_info info;
 
 	if (ifr->ifr_settings.type == IF_GET_PROTO) {
@@ -416,17 +422,9 @@
 	return -EINVAL;
 }
 
-
-static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
-{
-	return &dev_to_desc(dev)->stats;
-}
-
-
-
 static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	pvc_device *pvc = dev_to_pvc(dev);
+	pvc_device *pvc = pvcdev_to_desc(dev)->pvc;
 	struct net_device_stats *stats = pvc_get_stats(dev);
 
 	if (pvc->state.active) {
@@ -957,7 +955,7 @@
 
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-		dev_to_desc(frad)->stats.rx_dropped++;
+		dev_to_hdlc(frad)->stats.rx_dropped++;
 		return NET_RX_DROP;
 	}
 
@@ -1018,7 +1016,7 @@
 	}
 
  rx_error:
-	dev_to_desc(frad)->stats.rx_errors++; /* Mark error */
+	dev_to_hdlc(frad)->stats.rx_errors++; /* Mark error */
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
@@ -1109,11 +1107,10 @@
 	used = pvc_is_used(pvc);
 
 	if (type == ARPHRD_ETHER)
-		dev = alloc_netdev(sizeof(struct net_device_stats),
-				   "pvceth%d", ether_setup);
+		dev = alloc_netdev(sizeof(struct pvc_desc), "pvceth%d",
+				   ether_setup);
 	else
-		dev = alloc_netdev(sizeof(struct net_device_stats),
-				   "pvc%d", pvc_setup);
+		dev = alloc_netdev(sizeof(struct pvc_desc), "pvc%d", pvc_setup);
 
 	if (!dev) {
 		printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
@@ -1122,10 +1119,9 @@
 		return -ENOBUFS;
 	}
 
-	if (type == ARPHRD_ETHER) {
-		memcpy(dev->dev_addr, "\x00\x01", 2);
-                get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
-	} else {
+	if (type == ARPHRD_ETHER)
+		random_ether_addr(dev->dev_addr);
+	else {
 		*(__be16*)dev->dev_addr = htons(dlci);
 		dlci_to_q922(dev->broadcast, dlci);
 	}
@@ -1137,7 +1133,7 @@
 	dev->change_mtu = pvc_change_mtu;
 	dev->mtu = HDLC_MAX_MTU;
 	dev->tx_queue_len = 0;
-	dev->priv = pvc;
+	pvcdev_to_desc(dev)->pvc = pvc;
 
 	result = dev_alloc_name(dev, dev->name);
 	if (result < 0) {
@@ -1219,6 +1215,7 @@
 	.stop		= fr_stop,
 	.detach		= fr_destroy,
 	.ioctl		= fr_ioctl,
+	.netif_rx	= fr_rx,
 	.module		= THIS_MODULE,
 };
 
@@ -1277,7 +1274,7 @@
 			return result;
 
 		if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */
-			result = attach_hdlc_protocol(dev, &proto, fr_rx,
+			result = attach_hdlc_protocol(dev, &proto,
 						      sizeof(struct frad_state));
 			if (result)
 				return result;
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 519e155..10396d9 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -122,7 +122,7 @@
 		if (result)
 			return result;
 
-		result = attach_hdlc_protocol(dev, &proto, NULL,
+		result = attach_hdlc_protocol(dev, &proto,
 					      sizeof(struct ppp_state));
 		if (result)
 			return result;
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c
index e23bc66..bbbb819 100644
--- a/drivers/net/wan/hdlc_raw.c
+++ b/drivers/net/wan/hdlc_raw.c
@@ -82,7 +82,7 @@
 		if (result)
 			return result;
 
-		result = attach_hdlc_protocol(dev, &proto, NULL,
+		result = attach_hdlc_protocol(dev, &proto,
 					      sizeof(raw_hdlc_proto));
 		if (result)
 			return result;
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c
index 8895394..d20c685 100644
--- a/drivers/net/wan/hdlc_raw_eth.c
+++ b/drivers/net/wan/hdlc_raw_eth.c
@@ -18,7 +18,6 @@
 #include <linux/init.h>
 #include <linux/skbuff.h>
 #include <linux/pkt_sched.h>
-#include <linux/random.h>
 #include <linux/inetdevice.h>
 #include <linux/lapb.h>
 #include <linux/rtnetlink.h>
@@ -96,7 +95,7 @@
 		if (result)
 			return result;
 
-		result = attach_hdlc_protocol(dev, &proto, NULL,
+		result = attach_hdlc_protocol(dev, &proto,
 					      sizeof(raw_hdlc_proto));
 		if (result)
 			return result;
@@ -107,8 +106,7 @@
 		ether_setup(dev);
 		dev->change_mtu = old_ch_mtu;
 		dev->tx_queue_len = old_qlen;
-		memcpy(dev->dev_addr, "\x00\x01", 2);
-                get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
+		random_ether_addr(dev->dev_addr);
 		netif_dormant_off(dev);
 		return 0;
 	}
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c
index cd7b22f..c15cc11 100644
--- a/drivers/net/wan/hdlc_x25.c
+++ b/drivers/net/wan/hdlc_x25.c
@@ -164,17 +164,17 @@
 
 static int x25_rx(struct sk_buff *skb)
 {
-	struct hdlc_device_desc *desc = dev_to_desc(skb->dev);
+	struct hdlc_device *hdlc = dev_to_hdlc(skb->dev);
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-		desc->stats.rx_dropped++;
+		hdlc->stats.rx_dropped++;
 		return NET_RX_DROP;
 	}
 
 	if (lapb_data_received(skb->dev, skb) == LAPB_OK)
 		return NET_RX_SUCCESS;
 
-	desc->stats.rx_errors++;
+	hdlc->stats.rx_errors++;
 	dev_kfree_skb_any(skb);
 	return NET_RX_DROP;
 }
@@ -184,6 +184,7 @@
 	.open		= x25_open,
 	.close		= x25_close,
 	.ioctl		= x25_ioctl,
+	.netif_rx	= x25_rx,
 	.module		= THIS_MODULE,
 };
 
@@ -211,8 +212,7 @@
 		if (result)
 			return result;
 
-		if ((result = attach_hdlc_protocol(dev, &proto,
-						   x25_rx, 0)) != 0)
+		if ((result = attach_hdlc_protocol(dev, &proto, 0)))
 			return result;
 		dev->hard_start_xmit = x25_xmit;
 		dev->type = ARPHRD_X25;
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 8a708b7..3dfb28a 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -337,7 +337,7 @@
 	return idx_to_prio[index];
 }
 
-u16 b43_dmacontroller_base(int dma64bit, int controller_idx)
+static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx)
 {
 	static const u16 map64[] = {
 		B43_MMIO_DMA64_BASE0,
@@ -356,7 +356,7 @@
 		B43_MMIO_DMA32_BASE5,
 	};
 
-	if (dma64bit) {
+	if (type == B43_DMA_64BIT) {
 		B43_WARN_ON(!(controller_idx >= 0 &&
 			      controller_idx < ARRAY_SIZE(map64)));
 		return map64[controller_idx];
@@ -437,7 +437,7 @@
 	 * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
 	 * which accounts for the GFP_DMA flag below.
 	 */
-	if (ring->dma64)
+	if (ring->type == B43_DMA_64BIT)
 		flags |= GFP_DMA;
 	ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
 					    &(ring->dmabase), flags);
@@ -459,7 +459,8 @@
 }
 
 /* Reset the RX DMA channel */
-int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
+static int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base,
+				      enum b43_dmatype type)
 {
 	int i;
 	u32 value;
@@ -467,12 +468,13 @@
 
 	might_sleep();
 
-	offset = dma64 ? B43_DMA64_RXCTL : B43_DMA32_RXCTL;
+	offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXCTL : B43_DMA32_RXCTL;
 	b43_write32(dev, mmio_base + offset, 0);
 	for (i = 0; i < 10; i++) {
-		offset = dma64 ? B43_DMA64_RXSTATUS : B43_DMA32_RXSTATUS;
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXSTATUS :
+						   B43_DMA32_RXSTATUS;
 		value = b43_read32(dev, mmio_base + offset);
-		if (dma64) {
+		if (type == B43_DMA_64BIT) {
 			value &= B43_DMA64_RXSTAT;
 			if (value == B43_DMA64_RXSTAT_DISABLED) {
 				i = -1;
@@ -496,7 +498,8 @@
 }
 
 /* Reset the TX DMA channel */
-int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
+static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base,
+				      enum b43_dmatype type)
 {
 	int i;
 	u32 value;
@@ -505,9 +508,10 @@
 	might_sleep();
 
 	for (i = 0; i < 10; i++) {
-		offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS;
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS :
+						   B43_DMA32_TXSTATUS;
 		value = b43_read32(dev, mmio_base + offset);
-		if (dma64) {
+		if (type == B43_DMA_64BIT) {
 			value &= B43_DMA64_TXSTAT;
 			if (value == B43_DMA64_TXSTAT_DISABLED ||
 			    value == B43_DMA64_TXSTAT_IDLEWAIT ||
@@ -522,12 +526,13 @@
 		}
 		msleep(1);
 	}
-	offset = dma64 ? B43_DMA64_TXCTL : B43_DMA32_TXCTL;
+	offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXCTL : B43_DMA32_TXCTL;
 	b43_write32(dev, mmio_base + offset, 0);
 	for (i = 0; i < 10; i++) {
-		offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS;
+		offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS :
+						   B43_DMA32_TXSTATUS;
 		value = b43_read32(dev, mmio_base + offset);
-		if (dma64) {
+		if (type == B43_DMA_64BIT) {
 			value &= B43_DMA64_TXSTAT;
 			if (value == B43_DMA64_TXSTAT_DISABLED) {
 				i = -1;
@@ -552,6 +557,33 @@
 	return 0;
 }
 
+/* Check if a DMA mapping address is invalid. */
+static bool b43_dma_mapping_error(struct b43_dmaring *ring,
+				  dma_addr_t addr,
+				  size_t buffersize)
+{
+	if (unlikely(dma_mapping_error(addr)))
+		return 1;
+
+	switch (ring->type) {
+	case B43_DMA_30BIT:
+		if ((u64)addr + buffersize > (1ULL << 30))
+			return 1;
+		break;
+	case B43_DMA_32BIT:
+		if ((u64)addr + buffersize > (1ULL << 32))
+			return 1;
+		break;
+	case B43_DMA_64BIT:
+		/* Currently we can't have addresses beyond
+		 * 64bit in the kernel. */
+		break;
+	}
+
+	/* The address is OK. */
+	return 0;
+}
+
 static int setup_rx_descbuffer(struct b43_dmaring *ring,
 			       struct b43_dmadesc_generic *desc,
 			       struct b43_dmadesc_meta *meta, gfp_t gfp_flags)
@@ -567,7 +599,7 @@
 	if (unlikely(!skb))
 		return -ENOMEM;
 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
-	if (dma_mapping_error(dmaaddr)) {
+	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
 		/* ugh. try to realloc in zone_dma */
 		gfp_flags |= GFP_DMA;
 
@@ -580,7 +612,7 @@
 					 ring->rx_buffersize, 0);
 	}
 
-	if (dma_mapping_error(dmaaddr)) {
+	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
 		dev_kfree_skb_any(skb);
 		return -EIO;
 	}
@@ -645,7 +677,7 @@
 	u32 trans = ssb_dma_translation(ring->dev->dev);
 
 	if (ring->tx) {
-		if (ring->dma64) {
+		if (ring->type == B43_DMA_64BIT) {
 			u64 ringbase = (u64) (ring->dmabase);
 
 			addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
@@ -677,7 +709,7 @@
 		err = alloc_initial_descbuffers(ring);
 		if (err)
 			goto out;
-		if (ring->dma64) {
+		if (ring->type == B43_DMA_64BIT) {
 			u64 ringbase = (u64) (ring->dmabase);
 
 			addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
@@ -722,16 +754,16 @@
 {
 	if (ring->tx) {
 		b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
-					   ring->dma64);
-		if (ring->dma64) {
+					   ring->type);
+		if (ring->type == B43_DMA_64BIT) {
 			b43_dma_write(ring, B43_DMA64_TXRINGLO, 0);
 			b43_dma_write(ring, B43_DMA64_TXRINGHI, 0);
 		} else
 			b43_dma_write(ring, B43_DMA32_TXRING, 0);
 	} else {
 		b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
-					   ring->dma64);
-		if (ring->dma64) {
+					   ring->type);
+		if (ring->type == B43_DMA_64BIT) {
 			b43_dma_write(ring, B43_DMA64_RXRINGLO, 0);
 			b43_dma_write(ring, B43_DMA64_RXRINGHI, 0);
 		} else
@@ -786,7 +818,8 @@
 static
 struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
 				      int controller_index,
-				      int for_tx, int dma64)
+				      int for_tx,
+				      enum b43_dmatype type)
 {
 	struct b43_dmaring *ring;
 	int err;
@@ -796,6 +829,7 @@
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
 		goto out;
+	ring->type = type;
 
 	nr_slots = B43_RXRING_SLOTS;
 	if (for_tx)
@@ -818,7 +852,7 @@
 					  b43_txhdr_size(dev),
 					  DMA_TO_DEVICE);
 
-		if (dma_mapping_error(dma_test)) {
+		if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) {
 			/* ugh realloc */
 			kfree(ring->txhdr_cache);
 			ring->txhdr_cache = kcalloc(nr_slots,
@@ -832,7 +866,8 @@
 						  b43_txhdr_size(dev),
 						  DMA_TO_DEVICE);
 
-			if (dma_mapping_error(dma_test))
+			if (b43_dma_mapping_error(ring, dma_test,
+						  b43_txhdr_size(dev)))
 				goto err_kfree_txhdr_cache;
 		}
 
@@ -843,10 +878,9 @@
 
 	ring->dev = dev;
 	ring->nr_slots = nr_slots;
-	ring->mmio_base = b43_dmacontroller_base(dma64, controller_index);
+	ring->mmio_base = b43_dmacontroller_base(type, controller_index);
 	ring->index = controller_index;
-	ring->dma64 = !!dma64;
-	if (dma64)
+	if (type == B43_DMA_64BIT)
 		ring->ops = &dma64_ops;
 	else
 		ring->ops = &dma32_ops;
@@ -896,8 +930,8 @@
 	if (!ring)
 		return;
 
-	b43dbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots: %d/%d\n",
-	       (ring->dma64) ? "64" : "32",
+	b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n",
+	       (unsigned int)(ring->type),
 	       ring->mmio_base,
 	       (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots);
 	/* Device IRQs are disabled prior entering this function,
@@ -941,12 +975,22 @@
 	struct b43_dmaring *ring;
 	int err;
 	u64 dmamask;
-	int dma64 = 0;
+	enum b43_dmatype type;
 
 	dmamask = supported_dma_mask(dev);
-	if (dmamask == DMA_64BIT_MASK)
-		dma64 = 1;
-
+	switch (dmamask) {
+	default:
+		B43_WARN_ON(1);
+	case DMA_30BIT_MASK:
+		type = B43_DMA_30BIT;
+		break;
+	case DMA_32BIT_MASK:
+		type = B43_DMA_32BIT;
+		break;
+	case DMA_64BIT_MASK:
+		type = B43_DMA_64BIT;
+		break;
+	}
 	err = ssb_dma_set_mask(dev->dev, dmamask);
 	if (err) {
 		b43err(dev->wl, "The machine/kernel does not support "
@@ -958,52 +1002,51 @@
 
 	err = -ENOMEM;
 	/* setup TX DMA channels. */
-	ring = b43_setup_dmaring(dev, 0, 1, dma64);
+	ring = b43_setup_dmaring(dev, 0, 1, type);
 	if (!ring)
 		goto out;
 	dma->tx_ring0 = ring;
 
-	ring = b43_setup_dmaring(dev, 1, 1, dma64);
+	ring = b43_setup_dmaring(dev, 1, 1, type);
 	if (!ring)
 		goto err_destroy_tx0;
 	dma->tx_ring1 = ring;
 
-	ring = b43_setup_dmaring(dev, 2, 1, dma64);
+	ring = b43_setup_dmaring(dev, 2, 1, type);
 	if (!ring)
 		goto err_destroy_tx1;
 	dma->tx_ring2 = ring;
 
-	ring = b43_setup_dmaring(dev, 3, 1, dma64);
+	ring = b43_setup_dmaring(dev, 3, 1, type);
 	if (!ring)
 		goto err_destroy_tx2;
 	dma->tx_ring3 = ring;
 
-	ring = b43_setup_dmaring(dev, 4, 1, dma64);
+	ring = b43_setup_dmaring(dev, 4, 1, type);
 	if (!ring)
 		goto err_destroy_tx3;
 	dma->tx_ring4 = ring;
 
-	ring = b43_setup_dmaring(dev, 5, 1, dma64);
+	ring = b43_setup_dmaring(dev, 5, 1, type);
 	if (!ring)
 		goto err_destroy_tx4;
 	dma->tx_ring5 = ring;
 
 	/* setup RX DMA channels. */
-	ring = b43_setup_dmaring(dev, 0, 0, dma64);
+	ring = b43_setup_dmaring(dev, 0, 0, type);
 	if (!ring)
 		goto err_destroy_tx5;
 	dma->rx_ring0 = ring;
 
 	if (dev->dev->id.revision < 5) {
-		ring = b43_setup_dmaring(dev, 3, 0, dma64);
+		ring = b43_setup_dmaring(dev, 3, 0, type);
 		if (!ring)
 			goto err_destroy_rx0;
 		dma->rx_ring3 = ring;
 	}
 
-	b43dbg(dev->wl, "%d-bit DMA initialized\n",
-	       (dmamask == DMA_64BIT_MASK) ? 64 :
-	       (dmamask == DMA_32BIT_MASK) ? 32 : 30);
+	b43dbg(dev->wl, "%u-bit DMA initialized\n",
+	       (unsigned int)type);
 	err = 0;
       out:
 	return err;
@@ -1146,7 +1189,7 @@
 
 	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
 					   hdrsize, 1);
-	if (dma_mapping_error(meta_hdr->dmaaddr)) {
+	if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) {
 		ring->current_slot = old_top_slot;
 		ring->used_slots = old_used_slots;
 		return -EIO;
@@ -1165,7 +1208,7 @@
 
 	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	/* create a bounce buffer in zone_dma on mapping failure. */
-	if (dma_mapping_error(meta->dmaaddr)) {
+	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
 		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb) {
 			ring->current_slot = old_top_slot;
@@ -1179,7 +1222,7 @@
 		skb = bounce_skb;
 		meta->skb = skb;
 		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
-		if (dma_mapping_error(meta->dmaaddr)) {
+		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
 			ring->current_slot = old_top_slot;
 			ring->used_slots = old_used_slots;
 			err = -EIO;
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index 58db03a..c0d6b69 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -203,6 +203,12 @@
 	void (*set_current_rxslot) (struct b43_dmaring * ring, int slot);
 };
 
+enum b43_dmatype {
+	B43_DMA_30BIT	= 30,
+	B43_DMA_32BIT	= 32,
+	B43_DMA_64BIT	= 64,
+};
+
 struct b43_dmaring {
 	/* Lowlevel DMA ops. */
 	const struct b43_dma_ops *ops;
@@ -235,8 +241,8 @@
 	int index;
 	/* Boolean. Is this a TX ring? */
 	bool tx;
-	/* Boolean. 64bit DMA if true, 32bit DMA otherwise. */
-	bool dma64;
+	/* The type of DMA engine used. */
+	enum b43_dmatype type;
 	/* Boolean. Is this ring stopped at ieee80211 level? */
 	bool stopped;
 	/* Lock, only used for TX. */
@@ -255,8 +261,7 @@
 	return b43_read32(ring->dev, ring->mmio_base + offset);
 }
 
-static inline
-    void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value)
+static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value)
 {
 	b43_write32(ring->dev, ring->mmio_base + offset, value);
 }
@@ -264,13 +269,6 @@
 int b43_dma_init(struct b43_wldev *dev);
 void b43_dma_free(struct b43_wldev *dev);
 
-int b43_dmacontroller_rx_reset(struct b43_wldev *dev,
-			       u16 dmacontroller_mmio_base, int dma64);
-int b43_dmacontroller_tx_reset(struct b43_wldev *dev,
-			       u16 dmacontroller_mmio_base, int dma64);
-
-u16 b43_dmacontroller_base(int dma64bit, int dmacontroller_idx);
-
 void b43_dma_tx_suspend(struct b43_wldev *dev);
 void b43_dma_tx_resume(struct b43_wldev *dev);
 
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 83161d9..6e08405 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -1164,7 +1164,7 @@
 {
 	const struct b43legacy_dma_ops *ops = ring->ops;
 	u8 *header;
-	int slot;
+	int slot, old_top_slot, old_used_slots;
 	int err;
 	struct b43legacy_dmadesc_generic *desc;
 	struct b43legacy_dmadesc_meta *meta;
@@ -1174,6 +1174,9 @@
 #define SLOTS_PER_PACKET  2
 	B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
 
+	old_top_slot = ring->current_slot;
+	old_used_slots = ring->used_slots;
+
 	/* Get a slot for the header. */
 	slot = request_slot(ring);
 	desc = ops->idx2desc(ring, slot, &meta_hdr);
@@ -1181,9 +1184,14 @@
 
 	header = &(ring->txhdr_cache[slot * sizeof(
 			       struct b43legacy_txhdr_fw3)]);
-	b43legacy_generate_txhdr(ring->dev, header,
+	err = b43legacy_generate_txhdr(ring->dev, header,
 				 skb->data, skb->len, ctl,
 				 generate_cookie(ring, slot));
+	if (unlikely(err)) {
+		ring->current_slot = old_top_slot;
+		ring->used_slots = old_used_slots;
+		return err;
+	}
 
 	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
 				       sizeof(struct b43legacy_txhdr_fw3), 1);
@@ -1206,6 +1214,8 @@
 	if (dma_mapping_error(meta->dmaaddr)) {
 		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
 		if (!bounce_skb) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -ENOMEM;
 			goto out_unmap_hdr;
 		}
@@ -1216,6 +1226,8 @@
 		meta->skb = skb;
 		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 		if (dma_mapping_error(meta->dmaaddr)) {
+			ring->current_slot = old_top_slot;
+			ring->used_slots = old_used_slots;
 			err = -EIO;
 			goto out_free_bounce;
 		}
@@ -1282,6 +1294,13 @@
 	B43legacy_BUG_ON(ring->stopped);
 
 	err = dma_tx_fragment(ring, skb, ctl);
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		dev_kfree_skb_any(skb);
+		err = 0;
+		goto out_unlock;
+	}
 	if (unlikely(err)) {
 		b43legacyerr(dev->wl, "DMA tx mapping failure\n");
 		goto out_unlock;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index aa20d5d..53f7f2e 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3160,8 +3160,6 @@
 	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
 
 	ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
-	memset(wl->bssid, 0, ETH_ALEN);
-	memset(wl->mac_addr, 0, ETH_ALEN);
 	b43legacy_upload_card_macaddress(dev);
 	b43legacy_security_init(dev);
 	b43legacy_rng_init(wl);
@@ -3263,6 +3261,13 @@
 	 * LEDs that are registered later depend on it. */
 	b43legacy_rfkill_init(dev);
 
+	/* Kill all old instance specific information to make sure
+	 * the card won't use it in the short timeframe between start
+	 * and mac80211 reconfiguring it. */
+	memset(wl->bssid, 0, ETH_ALEN);
+	memset(wl->mac_addr, 0, ETH_ALEN);
+	wl->filter_flags = 0;
+
 	mutex_lock(&wl->mutex);
 
 	if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index e4f4c5c..bcdd54e 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -181,7 +181,7 @@
 	struct b43legacy_txhdr_fw3 txhdr_fw3;
 };
 
-static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
+static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
 				  struct sk_buff *skb,
 				  struct b43legacy_pio_txpacket *packet,
 				  size_t txhdr_size)
@@ -189,14 +189,17 @@
 	union txhdr_union txhdr_data;
 	u8 *txhdr = NULL;
 	unsigned int octets;
+	int err;
 
 	txhdr = (u8 *)(&txhdr_data.txhdr_fw3);
 
 	B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
-	b43legacy_generate_txhdr(queue->dev,
+	err = b43legacy_generate_txhdr(queue->dev,
 				 txhdr, skb->data, skb->len,
 				 &packet->txstat.control,
 				 generate_cookie(queue, packet));
+	if (err)
+		return err;
 
 	tx_start(queue);
 	octets = skb->len + txhdr_size;
@@ -204,6 +207,8 @@
 		octets--;
 	tx_data(queue, txhdr, (u8 *)skb->data, octets);
 	tx_complete(queue, skb);
+
+	return 0;
 }
 
 static void free_txpacket(struct b43legacy_pio_txpacket *packet,
@@ -226,6 +231,7 @@
 	struct b43legacy_pioqueue *queue = packet->queue;
 	struct sk_buff *skb = packet->skb;
 	u16 octets;
+	int err;
 
 	octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3);
 	if (queue->tx_devq_size < octets) {
@@ -247,8 +253,14 @@
 	if (queue->tx_devq_used + octets > queue->tx_devq_size)
 		return -EBUSY;
 	/* Now poke the device. */
-	pio_tx_write_fragment(queue, skb, packet,
+	err = pio_tx_write_fragment(queue, skb, packet,
 			      sizeof(struct b43legacy_txhdr_fw3));
+	if (unlikely(err == -ENOKEY)) {
+		/* Drop this packet, as we don't have the encryption key
+		 * anymore and must not transmit it unencrypted. */
+		free_txpacket(packet, 1);
+		return 0;
+	}
 
 	/* Account for the packet size.
 	 * (We must not overflow the device TX queue)
@@ -486,6 +498,9 @@
 	queue = parse_cookie(dev, status->cookie, &packet);
 	B43legacy_WARN_ON(!queue);
 
+	if (!packet->skb)
+		return;
+
 	queue->tx_devq_packets--;
 	queue->tx_devq_used -= (packet->skb->len +
 				sizeof(struct b43legacy_txhdr_fw3));
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index e20c552..d84408a 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -181,7 +181,7 @@
 	return 0;
 }
 
-static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
+static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
 			       struct b43legacy_txhdr_fw3 *txhdr,
 			       const unsigned char *fragment_data,
 			       unsigned int fragment_len,
@@ -252,6 +252,13 @@
 			iv_len = min((size_t)txctl->iv_len,
 				     ARRAY_SIZE(txhdr->iv));
 			memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
+		} else {
+			/* This key is invalid. This might only happen
+			 * in a short timeframe after machine resume before
+			 * we were able to reconfigure keys.
+			 * Drop this packet completely. Do not transmit it
+			 * unencrypted to avoid leaking information. */
+			return -ENOKEY;
 		}
 	}
 	b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
@@ -345,16 +352,18 @@
 	/* Apply the bitfields */
 	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
 	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
+
+	return 0;
 }
 
-void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
 			      u8 *txhdr,
 			      const unsigned char *fragment_data,
 			      unsigned int fragment_len,
 			      const struct ieee80211_tx_control *txctl,
 			      u16 cookie)
 {
-	generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
+	return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
 			   fragment_data, fragment_len,
 			   txctl, cookie);
 }
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h
index 8a155d0..bab4792 100644
--- a/drivers/net/wireless/b43legacy/xmit.h
+++ b/drivers/net/wireless/b43legacy/xmit.h
@@ -76,7 +76,7 @@
 
 
 
-void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
 			      u8 *txhdr,
 			      const unsigned char *fragment_data,
 			      unsigned int fragment_len,
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index f55c757..5ee1ad6 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4207,13 +4207,13 @@
  * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
 int iwl3945_calc_db_from_ratio(int sig_ratio)
 {
-	/* Anything above 1000:1 just report as 60 dB */
-	if (sig_ratio > 1000)
+	/* 1000:1 or higher just report as 60 dB */
+	if (sig_ratio >= 1000)
 		return 60;
 
-	/* Above 100:1, divide by 10 and use table,
+	/* 100:1 or higher, divide by 10 and use table,
 	 *   add 20 dB to make up for divide by 10 */
-	if (sig_ratio > 100)
+	if (sig_ratio >= 100)
 		return (20 + (int)ratio2dB[sig_ratio/10]);
 
 	/* We shouldn't see this */
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index e9743d3..238628d 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1540,6 +1540,38 @@
 	smsc_check(0x3f0,0x44);
 	smsc_check(0x370,0x44);
 }
+
+static void __devinit detect_and_report_it87(void)
+{
+	u16 dev;
+	u8 r;
+	if (verbose_probing)
+		printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
+	if (!request_region(0x2e, 1, __FUNCTION__))
+		return;
+	outb(0x87, 0x2e);
+	outb(0x01, 0x2e);
+	outb(0x55, 0x2e);
+	outb(0x55, 0x2e);
+	outb(0x20, 0x2e);
+	dev = inb(0x2f) << 8;
+	outb(0x21, 0x2e);
+	dev |= inb(0x2f);
+	if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 ||
+	    dev == 0x8716 || dev == 0x8718 || dev == 0x8726) {
+		printk(KERN_INFO "IT%04X SuperIO detected.\n", dev);
+		outb(0x07, 0x2E);	/* Parallel Port */
+		outb(0x03, 0x2F);
+		outb(0xF0, 0x2E);	/* BOOT 0x80 off */
+		r = inb(0x2f);
+		outb(0xF0, 0x2E);
+		outb(r | 8, 0x2F);
+		outb(0x02, 0x2E);	/* Lock */
+		outb(0x02, 0x2F);
+
+		release_region(0x2e, 1);
+	}
+}
 #endif /* CONFIG_PARPORT_PC_SUPERIO */
 
 static int get_superio_dma (struct parport *p)
@@ -2767,6 +2799,7 @@
 	netmos_9755,
 	netmos_9805,
 	netmos_9815,
+	quatech_sppxp100,
 };
 
 
@@ -2843,6 +2876,7 @@
         /* netmos_9755 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
 	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
+	/* quatech_sppxp100 */		{ 1, { { 0, 1 }, } },
 };
 
 static const struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2926,6 +2960,9 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+	/* Quatech SPPXP-100 Parallel port PCI ExpressCard */
+	{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
@@ -3159,24 +3196,25 @@
 	int count = 0, err;
 
 #ifdef CONFIG_PARPORT_PC_SUPERIO
-	detect_and_report_winbond ();
-	detect_and_report_smsc ();
+	detect_and_report_it87();
+	detect_and_report_winbond();
+	detect_and_report_smsc();
 #endif
 
 	/* Onboard SuperIO chipsets that show themselves on the PCI bus. */
-	count += parport_pc_init_superio (autoirq, autodma);
+	count += parport_pc_init_superio(autoirq, autodma);
 
 	/* PnP ports, skip detection if SuperIO already found them */
 	if (!count) {
-		err = pnp_register_driver (&parport_pc_pnp_driver);
+		err = pnp_register_driver(&parport_pc_pnp_driver);
 		if (!err)
 			pnp_registered_parport = 1;
 	}
 
 	/* ISA ports and whatever (see asm/parport.h). */
-	parport_pc_find_nonpci_ports (autoirq, autodma);
+	parport_pc_find_nonpci_ports(autoirq, autodma);
 
-	err = pci_register_driver (&parport_pc_pci_driver);
+	err = pci_register_driver(&parport_pc_pci_driver);
 	if (!err)
 		pci_registered_parport = 1;
 }
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index bd6ad8b..e2e95b3 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -77,7 +77,7 @@
 	/* titan_110l */		{ 1, { { 3, -1 }, } },
 	/* titan_210l */		{ 1, { { 3, -1 }, } },
 	/* netmos_9xx5_combo */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
-	/* netmos_9855 */		{ 1, { { 0, -1 }, }, netmos_parallel_init },
+	/* netmos_9855 */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
 	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
 	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
 	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
@@ -185,7 +185,7 @@
 		.uart_offset	= 8,
 	},
 	[netmos_9855] = {
-		.flags		= FL_BASE2 | FL_BASE_BARS,
+		.flags		= FL_BASE4 | FL_BASE_BARS,
 		.num_ports	= 1,
 		.base_baud	= 115200,
 		.uart_offset	= 8,
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 91b2dc9..8ed2648 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/dmar.h>
 #include "iova.h"
+#include "intel-iommu.h"
 
 #undef PREFIX
 #define PREFIX "DMAR:"
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 4e01df9..31fa6c9 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1088,7 +1088,7 @@
 	int i;
 	u64 addr, size;
 
-	init_iova_domain(&reserved_iova_list);
+	init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
 
 	/* IOAPIC ranges shouldn't be accessed by DMA */
 	iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
@@ -1142,7 +1142,7 @@
 	int adjust_width, agaw;
 	unsigned long sagaw;
 
-	init_iova_domain(&domain->iovad);
+	init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
 	spin_lock_init(&domain->mapping_lock);
 
 	domain_reserve_special_ranges(domain);
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
index 459ad1f..0e48626 100644
--- a/drivers/pci/intel-iommu.h
+++ b/drivers/pci/intel-iommu.h
@@ -23,10 +23,24 @@
 
 #include <linux/types.h>
 #include <linux/msi.h>
+#include <linux/sysdev.h>
 #include "iova.h"
 #include <linux/io.h>
 
 /*
+ * We need a fixed PAGE_SIZE of 4K irrespective of
+ * arch PAGE_SIZE for IOMMU page tables.
+ */
+#define PAGE_SHIFT_4K		(12)
+#define PAGE_SIZE_4K		(1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K		(((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr)	(((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+#define IOVA_PFN(addr)		((addr) >> PAGE_SHIFT_4K)
+#define DMA_32BIT_PFN		IOVA_PFN(DMA_32BIT_MASK)
+#define DMA_64BIT_PFN		IOVA_PFN(DMA_64BIT_MASK)
+
+/*
  * Intel IOMMU register specification per version 1.0 public spec.
  */
 
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
index a84571c..8de7ab6c 100644
--- a/drivers/pci/iova.c
+++ b/drivers/pci/iova.c
@@ -9,19 +9,19 @@
 #include "iova.h"
 
 void
-init_iova_domain(struct iova_domain *iovad)
+init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit)
 {
 	spin_lock_init(&iovad->iova_alloc_lock);
 	spin_lock_init(&iovad->iova_rbtree_lock);
 	iovad->rbroot = RB_ROOT;
 	iovad->cached32_node = NULL;
-
+	iovad->dma_32bit_pfn = pfn_32bit;
 }
 
 static struct rb_node *
 __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
 {
-	if ((*limit_pfn != DMA_32BIT_PFN) ||
+	if ((*limit_pfn != iovad->dma_32bit_pfn) ||
 		(iovad->cached32_node == NULL))
 		return rb_last(&iovad->rbroot);
 	else {
@@ -37,7 +37,7 @@
 __cached_rbnode_insert_update(struct iova_domain *iovad,
 	unsigned long limit_pfn, struct iova *new)
 {
-	if (limit_pfn != DMA_32BIT_PFN)
+	if (limit_pfn != iovad->dma_32bit_pfn)
 		return;
 	iovad->cached32_node = &new->node;
 }
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h
index ae3028d..d521b5b 100644
--- a/drivers/pci/iova.h
+++ b/drivers/pci/iova.h
@@ -15,22 +15,9 @@
 #include <linux/rbtree.h>
 #include <linux/dma-mapping.h>
 
-/*
- * We need a fixed PAGE_SIZE of 4K irrespective of
- * arch PAGE_SIZE for IOMMU page tables.
- */
-#define PAGE_SHIFT_4K		(12)
-#define PAGE_SIZE_4K		(1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K		(((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr)	(((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
 /* IO virtual address start page frame number */
 #define IOVA_START_PFN		(1)
 
-#define IOVA_PFN(addr)		((addr) >> PAGE_SHIFT_4K)
-#define DMA_32BIT_PFN	IOVA_PFN(DMA_32BIT_MASK)
-#define DMA_64BIT_PFN	IOVA_PFN(DMA_64BIT_MASK)
-
 /* iova structure */
 struct iova {
 	struct rb_node	node;
@@ -44,6 +31,7 @@
 	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
 	struct rb_root	rbroot;		/* iova domain rbtree root */
 	struct rb_node	*cached32_node; /* Save last alloced node */
+	unsigned long	dma_32bit_pfn;
 };
 
 struct iova *alloc_iova_mem(void);
@@ -56,7 +44,7 @@
 struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
 	unsigned long pfn_hi);
 void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to);
-void init_iova_domain(struct iova_domain *iovad);
+void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit);
 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
 void put_iova_domain(struct iova_domain *iovad);
 
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index a262762..12a1645 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -161,8 +161,7 @@
 			return error;
 	}
 
-	if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) &&
-	    pnp_can_disable(pnp_dev)) {
+	if (pnp_can_disable(pnp_dev)) {
 		error = pnp_stop_dev(pnp_dev);
 		if (error)
 			return error;
@@ -185,14 +184,17 @@
 	if (pnp_dev->protocol && pnp_dev->protocol->resume)
 		pnp_dev->protocol->resume(pnp_dev);
 
-	if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
+	if (pnp_can_write(pnp_dev)) {
 		error = pnp_start_dev(pnp_dev);
 		if (error)
 			return error;
 	}
 
-	if (pnp_drv->resume)
-		return pnp_drv->resume(pnp_dev);
+	if (pnp_drv->resume) {
+		error = pnp_drv->resume(pnp_dev);
+		if (error)
+			return error;
+	}
 
 	return 0;
 }
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 3154804..9826584 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -10,9 +10,12 @@
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/types.h>
+#include <linux/pnp.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
+
 #include <asm/uaccess.h>
 
 #include "base.h"
@@ -315,8 +318,6 @@
 	return ret;
 }
 
-extern struct semaphore pnp_res_mutex;
-
 static ssize_t
 pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
 			  const char *ubuf, size_t count)
@@ -361,10 +362,10 @@
 		goto done;
 	}
 	if (!strnicmp(buf, "get", 3)) {
-		down(&pnp_res_mutex);
+		mutex_lock(&pnp_res_mutex);
 		if (pnp_can_read(dev))
 			dev->protocol->get(dev, &dev->res);
-		up(&pnp_res_mutex);
+		mutex_unlock(&pnp_res_mutex);
 		goto done;
 	}
 	if (!strnicmp(buf, "set", 3)) {
@@ -373,7 +374,7 @@
 			goto done;
 		buf += 3;
 		pnp_init_resource_table(&dev->res);
-		down(&pnp_res_mutex);
+		mutex_lock(&pnp_res_mutex);
 		while (1) {
 			while (isspace(*buf))
 				++buf;
@@ -455,7 +456,7 @@
 			}
 			break;
 		}
-		up(&pnp_res_mutex);
+		mutex_unlock(&pnp_res_mutex);
 		goto done;
 	}
 
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index c6b3d4e..c28caf2 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -12,9 +12,10 @@
 #include <linux/pnp.h>
 #include <linux/slab.h>
 #include <linux/bitmap.h>
+#include <linux/mutex.h>
 #include "base.h"
 
-DECLARE_MUTEX(pnp_res_mutex);
+DEFINE_MUTEX(pnp_res_mutex);
 
 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
 {
@@ -297,7 +298,7 @@
 	if (!pnp_can_configure(dev))
 		return -ENODEV;
 
-	down(&pnp_res_mutex);
+	mutex_lock(&pnp_res_mutex);
 	pnp_clean_resource_table(&dev->res);	/* start with a fresh slate */
 	if (dev->independent) {
 		port = dev->independent->port;
@@ -366,12 +367,12 @@
 	} else if (dev->dependent)
 		goto fail;
 
-	up(&pnp_res_mutex);
+	mutex_unlock(&pnp_res_mutex);
 	return 1;
 
 fail:
 	pnp_clean_resource_table(&dev->res);
-	up(&pnp_res_mutex);
+	mutex_unlock(&pnp_res_mutex);
 	return 0;
 }
 
@@ -396,7 +397,7 @@
 		return -ENOMEM;
 	*bak = dev->res;
 
-	down(&pnp_res_mutex);
+	mutex_lock(&pnp_res_mutex);
 	dev->res = *res;
 	if (!(mode & PNP_CONFIG_FORCE)) {
 		for (i = 0; i < PNP_MAX_PORT; i++) {
@@ -416,14 +417,14 @@
 				goto fail;
 		}
 	}
-	up(&pnp_res_mutex);
+	mutex_unlock(&pnp_res_mutex);
 
 	kfree(bak);
 	return 0;
 
 fail:
 	dev->res = *bak;
-	up(&pnp_res_mutex);
+	mutex_unlock(&pnp_res_mutex);
 	kfree(bak);
 	return -EINVAL;
 }
@@ -513,7 +514,7 @@
 	int error;
 
 	if (dev->active)
-		return 0;	/* the device is already active */
+		return 0;
 
 	/* ensure resources are allocated */
 	if (pnp_auto_config_dev(dev))
@@ -524,7 +525,7 @@
 		return error;
 
 	dev->active = 1;
-	return 1;
+	return 0;
 }
 
 /**
@@ -538,7 +539,7 @@
 	int error;
 
 	if (!dev->active)
-		return 0;	/* the device is already disabled */
+		return 0;
 
 	error = pnp_stop_dev(dev);
 	if (error)
@@ -547,11 +548,11 @@
 	dev->active = 0;
 
 	/* release the resources so that other devices can use them */
-	down(&pnp_res_mutex);
+	mutex_lock(&pnp_res_mutex);
 	pnp_clean_resource_table(&dev->res);
-	up(&pnp_res_mutex);
+	mutex_unlock(&pnp_res_mutex);
 
-	return 1;
+	return 0;
 }
 
 /**
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 6b9840c..6aa231e 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -391,8 +391,8 @@
 				   pnpacpi_allocated_resource, res);
 }
 
-static void pnpacpi_parse_dma_option(struct pnp_option *option,
-				     struct acpi_resource_dma *p)
+static __init void pnpacpi_parse_dma_option(struct pnp_option *option,
+					    struct acpi_resource_dma *p)
 {
 	int i;
 	struct pnp_dma *dma;
@@ -411,8 +411,8 @@
 	pnp_register_dma_resource(option, dma);
 }
 
-static void pnpacpi_parse_irq_option(struct pnp_option *option,
-				     struct acpi_resource_irq *p)
+static __init void pnpacpi_parse_irq_option(struct pnp_option *option,
+					    struct acpi_resource_irq *p)
 {
 	int i;
 	struct pnp_irq *irq;
@@ -431,8 +431,8 @@
 	pnp_register_irq_resource(option, irq);
 }
 
-static void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
-					 struct acpi_resource_extended_irq *p)
+static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option,
+					struct acpi_resource_extended_irq *p)
 {
 	int i;
 	struct pnp_irq *irq;
@@ -451,8 +451,8 @@
 	pnp_register_irq_resource(option, irq);
 }
 
-static void pnpacpi_parse_port_option(struct pnp_option *option,
-				      struct acpi_resource_io *io)
+static __init void pnpacpi_parse_port_option(struct pnp_option *option,
+					     struct acpi_resource_io *io)
 {
 	struct pnp_port *port;
 
@@ -470,8 +470,8 @@
 	pnp_register_port_resource(option, port);
 }
 
-static void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
-					    struct acpi_resource_fixed_io *io)
+static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option,
+					struct acpi_resource_fixed_io *io)
 {
 	struct pnp_port *port;
 
@@ -487,8 +487,8 @@
 	pnp_register_port_resource(option, port);
 }
 
-static void pnpacpi_parse_mem24_option(struct pnp_option *option,
-				       struct acpi_resource_memory24 *p)
+static __init void pnpacpi_parse_mem24_option(struct pnp_option *option,
+					      struct acpi_resource_memory24 *p)
 {
 	struct pnp_mem *mem;
 
@@ -508,8 +508,8 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpacpi_parse_mem32_option(struct pnp_option *option,
-				       struct acpi_resource_memory32 *p)
+static __init void pnpacpi_parse_mem32_option(struct pnp_option *option,
+					      struct acpi_resource_memory32 *p)
 {
 	struct pnp_mem *mem;
 
@@ -529,8 +529,8 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
-					 struct acpi_resource_fixed_memory32 *p)
+static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
+					struct acpi_resource_fixed_memory32 *p)
 {
 	struct pnp_mem *mem;
 
@@ -549,8 +549,8 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpacpi_parse_address_option(struct pnp_option *option,
-					 struct acpi_resource *r)
+static __init void pnpacpi_parse_address_option(struct pnp_option *option,
+						struct acpi_resource *r)
 {
 	struct acpi_resource_address64 addr, *p = &addr;
 	acpi_status status;
@@ -596,8 +596,8 @@
 	struct pnp_dev *dev;
 };
 
-static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
-					   void *data)
+static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
+						  void *data)
 {
 	int priority = 0;
 	struct acpipnp_parse_option_s *parse_data = data;
@@ -696,8 +696,8 @@
 	return AE_OK;
 }
 
-acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle,
-					       struct pnp_dev * dev)
+acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle,
+						      struct pnp_dev *dev)
 {
 	acpi_status status;
 	struct acpipnp_parse_option_s parse_data;
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index e33e03f..f7e6719 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -315,7 +315,7 @@
 	.disable = pnpbios_disable_resources,
 };
 
-static int insert_device(struct pnp_bios_node *node)
+static int __init insert_device(struct pnp_bios_node *node)
 {
 	struct list_head *pos;
 	struct pnp_dev *dev;
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index 3fabf11..caade35 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -262,8 +262,8 @@
  * Resource Configuration Options
  */
 
-static void pnpbios_parse_mem_option(unsigned char *p, int size,
-				     struct pnp_option *option)
+static __init void pnpbios_parse_mem_option(unsigned char *p, int size,
+					    struct pnp_option *option)
 {
 	struct pnp_mem *mem;
 
@@ -278,8 +278,8 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpbios_parse_mem32_option(unsigned char *p, int size,
-				       struct pnp_option *option)
+static __init void pnpbios_parse_mem32_option(unsigned char *p, int size,
+					      struct pnp_option *option)
 {
 	struct pnp_mem *mem;
 
@@ -294,8 +294,8 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
-					     struct pnp_option *option)
+static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size,
+						    struct pnp_option *option)
 {
 	struct pnp_mem *mem;
 
@@ -309,7 +309,7 @@
 	pnp_register_mem_resource(option, mem);
 }
 
-static void pnpbios_parse_irq_option(unsigned char *p, int size,
+static __init void pnpbios_parse_irq_option(unsigned char *p, int size,
 				     struct pnp_option *option)
 {
 	struct pnp_irq *irq;
@@ -327,7 +327,7 @@
 	pnp_register_irq_resource(option, irq);
 }
 
-static void pnpbios_parse_dma_option(unsigned char *p, int size,
+static __init void pnpbios_parse_dma_option(unsigned char *p, int size,
 				     struct pnp_option *option)
 {
 	struct pnp_dma *dma;
@@ -340,8 +340,8 @@
 	pnp_register_dma_resource(option, dma);
 }
 
-static void pnpbios_parse_port_option(unsigned char *p, int size,
-				      struct pnp_option *option)
+static __init void pnpbios_parse_port_option(unsigned char *p, int size,
+					     struct pnp_option *option)
 {
 	struct pnp_port *port;
 
@@ -356,8 +356,8 @@
 	pnp_register_port_resource(option, port);
 }
 
-static void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
-					    struct pnp_option *option)
+static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size,
+						   struct pnp_option *option)
 {
 	struct pnp_port *port;
 
@@ -371,9 +371,9 @@
 	pnp_register_port_resource(option, port);
 }
 
-static unsigned char *pnpbios_parse_resource_option_data(unsigned char *p,
-							 unsigned char *end,
-							 struct pnp_dev *dev)
+static __init unsigned char *
+pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end,
+					struct pnp_dev *dev)
 {
 	unsigned int len, tag;
 	int priority = 0;
@@ -781,7 +781,8 @@
  * Core Parsing Functions
  */
 
-int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node *node)
+int __init pnpbios_parse_data_stream(struct pnp_dev *dev,
+					struct pnp_bios_node *node)
 {
 	unsigned char *p = (char *)node->data;
 	unsigned char *end = (char *)(node->data + node->size);
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index e903b8c..4065139 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include <linux/io.h>
+#include <linux/dmi.h>
 #include <linux/kallsyms.h>
 #include "base.h"
 
@@ -108,6 +109,46 @@
 		       "pnp: SB audio device quirk - increasing port range\n");
 }
 
+static void quirk_supermicro_h8dce_system(struct pnp_dev *dev)
+{
+	int i;
+	static struct dmi_system_id supermicro_h8dce[] = {
+		{
+			.ident = "Supermicro H8DCE",
+			.matches = {
+				DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+				DMI_MATCH(DMI_PRODUCT_NAME, "H8DCE"),
+			},
+		},
+		{ }
+	};
+
+	if (!dmi_check_system(supermicro_h8dce))
+		return;
+
+	/*
+	 * On the Supermicro H8DCE, there's a system device with resources
+	 * that overlap BAR 6 of the built-in SATA PCI adapter.  If the PNP
+	 * system device claims them, the sata_nv driver won't be able to.
+	 * More details at:
+	 *     https://bugzilla.redhat.com/show_bug.cgi?id=280641
+	 *     https://bugzilla.redhat.com/show_bug.cgi?id=313491
+	 *     http://lkml.org/lkml/2008/1/9/449
+	 *     http://thread.gmane.org/gmane.linux.acpi.devel/27312
+	 */
+	for (i = 0; i < PNP_MAX_MEM; i++) {
+		if (pnp_mem_valid(dev, i) && pnp_mem_len(dev, i) &&
+		    (pnp_mem_start(dev, i) & 0xdfef0000) == 0xdfef0000) {
+			dev_warn(&dev->dev, "disabling 0x%llx-0x%llx to prevent"
+				" conflict with sata_nv PCI device\n",
+				(unsigned long long) pnp_mem_start(dev, i),
+				(unsigned long long) (pnp_mem_start(dev, i) +
+					pnp_mem_len(dev, i) - 1));
+			pnp_mem_flags(dev, i) = 0;
+		}
+	}
+}
+
 /*
  *  PnP Quirks
  *  Cards or devices that need some tweaking due to incomplete resource info
@@ -128,6 +169,8 @@
 	{"CTL0043", quirk_sb16audio_resources},
 	{"CTL0044", quirk_sb16audio_resources},
 	{"CTL0045", quirk_sb16audio_resources},
+	{"PNP0c01", quirk_supermicro_h8dce_system},
+	{"PNP0c02", quirk_supermicro_h8dce_system},
 	{""}
 };
 
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c
index 87b3493..6f2f90e 100644
--- a/drivers/ps3/ps3av.c
+++ b/drivers/ps3/ps3av.c
@@ -78,23 +78,21 @@
 	u32 aspect;
 	u32 x;
 	u32 y;
-	u32 interlace;
-	u32 freq;
 } video_mode_table[] = {
 	{     0, }, /* auto */
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480, 1, 60},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480, 0, 60},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720, 0, 60},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576, 1, 50},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576, 0, 50},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720, 0, 50},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50},
-	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50},
-	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768, 0, 60},
-	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024, 0, 60},
-	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200, 0, 60},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I,       A_N,  720,  480},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P,       A_N,  720,  480},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ,  A_N, 1280,  720},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I,       A_N,  720,  576},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P,       A_N,  720,  576},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ,  A_N, 1280,  720},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080},
+	{YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA,       A_W, 1280,  768},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA,       A_N, 1280, 1024},
+	{  RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA,      A_W, 1920, 1200},
 };
 
 /* supported CIDs */
@@ -544,7 +542,7 @@
 
 static void ps3av_set_videomode_cont(u32 id, u32 old_id)
 {
-	static int vesa = 0;
+	static int vesa;
 	int res;
 
 	/* video signal off */
@@ -554,9 +552,9 @@
 	 * AV backend needs non-VESA mode setting at least one time
 	 * when VESA mode is used.
 	 */
-	if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) {
+	if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) {
 		/* vesa mode */
-		ps3av_set_videomode_packet(2);	/* 480P */
+		ps3av_set_videomode_packet(PS3AV_MODE_480P);
 	}
 	vesa = 1;
 
@@ -596,20 +594,21 @@
 	unsigned mask : 19;
 	unsigned id :  4;
 } ps3av_preferred_modes[] = {
-	{ .mask = PS3AV_RESBIT_WUXGA		<< SHIFT_VESA,	.id = 13 },
-	{ .mask = PS3AV_RESBIT_1920x1080P	<< SHIFT_60,	.id = 5 },
-	{ .mask = PS3AV_RESBIT_1920x1080P	<< SHIFT_50,	.id = 10 },
-	{ .mask = PS3AV_RESBIT_1920x1080I	<< SHIFT_60,	.id = 4 },
-	{ .mask = PS3AV_RESBIT_1920x1080I	<< SHIFT_50,	.id = 9 },
-	{ .mask = PS3AV_RESBIT_SXGA		<< SHIFT_VESA,	.id = 12 },
-	{ .mask = PS3AV_RESBIT_WXGA		<< SHIFT_VESA,	.id = 11 },
-	{ .mask = PS3AV_RESBIT_1280x720P	<< SHIFT_60,	.id = 3 },
-	{ .mask = PS3AV_RESBIT_1280x720P	<< SHIFT_50,	.id = 8 },
-	{ .mask = PS3AV_RESBIT_720x480P		<< SHIFT_60,	.id = 2 },
-	{ .mask = PS3AV_RESBIT_720x576P		<< SHIFT_50,	.id = 7 },
+	{ PS3AV_RESBIT_WUXGA      << SHIFT_VESA, PS3AV_MODE_WUXGA   },
+	{ PS3AV_RESBIT_1920x1080P << SHIFT_60,   PS3AV_MODE_1080P60 },
+	{ PS3AV_RESBIT_1920x1080P << SHIFT_50,   PS3AV_MODE_1080P50 },
+	{ PS3AV_RESBIT_1920x1080I << SHIFT_60,   PS3AV_MODE_1080I60 },
+	{ PS3AV_RESBIT_1920x1080I << SHIFT_50,   PS3AV_MODE_1080I50 },
+	{ PS3AV_RESBIT_SXGA       << SHIFT_VESA, PS3AV_MODE_SXGA    },
+	{ PS3AV_RESBIT_WXGA       << SHIFT_VESA, PS3AV_MODE_WXGA    },
+	{ PS3AV_RESBIT_1280x720P  << SHIFT_60,   PS3AV_MODE_720P60  },
+	{ PS3AV_RESBIT_1280x720P  << SHIFT_50,   PS3AV_MODE_720P50  },
+	{ PS3AV_RESBIT_720x480P   << SHIFT_60,   PS3AV_MODE_480P    },
+	{ PS3AV_RESBIT_720x576P   << SHIFT_50,   PS3AV_MODE_576P    },
 };
 
-static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa)
+static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60,
+					   u32 res_vesa)
 {
 	unsigned int i;
 	u32 res_all;
@@ -638,9 +637,9 @@
 	return 0;
 }
 
-static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
+static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info)
 {
-	int id;
+	enum ps3av_mode_num id;
 
 	if (safe_mode)
 		return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60;
@@ -854,7 +853,7 @@
 
 	/* auto mode */
 	option = id & ~PS3AV_MODE_MASK;
-	if ((id & PS3AV_MODE_MASK) == 0) {
+	if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) {
 		id = ps3av_auto_videomode(&ps3av->av_hw_conf);
 		if (id < 1) {
 			printk(KERN_ERR "%s: invalid id :%d\n", __func__, id);
@@ -889,36 +888,6 @@
 
 EXPORT_SYMBOL_GPL(ps3av_get_mode);
 
-int ps3av_get_scanmode(int id)
-{
-	int size;
-
-	id = id & PS3AV_MODE_MASK;
-	size = ARRAY_SIZE(video_mode_table);
-	if (id > size - 1 || id < 0) {
-		printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
-		return -EINVAL;
-	}
-	return video_mode_table[id].interlace;
-}
-
-EXPORT_SYMBOL_GPL(ps3av_get_scanmode);
-
-int ps3av_get_refresh_rate(int id)
-{
-	int size;
-
-	id = id & PS3AV_MODE_MASK;
-	size = ARRAY_SIZE(video_mode_table);
-	if (id > size - 1 || id < 0) {
-		printk(KERN_ERR "%s: invalid mode %d\n", __func__, id);
-		return -EINVAL;
-	}
-	return video_mode_table[id].freq;
-}
-
-EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate);
-
 /* get resolution by video_mode */
 int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres)
 {
@@ -990,7 +959,7 @@
 		return -ENOMEM;
 
 	mutex_init(&ps3av->mutex);
-	ps3av->ps3av_mode = 0;
+	ps3av->ps3av_mode = PS3AV_MODE_AUTO;
 	ps3av->dev = dev;
 
 	INIT_WORK(&ps3av->work, ps3avd);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 45e4b96..6402d69 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -20,6 +20,10 @@
 
 if RTC_CLASS
 
+if GEN_RTC || RTC
+comment "Conflicting RTC option has been selected, check GEN_RTC and RTC"
+endif
+
 config RTC_HCTOSYS
 	bool "Set system time from RTC on startup and resume"
 	depends on RTC_CLASS = y
@@ -49,7 +53,7 @@
 
 	  If the clock you specify here is not battery backed, it may still
 	  be useful to reinitialize system time when resuming from system
-	  sleep states.  Do not specify an RTC here unless it stays powered
+	  sleep states. Do not specify an RTC here unless it stays powered
 	  during all this system's supported sleep states.
 
 config RTC_DEBUG
@@ -142,7 +146,7 @@
 	  will be called rtc-ds1307.
 
 config RTC_DRV_DS1374
-	tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+	tristate "Dallas/Maxim DS1374"
 	depends on RTC_CLASS && I2C
 	help
 	  If you say yes here you get support for Dallas Semiconductor
@@ -162,7 +166,7 @@
 	  will be called rtc-ds1672.
 
 config RTC_DRV_MAX6900
-	tristate "Maxim 6900"
+	tristate "Maxim MAX6900"
 	help
 	  If you say yes here you will get support for the
 	  Maxim MAX6900 I2C RTC chip.
@@ -180,10 +184,10 @@
 	  will be called rtc-rs5c372.
 
 config RTC_DRV_ISL1208
-	tristate "Intersil 1208"
+	tristate "Intersil ISL1208"
 	help
 	  If you say yes here you get support for the
-	  Intersil 1208 RTC chip.
+	  Intersil ISL1208 RTC chip.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-isl1208.
@@ -220,7 +224,7 @@
 	  will be called rtc-pcf8583.
 
 config RTC_DRV_M41T80
-	tristate "ST M41T80 series RTC"
+	tristate "ST M41T80/81/82/83/84/85/87"
 	help
 	  If you say Y here you will get support for the
 	  ST M41T80 RTC chips series. Currently following chips are
@@ -252,6 +256,24 @@
 
 if SPI_MASTER
 
+config RTC_DRV_MAX6902
+	tristate "Maxim MAX6902"
+	help
+	  If you say yes here you will get support for the
+	  Maxim MAX6902 SPI RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-max6902.
+
+config RTC_DRV_R9701
+	tristate "Epson RTC-9701JE"
+	help
+	  If you say yes here you will get support for the
+	  Epson RTC-9701JE SPI RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-r9701.
+
 config RTC_DRV_RS5C348
 	tristate "Ricoh RS5C348A/B"
 	help
@@ -261,15 +283,6 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rs5c348.
 
-config RTC_DRV_MAX6902
-	tristate "Maxim 6902"
-	help
-	  If you say yes here you will get support for the
-	  Maxim MAX6902 SPI RTC chip.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-max6902.
-
 endif # SPI_MASTER
 
 comment "Platform RTC drivers"
@@ -302,15 +315,40 @@
 	help
 	  If you say yes here you get support for the Dallas DS1216 RTC chips.
 
-config RTC_DRV_DS1553
-	tristate "Dallas DS1553"
+config RTC_DRV_DS1302
+	tristate "Dallas DS1302"
+	depends on SH_SECUREEDGE5410
+	help
+	  If you say yes here you get support for the Dallas DS1302 RTC chips.
+
+config RTC_DRV_DS1511
+	tristate "Dallas DS1511"
+	depends on RTC_CLASS
 	help
 	  If you say yes here you get support for the
-	  Dallas DS1553 timekeeping chip.
+	  Dallas DS1511 timekeeping/watchdog chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1511.
+
+config RTC_DRV_DS1553
+	tristate "Maxim/Dallas DS1553"
+	help
+	  If you say yes here you get support for the
+	  Maxim/Dallas DS1553 timekeeping chip.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1553.
 
+config RTC_DRV_DS1742
+	tristate "Maxim/Dallas DS1742/1743"
+	help
+	  If you say yes here you get support for the
+	  Maxim/Dallas DS1742/1743 timekeeping chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1742.
+
 config RTC_DRV_STK17TA8
 	tristate "Simtek STK17TA8"
 	depends on RTC_CLASS
@@ -321,15 +359,6 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-stk17ta8.
 
-config RTC_DRV_DS1742
-	tristate "Dallas DS1742/1743"
-	help
-	  If you say yes here you get support for the
-	  Dallas DS1742/1743 timekeeping chip.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called rtc-ds1742.
-
 config RTC_DRV_M48T86
 	tristate "ST M48T86/Dallas DS12887"
 	help
@@ -440,10 +469,47 @@
 	  AT32AP700x family processors.
 
 config RTC_DRV_AT91RM9200
-	tristate "AT91RM9200"
-	depends on ARCH_AT91RM9200
+	tristate "AT91RM9200 or AT91SAM9RL"
+	depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL
 	help
-	  Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock).
+	  Driver for the internal RTC (Realtime Clock) module found on
+	  Atmel AT91RM9200's and AT91SAM9RL chips.  On SAM9RL chips
+	  this is powered by the backup power supply.
+
+config RTC_DRV_AT91SAM9
+	tristate "AT91SAM9x"
+	depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40)
+	help
+	  RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer).
+	  These timers are powered by the backup power supply (such as a
+	  small coin cell battery), but do not need to be used as RTCs.
+
+	  (On AT91SAM9rl chips you probably want to use the dedicated RTC
+	  module and leave the RTT available for other uses.)
+
+config RTC_DRV_AT91SAM9_RTT
+	int
+	range 0 1
+	default 0
+	prompt "RTT module Number" if ARCH_AT91SAM9263
+	depends on RTC_DRV_AT91SAM9
+	help
+	  More than one RTT module is available.  You can choose which
+	  one will be used as an RTC.  The default of zero is normally
+	  OK to use, though some systems use that for non-RTC purposes.
+
+config RTC_DRV_AT91SAM9_GPBR
+	int
+	range 0 3 if !ARCH_AT91SAM9263
+	range 0 15 if ARCH_AT91SAM9263
+	default 0
+	prompt "Backup Register Number"
+	depends on RTC_DRV_AT91SAM9
+	help
+	  The RTC driver needs to use one of the General Purpose Backup
+	  Registers (GPBRs) as well as the RTT.  You can choose which one
+	  will be used.  The default of zero is normally OK to use, but
+	  on some systems other software needs to use that register.
 
 config RTC_DRV_BFIN
 	tristate "Blackfin On-Chip RTC"
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 465db4d..ec703f3 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -19,11 +19,14 @@
 
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
+obj-$(CONFIG_RTC_DRV_AT91SAM9)	+= rtc-at91sam9.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
+obj-$(CONFIG_RTC_DRV_DS1302)	+= rtc-ds1302.o
 obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1374)	+= rtc-ds1374.o
+obj-$(CONFIG_RTC_DRV_DS1511)	+= rtc-ds1511.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
@@ -38,6 +41,7 @@
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_R9701)	+= rtc-r9701.o
 obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
new file mode 100644
index 0000000..bbf10ec
--- /dev/null
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -0,0 +1,520 @@
+/*
+ * "RTT as Real Time Clock" driver for AT91SAM9 SoC family
+ *
+ * (C) 2007 Michel Benoit
+ *
+ * Based on rtc-at91rm9200.c by Rick Bronson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+
+#include <asm/mach/time.h>
+#include <asm/arch/board.h>
+#include <asm/arch/at91_rtt.h>
+
+
+/*
+ * This driver uses two configurable hardware resources that live in the
+ * AT91SAM9 backup power domain (intended to be powered at all times)
+ * to implement the Real Time Clock interfaces
+ *
+ *  - A "Real-time Timer" (RTT) counts up in seconds from a base time.
+ *    We can't assign the counter value (CRTV) ... but we can reset it.
+ *
+ *  - One of the "General Purpose Backup Registers" (GPBRs) holds the
+ *    base time, normally an offset from the beginning of the POSIX
+ *    epoch (1970-Jan-1 00:00:00 UTC).  Some systems also include the
+ *    local timezone's offset.
+ *
+ * The RTC's value is the RTT counter plus that offset.  The RTC's alarm
+ * is likewise a base (ALMV) plus that offset.
+ *
+ * Not all RTTs will be used as RTCs; some systems have multiple RTTs to
+ * choose from, or a "real" RTC module.  All systems have multiple GPBR
+ * registers available, likewise usable for more than "RTC" support.
+ */
+
+/*
+ * We store ALARM_DISABLED in ALMV to record that no alarm is set.
+ * It's also the reset value for that field.
+ */
+#define ALARM_DISABLED	((u32)~0)
+
+
+struct sam9_rtc {
+	void __iomem		*rtt;
+	struct rtc_device	*rtcdev;
+	u32			imr;
+};
+
+#define rtt_readl(rtc, field) \
+	__raw_readl((rtc)->rtt + AT91_RTT_ ## field)
+#define rtt_writel(rtc, field, val) \
+	__raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field)
+
+#define gpbr_readl(rtc) \
+	at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR)
+#define gpbr_writel(rtc, val) \
+	at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val))
+
+/*
+ * Read current time and date in RTC
+ */
+static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	u32 secs, secs2;
+	u32 offset;
+
+	/* read current time offset */
+	offset = gpbr_readl(rtc);
+	if (offset == 0)
+		return -EILSEQ;
+
+	/* reread the counter to help sync the two clock domains */
+	secs = rtt_readl(rtc, VR);
+	secs2 = rtt_readl(rtc, VR);
+	if (secs != secs2)
+		secs = rtt_readl(rtc, VR);
+
+	rtc_time_to_tm(offset + secs, tm);
+
+	dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime",
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+/*
+ * Set current time and date in RTC
+ */
+static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	int err;
+	u32 offset, alarm, mr;
+	unsigned long secs;
+
+	dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime",
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	err = rtc_tm_to_time(tm, &secs);
+	if (err != 0)
+		return err;
+
+	mr = rtt_readl(rtc, MR);
+
+	/* disable interrupts */
+	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
+
+	/* read current time offset */
+	offset = gpbr_readl(rtc);
+
+	/* store the new base time in a battery backup register */
+	secs += 1;
+	gpbr_writel(rtc, secs);
+
+	/* adjust the alarm time for the new base */
+	alarm = rtt_readl(rtc, AR);
+	if (alarm != ALARM_DISABLED) {
+		if (offset > secs) {
+			/* time jumped backwards, increase time until alarm */
+			alarm += (offset - secs);
+		} else if ((alarm + offset) > secs) {
+			/* time jumped forwards, decrease time until alarm */
+			alarm -= (secs - offset);
+		} else {
+			/* time jumped past the alarm, disable alarm */
+			alarm = ALARM_DISABLED;
+			mr &= ~AT91_RTT_ALMIEN;
+		}
+		rtt_writel(rtc, AR, alarm);
+	}
+
+	/* reset the timer, and re-enable interrupts */
+	rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST);
+
+	return 0;
+}
+
+static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alrm->time;
+	u32 alarm = rtt_readl(rtc, AR);
+	u32 offset;
+
+	offset = gpbr_readl(rtc);
+	if (offset == 0)
+		return -EILSEQ;
+
+	memset(alrm, 0, sizeof(alrm));
+	if (alarm != ALARM_DISABLED && offset != 0) {
+		rtc_time_to_tm(offset + alarm, tm);
+
+		dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm",
+			1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+			tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+		if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN)
+			alrm->enabled = 1;
+	}
+
+	return 0;
+}
+
+static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	struct rtc_time *tm = &alrm->time;
+	unsigned long secs;
+	u32 offset;
+	u32 mr;
+	int err;
+
+	err = rtc_tm_to_time(tm, &secs);
+	if (err != 0)
+		return err;
+
+	offset = gpbr_readl(rtc);
+	if (offset == 0) {
+		/* time is not set */
+		return -EILSEQ;
+	}
+	mr = rtt_readl(rtc, MR);
+	rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN);
+
+	/* alarm in the past? finish and leave disabled */
+	if (secs <= offset) {
+		rtt_writel(rtc, AR, ALARM_DISABLED);
+		return 0;
+	}
+
+	/* else set alarm and maybe enable it */
+	rtt_writel(rtc, AR, secs - offset);
+	if (alrm->enabled)
+		rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN);
+
+	dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm",
+		tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
+		tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	int ret = 0;
+	u32 mr = rtt_readl(rtc, MR);
+
+	dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr);
+
+	switch (cmd) {
+	case RTC_AIE_OFF:		/* alarm off */
+		rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN);
+		break;
+	case RTC_AIE_ON:		/* alarm on */
+		rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN);
+		break;
+	case RTC_UIE_OFF:		/* update off */
+		rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
+		break;
+	case RTC_UIE_ON:		/* update on */
+		rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Provide additional RTC information in /proc/driver/rtc
+ */
+static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	struct sam9_rtc *rtc = dev_get_drvdata(dev);
+	u32 mr = mr = rtt_readl(rtc, MR);
+
+	seq_printf(seq, "update_IRQ\t: %s\n",
+			(mr & AT91_RTT_RTTINCIEN) ? "yes" : "no");
+	return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc)
+{
+	struct sam9_rtc *rtc = _rtc;
+	u32 sr, mr;
+	unsigned long events = 0;
+
+	/* Shared interrupt may be for another device.  Note: reading
+	 * SR clears it, so we must only read it in this irq handler!
+	 */
+	mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
+	sr = rtt_readl(rtc, SR) & mr;
+	if (!sr)
+		return IRQ_NONE;
+
+	/* alarm status */
+	if (sr & AT91_RTT_ALMS)
+		events |= (RTC_AF | RTC_IRQF);
+
+	/* timer update/increment */
+	if (sr & AT91_RTT_RTTINC)
+		events |= (RTC_UF | RTC_IRQF);
+
+	rtc_update_irq(rtc->rtcdev, 1, events);
+
+	pr_debug("%s: num=%ld, events=0x%02lx\n", __FUNCTION__,
+		events >> 8, events & 0x000000FF);
+
+	return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops at91_rtc_ops = {
+	.ioctl		= at91_rtc_ioctl,
+	.read_time	= at91_rtc_readtime,
+	.set_time	= at91_rtc_settime,
+	.read_alarm	= at91_rtc_readalarm,
+	.set_alarm	= at91_rtc_setalarm,
+	.proc		= at91_rtc_proc,
+};
+
+/*
+ * Initialize and install RTC driver
+ */
+static int __init at91_rtc_probe(struct platform_device *pdev)
+{
+	struct resource	*r;
+	struct sam9_rtc	*rtc;
+	int		ret;
+	u32		mr;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -ENODEV;
+
+	rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rtc);
+	rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS);
+	rtc->rtt += r->start;
+
+	mr = rtt_readl(rtc, MR);
+
+	/* unless RTT is counting at 1 Hz, re-initialize it */
+	if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) {
+		mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES);
+		gpbr_writel(rtc, 0);
+	}
+
+	/* disable all interrupts (same as on shutdown path) */
+	mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
+	rtt_writel(rtc, MR, mr);
+
+	rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev,
+				&at91_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtcdev)) {
+		ret = PTR_ERR(rtc->rtcdev);
+		goto fail;
+	}
+
+	/* register irq handler after we know what name we'll use */
+	ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
+				IRQF_DISABLED | IRQF_SHARED,
+				rtc->rtcdev->dev.bus_id, rtc);
+	if (ret) {
+		dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
+		rtc_device_unregister(rtc->rtcdev);
+		goto fail;
+	}
+
+	/* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
+	 * RTT on at least some reboots.  If you have that chip, you must
+	 * initialize the time from some external source like a GPS, wall
+	 * clock, discrete RTC, etc
+	 */
+
+	if (gpbr_readl(rtc) == 0)
+		dev_warn(&pdev->dev, "%s: SET TIME!\n",
+				rtc->rtcdev->dev.bus_id);
+
+	return 0;
+
+fail:
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc);
+	return ret;
+}
+
+/*
+ * Disable and remove the RTC driver
+ */
+static int __exit at91_rtc_remove(struct platform_device *pdev)
+{
+	struct sam9_rtc	*rtc = platform_get_drvdata(pdev);
+	u32		mr = rtt_readl(rtc, MR);
+
+	/* disable all interrupts */
+	rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
+	free_irq(AT91_ID_SYS, rtc);
+
+	rtc_device_unregister(rtc->rtcdev);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc);
+	return 0;
+}
+
+static void at91_rtc_shutdown(struct platform_device *pdev)
+{
+	struct sam9_rtc	*rtc = platform_get_drvdata(pdev);
+	u32		mr = rtt_readl(rtc, MR);
+
+	rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
+	rtt_writel(rtc, MR, mr & ~rtc->imr);
+}
+
+#ifdef CONFIG_PM
+
+/* AT91SAM9 RTC Power management control */
+
+static int at91_rtc_suspend(struct platform_device *pdev,
+					pm_message_t state)
+{
+	struct sam9_rtc	*rtc = platform_get_drvdata(pdev);
+	u32		mr = rtt_readl(rtc, MR);
+
+	/*
+	 * This IRQ is shared with DBGU and other hardware which isn't
+	 * necessarily a wakeup event source.
+	 */
+	rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
+	if (rtc->imr) {
+		if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
+			enable_irq_wake(AT91_ID_SYS);
+			/* don't let RTTINC cause wakeups */
+			if (mr & AT91_RTT_RTTINCIEN)
+				rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
+		} else
+			rtt_writel(rtc, MR, mr & ~rtc->imr);
+	}
+
+	return 0;
+}
+
+static int at91_rtc_resume(struct platform_device *pdev)
+{
+	struct sam9_rtc	*rtc = platform_get_drvdata(pdev);
+	u32		mr;
+
+	if (rtc->imr) {
+		if (device_may_wakeup(&pdev->dev))
+			disable_irq_wake(AT91_ID_SYS);
+		mr = rtt_readl(rtc, MR);
+		rtt_writel(rtc, MR, mr | rtc->imr);
+	}
+
+	return 0;
+}
+#else
+#define at91_rtc_suspend	NULL
+#define at91_rtc_resume		NULL
+#endif
+
+static struct platform_driver at91_rtc_driver = {
+	.driver.name	= "rtc-at91sam9",
+	.driver.owner	= THIS_MODULE,
+	.remove		= __exit_p(at91_rtc_remove),
+	.shutdown	= at91_rtc_shutdown,
+	.suspend	= at91_rtc_suspend,
+	.resume		= at91_rtc_resume,
+};
+
+/* Chips can have more than one RTT module, and they can be used for more
+ * than just RTCs.  So we can't just register as "the" RTT driver.
+ *
+ * A normal approach in such cases is to create a library to allocate and
+ * free the modules.  Here we just use bus_find_device() as like such a
+ * library, binding directly ... no runtime "library" footprint is needed.
+ */
+static int __init at91_rtc_match(struct device *dev, void *v)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int ret;
+
+	/* continue searching if this isn't the RTT we need */
+	if (strcmp("at91_rtt", pdev->name) != 0
+			|| pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT)
+		goto fail;
+
+	/* else we found it ... but fail unless we can bind to the RTC driver */
+	if (dev->driver) {
+		dev_dbg(dev, "busy, can't use as RTC!\n");
+		goto fail;
+	}
+	dev->driver = &at91_rtc_driver.driver;
+	if (device_attach(dev) == 0) {
+		dev_dbg(dev, "can't attach RTC!\n");
+		goto fail;
+	}
+	ret = at91_rtc_probe(pdev);
+	if (ret == 0)
+		return true;
+
+	dev_dbg(dev, "RTC probe err %d!\n", ret);
+fail:
+	return false;
+}
+
+static int __init at91_rtc_init(void)
+{
+	int status;
+	struct device *rtc;
+
+	status = platform_driver_register(&at91_rtc_driver);
+	if (status)
+		return status;
+	rtc = bus_find_device(&platform_bus_type, NULL,
+			NULL, at91_rtc_match);
+	if (!rtc)
+		platform_driver_unregister(&at91_rtc_driver);
+	return rtc ? 0 : -ENODEV;
+}
+module_init(at91_rtc_init);
+
+static void __exit at91_rtc_exit(void)
+{
+	platform_driver_unregister(&at91_rtc_driver);
+}
+module_exit(at91_rtc_exit);
+
+
+MODULE_AUTHOR("Michel Benoit");
+MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index 1aa709d..d90ba86 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -1,6 +1,6 @@
 /*
  * Blackfin On-Chip Real Time Clock Driver
- *  Supports BF53[123]/BF53[467]/BF54[2489]
+ *  Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789]
  *
  * Copyright 2004-2007 Analog Devices Inc.
  *
@@ -32,26 +32,25 @@
  * writes to clear status registers complete immediately.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
 #include <linux/bcd.h>
-#include <linux/rtc.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/seq_file.h>
 
 #include <asm/blackfin.h>
 
-#define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args)
-#define stampit() stamp("here i am")
+#define dev_dbg_stamp(dev) dev_dbg(dev, "%s:%i: here i am\n", __func__, __LINE__)
 
 struct bfin_rtc {
 	struct rtc_device *rtc_dev;
 	struct rtc_time rtc_alarm;
-	spinlock_t lock;
+	u16 rtc_wrote_regs;
 };
 
 /* Bit values for the ISTAT / ICTL registers */
@@ -72,7 +71,7 @@
 #define SEC_BITS_OFF    0
 
 /* Some helper functions to convert between the common RTC notion of time
- * and the internal Blackfin notion that is stored in 32bits.
+ * and the internal Blackfin notion that is encoded in 32bits.
  */
 static inline u32 rtc_time_to_bfin(unsigned long now)
 {
@@ -97,7 +96,10 @@
 	rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm);
 }
 
-/* Wait for the previous write to a RTC register to complete.
+/**
+ *	bfin_rtc_sync_pending - make sure pending writes have complete
+ *
+ * Wait for the previous write to a RTC register to complete.
  * Unfortunately, we can't sleep here as that introduces a race condition when
  * turning on interrupt events.  Consider this:
  *  - process sets alarm
@@ -112,188 +114,202 @@
  * If anyone can point out the obvious solution here, i'm listening :).  This
  * shouldn't be an issue on an SMP or preempt system as this function should
  * only be called with the rtc lock held.
+ *
+ * Other options:
+ *  - disable PREN so the sync happens at 32.768kHZ ... but this changes the
+ *    inc rate for all RTC registers from 1HZ to 32.768kHZ ...
+ *  - use the write complete IRQ
  */
-static void rtc_bfin_sync_pending(void)
+/*
+static void bfin_rtc_sync_pending_polled(void)
 {
-	stampit();
-	while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) {
+	while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE))
 		if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING))
 			break;
-	}
 	bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE);
 }
-
-static void rtc_bfin_reset(struct bfin_rtc *rtc)
+*/
+static DECLARE_COMPLETION(bfin_write_complete);
+static void bfin_rtc_sync_pending(struct device *dev)
 {
-	/* Initialize the RTC. Enable pre-scaler to scale RTC clock
-	 * to 1Hz and clear interrupt/status registers. */
-	spin_lock_irq(&rtc->lock);
-	rtc_bfin_sync_pending();
+	dev_dbg_stamp(dev);
+	while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)
+		wait_for_completion_timeout(&bfin_write_complete, HZ * 5);
+	dev_dbg_stamp(dev);
+}
+
+/**
+ *	bfin_rtc_reset - set RTC to sane/known state
+ *
+ * Initialize the RTC.  Enable pre-scaler to scale RTC clock
+ * to 1Hz and clear interrupt/status registers.
+ */
+static void bfin_rtc_reset(struct device *dev)
+{
+	struct bfin_rtc *rtc = dev_get_drvdata(dev);
+	dev_dbg_stamp(dev);
+	bfin_rtc_sync_pending(dev);
 	bfin_write_RTC_PREN(0x1);
-	bfin_write_RTC_ICTL(0);
+	bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE);
 	bfin_write_RTC_SWCNT(0);
 	bfin_write_RTC_ALARM(0);
 	bfin_write_RTC_ISTAT(0xFFFF);
-	spin_unlock_irq(&rtc->lock);
+	rtc->rtc_wrote_regs = 0;
 }
 
+/**
+ *	bfin_rtc_interrupt - handle interrupt from RTC
+ *
+ * Since we handle all RTC events here, we have to make sure the requested
+ * interrupt is enabled (in RTC_ICTL) as the event status register (RTC_ISTAT)
+ * always gets updated regardless of the interrupt being enabled.  So when one
+ * even we care about (e.g. stopwatch) goes off, we don't want to turn around
+ * and say that other events have happened as well (e.g. second).  We do not
+ * have to worry about pending writes to the RTC_ICTL register as interrupts
+ * only fire if they are enabled in the RTC_ICTL register.
+ */
 static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
 {
-	struct platform_device *pdev = to_platform_device(dev_id);
-	struct bfin_rtc *rtc = platform_get_drvdata(pdev);
+	struct device *dev = dev_id;
+	struct bfin_rtc *rtc = dev_get_drvdata(dev);
 	unsigned long events = 0;
-	u16 rtc_istat;
+	bool write_complete = false;
+	u16 rtc_istat, rtc_ictl;
 
-	stampit();
-
-	spin_lock_irq(&rtc->lock);
+	dev_dbg_stamp(dev);
 
 	rtc_istat = bfin_read_RTC_ISTAT();
+	rtc_ictl = bfin_read_RTC_ICTL();
 
-	if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) {
-		bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY);
-		events |= RTC_AF | RTC_IRQF;
+	if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) {
+		bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE);
+		write_complete = true;
+		complete(&bfin_write_complete);
 	}
 
-	if (rtc_istat & RTC_ISTAT_STOPWATCH) {
-		bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
-		events |= RTC_PF | RTC_IRQF;
-		bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
+	if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) {
+		if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) {
+			bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY);
+			events |= RTC_AF | RTC_IRQF;
+		}
 	}
 
-	if (rtc_istat & RTC_ISTAT_SEC) {
-		bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
-		events |= RTC_UF | RTC_IRQF;
+	if (rtc_ictl & RTC_ISTAT_STOPWATCH) {
+		if (rtc_istat & RTC_ISTAT_STOPWATCH) {
+			bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
+			events |= RTC_PF | RTC_IRQF;
+			bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
+		}
 	}
 
-	rtc_update_irq(rtc->rtc_dev, 1, events);
+	if (rtc_ictl & RTC_ISTAT_SEC) {
+		if (rtc_istat & RTC_ISTAT_SEC) {
+			bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
+			events |= RTC_UF | RTC_IRQF;
+		}
+	}
 
-	spin_unlock_irq(&rtc->lock);
+	if (events)
+		rtc_update_irq(rtc->rtc_dev, 1, events);
 
-	return IRQ_HANDLED;
+	if (write_complete || events)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
 }
 
 static int bfin_rtc_open(struct device *dev)
 {
-	struct bfin_rtc *rtc = dev_get_drvdata(dev);
 	int ret;
 
-	stampit();
+	dev_dbg_stamp(dev);
 
-	ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev);
-	if (unlikely(ret)) {
-		dev_err(dev, "request RTC IRQ failed with %d\n", ret);
-		return ret;
-	}
-
-	rtc_bfin_reset(rtc);
+	ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev);
+	if (!ret)
+		bfin_rtc_reset(dev);
 
 	return ret;
 }
 
 static void bfin_rtc_release(struct device *dev)
 {
-	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	stampit();
-	rtc_bfin_reset(rtc);
+	dev_dbg_stamp(dev);
+	bfin_rtc_reset(dev);
 	free_irq(IRQ_RTC, dev);
 }
 
+static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int)
+{
+	bfin_write_RTC_ISTAT(rtc_int);
+	bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int);
+}
+static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int)
+{
+	bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int);
+}
+static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc)
+{
+	/* Blackfin has different bits for whether the alarm is
+	 * more than 24 hours away.
+	 */
+	bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY));
+}
 static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	struct bfin_rtc *rtc = dev_get_drvdata(dev);
+	int ret = 0;
 
-	stampit();
+	dev_dbg_stamp(dev);
+
+	bfin_rtc_sync_pending(dev);
 
 	switch (cmd) {
 	case RTC_PIE_ON:
-		stampit();
-		spin_lock_irq(&rtc->lock);
-		rtc_bfin_sync_pending();
-		bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH);
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH);
 		bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq);
-		bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH);
-		spin_unlock_irq(&rtc->lock);
-		return 0;
+		break;
 	case RTC_PIE_OFF:
-		stampit();
-		spin_lock_irq(&rtc->lock);
-		rtc_bfin_sync_pending();
-		bfin_write_RTC_SWCNT(0);
-		bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH);
-		spin_unlock_irq(&rtc->lock);
-		return 0;
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH);
+		break;
 
 	case RTC_UIE_ON:
-		stampit();
-		spin_lock_irq(&rtc->lock);
-		rtc_bfin_sync_pending();
-		bfin_write_RTC_ISTAT(RTC_ISTAT_SEC);
-		bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC);
-		spin_unlock_irq(&rtc->lock);
-		return 0;
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_set(rtc, RTC_ISTAT_SEC);
+		break;
 	case RTC_UIE_OFF:
-		stampit();
-		spin_lock_irq(&rtc->lock);
-		rtc_bfin_sync_pending();
-		bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC);
-		spin_unlock_irq(&rtc->lock);
-		return 0;
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC);
+		break;
 
-	case RTC_AIE_ON: {
-		unsigned long rtc_alarm;
-		u16 which_alarm;
-		int ret = 0;
-
-		stampit();
-
-		spin_lock_irq(&rtc->lock);
-
-		rtc_bfin_sync_pending();
-		if (rtc->rtc_alarm.tm_yday == -1) {
-			struct rtc_time now;
-			rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now);
-			now.tm_sec = rtc->rtc_alarm.tm_sec;
-			now.tm_min = rtc->rtc_alarm.tm_min;
-			now.tm_hour = rtc->rtc_alarm.tm_hour;
-			ret = rtc_tm_to_time(&now, &rtc_alarm);
-			which_alarm = RTC_ISTAT_ALARM;
-		} else {
-			ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm);
-			which_alarm = RTC_ISTAT_ALARM_DAY;
-		}
-		if (ret == 0) {
-			bfin_write_RTC_ISTAT(which_alarm);
-			bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm));
-			bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm);
-		}
-
-		spin_unlock_irq(&rtc->lock);
-
-		return ret;
-	}
+	case RTC_AIE_ON:
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_set_alarm(rtc);
+		break;
 	case RTC_AIE_OFF:
-		stampit();
-		spin_lock_irq(&rtc->lock);
-		rtc_bfin_sync_pending();
-		bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
-		spin_unlock_irq(&rtc->lock);
-		return 0;
+		dev_dbg_stamp(dev);
+		bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+		break;
+
+	default:
+		dev_dbg_stamp(dev);
+		ret = -ENOIOCTLCMD;
 	}
 
-	return -ENOIOCTLCMD;
+	return ret;
 }
 
 static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct bfin_rtc *rtc = dev_get_drvdata(dev);
 
-	stampit();
+	dev_dbg_stamp(dev);
 
-	spin_lock_irq(&rtc->lock);
-	rtc_bfin_sync_pending();
+	if (rtc->rtc_wrote_regs & 0x1)
+		bfin_rtc_sync_pending(dev);
+
 	rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm);
-	spin_unlock_irq(&rtc->lock);
 
 	return 0;
 }
@@ -304,64 +320,79 @@
 	int ret;
 	unsigned long now;
 
-	stampit();
-
-	spin_lock_irq(&rtc->lock);
+	dev_dbg_stamp(dev);
 
 	ret = rtc_tm_to_time(tm, &now);
 	if (ret == 0) {
-		rtc_bfin_sync_pending();
+		if (rtc->rtc_wrote_regs & 0x1)
+			bfin_rtc_sync_pending(dev);
 		bfin_write_RTC_STAT(rtc_time_to_bfin(now));
+		rtc->rtc_wrote_regs = 0x1;
 	}
 
-	spin_unlock_irq(&rtc->lock);
-
 	return ret;
 }
 
 static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	stampit();
-	memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time));
-	alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+	dev_dbg_stamp(dev);
+	alrm->time = rtc->rtc_alarm;
+	bfin_rtc_sync_pending(dev);
+	alrm->enabled = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
 	return 0;
 }
 
 static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	stampit();
-	memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time));
+	unsigned long rtc_alarm;
+
+	dev_dbg_stamp(dev);
+
+	if (rtc_tm_to_time(&alrm->time, &rtc_alarm))
+		return -EINVAL;
+
+	rtc->rtc_alarm = alrm->time;
+
+	bfin_rtc_sync_pending(dev);
+	bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm));
+	if (alrm->enabled)
+		bfin_rtc_int_set_alarm(rtc);
+
 	return 0;
 }
 
 static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-#define yesno(x) (x ? "yes" : "no")
+#define yesno(x) ((x) ? "yes" : "no")
 	u16 ictl = bfin_read_RTC_ICTL();
-	stampit();
-	seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM));
-	seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY));
-	seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC));
-	seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH));
-#ifdef DEBUG
-	seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT());
-	seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL());
-	seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT());
-	seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT());
-	seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM());
-	seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN());
-#endif
+	dev_dbg_stamp(dev);
+	seq_printf(seq,
+		"alarm_IRQ\t: %s\n"
+		"wkalarm_IRQ\t: %s\n"
+		"seconds_IRQ\t: %s\n"
+		"periodic_IRQ\t: %s\n",
+		yesno(ictl & RTC_ISTAT_ALARM),
+		yesno(ictl & RTC_ISTAT_ALARM_DAY),
+		yesno(ictl & RTC_ISTAT_SEC),
+		yesno(ictl & RTC_ISTAT_STOPWATCH));
 	return 0;
+#undef yesno
 }
 
+/**
+ *	bfin_irq_set_freq - make sure hardware supports requested freq
+ *	@dev: pointer to RTC device structure
+ *	@freq: requested frequency rate
+ *
+ *	The Blackfin RTC can only generate periodic events at 1 per
+ *	second (1 Hz), so reject any attempt at changing it.
+ */
 static int bfin_irq_set_freq(struct device *dev, int freq)
 {
-	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	stampit();
-	rtc->rtc_dev->irq_freq = freq;
-	return 0;
+	dev_dbg_stamp(dev);
+	return -ENOTTY;
 }
 
 static struct rtc_class_ops bfin_rtc_ops = {
@@ -381,27 +412,24 @@
 	struct bfin_rtc *rtc;
 	int ret = 0;
 
-	stampit();
+	dev_dbg_stamp(&pdev->dev);
 
 	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
 	if (unlikely(!rtc))
 		return -ENOMEM;
 
-	spin_lock_init(&rtc->lock);
-
 	rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE);
 	if (unlikely(IS_ERR(rtc))) {
 		ret = PTR_ERR(rtc->rtc_dev);
 		goto err;
 	}
-	rtc->rtc_dev->irq_freq = 0;
-	rtc->rtc_dev->max_user_freq = (2 << 16); /* stopwatch is an unsigned 16 bit reg */
+	rtc->rtc_dev->irq_freq = 1;
 
 	platform_set_drvdata(pdev, rtc);
 
 	return 0;
 
-err:
+ err:
 	kfree(rtc);
 	return ret;
 }
@@ -428,7 +456,6 @@
 
 static int __init bfin_rtc_init(void)
 {
-	stampit();
 	return platform_driver_register(&bfin_rtc_driver);
 }
 
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 29cf145..e059f94 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -36,9 +36,24 @@
 #include <linux/platform_device.h>
 #include <linux/mod_devicetable.h>
 
+#ifdef CONFIG_HPET_EMULATE_RTC
+#include <asm/hpet.h>
+#endif
+
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
 
+#ifndef CONFIG_HPET_EMULATE_RTC
+#define is_hpet_enabled()			0
+#define hpet_set_alarm_time(hrs, min, sec) 	do { } while (0)
+#define hpet_set_periodic_freq(arg) 		0
+#define hpet_mask_rtc_irq_bit(arg) 		do { } while (0)
+#define hpet_set_rtc_irq_bit(arg) 		do { } while (0)
+#define hpet_rtc_timer_init() 			do { } while (0)
+#define hpet_register_irq_handler(h) 		0
+#define hpet_unregister_irq_handler(h)		do { } while (0)
+extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
+#endif
 
 struct cmos_rtc {
 	struct rtc_device	*rtc;
@@ -199,6 +214,7 @@
 	sec = t->time.tm_sec;
 	sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
 
+	hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
 	spin_lock_irq(&rtc_lock);
 
 	/* next rtc irq must not be from previous alarm setting */
@@ -252,7 +268,8 @@
 	f = 16 - f;
 
 	spin_lock_irqsave(&rtc_lock, flags);
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
+	if (!hpet_set_periodic_freq(freq))
+		CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
 	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
@@ -314,28 +331,37 @@
 	switch (cmd) {
 	case RTC_AIE_OFF:	/* alarm off */
 		rtc_control &= ~RTC_AIE;
+		hpet_mask_rtc_irq_bit(RTC_AIE);
 		break;
 	case RTC_AIE_ON:	/* alarm on */
 		rtc_control |= RTC_AIE;
+		hpet_set_rtc_irq_bit(RTC_AIE);
 		break;
 	case RTC_UIE_OFF:	/* update off */
 		rtc_control &= ~RTC_UIE;
+		hpet_mask_rtc_irq_bit(RTC_UIE);
 		break;
 	case RTC_UIE_ON:	/* update on */
 		rtc_control |= RTC_UIE;
+		hpet_set_rtc_irq_bit(RTC_UIE);
 		break;
 	case RTC_PIE_OFF:	/* periodic off */
 		rtc_control &= ~RTC_PIE;
+		hpet_mask_rtc_irq_bit(RTC_PIE);
 		break;
 	case RTC_PIE_ON:	/* periodic on */
 		rtc_control |= RTC_PIE;
+		hpet_set_rtc_irq_bit(RTC_PIE);
 		break;
 	}
-	CMOS_WRITE(rtc_control, RTC_CONTROL);
+	if (!is_hpet_enabled())
+		CMOS_WRITE(rtc_control, RTC_CONTROL);
+
 	rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
 	rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
 	if (is_intr(rtc_intr))
 		rtc_update_irq(cmos->rtc, 1, rtc_intr);
+
 	spin_unlock_irqrestore(&rtc_lock, flags);
 	return 0;
 }
@@ -393,15 +419,111 @@
 
 /*----------------------------------------------------------------*/
 
+/*
+ * All these chips have at least 64 bytes of address space, shared by
+ * RTC registers and NVRAM.  Most of those bytes of NVRAM are used
+ * by boot firmware.  Modern chips have 128 or 256 bytes.
+ */
+
+#define NVRAM_OFFSET	(RTC_REG_D + 1)
+
+static ssize_t
+cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	int	retval;
+
+	if (unlikely(off >= attr->size))
+		return 0;
+	if ((off + count) > attr->size)
+		count = attr->size - off;
+
+	spin_lock_irq(&rtc_lock);
+	for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++)
+		*buf++ = CMOS_READ(off);
+	spin_unlock_irq(&rtc_lock);
+
+	return retval;
+}
+
+static ssize_t
+cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct cmos_rtc	*cmos;
+	int		retval;
+
+	cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (unlikely(off >= attr->size))
+		return -EFBIG;
+	if ((off + count) > attr->size)
+		count = attr->size - off;
+
+	/* NOTE:  on at least PCs and Ataris, the boot firmware uses a
+	 * checksum on part of the NVRAM data.  That's currently ignored
+	 * here.  If userspace is smart enough to know what fields of
+	 * NVRAM to update, updating checksums is also part of its job.
+	 */
+	spin_lock_irq(&rtc_lock);
+	for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) {
+		/* don't trash RTC registers */
+		if (off == cmos->day_alrm
+				|| off == cmos->mon_alrm
+				|| off == cmos->century)
+			buf++;
+		else
+			CMOS_WRITE(*buf++, off);
+	}
+	spin_unlock_irq(&rtc_lock);
+
+	return retval;
+}
+
+static struct bin_attribute nvram = {
+	.attr = {
+		.name	= "nvram",
+		.mode	= S_IRUGO | S_IWUSR,
+		.owner	= THIS_MODULE,
+	},
+
+	.read	= cmos_nvram_read,
+	.write	= cmos_nvram_write,
+	/* size gets set up later */
+};
+
+/*----------------------------------------------------------------*/
+
 static struct cmos_rtc	cmos_rtc;
 
 static irqreturn_t cmos_interrupt(int irq, void *p)
 {
 	u8		irqstat;
+	u8		rtc_control;
 
 	spin_lock(&rtc_lock);
-	irqstat = CMOS_READ(RTC_INTR_FLAGS);
-	irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF;
+	/*
+	 * In this case it is HPET RTC interrupt handler
+	 * calling us, with the interrupt information
+	 * passed as arg1, instead of irq.
+	 */
+	if (is_hpet_enabled())
+		irqstat = (unsigned long)irq & 0xF0;
+	else {
+		irqstat = CMOS_READ(RTC_INTR_FLAGS);
+		rtc_control = CMOS_READ(RTC_CONTROL);
+		irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
+	}
+
+	/* All Linux RTC alarms should be treated as if they were oneshot.
+	 * Similar code may be needed in system wakeup paths, in case the
+	 * alarm woke the system.
+	 */
+	if (irqstat & RTC_AIE) {
+		rtc_control = CMOS_READ(RTC_CONTROL);
+		rtc_control &= ~RTC_AIE;
+		CMOS_WRITE(rtc_control, RTC_CONTROL);
+		CMOS_READ(RTC_INTR_FLAGS);
+	}
 	spin_unlock(&rtc_lock);
 
 	if (is_intr(irqstat)) {
@@ -412,11 +534,9 @@
 }
 
 #ifdef	CONFIG_PNP
-#define	is_pnp()	1
 #define	INITSECTION
 
 #else
-#define	is_pnp()	0
 #define	INITSECTION	__init
 #endif
 
@@ -426,6 +546,7 @@
 	struct cmos_rtc_board_info	*info = dev->platform_data;
 	int				retval = 0;
 	unsigned char			rtc_control;
+	unsigned			address_space;
 
 	/* there can be only one ... */
 	if (cmos_rtc.dev)
@@ -450,15 +571,36 @@
 	cmos_rtc.irq = rtc_irq;
 	cmos_rtc.iomem = ports;
 
+	/* Heuristic to deduce NVRAM size ... do what the legacy NVRAM
+	 * driver did, but don't reject unknown configs.   Old hardware
+	 * won't address 128 bytes, and for now we ignore the way newer
+	 * chips can address 256 bytes (using two more i/o ports).
+	 */
+#if	defined(CONFIG_ATARI)
+	address_space = 64;
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)
+	address_space = 128;
+#else
+#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
+	address_space = 128;
+#endif
+
 	/* For ACPI systems extension info comes from the FADT.  On others,
 	 * board specific setup provides it as appropriate.  Systems where
 	 * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and
 	 * some almost-clones) can provide hooks to make that behave.
+	 *
+	 * Note that ACPI doesn't preclude putting these registers into
+	 * "extended" areas of the chip, including some that we won't yet
+	 * expect CMOS_READ and friends to handle.
 	 */
 	if (info) {
-		cmos_rtc.day_alrm = info->rtc_day_alarm;
-		cmos_rtc.mon_alrm = info->rtc_mon_alarm;
-		cmos_rtc.century = info->rtc_century;
+		if (info->rtc_day_alarm && info->rtc_day_alarm < 128)
+			cmos_rtc.day_alrm = info->rtc_day_alarm;
+		if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128)
+			cmos_rtc.mon_alrm = info->rtc_mon_alarm;
+		if (info->rtc_century && info->rtc_century < 128)
+			cmos_rtc.century = info->rtc_century;
 
 		if (info->wake_on && info->wake_off) {
 			cmos_rtc.wake_on = info->wake_on;
@@ -485,8 +627,9 @@
 	 * doesn't use 32KHz here ... for portability we might need to
 	 * do something about other clock frequencies.
 	 */
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
 	cmos_rtc.rtc->irq_freq = 1024;
+	if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq))
+		CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
 
 	/* disable irqs.
 	 *
@@ -509,19 +652,39 @@
 		goto cleanup1;
 	}
 
-	if (is_valid_irq(rtc_irq))
-		retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED,
-				cmos_rtc.rtc->dev.bus_id,
-				cmos_rtc.rtc);
-	if (retval < 0) {
-		dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
-		goto cleanup1;
-	}
+	if (is_valid_irq(rtc_irq)) {
+		irq_handler_t rtc_cmos_int_handler;
 
-	/* REVISIT optionally make 50 or 114 bytes NVRAM available,
-	 * like rtc-ds1553, rtc-ds1742 ... this will often include
-	 * registers for century, and day/month alarm.
-	 */
+		if (is_hpet_enabled()) {
+			int err;
+
+			rtc_cmos_int_handler = hpet_rtc_interrupt;
+			err = hpet_register_irq_handler(cmos_interrupt);
+			if (err != 0) {
+				printk(KERN_WARNING "hpet_register_irq_handler "
+						" failed in rtc_init().");
+				goto cleanup1;
+			}
+		} else
+			rtc_cmos_int_handler = cmos_interrupt;
+
+		retval = request_irq(rtc_irq, rtc_cmos_int_handler,
+				IRQF_DISABLED, cmos_rtc.rtc->dev.bus_id,
+				cmos_rtc.rtc);
+		if (retval < 0) {
+			dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
+			goto cleanup1;
+		}
+	}
+	hpet_rtc_timer_init();
+
+	/* export at least the first block of NVRAM */
+	nvram.size = address_space - NVRAM_OFFSET;
+	retval = sysfs_create_bin_file(&dev->kobj, &nvram);
+	if (retval < 0) {
+		dev_dbg(dev, "can't create nvram file? %d\n", retval);
+		goto cleanup2;
+	}
 
 	pr_info("%s: alarms up to one %s%s\n",
 			cmos_rtc.rtc->dev.bus_id,
@@ -536,6 +699,9 @@
 
 	return 0;
 
+cleanup2:
+	if (is_valid_irq(rtc_irq))
+		free_irq(rtc_irq, cmos_rtc.rtc);
 cleanup1:
 	cmos_rtc.dev = NULL;
 	rtc_device_unregister(cmos_rtc.rtc);
@@ -563,8 +729,12 @@
 
 	cmos_do_shutdown();
 
-	if (is_valid_irq(cmos->irq))
+	sysfs_remove_bin_file(&dev->kobj, &nvram);
+
+	if (is_valid_irq(cmos->irq)) {
 		free_irq(cmos->irq, cmos->rtc);
+		hpet_unregister_irq_handler(cmos_interrupt);
+	}
 
 	rtc_device_unregister(cmos->rtc);
 	cmos->rtc = NULL;
@@ -659,9 +829,12 @@
 
 /*----------------------------------------------------------------*/
 
-/* The "CMOS" RTC normally lives on the platform_bus.  On ACPI systems,
- * the device node will always be created as a PNPACPI device.  Plus
- * pre-ACPI PCs probably list it in the PNPBIOS tables.
+/* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus.
+ * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs
+ * probably list them in similar PNPBIOS tables; so PNP is more common.
+ *
+ * We don't use legacy "poke at the hardware" probing.  Ancient PCs that
+ * predate even PNPBIOS should set up platform_bus devices.
  */
 
 #ifdef	CONFIG_PNP
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 025c60a..90dfa0d 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -246,6 +246,15 @@
 	/* if the driver does not provide the ioctl interface
 	 * or if that particular ioctl was not implemented
 	 * (-ENOIOCTLCMD), we will try to emulate here.
+	 *
+	 * Drivers *SHOULD NOT* provide ioctl implementations
+	 * for these requests.  Instead, provide methods to
+	 * support the following code, so that the RTC's main
+	 * features are accessible without using ioctls.
+	 *
+	 * RTC and alarm times will be in UTC, by preference,
+	 * but dual-booting with MS-Windows implies RTCs must
+	 * use the local wall clock time.
 	 */
 
 	switch (cmd) {
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c
new file mode 100644
index 0000000..7b002ce
--- /dev/null
+++ b/drivers/rtc/rtc-ds1302.c
@@ -0,0 +1,262 @@
+/*
+ * Dallas DS1302 RTC Support
+ *
+ *  Copyright (C) 2002  David McCullough
+ *  Copyright (C) 2003 - 2007  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/bcd.h>
+#include <asm/rtc.h>
+
+#define DRV_NAME	"rtc-ds1302"
+#define DRV_VERSION	"0.1.0"
+
+#define	RTC_CMD_READ	0x81		/* Read command */
+#define	RTC_CMD_WRITE	0x80		/* Write command */
+
+#define RTC_ADDR_RAM0	0x20		/* Address of RAM0 */
+#define RTC_ADDR_TCR	0x08		/* Address of trickle charge register */
+#define	RTC_ADDR_YEAR	0x06		/* Address of year register */
+#define	RTC_ADDR_DAY	0x05		/* Address of day of week register */
+#define	RTC_ADDR_MON	0x04		/* Address of month register */
+#define	RTC_ADDR_DATE	0x03		/* Address of day of month register */
+#define	RTC_ADDR_HOUR	0x02		/* Address of hour register */
+#define	RTC_ADDR_MIN	0x01		/* Address of minute register */
+#define	RTC_ADDR_SEC	0x00		/* Address of second register */
+
+#define	RTC_RESET	0x1000
+#define	RTC_IODATA	0x0800
+#define	RTC_SCLK	0x0400
+
+#ifdef CONFIG_SH_SECUREEDGE5410
+#include <asm/snapgear.h>
+#define set_dp(x)	SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
+#define get_dp()	SECUREEDGE_READ_IOPORT()
+#else
+#error "Add support for your platform"
+#endif
+
+struct ds1302_rtc {
+	struct rtc_device *rtc_dev;
+	spinlock_t lock;
+};
+
+static void ds1302_sendbits(unsigned int val)
+{
+	int i;
+
+	for (i = 8; (i); i--, val >>= 1) {
+		set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ?
+			RTC_IODATA : 0));
+		set_dp(get_dp() | RTC_SCLK);	/* clock high */
+		set_dp(get_dp() & ~RTC_SCLK);	/* clock low */
+	}
+}
+
+static unsigned int ds1302_recvbits(void)
+{
+	unsigned int val;
+	int i;
+
+	for (i = 0, val = 0; (i < 8); i++) {
+		val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
+		set_dp(get_dp() | RTC_SCLK);	/* clock high */
+		set_dp(get_dp() & ~RTC_SCLK);	/* clock low */
+	}
+
+	return val;
+}
+
+static unsigned int ds1302_readbyte(unsigned int addr)
+{
+	unsigned int val;
+
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+
+	set_dp(get_dp() | RTC_RESET);
+	ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
+	val = ds1302_recvbits();
+	set_dp(get_dp() & ~RTC_RESET);
+
+	return val;
+}
+
+static void ds1302_writebyte(unsigned int addr, unsigned int val)
+{
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+	set_dp(get_dp() | RTC_RESET);
+	ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
+	ds1302_sendbits(val);
+	set_dp(get_dp() & ~RTC_RESET);
+}
+
+static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct ds1302_rtc *rtc = dev_get_drvdata(dev);
+
+	spin_lock_irq(&rtc->lock);
+
+	tm->tm_sec	= BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC));
+	tm->tm_min	= BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN));
+	tm->tm_hour	= BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR));
+	tm->tm_wday	= BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY));
+	tm->tm_mday	= BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE));
+	tm->tm_mon	= BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1;
+	tm->tm_year	= BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR));
+
+	if (tm->tm_year < 70)
+		tm->tm_year += 100;
+
+	spin_unlock_irq(&rtc->lock);
+
+	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+		"mday=%d, mon=%d, year=%d, wday=%d\n",
+		__FUNCTION__,
+		tm->tm_sec, tm->tm_min, tm->tm_hour,
+		tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday);
+
+	if (rtc_valid_tm(tm) < 0)
+		dev_err(dev, "invalid date\n");
+
+	return 0;
+}
+
+static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct ds1302_rtc *rtc = dev_get_drvdata(dev);
+
+	spin_lock_irq(&rtc->lock);
+
+	/* Stop RTC */
+	ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
+
+	ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec));
+	ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min));
+	ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour));
+	ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday));
+	ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday));
+	ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1));
+	ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100));
+
+	/* Start RTC */
+	ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
+
+	spin_unlock_irq(&rtc->lock);
+
+	return 0;
+}
+
+static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd,
+			    unsigned long arg)
+{
+	switch (cmd) {
+#ifdef RTC_SET_CHARGE
+	case RTC_SET_CHARGE:
+	{
+		struct ds1302_rtc *rtc = dev_get_drvdata(dev);
+		int tcs_val;
+
+		if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int)))
+			return -EFAULT;
+
+		spin_lock_irq(&rtc->lock);
+		ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf));
+		spin_unlock_irq(&rtc->lock);
+		return 0;
+	}
+#endif
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static struct rtc_class_ops ds1302_rtc_ops = {
+	.read_time	= ds1302_rtc_read_time,
+	.set_time	= ds1302_rtc_set_time,
+	.ioctl		= ds1302_rtc_ioctl,
+};
+
+static int __devinit ds1302_rtc_probe(struct platform_device *pdev)
+{
+	struct ds1302_rtc *rtc;
+	int ret;
+
+	/* Reset */
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+
+	/* Write a magic value to the DS1302 RAM, and see if it sticks. */
+	ds1302_writebyte(RTC_ADDR_RAM0, 0x42);
+	if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42)
+		return -ENODEV;
+
+	rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL);
+	if (unlikely(!rtc))
+		return -ENOMEM;
+
+	spin_lock_init(&rtc->lock);
+	rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev,
+					   &ds1302_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc->rtc_dev)) {
+		ret = PTR_ERR(rtc->rtc_dev);
+		goto out;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	return 0;
+out:
+	kfree(rtc);
+	return ret;
+}
+
+static int __devexit ds1302_rtc_remove(struct platform_device *pdev)
+{
+	struct ds1302_rtc *rtc = platform_get_drvdata(pdev);
+
+	if (likely(rtc->rtc_dev))
+		rtc_device_unregister(rtc->rtc_dev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	kfree(rtc);
+
+	return 0;
+}
+
+static struct platform_driver ds1302_platform_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ds1302_rtc_probe,
+	.remove		= __devexit_p(ds1302_rtc_remove),
+};
+
+static int __init ds1302_rtc_init(void)
+{
+	return platform_driver_register(&ds1302_platform_driver);
+}
+
+static void __exit ds1302_rtc_exit(void)
+{
+	platform_driver_unregister(&ds1302_platform_driver);
+}
+
+module_init(ds1302_rtc_init);
+module_exit(ds1302_rtc_exit);
+
+MODULE_DESCRIPTION("Dallas DS1302 RTC driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Paul Mundt, David McCullough");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index bc1c7fe..f389a28 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -256,7 +256,7 @@
 	struct i2c_msg		msg[2];
 	int			result;
 
-	client = to_i2c_client(container_of(kobj, struct device, kobj));
+	client = kobj_to_i2c_client(kobj);
 	ds1307 = i2c_get_clientdata(client);
 
 	if (unlikely(off >= NVRAM_SIZE))
@@ -294,7 +294,7 @@
 	u8			buffer[NVRAM_SIZE + 1];
 	int			ret;
 
-	client = to_i2c_client(container_of(kobj, struct device, kobj));
+	client = kobj_to_i2c_client(kobj);
 
 	if (unlikely(off >= NVRAM_SIZE))
 		return -EFBIG;
@@ -412,11 +412,6 @@
 	 */
 	tmp = ds1307->regs[DS1307_REG_SECS];
 	switch (ds1307->type) {
-	case ds_1340:
-		/* FIXME read register with DS1340_BIT_OSF, use that to
-		 * trigger the "set time" warning (*after* restarting the
-		 * oscillator!) instead of this weaker ds1307/m41t00 test.
-		 */
 	case ds_1307:
 	case m41t00:
 		/* clock halted?  turn it on, so clock can tick. */
@@ -440,6 +435,24 @@
 			goto read_rtc;
 		}
 		break;
+	case ds_1340:
+		/* clock halted?  turn it on, so clock can tick. */
+		if (tmp & DS1340_BIT_nEOSC)
+			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+
+		tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG);
+		if (tmp < 0) {
+			pr_debug("read error %d\n", tmp);
+			err = -EIO;
+			goto exit_free;
+		}
+
+		/* oscillator fault?  clear flag, and warn */
+		if (tmp & DS1340_BIT_OSF) {
+			i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0);
+			dev_warn(&client->dev, "SET TIME!\n");
+		}
+		break;
 	case ds_1337:
 	case ds_1339:
 		break;
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
new file mode 100644
index 0000000..d74b808
--- /dev/null
+++ b/drivers/rtc/rtc-ds1511.c
@@ -0,0 +1,656 @@
+/*
+ * An rtc driver for the Dallas DS1511
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com>
+ *
+ * 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.
+ *
+ * Real time clock driver for the Dallas 1511 chip, which also
+ * contains a watchdog timer.  There is a tiny amount of code that
+ * platform code could use to mess with the watchdog device a little
+ * bit, but not a full watchdog driver.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.6"
+
+enum ds1511reg {
+	DS1511_SEC = 0x0,
+	DS1511_MIN = 0x1,
+	DS1511_HOUR = 0x2,
+	DS1511_DOW = 0x3,
+	DS1511_DOM = 0x4,
+	DS1511_MONTH = 0x5,
+	DS1511_YEAR = 0x6,
+	DS1511_CENTURY = 0x7,
+	DS1511_AM1_SEC = 0x8,
+	DS1511_AM2_MIN = 0x9,
+	DS1511_AM3_HOUR = 0xa,
+	DS1511_AM4_DATE = 0xb,
+	DS1511_WD_MSEC = 0xc,
+	DS1511_WD_SEC = 0xd,
+	DS1511_CONTROL_A = 0xe,
+	DS1511_CONTROL_B = 0xf,
+	DS1511_RAMADDR_LSB = 0x10,
+	DS1511_RAMDATA = 0x13
+};
+
+#define DS1511_BLF1	0x80
+#define DS1511_BLF2	0x40
+#define DS1511_PRS	0x20
+#define DS1511_PAB	0x10
+#define DS1511_TDF	0x08
+#define DS1511_KSF	0x04
+#define DS1511_WDF	0x02
+#define DS1511_IRQF	0x01
+#define DS1511_TE	0x80
+#define DS1511_CS	0x40
+#define DS1511_BME	0x20
+#define DS1511_TPE	0x10
+#define DS1511_TIE	0x08
+#define DS1511_KIE	0x04
+#define DS1511_WDE	0x02
+#define DS1511_WDS	0x01
+#define DS1511_RAM_MAX	0xff
+
+#define RTC_CMD		DS1511_CONTROL_B
+#define RTC_CMD1	DS1511_CONTROL_A
+
+#define RTC_ALARM_SEC	DS1511_AM1_SEC
+#define RTC_ALARM_MIN	DS1511_AM2_MIN
+#define RTC_ALARM_HOUR	DS1511_AM3_HOUR
+#define RTC_ALARM_DATE	DS1511_AM4_DATE
+
+#define RTC_SEC		DS1511_SEC
+#define RTC_MIN		DS1511_MIN
+#define RTC_HOUR	DS1511_HOUR
+#define RTC_DOW		DS1511_DOW
+#define RTC_DOM		DS1511_DOM
+#define RTC_MON		DS1511_MONTH
+#define RTC_YEAR	DS1511_YEAR
+#define RTC_CENTURY	DS1511_CENTURY
+
+#define RTC_TIE	DS1511_TIE
+#define RTC_TE	DS1511_TE
+
+struct rtc_plat_data {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;		/* virtual base address */
+	unsigned long baseaddr;		/* physical base address */
+	int size;				/* amount of memory mapped */
+	int irq;
+	unsigned int irqen;
+	int alrm_sec;
+	int alrm_min;
+	int alrm_hour;
+	int alrm_mday;
+};
+
+static DEFINE_SPINLOCK(ds1511_lock);
+
+static __iomem char *ds1511_base;
+static u32 reg_spacing = 1;
+
+ static noinline void
+rtc_write(uint8_t val, uint32_t reg)
+{
+	writeb(val, ds1511_base + (reg * reg_spacing));
+}
+
+ static inline void
+rtc_write_alarm(uint8_t val, enum ds1511reg reg)
+{
+	rtc_write((val | 0x80), reg);
+}
+
+ static noinline uint8_t
+rtc_read(enum ds1511reg reg)
+{
+	return readb(ds1511_base + (reg * reg_spacing));
+}
+
+ static inline void
+rtc_disable_update(void)
+{
+	rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD);
+}
+
+ static void
+rtc_enable_update(void)
+{
+	rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD);
+}
+
+/*
+ * #define DS1511_WDOG_RESET_SUPPORT
+ *
+ * Uncomment this if you want to use these routines in
+ * some platform code.
+ */
+#ifdef DS1511_WDOG_RESET_SUPPORT
+/*
+ * just enough code to set the watchdog timer so that it
+ * will reboot the system
+ */
+ void
+ds1511_wdog_set(unsigned long deciseconds)
+{
+	/*
+	 * the wdog timer can take 99.99 seconds
+	 */
+	deciseconds %= 10000;
+	/*
+	 * set the wdog values in the wdog registers
+	 */
+	rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC);
+	rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC);
+	/*
+	 * set wdog enable and wdog 'steering' bit to issue a reset
+	 */
+	rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD);
+}
+
+ void
+ds1511_wdog_disable(void)
+{
+	/*
+	 * clear wdog enable and wdog 'steering' bits
+	 */
+	rtc_write(rtc_read(RTC_CMD) & ~(DS1511_WDE | DS1511_WDS), RTC_CMD);
+	/*
+	 * clear the wdog counter
+	 */
+	rtc_write(0, DS1511_WD_MSEC);
+	rtc_write(0, DS1511_WD_SEC);
+}
+#endif
+
+/*
+ * set the rtc chip's idea of the time.
+ * stupidly, some callers call with year unmolested;
+ * and some call with  year = year - 1900.  thanks.
+ */
+ int
+ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
+{
+	u8 mon, day, dow, hrs, min, sec, yrs, cen;
+	unsigned int flags;
+
+	/*
+	 * won't have to change this for a while
+	 */
+	if (rtc_tm->tm_year < 1900) {
+		rtc_tm->tm_year += 1900;
+	}
+
+	if (rtc_tm->tm_year < 1970) {
+		return -EINVAL;
+	}
+	yrs = rtc_tm->tm_year % 100;
+	cen = rtc_tm->tm_year / 100;
+	mon = rtc_tm->tm_mon + 1;   /* tm_mon starts at zero */
+	day = rtc_tm->tm_mday;
+	dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */
+	hrs = rtc_tm->tm_hour;
+	min = rtc_tm->tm_min;
+	sec = rtc_tm->tm_sec;
+
+	if ((mon > 12) || (day == 0)) {
+		return -EINVAL;
+	}
+
+	if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) {
+		return -EINVAL;
+	}
+
+	if ((hrs >= 24) || (min >= 60) || (sec >= 60)) {
+		return -EINVAL;
+	}
+
+	/*
+	 * each register is a different number of valid bits
+	 */
+	sec = BIN2BCD(sec) & 0x7f;
+	min = BIN2BCD(min) & 0x7f;
+	hrs = BIN2BCD(hrs) & 0x3f;
+	day = BIN2BCD(day) & 0x3f;
+	mon = BIN2BCD(mon) & 0x1f;
+	yrs = BIN2BCD(yrs) & 0xff;
+	cen = BIN2BCD(cen) & 0xff;
+
+	spin_lock_irqsave(&ds1511_lock, flags);
+	rtc_disable_update();
+	rtc_write(cen, RTC_CENTURY);
+	rtc_write(yrs, RTC_YEAR);
+	rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON);
+	rtc_write(day, RTC_DOM);
+	rtc_write(hrs, RTC_HOUR);
+	rtc_write(min, RTC_MIN);
+	rtc_write(sec, RTC_SEC);
+	rtc_write(dow, RTC_DOW);
+	rtc_enable_update();
+	spin_unlock_irqrestore(&ds1511_lock, flags);
+
+	return 0;
+}
+
+ int
+ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
+{
+	unsigned int century;
+	unsigned int flags;
+
+	spin_lock_irqsave(&ds1511_lock, flags);
+	rtc_disable_update();
+
+	rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f;
+	rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f;
+	rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f;
+	rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f;
+	rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7;
+	rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f;
+	rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f;
+	century = rtc_read(RTC_CENTURY);
+
+	rtc_enable_update();
+	spin_unlock_irqrestore(&ds1511_lock, flags);
+
+	rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
+	rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
+	rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
+	rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
+	rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday);
+	rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
+	rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
+	century = BCD2BIN(century) * 100;
+
+	/*
+	 * Account for differences between how the RTC uses the values
+	 * and how they are defined in a struct rtc_time;
+	 */
+	century += rtc_tm->tm_year;
+	rtc_tm->tm_year = century - 1900;
+
+	rtc_tm->tm_mon--;
+
+	if (rtc_valid_tm(rtc_tm) < 0) {
+		dev_err(dev, "retrieved date/time is not valid.\n");
+		rtc_time_to_tm(0, rtc_tm);
+	}
+	return 0;
+}
+
+/*
+ * write the alarm register settings
+ *
+ * we only have the use to interrupt every second, otherwise
+ * known as the update interrupt, or the interrupt if the whole
+ * date/hours/mins/secs matches.  the ds1511 has many more
+ * permutations, but the kernel doesn't.
+ */
+ static void
+ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+	rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f,
+	       RTC_ALARM_DATE);
+	rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f,
+	       RTC_ALARM_HOUR);
+	rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_min) & 0x7f,
+	       RTC_ALARM_MIN);
+	rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f,
+	       RTC_ALARM_SEC);
+	rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD);
+	rtc_read(RTC_CMD1);	/* clear interrupts */
+	spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+}
+
+ static int
+ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0) {
+		return -EINVAL;
+	}
+	pdata->alrm_mday = alrm->time.tm_mday;
+	pdata->alrm_hour = alrm->time.tm_hour;
+	pdata->alrm_min = alrm->time.tm_min;
+	pdata->alrm_sec = alrm->time.tm_sec;
+	if (alrm->enabled) {
+		pdata->irqen |= RTC_AF;
+	}
+	ds1511_rtc_update_alarm(pdata);
+	return 0;
+}
+
+ static int
+ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0) {
+		return -EINVAL;
+	}
+	alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
+	alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
+	alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
+	alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
+	alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
+	return 0;
+}
+
+ static irqreturn_t
+ds1511_interrupt(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	unsigned long events = RTC_IRQF;
+
+	/*
+	 * read and clear interrupt
+	 */
+	if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) {
+		return IRQ_NONE;
+	}
+	if (rtc_read(RTC_ALARM_SEC) & 0x80) {
+		events |= RTC_UF;
+	} else {
+		events |= RTC_AF;
+	}
+	rtc_update_irq(pdata->rtc, 1, events);
+	return IRQ_HANDLED;
+}
+
+ static void
+ds1511_rtc_release(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq >= 0) {
+		pdata->irqen = 0;
+		ds1511_rtc_update_alarm(pdata);
+	}
+}
+
+ static int
+ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0) {
+		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
+	}
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		pdata->irqen &= ~RTC_AF;
+		ds1511_rtc_update_alarm(pdata);
+		break;
+	case RTC_AIE_ON:
+		pdata->irqen |= RTC_AF;
+		ds1511_rtc_update_alarm(pdata);
+		break;
+	case RTC_UIE_OFF:
+		pdata->irqen &= ~RTC_UF;
+		ds1511_rtc_update_alarm(pdata);
+		break;
+	case RTC_UIE_ON:
+		pdata->irqen |= RTC_UF;
+		ds1511_rtc_update_alarm(pdata);
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static const struct rtc_class_ops ds1511_rtc_ops = {
+	.read_time	= ds1511_rtc_read_time,
+	.set_time	= ds1511_rtc_set_time,
+	.read_alarm	= ds1511_rtc_read_alarm,
+	.set_alarm	= ds1511_rtc_set_alarm,
+	.release	= ds1511_rtc_release,
+	.ioctl		= ds1511_rtc_ioctl,
+};
+
+ static ssize_t
+ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba,
+				char *buf, loff_t pos, size_t size)
+{
+	ssize_t count;
+
+	/*
+	 * if count is more than one, turn on "burst" mode
+	 * turn it off when you're done
+	 */
+	if (size > 1) {
+		rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
+	}
+	if (pos > DS1511_RAM_MAX) {
+		pos = DS1511_RAM_MAX;
+	}
+	if (size + pos > DS1511_RAM_MAX + 1) {
+		size = DS1511_RAM_MAX - pos + 1;
+	}
+	rtc_write(pos, DS1511_RAMADDR_LSB);
+	for (count = 0; size > 0; count++, size--) {
+		*buf++ = rtc_read(DS1511_RAMDATA);
+	}
+	if (count > 1) {
+		rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
+	}
+	return count;
+}
+
+ static ssize_t
+ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t size)
+{
+	ssize_t count;
+
+	/*
+	 * if count is more than one, turn on "burst" mode
+	 * turn it off when you're done
+	 */
+	if (size > 1) {
+		rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
+	}
+	if (pos > DS1511_RAM_MAX) {
+		pos = DS1511_RAM_MAX;
+	}
+	if (size + pos > DS1511_RAM_MAX + 1) {
+		size = DS1511_RAM_MAX - pos + 1;
+	}
+	rtc_write(pos, DS1511_RAMADDR_LSB);
+	for (count = 0; size > 0; count++, size--) {
+		rtc_write(*buf++, DS1511_RAMDATA);
+	}
+	if (count > 1) {
+		rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
+	}
+	return count;
+}
+
+static struct bin_attribute ds1511_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = DS1511_RAM_MAX,
+	.read = ds1511_nvram_read,
+	.write = ds1511_nvram_write,
+};
+
+ static int __devinit
+ds1511_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	struct rtc_plat_data *pdata = NULL;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		return -ENODEV;
+	}
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		return -ENOMEM;
+	}
+	pdata->irq = -1;
+	pdata->size = res->end - res->start + 1;
+	if (!request_mem_region(res->start, pdata->size, pdev->name)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	pdata->baseaddr = res->start;
+	pdata->size = pdata->size;
+	ds1511_base = ioremap(pdata->baseaddr, pdata->size);
+	if (!ds1511_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	pdata->ioaddr = ds1511_base;
+	pdata->irq = platform_get_irq(pdev, 0);
+
+	/*
+	 * turn on the clock and the crystal, etc.
+	 */
+	rtc_write(0, RTC_CMD);
+	rtc_write(0, RTC_CMD1);
+	/*
+	 * clear the wdog counter
+	 */
+	rtc_write(0, DS1511_WD_MSEC);
+	rtc_write(0, DS1511_WD_SEC);
+	/*
+	 * start the clock
+	 */
+	rtc_enable_update();
+
+	/*
+	 * check for a dying bat-tree
+	 */
+	if (rtc_read(RTC_CMD1) & DS1511_BLF1) {
+		dev_warn(&pdev->dev, "voltage-low detected.\n");
+	}
+
+	/*
+	 * if the platform has an interrupt in mind for this device,
+	 * then by all means, set it
+	 */
+	if (pdata->irq >= 0) {
+		rtc_read(RTC_CMD1);
+		if (request_irq(pdata->irq, ds1511_interrupt,
+			IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) {
+
+			dev_warn(&pdev->dev, "interrupt not available.\n");
+			pdata->irq = -1;
+		}
+	}
+
+	rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops,
+		THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto out;
+	}
+	pdata->rtc = rtc;
+	platform_set_drvdata(pdev, pdata);
+	ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
+	if (ret) {
+		goto out;
+	}
+	return 0;
+ out:
+	if (pdata->rtc) {
+		rtc_device_unregister(pdata->rtc);
+	}
+	if (pdata->irq >= 0) {
+		free_irq(pdata->irq, pdev);
+	}
+	if (ds1511_base) {
+		iounmap(ds1511_base);
+		ds1511_base = NULL;
+	}
+	if (pdata->baseaddr) {
+		release_mem_region(pdata->baseaddr, pdata->size);
+	}
+
+	kfree(pdata);
+	return ret;
+}
+
+ static int __devexit
+ds1511_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
+	rtc_device_unregister(pdata->rtc);
+	pdata->rtc = NULL;
+	if (pdata->irq >= 0) {
+		/*
+		 * disable the alarm interrupt
+		 */
+		rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD);
+		rtc_read(RTC_CMD1);
+		free_irq(pdata->irq, pdev);
+	}
+	iounmap(pdata->ioaddr);
+	ds1511_base = NULL;
+	release_mem_region(pdata->baseaddr, pdata->size);
+	kfree(pdata);
+	return 0;
+}
+
+static struct platform_driver ds1511_rtc_driver = {
+	.probe		= ds1511_rtc_probe,
+	.remove		= __devexit_p(ds1511_rtc_remove),
+	.driver		= {
+		.name	= "ds1511",
+		.owner	= THIS_MODULE,
+	},
+};
+
+ static int __init
+ds1511_rtc_init(void)
+{
+	return platform_driver_register(&ds1511_rtc_driver);
+}
+
+ static void __exit
+ds1511_rtc_exit(void)
+{
+	return platform_driver_unregister(&ds1511_rtc_driver);
+}
+
+module_init(ds1511_rtc_init);
+module_exit(ds1511_rtc_exit);
+
+MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>");
+MODULE_DESCRIPTION("Dallas DS1511 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index c973ba9..8b39970 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -163,27 +163,17 @@
 
 static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
 {
-	unsigned char addr[1];
-	struct i2c_msg msgs[2] = {
-		{
-			.addr = client->addr,
-			.flags = 0,
-			.len = 1,
-			.buf = addr,
-		}, {
-			.addr = client->addr,
-			.flags = I2C_M_NOSTART,
-			.len = mem->nr,
-			.buf = mem->data,
-		}
-	};
+	unsigned char buf[9];
+	int ret;
 
-	if (mem->loc < 8)
+	if (mem->loc < 8 || mem->nr > 8)
 		return -EINVAL;
 
-	addr[0] = mem->loc;
+	buf[0] = mem->loc;
+	memcpy(buf + 1, mem->data, mem->nr);
 
-	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+	ret = i2c_master_send(client, buf, mem->nr + 1);
+	return ret == mem->nr + 1 ? 0 : -EIO;
 }
 
 static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
new file mode 100644
index 0000000..a64626a
--- /dev/null
+++ b/drivers/rtc/rtc-r9701.c
@@ -0,0 +1,178 @@
+/*
+ * Driver for Epson RTC-9701JE
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * Based on rtc-max6902.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 Compulab Ltd.
+ *
+ * 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/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#define RSECCNT	0x00	/* Second Counter */
+#define RMINCNT	0x01	/* Minute Counter */
+#define RHRCNT	0x02	/* Hour Counter */
+#define RWKCNT	0x03	/* Week Counter */
+#define RDAYCNT	0x04	/* Day Counter */
+#define RMONCNT	0x05	/* Month Counter */
+#define RYRCNT	0x06	/* Year Counter */
+#define R100CNT	0x07	/* Y100 Counter */
+#define RMINAR	0x08	/* Minute Alarm */
+#define RHRAR	0x09	/* Hour Alarm */
+#define RWKAR	0x0a	/* Week/Day Alarm */
+#define RTIMCNT	0x0c	/* Interval Timer */
+#define REXT	0x0d	/* Extension Register */
+#define RFLAG	0x0e	/* RTC Flag Register */
+#define RCR	0x0f	/* RTC Control Register */
+
+static int write_reg(struct device *dev, int address, unsigned char data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	unsigned char buf[2];
+
+	buf[0] = address & 0x7f;
+	buf[1] = data;
+
+	return spi_write(spi, buf, ARRAY_SIZE(buf));
+}
+
+static int read_regs(struct device *dev, unsigned char *regs, int no_regs)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	u8 txbuf[1], rxbuf[1];
+	int k, ret;
+
+	ret = 0;
+
+	for (k = 0; ret == 0 && k < no_regs; k++) {
+		txbuf[0] = 0x80 | regs[k];
+		ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
+		regs[k] = rxbuf[0];
+	}
+
+	return ret;
+}
+
+static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+	unsigned long time;
+	int ret;
+	unsigned char buf[] = { RSECCNT, RMINCNT, RHRCNT,
+				RDAYCNT, RMONCNT, RYRCNT };
+
+	ret = read_regs(dev, buf, ARRAY_SIZE(buf));
+	if (ret)
+		return ret;
+
+	memset(dt, 0, sizeof(*dt));
+
+	dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */
+	dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */
+	dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */
+
+	dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */
+	dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */
+	dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */
+
+	/* the rtc device may contain illegal values on power up
+	 * according to the data sheet. make sure they are valid.
+	 */
+
+	return rtc_valid_tm(dt);
+}
+
+static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+	int ret, year;
+
+	year = dt->tm_year + 1900;
+	if (year >= 2100 || year < 2000)
+		return -EINVAL;
+
+	ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour));
+	ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min));
+	ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec));
+	ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday));
+	ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1));
+	ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100));
+	ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday);
+
+	return ret;
+}
+
+static const struct rtc_class_ops r9701_rtc_ops = {
+	.read_time	= r9701_get_datetime,
+	.set_time	= r9701_set_datetime,
+};
+
+static int __devinit r9701_probe(struct spi_device *spi)
+{
+	struct rtc_device *rtc;
+	unsigned char tmp;
+	int res;
+
+	rtc = rtc_device_register("r9701",
+				&spi->dev, &r9701_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	dev_set_drvdata(&spi->dev, rtc);
+
+	tmp = R100CNT;
+	res = read_regs(&spi->dev, &tmp, 1);
+	if (res || tmp != 0x20) {
+		rtc_device_unregister(rtc);
+		return res;
+	}
+
+	return 0;
+}
+
+static int __devexit r9701_remove(struct spi_device *spi)
+{
+	struct rtc_device *rtc = dev_get_drvdata(&spi->dev);
+
+	rtc_device_unregister(rtc);
+	return 0;
+}
+
+static struct spi_driver r9701_driver = {
+	.driver = {
+		.name	= "rtc-r9701",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= r9701_probe,
+	.remove = __devexit_p(r9701_remove),
+};
+
+static __init int r9701_init(void)
+{
+	return spi_register_driver(&r9701_driver);
+}
+module_init(r9701_init);
+
+static __exit void r9701_exit(void)
+{
+	spi_unregister_driver(&r9701_driver);
+}
+module_exit(r9701_exit);
+
+MODULE_DESCRIPTION("r9701 spi RTC driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index e2041b4..86766f1 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -20,6 +20,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/clk.h>
+#include <linux/log2.h>
 
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
@@ -309,9 +310,7 @@
 		break;
 
 	case RTC_IRQP_SET:
-		/* check for power of 2 */
-
-		if ((arg & (arg-1)) != 0 || arg < 1) {
+		if (!is_power_of_2(arg)) {
 			ret = -EINVAL;
 			goto exit;
 		}
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 2eb3852..ee253cc 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -357,23 +357,15 @@
 #ifdef CONFIG_PM
 static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	if (pdev->dev.power.power_state.event != state.event) {
-		if (state.event == PM_EVENT_SUSPEND &&
-		    device_may_wakeup(&pdev->dev))
-			enable_irq_wake(IRQ_RTCAlrm);
-
-		pdev->dev.power.power_state = state;
-	}
+	if (device_may_wakeup(&pdev->dev))
+		enable_irq_wake(IRQ_RTCAlrm);
 	return 0;
 }
 
 static int sa1100_rtc_resume(struct platform_device *pdev)
 {
-	if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
-		if (device_may_wakeup(&pdev->dev))
-			disable_irq_wake(IRQ_RTCAlrm);
-		pdev->dev.power.power_state = PMSG_ON;
-	}
+	if (device_may_wakeup(&pdev->dev))
+		disable_irq_wake(IRQ_RTCAlrm);
 	return 0;
 }
 #else
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index 2ae0e83..4d27ccc 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -17,6 +17,13 @@
 
 /* device attributes */
 
+/*
+ * NOTE:  RTC times displayed in sysfs use the RTC's timezone.  That's
+ * ideally UTC.  However, PCs that also boot to MS-Windows normally use
+ * the local time and change to match daylight savings time.  That affects
+ * attributes including date, time, since_epoch, and wakealarm.
+ */
+
 static ssize_t
 rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -113,13 +120,13 @@
 	unsigned long alarm;
 	struct rtc_wkalrm alm;
 
-	/* Don't show disabled alarms; but the RTC could leave the
-	 * alarm enabled after it's already triggered.  Alarms are
-	 * conceptually one-shot, even though some common hardware
-	 * (PCs) doesn't actually work that way.
+	/* Don't show disabled alarms.  For uniformity, RTC alarms are
+	 * conceptually one-shot, even though some common RTCs (on PCs)
+	 * don't actually work that way.
 	 *
-	 * REVISIT maybe we should require RTC implementations to
-	 * disable the RTC alarm after it triggers, for uniformity.
+	 * NOTE: RTC implementations where the alarm doesn't match an
+	 * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC
+	 * alarms after they trigger, to ensure one-shot semantics.
 	 */
 	retval = rtc_read_alarm(to_rtc_device(dev), &alm);
 	if (retval == 0 && alm.enabled) {
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c
index 19343f9..291ff62 100644
--- a/drivers/s390/sysinfo.c
+++ b/drivers/s390/sysinfo.c
@@ -422,7 +422,7 @@
 /*
  * calibrate the delay loop
  */
-void __init calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
 {
 	s390_adjust_jiffies();
 	/* Print the good old Bogomips line .. */
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 23f27c9..5ac3a3e 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -46,8 +46,7 @@
     struct Scsi_Host *instance = cmd->device->host;
 
     /* don't allow DMA if the physical address is bad */
-    if (addr & A2091_XFER_MASK ||
-	(!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
+    if (addr & A2091_XFER_MASK)
     {
 	HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index d7255c8..3aeec96 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -54,8 +54,7 @@
      * end of a physical memory chunk, then allocate a bounce
      * buffer
      */
-    if (addr & A3000_XFER_MASK ||
-	(!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
+    if (addr & A3000_XFER_MASK)
     {
 	HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 3bfd929..93984c9 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -6472,7 +6472,7 @@
   unsigned long cpu_flags;
   struct aic7xxx_host *p;
   
-  p = (struct aic7xxx_host *)dev_id;
+  p = dev_id;
   if(!p)
     return IRQ_NONE;
   spin_lock_irqsave(p->host->host_lock, cpu_flags);
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 37741e9..91f8522 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -54,8 +54,7 @@
     static int scsi_alloc_out_of_range = 0;
 
     /* use bounce buffer if the physical address is bad */
-    if (addr & HDATA(cmd->device->host)->dma_xfer_mask ||
-	(!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
+    if (addr & HDATA(cmd->device->host)->dma_xfer_mask)
     {
 	HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c
index d63f11e95..bd62131 100644
--- a/drivers/scsi/ibmvscsi/ibmvstgt.c
+++ b/drivers/scsi/ibmvscsi/ibmvstgt.c
@@ -539,9 +539,9 @@
 		srp_iu_put(iue);
 }
 
-static irqreturn_t ibmvstgt_interrupt(int irq, void *data)
+static irqreturn_t ibmvstgt_interrupt(int dummy, void *data)
 {
-	struct srp_target *target = (struct srp_target *) data;
+	struct srp_target *target = data;
 	struct vio_port *vport = target_to_port(target);
 
 	vio_disable_interrupts(vport->dma_dev);
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 672c759..77a62a1 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -31,7 +31,6 @@
 #include <linux/moduleparam.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/uio.h>
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 4fa7927..6a44fb1 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -877,15 +877,15 @@
 	  systems.  Say Y if you want to be able to use this device.
 
 config SERIAL_IP22_ZILOG
-	tristate "IP22 Zilog8530 serial support"
-	depends on SGI_IP22
+	tristate "SGI Zilog8530 serial support"
+	depends on SGI_HAS_ZILOG
 	select SERIAL_CORE
 	help
-	  This driver supports the Zilog8530 serial ports found on SGI IP22
+	  This driver supports the Zilog8530 serial ports found on SGI
 	  systems.  Say Y or M if you want to be able to these serial ports.
 
 config SERIAL_IP22_ZILOG_CONSOLE
-	bool "Console on IP22 Zilog8530 serial port"
+	bool "Console on SGI Zilog8530 serial port"
 	depends on SERIAL_IP22_ZILOG=y
 	select SERIAL_CORE_CONSOLE
 
@@ -1318,4 +1318,19 @@
 	  This driver supports the QE serial ports on Freescale embedded
 	  PowerPC that contain a QUICC Engine.
 
+config SERIAL_SC26XX
+	tristate "SC2681/SC2692 serial port support"
+	depends on SNI_RM
+	select SERIAL_CORE
+	help
+	  This is a driver for the onboard serial ports of
+	  older RM400 machines.
+
+config SERIAL_SC26XX_CONSOLE
+	bool "Console on SC2681/SC2692 serial port"
+	depends on SERIAL_SC26XX
+	select SERIAL_CORE_CONSOLE
+	help
+	  Support for Console on SC2681/SC2692 serial ports.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 2dd41b4..640cfe4 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -55,6 +55,7 @@
 obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
 obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
+obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b5e4478..236af9d 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -380,7 +380,7 @@
 static irqreturn_t cpm_uart_int(int irq, void *data)
 {
 	u8 events;
-	struct uart_port *port = (struct uart_port *)data;
+	struct uart_port *port = data;
 	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
 	smc_t __iomem *smcp = pinfo->smcp;
 	scc_t __iomem *sccp = pinfo->sccp;
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c
index d31721f..bbae5a2 100644
--- a/drivers/serial/dz.c
+++ b/drivers/serial/dz.c
@@ -324,7 +324,7 @@
  */
 static irqreturn_t dz_interrupt(int irq, void *dev)
 {
-	struct dz_port *dport = (struct dz_port *)dev;
+	struct dz_port *dport = dev;
 	unsigned short status;
 
 	/* get the reason why we just got an irq */
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c
index dc19671..56af1f5 100644
--- a/drivers/serial/imx.c
+++ b/drivers/serial/imx.c
@@ -308,7 +308,7 @@
 
 static irqreturn_t imx_rtsint(int irq, void *dev_id)
 {
-	struct imx_port *sport = (struct imx_port *)dev_id;
+	struct imx_port *sport = dev_id;
 	unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS;
 	unsigned long flags;
 
@@ -324,7 +324,7 @@
 
 static irqreturn_t imx_txint(int irq, void *dev_id)
 {
-	struct imx_port *sport = (struct imx_port *)dev_id;
+	struct imx_port *sport = dev_id;
 	struct circ_buf *xmit = &sport->port.info->xmit;
 	unsigned long flags;
 
diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c
new file mode 100644
index 0000000..a350b6d
--- /dev/null
+++ b/drivers/serial/sc26xx.c
@@ -0,0 +1,755 @@
+/*
+ * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices.
+ *
+ * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/circ_buf.h>
+#include <linux/serial.h>
+#include <linux/sysrq.h>
+#include <linux/console.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+
+#if defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+#define SC26XX_MAJOR         204
+#define SC26XX_MINOR_START   205
+#define SC26XX_NR            2
+
+struct uart_sc26xx_port {
+	struct uart_port      port[2];
+	u8     dsr_mask[2];
+	u8     cts_mask[2];
+	u8     dcd_mask[2];
+	u8     ri_mask[2];
+	u8     dtr_mask[2];
+	u8     rts_mask[2];
+	u8     imr;
+};
+
+/* register common to both ports */
+#define RD_ISR      0x14
+#define RD_IPR      0x34
+
+#define WR_ACR      0x10
+#define WR_IMR      0x14
+#define WR_OPCR     0x34
+#define WR_OPR_SET  0x38
+#define WR_OPR_CLR  0x3C
+
+/* access common register */
+#define READ_SC(p, r)        readb((p)->membase + RD_##r)
+#define WRITE_SC(p, r, v)    writeb((v), (p)->membase + WR_##r)
+
+/* register per port */
+#define RD_PORT_MRx 0x00
+#define RD_PORT_SR  0x04
+#define RD_PORT_RHR 0x0c
+
+#define WR_PORT_MRx 0x00
+#define WR_PORT_CSR 0x04
+#define WR_PORT_CR  0x08
+#define WR_PORT_THR 0x0c
+
+/* SR bits */
+#define SR_BREAK    (1 << 7)
+#define SR_FRAME    (1 << 6)
+#define SR_PARITY   (1 << 5)
+#define SR_OVERRUN  (1 << 4)
+#define SR_TXRDY    (1 << 2)
+#define SR_RXRDY    (1 << 0)
+
+#define CR_RES_MR   (1 << 4)
+#define CR_RES_RX   (2 << 4)
+#define CR_RES_TX   (3 << 4)
+#define CR_STRT_BRK (6 << 4)
+#define CR_STOP_BRK (7 << 4)
+#define CR_DIS_TX   (1 << 3)
+#define CR_ENA_TX   (1 << 2)
+#define CR_DIS_RX   (1 << 1)
+#define CR_ENA_RX   (1 << 0)
+
+/* ISR bits */
+#define ISR_RXRDYB  (1 << 5)
+#define ISR_TXRDYB  (1 << 4)
+#define ISR_RXRDYA  (1 << 1)
+#define ISR_TXRDYA  (1 << 0)
+
+/* IMR bits */
+#define IMR_RXRDY   (1 << 1)
+#define IMR_TXRDY   (1 << 0)
+
+/* access port register */
+static inline u8 read_sc_port(struct uart_port *p, u8 reg)
+{
+	return readb(p->membase + p->line * 0x20 + reg);
+}
+
+static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val)
+{
+	writeb(val, p->membase + p->line * 0x20 + reg);
+}
+
+#define READ_SC_PORT(p, r)     read_sc_port(p, RD_PORT_##r)
+#define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v)
+
+static void sc26xx_enable_irq(struct uart_port *port, int mask)
+{
+	struct uart_sc26xx_port *up;
+	int line = port->line;
+
+	port -= line;
+	up = container_of(port, struct uart_sc26xx_port, port[0]);
+
+	up->imr |= mask << (line * 4);
+	WRITE_SC(port, IMR, up->imr);
+}
+
+static void sc26xx_disable_irq(struct uart_port *port, int mask)
+{
+	struct uart_sc26xx_port *up;
+	int line = port->line;
+
+	port -= line;
+	up = container_of(port, struct uart_sc26xx_port, port[0]);
+
+	up->imr &= ~(mask << (line * 4));
+	WRITE_SC(port, IMR, up->imr);
+}
+
+static struct tty_struct *receive_chars(struct uart_port *port)
+{
+	struct tty_struct *tty = NULL;
+	int limit = 10000;
+	unsigned char ch;
+	char flag;
+	u8 status;
+
+	if (port->info != NULL)		/* Unopened serial console */
+		tty = port->info->tty;
+
+	while (limit-- > 0) {
+		status = READ_SC_PORT(port, SR);
+		if (!(status & SR_RXRDY))
+			break;
+		ch = READ_SC_PORT(port, RHR);
+
+		flag = TTY_NORMAL;
+		port->icount.rx++;
+
+		if (unlikely(status & (SR_BREAK | SR_FRAME |
+				       SR_PARITY | SR_OVERRUN))) {
+			if (status & SR_BREAK) {
+				status &= ~(SR_PARITY | SR_FRAME);
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					continue;
+			} else if (status & SR_PARITY)
+				port->icount.parity++;
+			else if (status & SR_FRAME)
+				port->icount.frame++;
+			if (status & SR_OVERRUN)
+				port->icount.overrun++;
+
+			status &= port->read_status_mask;
+			if (status & SR_BREAK)
+				flag = TTY_BREAK;
+			else if (status & SR_PARITY)
+				flag = TTY_PARITY;
+			else if (status & SR_FRAME)
+				flag = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(port, ch))
+			continue;
+
+		if (status & port->ignore_status_mask)
+			continue;
+
+		tty_insert_flip_char(tty, ch, flag);
+	}
+	return tty;
+}
+
+static void transmit_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit;
+
+	if (!port->info)
+		return;
+
+	xmit = &port->info->xmit;
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		sc26xx_disable_irq(port, IMR_TXRDY);
+		return;
+	}
+	while (!uart_circ_empty(xmit)) {
+		if (!(READ_SC_PORT(port, SR) & SR_TXRDY))
+			break;
+
+		WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+}
+
+static irqreturn_t sc26xx_interrupt(int irq, void *dev_id)
+{
+	struct uart_sc26xx_port *up = dev_id;
+	struct tty_struct *tty;
+	unsigned long flags;
+	u8 isr;
+
+	spin_lock_irqsave(&up->port[0].lock, flags);
+
+	tty = NULL;
+	isr = READ_SC(&up->port[0], ISR);
+	if (isr & ISR_TXRDYA)
+	    transmit_chars(&up->port[0]);
+	if (isr & ISR_RXRDYA)
+	    tty = receive_chars(&up->port[0]);
+
+	spin_unlock(&up->port[0].lock);
+
+	if (tty)
+		tty_flip_buffer_push(tty);
+
+	spin_lock(&up->port[1].lock);
+
+	tty = NULL;
+	if (isr & ISR_TXRDYB)
+	    transmit_chars(&up->port[1]);
+	if (isr & ISR_RXRDYB)
+	    tty = receive_chars(&up->port[1]);
+
+	spin_unlock_irqrestore(&up->port[1].lock, flags);
+
+	if (tty)
+		tty_flip_buffer_push(tty);
+
+	return IRQ_HANDLED;
+}
+
+/* port->lock is not held.  */
+static unsigned int sc26xx_tx_empty(struct uart_port *port)
+{
+	return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0;
+}
+
+/* port->lock held by caller.  */
+static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	struct uart_sc26xx_port *up;
+	int line = port->line;
+
+	port -= line;
+	up = container_of(port, struct uart_sc26xx_port, port[0]);
+
+	if (up->dtr_mask[line]) {
+		if (mctrl & TIOCM_DTR)
+			WRITE_SC(port, OPR_SET, up->dtr_mask[line]);
+		else
+			WRITE_SC(port, OPR_CLR, up->dtr_mask[line]);
+	}
+	if (up->rts_mask[line]) {
+		if (mctrl & TIOCM_RTS)
+			WRITE_SC(port, OPR_SET, up->rts_mask[line]);
+		else
+			WRITE_SC(port, OPR_CLR, up->rts_mask[line]);
+	}
+}
+
+/* port->lock is held by caller and interrupts are disabled.  */
+static unsigned int sc26xx_get_mctrl(struct uart_port *port)
+{
+	struct uart_sc26xx_port *up;
+	int line = port->line;
+	unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
+	u8 ipr;
+
+	port -= line;
+	up = container_of(port, struct uart_sc26xx_port, port[0]);
+	ipr = READ_SC(port, IPR) ^ 0xff;
+
+	if (up->dsr_mask[line]) {
+		mctrl &= ~TIOCM_DSR;
+		mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0;
+	}
+	if (up->cts_mask[line]) {
+		mctrl &= ~TIOCM_CTS;
+		mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0;
+	}
+	if (up->dcd_mask[line]) {
+		mctrl &= ~TIOCM_CAR;
+		mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0;
+	}
+	if (up->ri_mask[line]) {
+		mctrl &= ~TIOCM_RNG;
+		mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0;
+	}
+	return mctrl;
+}
+
+/* port->lock held by caller.  */
+static void sc26xx_stop_tx(struct uart_port *port)
+{
+	return;
+}
+
+/* port->lock held by caller.  */
+static void sc26xx_start_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+
+	while (!uart_circ_empty(xmit)) {
+		if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) {
+			sc26xx_enable_irq(port, IMR_TXRDY);
+			break;
+		}
+		WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+}
+
+/* port->lock held by caller.  */
+static void sc26xx_stop_rx(struct uart_port *port)
+{
+}
+
+/* port->lock held by caller.  */
+static void sc26xx_enable_ms(struct uart_port *port)
+{
+}
+
+/* port->lock is not held.  */
+static void sc26xx_break_ctl(struct uart_port *port, int break_state)
+{
+	if (break_state == -1)
+		WRITE_SC_PORT(port, CR, CR_STRT_BRK);
+	else
+		WRITE_SC_PORT(port, CR, CR_STOP_BRK);
+}
+
+/* port->lock is not held.  */
+static int sc26xx_startup(struct uart_port *port)
+{
+	sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
+	WRITE_SC(port, OPCR, 0);
+
+	/* reset tx and rx */
+	WRITE_SC_PORT(port, CR, CR_RES_RX);
+	WRITE_SC_PORT(port, CR, CR_RES_TX);
+
+	/* start rx/tx */
+	WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
+
+	/* enable irqs */
+	sc26xx_enable_irq(port, IMR_RXRDY);
+	return 0;
+}
+
+/* port->lock is not held.  */
+static void sc26xx_shutdown(struct uart_port *port)
+{
+	/* disable interrupst */
+	sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY);
+
+	/* stop tx/rx */
+	WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
+}
+
+/* port->lock is not held.  */
+static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios,
+			      struct ktermios *old)
+{
+	unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
+	unsigned int quot = uart_get_divisor(port, baud);
+	unsigned int iflag, cflag;
+	unsigned long flags;
+	u8 mr1, mr2, csr;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
+		udelay(2);
+
+	WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX);
+
+	iflag = termios->c_iflag;
+	cflag = termios->c_cflag;
+
+	port->read_status_mask = SR_OVERRUN;
+	if (iflag & INPCK)
+		port->read_status_mask |= SR_PARITY | SR_FRAME;
+	if (iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= SR_BREAK;
+
+	port->ignore_status_mask = 0;
+	if (iflag & IGNBRK)
+		port->ignore_status_mask |= SR_BREAK;
+	if ((cflag & CREAD) == 0)
+		port->ignore_status_mask |= SR_BREAK | SR_FRAME |
+					    SR_PARITY | SR_OVERRUN;
+
+	switch (cflag & CSIZE) {
+	case CS5:
+		mr1 = 0x00;
+		break;
+	case CS6:
+		mr1 = 0x01;
+		break;
+	case CS7:
+		mr1 = 0x02;
+		break;
+	default:
+	case CS8:
+		mr1 = 0x03;
+		break;
+	}
+	mr2 = 0x07;
+	if (cflag & CSTOPB)
+		mr2 = 0x0f;
+	if (cflag & PARENB) {
+		if (cflag & PARODD)
+			mr1 |= (1 << 2);
+	} else
+		mr1 |= (2 << 3);
+
+	switch (baud) {
+	case 50:
+		csr = 0x00;
+		break;
+	case 110:
+		csr = 0x11;
+		break;
+	case 134:
+		csr = 0x22;
+		break;
+	case 200:
+		csr = 0x33;
+		break;
+	case 300:
+		csr = 0x44;
+		break;
+	case 600:
+		csr = 0x55;
+		break;
+	case 1200:
+		csr = 0x66;
+		break;
+	case 2400:
+		csr = 0x88;
+		break;
+	case 4800:
+		csr = 0x99;
+		break;
+	default:
+	case 9600:
+		csr = 0xbb;
+		break;
+	case 19200:
+		csr = 0xcc;
+		break;
+	}
+
+	WRITE_SC_PORT(port, CR, CR_RES_MR);
+	WRITE_SC_PORT(port, MRx, mr1);
+	WRITE_SC_PORT(port, MRx, mr2);
+
+	WRITE_SC(port, ACR, 0x80);
+	WRITE_SC_PORT(port, CSR, csr);
+
+	/* reset tx and rx */
+	WRITE_SC_PORT(port, CR, CR_RES_RX);
+	WRITE_SC_PORT(port, CR, CR_RES_TX);
+
+	WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX);
+	while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc)
+		udelay(2);
+
+	/* XXX */
+	uart_update_timeout(port, cflag,
+			    (port->uartclk / (16 * quot)));
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *sc26xx_type(struct uart_port *port)
+{
+	return "SC26XX";
+}
+
+static void sc26xx_release_port(struct uart_port *port)
+{
+}
+
+static int sc26xx_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void sc26xx_config_port(struct uart_port *port, int flags)
+{
+}
+
+static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	return -EINVAL;
+}
+
+static struct uart_ops sc26xx_ops = {
+	.tx_empty	= sc26xx_tx_empty,
+	.set_mctrl	= sc26xx_set_mctrl,
+	.get_mctrl	= sc26xx_get_mctrl,
+	.stop_tx	= sc26xx_stop_tx,
+	.start_tx	= sc26xx_start_tx,
+	.stop_rx	= sc26xx_stop_rx,
+	.enable_ms	= sc26xx_enable_ms,
+	.break_ctl	= sc26xx_break_ctl,
+	.startup	= sc26xx_startup,
+	.shutdown	= sc26xx_shutdown,
+	.set_termios	= sc26xx_set_termios,
+	.type		= sc26xx_type,
+	.release_port	= sc26xx_release_port,
+	.request_port	= sc26xx_request_port,
+	.config_port	= sc26xx_config_port,
+	.verify_port	= sc26xx_verify_port,
+};
+
+static struct uart_port *sc26xx_port;
+
+#ifdef CONFIG_SERIAL_SC26XX_CONSOLE
+static void sc26xx_console_putchar(struct uart_port *port, char c)
+{
+	unsigned long flags;
+	int limit = 1000000;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	while (limit-- > 0) {
+		if (READ_SC_PORT(port, SR) & SR_TXRDY) {
+			WRITE_SC_PORT(port, THR, c);
+			break;
+		}
+		udelay(2);
+	}
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void sc26xx_console_write(struct console *con, const char *s, unsigned n)
+{
+	struct uart_port *port = sc26xx_port;
+	int i;
+
+	for (i = 0; i < n; i++) {
+		if (*s == '\n')
+			sc26xx_console_putchar(port, '\r');
+		sc26xx_console_putchar(port, *s++);
+	}
+}
+
+static int __init sc26xx_console_setup(struct console *con, char *options)
+{
+	struct uart_port *port = sc26xx_port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (port->type != PORT_SC26XX)
+		return -1;
+
+	printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index);
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, con, baud, parity, bits, flow);
+}
+
+static struct uart_driver sc26xx_reg;
+static struct console sc26xx_console = {
+	.name	=	"ttySC",
+	.write	=	sc26xx_console_write,
+	.device	=	uart_console_device,
+	.setup  =       sc26xx_console_setup,
+	.flags	=	CON_PRINTBUFFER,
+	.index	=	-1,
+	.data	=	&sc26xx_reg,
+};
+#define SC26XX_CONSOLE   &sc26xx_console
+#else
+#define SC26XX_CONSOLE   NULL
+#endif
+
+static struct uart_driver sc26xx_reg = {
+	.owner			= THIS_MODULE,
+	.driver_name		= "SC26xx",
+	.dev_name		= "ttySC",
+	.major			= SC26XX_MAJOR,
+	.minor			= SC26XX_MINOR_START,
+	.nr			= SC26XX_NR,
+	.cons                   = SC26XX_CONSOLE,
+};
+
+static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos)
+{
+	unsigned int bit = (flags >> bitpos) & 15;
+
+	return bit ? (1 << (bit - 1)) : 0;
+}
+
+static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up,
+					int line, unsigned int data)
+{
+	up->dtr_mask[line] = sc26xx_flags2mask(data,  0);
+	up->rts_mask[line] = sc26xx_flags2mask(data,  4);
+	up->dsr_mask[line] = sc26xx_flags2mask(data,  8);
+	up->cts_mask[line] = sc26xx_flags2mask(data, 12);
+	up->dcd_mask[line] = sc26xx_flags2mask(data, 16);
+	up->ri_mask[line]  = sc26xx_flags2mask(data, 20);
+}
+
+static int __devinit sc26xx_probe(struct platform_device *dev)
+{
+	struct resource *res;
+	struct uart_sc26xx_port *up;
+	unsigned int *sc26xx_data = dev->dev.platform_data;
+	int err;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	up = kzalloc(sizeof *up, GFP_KERNEL);
+	if (unlikely(!up))
+		return -ENOMEM;
+
+	up->port[0].line = 0;
+	up->port[0].ops = &sc26xx_ops;
+	up->port[0].type = PORT_SC26XX;
+	up->port[0].uartclk = (29491200 / 16); /* arbitrary */
+
+	up->port[0].mapbase = res->start;
+	up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40);
+	up->port[0].iotype = UPIO_MEM;
+	up->port[0].irq = platform_get_irq(dev, 0);
+
+	up->port[0].dev = &dev->dev;
+
+	sc26xx_init_masks(up, 0, sc26xx_data[0]);
+
+	sc26xx_port = &up->port[0];
+
+	up->port[1].line = 1;
+	up->port[1].ops = &sc26xx_ops;
+	up->port[1].type = PORT_SC26XX;
+	up->port[1].uartclk = (29491200 / 16); /* arbitrary */
+
+	up->port[1].mapbase = up->port[0].mapbase;
+	up->port[1].membase = up->port[0].membase;
+	up->port[1].iotype = UPIO_MEM;
+	up->port[1].irq = up->port[0].irq;
+
+	up->port[1].dev = &dev->dev;
+
+	sc26xx_init_masks(up, 1, sc26xx_data[1]);
+
+	err = uart_register_driver(&sc26xx_reg);
+	if (err)
+		goto out_free_port;
+
+	sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor;
+
+	err = uart_add_one_port(&sc26xx_reg, &up->port[0]);
+	if (err)
+		goto out_unregister_driver;
+
+	err = uart_add_one_port(&sc26xx_reg, &up->port[1]);
+	if (err)
+		goto out_remove_port0;
+
+	err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up);
+	if (err)
+		goto out_remove_ports;
+
+	dev_set_drvdata(&dev->dev, up);
+	return 0;
+
+out_remove_ports:
+	uart_remove_one_port(&sc26xx_reg, &up->port[1]);
+out_remove_port0:
+	uart_remove_one_port(&sc26xx_reg, &up->port[0]);
+
+out_unregister_driver:
+	uart_unregister_driver(&sc26xx_reg);
+
+out_free_port:
+	kfree(up);
+	sc26xx_port = NULL;
+	return err;
+}
+
+
+static int __exit sc26xx_driver_remove(struct platform_device *dev)
+{
+	struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev);
+
+	free_irq(up->port[0].irq, up);
+
+	uart_remove_one_port(&sc26xx_reg, &up->port[0]);
+	uart_remove_one_port(&sc26xx_reg, &up->port[1]);
+
+	uart_unregister_driver(&sc26xx_reg);
+
+	kfree(up);
+	sc26xx_port = NULL;
+
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+static struct platform_driver sc26xx_driver = {
+	.probe	= sc26xx_probe,
+	.remove	= __devexit_p(sc26xx_driver_remove),
+	.driver	= {
+		.name	= "SC26xx",
+	},
+};
+
+static int __init sc26xx_init(void)
+{
+	return platform_driver_register(&sc26xx_driver);
+}
+
+static void __exit sc26xx_exit(void)
+{
+	platform_driver_unregister(&sc26xx_driver);
+}
+
+module_init(sc26xx_init);
+module_exit(sc26xx_exit);
+
+
+MODULE_AUTHOR("Thomas Bogendörfer");
+MODULE_DESCRIPTION("SC681/SC2692 serial driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 8094340..bacf68d 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -142,7 +142,7 @@
 
 static irqreturn_t ulite_isr(int irq, void *dev_id)
 {
-	struct uart_port *port = (struct uart_port *)dev_id;
+	struct uart_port *port = dev_id;
 	int busy;
 
 	do {
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index aaaea81..d810789 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -144,10 +144,10 @@
 	  This hooks up to the MicroWire controller on OMAP1 chips.
 
 config SPI_OMAP24XX
-	tristate "McSPI driver for OMAP24xx"
-	depends on SPI_MASTER && ARCH_OMAP24XX
+	tristate "McSPI driver for OMAP24xx/OMAP34xx"
+	depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX)
 	help
-	  SPI master controller for OMAP24xx Multichannel SPI
+	  SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI
 	  (McSPI) modules.
 
 config SPI_PXA2XX
@@ -176,6 +176,13 @@
 	  the inbuilt hardware cannot provide the transfer mode, or
 	  where the board is using non hardware connected pins.
 
+config SPI_SH_SCI
+	tristate "SuperH SCI SPI controller"
+	depends on SPI_MASTER && SUPERH
+	select SPI_BITBANG
+	help
+	  SPI driver for SuperH SCI blocks.
+
 config SPI_TXX9
 	tristate "Toshiba TXx9 SPI controller"
 	depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 41fbac4..7fca043 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
+obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 # 	... add above this line ...
 
 # SPI protocol drivers (device/link on bus)
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index ff10808..293b7ca 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -51,7 +51,9 @@
 	u8			stopping;
 	struct list_head	queue;
 	struct spi_transfer	*current_transfer;
-	unsigned long		remaining_bytes;
+	unsigned long		current_remaining_bytes;
+	struct spi_transfer	*next_transfer;
+	unsigned long		next_remaining_bytes;
 
 	void			*buffer;
 	dma_addr_t		buffer_dma;
@@ -121,6 +123,48 @@
 		gpio_set_value(gpio, !active);
 }
 
+static inline int atmel_spi_xfer_is_last(struct spi_message *msg,
+					struct spi_transfer *xfer)
+{
+	return msg->transfers.prev == &xfer->transfer_list;
+}
+
+static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer)
+{
+	return xfer->delay_usecs == 0 && !xfer->cs_change;
+}
+
+static void atmel_spi_next_xfer_data(struct spi_master *master,
+				struct spi_transfer *xfer,
+				dma_addr_t *tx_dma,
+				dma_addr_t *rx_dma,
+				u32 *plen)
+{
+	struct atmel_spi	*as = spi_master_get_devdata(master);
+	u32			len = *plen;
+
+	/* use scratch buffer only when rx or tx data is unspecified */
+	if (xfer->rx_buf)
+		*rx_dma = xfer->rx_dma + xfer->len - len;
+	else {
+		*rx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+	}
+	if (xfer->tx_buf)
+		*tx_dma = xfer->tx_dma + xfer->len - len;
+	else {
+		*tx_dma = as->buffer_dma;
+		if (len > BUFFER_SIZE)
+			len = BUFFER_SIZE;
+		memset(as->buffer, 0, len);
+		dma_sync_single_for_device(&as->pdev->dev,
+				as->buffer_dma, len, DMA_TO_DEVICE);
+	}
+
+	*plen = len;
+}
+
 /*
  * Submit next transfer for DMA.
  * lock is held, spi irq is blocked
@@ -130,53 +174,78 @@
 {
 	struct atmel_spi	*as = spi_master_get_devdata(master);
 	struct spi_transfer	*xfer;
-	u32			len;
+	u32			len, remaining, total;
 	dma_addr_t		tx_dma, rx_dma;
 
-	xfer = as->current_transfer;
-	if (!xfer || as->remaining_bytes == 0) {
-		if (xfer)
-			xfer = list_entry(xfer->transfer_list.next,
-					struct spi_transfer, transfer_list);
-		else
-			xfer = list_entry(msg->transfers.next,
-					struct spi_transfer, transfer_list);
-		as->remaining_bytes = xfer->len;
-		as->current_transfer = xfer;
+	if (!as->current_transfer)
+		xfer = list_entry(msg->transfers.next,
+				struct spi_transfer, transfer_list);
+	else if (!as->next_transfer)
+		xfer = list_entry(as->current_transfer->transfer_list.next,
+				struct spi_transfer, transfer_list);
+	else
+		xfer = NULL;
+
+	if (xfer) {
+		len = xfer->len;
+		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+		remaining = xfer->len - len;
+
+		spi_writel(as, RPR, rx_dma);
+		spi_writel(as, TPR, tx_dma);
+
+		if (msg->spi->bits_per_word > 8)
+			len >>= 1;
+		spi_writel(as, RCR, len);
+		spi_writel(as, TCR, len);
+
+		dev_dbg(&msg->spi->dev,
+			"  start xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+	} else {
+		xfer = as->next_transfer;
+		remaining = as->next_remaining_bytes;
 	}
 
-	len = as->remaining_bytes;
+	as->current_transfer = xfer;
+	as->current_remaining_bytes = remaining;
 
-	tx_dma = xfer->tx_dma + xfer->len - len;
-	rx_dma = xfer->rx_dma + xfer->len - len;
+	if (remaining > 0)
+		len = remaining;
+	else if (!atmel_spi_xfer_is_last(msg, xfer)
+			&& atmel_spi_xfer_can_be_chained(xfer)) {
+		xfer = list_entry(xfer->transfer_list.next,
+				struct spi_transfer, transfer_list);
+		len = xfer->len;
+	} else
+		xfer = NULL;
 
-	/* use scratch buffer only when rx or tx data is unspecified */
-	if (!xfer->rx_buf) {
-		rx_dma = as->buffer_dma;
-		if (len > BUFFER_SIZE)
-			len = BUFFER_SIZE;
-	}
-	if (!xfer->tx_buf) {
-		tx_dma = as->buffer_dma;
-		if (len > BUFFER_SIZE)
-			len = BUFFER_SIZE;
-		memset(as->buffer, 0, len);
-		dma_sync_single_for_device(&as->pdev->dev,
-				as->buffer_dma, len, DMA_TO_DEVICE);
+	as->next_transfer = xfer;
+
+	if (xfer) {
+		total = len;
+		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
+		as->next_remaining_bytes = total - len;
+
+		spi_writel(as, RNPR, rx_dma);
+		spi_writel(as, TNPR, tx_dma);
+
+		if (msg->spi->bits_per_word > 8)
+			len >>= 1;
+		spi_writel(as, RNCR, len);
+		spi_writel(as, TNCR, len);
+
+		dev_dbg(&msg->spi->dev,
+			"  next xfer %p: len %u tx %p/%08x rx %p/%08x\n",
+			xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
+			xfer->rx_buf, xfer->rx_dma);
+	} else {
+		spi_writel(as, RNCR, 0);
+		spi_writel(as, TNCR, 0);
 	}
 
-	spi_writel(as, RPR, rx_dma);
-	spi_writel(as, TPR, tx_dma);
-
-	as->remaining_bytes -= len;
-	if (msg->spi->bits_per_word > 8)
-		len >>= 1;
-
-	/* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer"
-	 * mechanism might help avoid the IRQ latency between transfers
-	 * (and improve the nCS0 errata handling on at91rm9200 chips)
-	 *
-	 * We're also waiting for ENDRX before we start the next
+	/* REVISIT: We're waiting for ENDRX before we start the next
 	 * transfer because we need to handle some difficult timing
 	 * issues otherwise. If we wait for ENDTX in one transfer and
 	 * then starts waiting for ENDRX in the next, it's difficult
@@ -186,17 +255,7 @@
 	 *
 	 * It should be doable, though. Just not now...
 	 */
-	spi_writel(as, TNCR, 0);
-	spi_writel(as, RNCR, 0);
 	spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES));
-
-	dev_dbg(&msg->spi->dev,
-		"  start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n",
-		xfer, xfer->len, xfer->tx_buf, xfer->tx_dma,
-		xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR));
-
-	spi_writel(as, RCR, len);
-	spi_writel(as, TCR, len);
 	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
 }
 
@@ -294,6 +353,7 @@
 	spin_lock(&as->lock);
 
 	as->current_transfer = NULL;
+	as->next_transfer = NULL;
 
 	/* continue if needed */
 	if (list_empty(&as->queue) || as->stopping)
@@ -377,7 +437,7 @@
 
 		spi_writel(as, IDR, pending);
 
-		if (as->remaining_bytes == 0) {
+		if (as->current_remaining_bytes == 0) {
 			msg->actual_length += xfer->len;
 
 			if (!msg->is_dma_mapped)
@@ -387,7 +447,7 @@
 			if (xfer->delay_usecs)
 				udelay(xfer->delay_usecs);
 
-			if (msg->transfers.prev == &xfer->transfer_list) {
+			if (atmel_spi_xfer_is_last(msg, xfer)) {
 				/* report completed message */
 				atmel_spi_msg_done(master, as, msg, 0,
 						xfer->cs_change);
@@ -490,9 +550,14 @@
 	if (!(spi->mode & SPI_CPHA))
 		csr |= SPI_BIT(NCPHA);
 
-	/* TODO: DLYBS and DLYBCT */
-	csr |= SPI_BF(DLYBS, 10);
-	csr |= SPI_BF(DLYBCT, 10);
+	/* DLYBS is mostly irrelevant since we manage chipselect using GPIOs.
+	 *
+	 * DLYBCT would add delays between words, slowing down transfers.
+	 * It could potentially be useful to cope with DMA bottlenecks, but
+	 * in those cases it's probably best to just use a lower bitrate.
+	 */
+	csr |= SPI_BF(DLYBS, 0);
+	csr |= SPI_BF(DLYBCT, 0);
 
 	/* chipselect must have been muxed as GPIO (e.g. in board setup) */
 	npcs_pin = (unsigned int)spi->controller_data;
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index ea61724..a6ba11a 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -915,6 +915,28 @@
 	OMAP24XX_DMA_SPI2_TX1,
 };
 
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
+static u8 __initdata spi3_rxdma_id[] = {
+	OMAP24XX_DMA_SPI3_RX0,
+	OMAP24XX_DMA_SPI3_RX1,
+};
+
+static u8 __initdata spi3_txdma_id[] = {
+	OMAP24XX_DMA_SPI3_TX0,
+	OMAP24XX_DMA_SPI3_TX1,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static u8 __initdata spi4_rxdma_id[] = {
+	OMAP34XX_DMA_SPI4_RX0,
+};
+
+static u8 __initdata spi4_txdma_id[] = {
+	OMAP34XX_DMA_SPI4_TX0,
+};
+#endif
+
 static int __init omap2_mcspi_probe(struct platform_device *pdev)
 {
 	struct spi_master	*master;
@@ -935,7 +957,20 @@
 		txdma_id = spi2_txdma_id;
 		num_chipselect = 2;
 		break;
-	/* REVISIT omap2430 has a third McSPI ... */
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+	case 3:
+		rxdma_id = spi3_rxdma_id;
+		txdma_id = spi3_txdma_id;
+		num_chipselect = 2;
+		break;
+#endif
+#ifdef CONFIG_ARCH_OMAP3
+	case 4:
+		rxdma_id = spi4_rxdma_id;
+		txdma_id = spi4_txdma_id;
+		num_chipselect = 1;
+		break;
+#endif
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index eb817b8..365e0e3 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1526,17 +1526,6 @@
 }
 
 #ifdef CONFIG_PM
-static int suspend_devices(struct device *dev, void *pm_message)
-{
-	pm_message_t *state = pm_message;
-
-	if (dev->power.power_state.event != state->event) {
-		dev_warn(dev, "pm state does not match request\n");
-		return -1;
-	}
-
-	return 0;
-}
 
 static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state)
 {
@@ -1544,12 +1533,6 @@
 	struct ssp_device *ssp = drv_data->ssp;
 	int status = 0;
 
-	/* Check all childern for current power state */
-	if (device_for_each_child(&pdev->dev, &state, suspend_devices) != 0) {
-		dev_warn(&pdev->dev, "suspend aborted\n");
-		return -1;
-	}
-
 	status = stop_queue(drv_data);
 	if (status != 0)
 		return status;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 682a6a4..1ad12af 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -18,7 +18,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/autoconf.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/init.h>
@@ -77,39 +76,33 @@
 
 #ifdef	CONFIG_PM
 
-/*
- * NOTE:  the suspend() method for an spi_master controller driver
- * should verify that all its child devices are marked as suspended;
- * suspend requests delivered through sysfs power/state files don't
- * enforce such constraints.
- */
 static int spi_suspend(struct device *dev, pm_message_t message)
 {
-	int			value;
+	int			value = 0;
 	struct spi_driver	*drv = to_spi_driver(dev->driver);
 
-	if (!drv || !drv->suspend)
-		return 0;
-
 	/* suspend will stop irqs and dma; no more i/o */
-	value = drv->suspend(to_spi_device(dev), message);
-	if (value == 0)
-		dev->power.power_state = message;
+	if (drv) {
+		if (drv->suspend)
+			value = drv->suspend(to_spi_device(dev), message);
+		else
+			dev_dbg(dev, "... can't suspend\n");
+	}
 	return value;
 }
 
 static int spi_resume(struct device *dev)
 {
-	int			value;
+	int			value = 0;
 	struct spi_driver	*drv = to_spi_driver(dev->driver);
 
-	if (!drv || !drv->resume)
-		return 0;
-
 	/* resume may restart the i/o queue */
-	value = drv->resume(to_spi_device(dev));
-	if (value == 0)
-		dev->power.power_state = PMSG_ON;
+	if (drv) {
+		if (drv->resume)
+			value = drv->resume(to_spi_device(dev));
+		else
+			dev_dbg(dev, "... can't resume\n");
+	}
 	return value;
 }
 
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7ef39a6..d853fceb 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -1,37 +1,11 @@
 /*
- * File:	drivers/spi/bfin5xx_spi.c
- * Maintainer:
- *		Bryan Wu <bryan.wu@analog.com>
- * Original Author:
- *		Luke Yang (Analog Devices Inc.)
- *
- * Created:	March. 10th 2006
- * Description:	SPI controller driver for Blackfin BF5xx
- * Bugs:	Enter bugs at http://blackfin.uclinux.org/
- *
- * Modified:
- *	March 10, 2006  bfin5xx_spi.c Created. (Luke Yang)
- *      August 7, 2006  added full duplex mode (Axel Weiss & Luke Yang)
- *      July  17, 2007  add support for BF54x SPI0 controller (Bryan Wu)
- *      July  30, 2007  add platfrom_resource interface to support multi-port
- *                      SPI controller (Bryan Wu)
+ * Blackfin On-Chip SPI Driver
  *
  * Copyright 2004-2007 Analog Devices 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, or (at your option)
- * any later version.
+ * Enter bugs at http://blackfin.uclinux.org/
  *
- * 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 ;  see the file COPYING.
- * If not, write to the Free Software Foundation,
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under the GPL-2 or later.
  */
 
 #include <linux/init.h>
@@ -223,10 +197,9 @@
 #define MAX_SPI_SSEL	7
 
 /* stop controller and re-config current chip*/
-static int restore_state(struct driver_data *drv_data)
+static void restore_state(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
-	int ret = 0;
 
 	/* Clear status and disable clock */
 	write_STAT(drv_data, BIT_STAT_CLR);
@@ -239,13 +212,6 @@
 
 	bfin_spi_enable(drv_data);
 	cs_active(drv_data, chip);
-
-	if (ret)
-		dev_dbg(&drv_data->pdev->dev,
-			": request chip select number %d failed\n",
-			chip->chip_select_num);
-
-	return ret;
 }
 
 /* used to kick off transfer in rx mode */
@@ -286,32 +252,30 @@
 	dev_dbg(&drv_data->pdev->dev,
 		"cr8-s is 0x%x\n", read_STAT(drv_data));
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
 		while (read_STAT(drv_data) & BIT_STAT_TXS)
 			cpu_relax();
 		++drv_data->tx;
 	}
+
+	/* poll for SPI completion before return */
+	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+		cpu_relax();
 }
 
 static void u8_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->tx < drv_data->tx_end) {
 		cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
 		while (read_STAT(drv_data) & BIT_STAT_TXS)
 			cpu_relax();
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+			cpu_relax();
 
 		cs_deactive(drv_data, chip);
 
@@ -350,43 +314,28 @@
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
-	/* clear TDBR buffer before read(else it will be shifted out) */
-	write_TDBR(drv_data, 0xFFFF);
-
-	cs_active(drv_data, chip);
-	dummy_read(drv_data);
-
-	while (drv_data->rx < drv_data->rx_end - 1) {
-		cs_deactive(drv_data, chip);
+	while (drv_data->rx < drv_data->rx_end) {
+		cs_active(drv_data, chip);
+		read_RDBR(drv_data);	/* kick off */
 
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
-		cs_active(drv_data, chip);
-		*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+			cpu_relax();
+
+		*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
+		cs_deactive(drv_data, chip);
+
 		++drv_data->rx;
 	}
-	cs_deactive(drv_data, chip);
-
-	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
-		cpu_relax();
-	*(u8 *) (drv_data->rx) = read_SHAW(drv_data);
-	++drv_data->rx;
 }
 
 static void u8_duplex(struct driver_data *drv_data)
 {
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	/* in duplex mode, clk is triggered by writing of TDBR */
 	while (drv_data->rx < drv_data->rx_end) {
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
@@ -400,15 +349,12 @@
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->rx < drv_data->rx_end) {
 		cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
+
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
@@ -426,32 +372,30 @@
 	dev_dbg(&drv_data->pdev->dev,
 		"cr16 is 0x%x\n", read_STAT(drv_data));
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
 		while ((read_STAT(drv_data) & BIT_STAT_TXS))
 			cpu_relax();
 		drv_data->tx += 2;
 	}
+
+	/* poll for SPI completion before return */
+	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+		cpu_relax();
 }
 
 static void u16_cs_chg_writer(struct driver_data *drv_data)
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->tx < drv_data->tx_end) {
 		cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
 		while ((read_STAT(drv_data) & BIT_STAT_TXS))
 			cpu_relax();
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
+			cpu_relax();
 
 		cs_deactive(drv_data, chip);
 
@@ -519,14 +463,10 @@
 
 static void u16_duplex(struct driver_data *drv_data)
 {
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	/* in duplex mode, clk is triggered by writing of TDBR */
 	while (drv_data->tx < drv_data->tx_end) {
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
@@ -540,15 +480,11 @@
 {
 	struct chip_data *chip = drv_data->cur_chip;
 
-	/* poll for SPI completion before start */
-	while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
-		cpu_relax();
-
 	while (drv_data->tx < drv_data->tx_end) {
 		cs_active(drv_data, chip);
 
 		write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		while (read_STAT(drv_data) & BIT_STAT_TXS)
+		while (!(read_STAT(drv_data) & BIT_STAT_SPIF))
 			cpu_relax();
 		while (!(read_STAT(drv_data) & BIT_STAT_RXS))
 			cpu_relax();
@@ -616,7 +552,7 @@
 
 static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 {
-	struct driver_data *drv_data = (struct driver_data *)dev_id;
+	struct driver_data *drv_data = dev_id;
 	struct chip_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
 
@@ -978,10 +914,7 @@
 
 	/* Setup the SSP using the per chip configuration */
 	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
-	if (restore_state(drv_data)) {
-		spin_unlock_irqrestore(&drv_data->lock, flags);
-		return;
-	};
+	restore_state(drv_data);
 
 	list_del_init(&drv_data->cur_msg->queue);
 
@@ -1187,7 +1120,7 @@
 	if ((chip->chip_select_num > 0)
 		&& (chip->chip_select_num <= spi->master->num_chipselect))
 		peripheral_request(ssel[spi->master->bus_num]
-			[chip->chip_select_num-1], DRV_NAME);
+			[chip->chip_select_num-1], spi->modalias);
 
 	cs_deactive(drv_data, chip);
 
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 639963e..1b06471 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -1686,17 +1686,6 @@
 }
 
 #ifdef CONFIG_PM
-static int suspend_devices(struct device *dev, void *pm_message)
-{
-	pm_message_t *state = pm_message;
-
-	if (dev->power.power_state.event != state->event) {
-		dev_warn(dev, "pm state does not match request\n");
-		return -1;
-	}
-
-	return 0;
-}
 
 static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state)
 {
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c
index 89d6685..6e834b8b 100644
--- a/drivers/spi/spi_s3c24xx.c
+++ b/drivers/spi/spi_s3c24xx.c
@@ -237,10 +237,8 @@
 {
 	struct s3c24xx_spi *hw;
 	struct spi_master *master;
-	struct spi_board_info *bi;
 	struct resource *res;
 	int err = 0;
-	int i;
 
 	master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi));
 	if (master == NULL) {
@@ -348,16 +346,6 @@
 		goto err_register;
 	}
 
-	/* register all the devices associated */
-
-	bi = &hw->pdata->board_info[0];
-	for (i = 0; i < hw->pdata->board_size; i++, bi++) {
-		dev_info(hw->dev, "registering %s\n", bi->modalias);
-
-		bi->controller_data = hw;
-		spi_new_device(master, bi);
-	}
-
 	return 0;
 
  err_register:
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
index 109d82c..82ae7d7 100644
--- a/drivers/spi/spi_s3c24xx_gpio.c
+++ b/drivers/spi/spi_s3c24xx_gpio.c
@@ -100,7 +100,6 @@
 	struct spi_master	*master;
 	struct s3c2410_spigpio  *sp;
 	int ret;
-	int i;
 
 	master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
 	if (master == NULL) {
@@ -143,17 +142,6 @@
 	if (ret)
 		goto err_no_bitbang;
 
-	/* register the chips to go with the board */
-
-	for (i = 0; i < sp->info->board_size; i++) {
-		dev_info(&dev->dev, "registering %p: %s\n",
-			 &sp->info->board_info[i],
-			 sp->info->board_info[i].modalias);
-
-		sp->info->board_info[i].controller_data = sp;
-		spi_new_device(master, sp->info->board_info + i);
-	}
-
 	return 0;
 
  err_no_bitbang:
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c
new file mode 100644
index 0000000..3dbe71b
--- /dev/null
+++ b/drivers/spi/spi_sh_sci.c
@@ -0,0 +1,205 @@
+/*
+ * SH SCI SPI interface
+ *
+ * Copyright (c) 2008 Magnus Damm
+ *
+ * Based on S3C24XX GPIO based SPI driver, which is:
+ *   Copyright (c) 2006 Ben Dooks
+ *   Copyright (c) 2006 Simtec Electronics
+ *
+ * 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/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+
+#include <asm/spi.h>
+#include <asm/io.h>
+
+struct sh_sci_spi {
+	struct spi_bitbang bitbang;
+
+	void __iomem *membase;
+	unsigned char val;
+	struct sh_spi_info *info;
+	struct platform_device *dev;
+};
+
+#define SCSPTR(sp)	(sp->membase + 0x1c)
+#define PIN_SCK		(1 << 2)
+#define PIN_TXD		(1 << 0)
+#define PIN_RXD		PIN_TXD
+#define PIN_INIT	((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD)
+
+static inline void setbits(struct sh_sci_spi *sp, int bits, int on)
+{
+	/*
+	 * We are the only user of SCSPTR so no locking is required.
+	 * Reading bit 2 and 0 in SCSPTR gives pin state as input.
+	 * Writing the same bits sets the output value.
+	 * This makes regular read-modify-write difficult so we
+	 * use sp->val to keep track of the latest register value.
+	 */
+
+	if (on)
+		sp->val |= bits;
+	else
+		sp->val &= ~bits;
+
+	iowrite8(sp->val, SCSPTR(sp));
+}
+
+static inline void setsck(struct spi_device *dev, int on)
+{
+	setbits(spi_master_get_devdata(dev->master), PIN_SCK, on);
+}
+
+static inline void setmosi(struct spi_device *dev, int on)
+{
+	setbits(spi_master_get_devdata(dev->master), PIN_TXD, on);
+}
+
+static inline u32 getmiso(struct spi_device *dev)
+{
+	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
+
+	return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0;
+}
+
+#define spidelay(x) ndelay(x)
+
+#define EXPAND_BITBANG_TXRX
+#include <linux/spi/spi_bitbang.h>
+
+static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
+}
+
+static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi,
+				      unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
+}
+
+static void sh_sci_spi_chipselect(struct spi_device *dev, int value)
+{
+	struct sh_sci_spi *sp = spi_master_get_devdata(dev->master);
+
+	if (sp->info && sp->info->chip_select)
+		(sp->info->chip_select)(sp->info, dev->chip_select, value);
+}
+
+static int sh_sci_spi_probe(struct platform_device *dev)
+{
+	struct resource	*r;
+	struct spi_master *master;
+	struct sh_sci_spi *sp;
+	int ret;
+
+	master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi));
+	if (master == NULL) {
+		dev_err(&dev->dev, "failed to allocate spi master\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	sp = spi_master_get_devdata(master);
+
+	platform_set_drvdata(dev, sp);
+	sp->info = dev->dev.platform_data;
+
+	/* setup spi bitbang adaptor */
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.master->bus_num = sp->info->bus_num;
+	sp->bitbang.master->num_chipselect = sp->info->num_chipselect;
+	sp->bitbang.chipselect = sh_sci_spi_chipselect;
+
+	sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0;
+	sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1;
+	sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2;
+	sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3;
+
+	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		ret = -ENOENT;
+		goto err1;
+	}
+	sp->membase = ioremap(r->start, r->end - r->start + 1);
+	if (!sp->membase) {
+		ret = -ENXIO;
+		goto err1;
+	}
+	sp->val = ioread8(SCSPTR(sp));
+	setbits(sp, PIN_INIT, 1);
+
+	ret = spi_bitbang_start(&sp->bitbang);
+	if (!ret)
+		return 0;
+
+	setbits(sp, PIN_INIT, 0);
+	iounmap(sp->membase);
+ err1:
+	spi_master_put(sp->bitbang.master);
+ err0:
+	return ret;
+}
+
+static int sh_sci_spi_remove(struct platform_device *dev)
+{
+	struct sh_sci_spi *sp = platform_get_drvdata(dev);
+
+	iounmap(sp->membase);
+	setbits(sp, PIN_INIT, 0);
+	spi_bitbang_stop(&sp->bitbang);
+	spi_master_put(sp->bitbang.master);
+	return 0;
+}
+
+static struct platform_driver sh_sci_spi_drv = {
+	.probe		= sh_sci_spi_probe,
+	.remove		= sh_sci_spi_remove,
+	.driver		= {
+		.name	= "spi_sh_sci",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init sh_sci_spi_init(void)
+{
+	return platform_driver_register(&sh_sci_spi_drv);
+}
+module_init(sh_sci_spi_init);
+
+static void __exit sh_sci_spi_exit(void)
+{
+	platform_driver_unregister(&sh_sci_spi_drv);
+}
+module_exit(sh_sci_spi_exit);
+
+MODULE_DESCRIPTION("SH SCI SPI Driver");
+MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index cc246fa..2a77e9d 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -417,30 +417,28 @@
 	idev->vma_count--;
 }
 
-static struct page *uio_vma_nopage(struct vm_area_struct *vma,
-				   unsigned long address, int *type)
+static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct uio_device *idev = vma->vm_private_data;
-	struct page* page = NOPAGE_SIGBUS;
+	struct page *page;
 
 	int mi = uio_find_mem_index(vma);
 	if (mi < 0)
-		return page;
+		return VM_FAULT_SIGBUS;
 
 	if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
 		page = virt_to_page(idev->info->mem[mi].addr);
 	else
 		page = vmalloc_to_page((void*)idev->info->mem[mi].addr);
 	get_page(page);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return page;
+	vmf->page = page;
+	return 0;
 }
 
 static struct vm_operations_struct uio_vm_ops = {
 	.open = uio_vma_open,
 	.close = uio_vma_close,
-	.nopage = uio_vma_nopage,
+	.fault = uio_vma_fault,
 };
 
 static int uio_mmap_physical(struct vm_area_struct *vma)
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index f8e7111..fc65c02 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -16,6 +16,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/backlight.h>
 
 #include <asm/arch/board.h>
 #include <asm/arch/cpu.h>
@@ -69,6 +70,107 @@
 }
 #endif
 
+static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
+		| ATMEL_LCDC_POL_POSITIVE
+		| ATMEL_LCDC_ENA_PWMENABLE;
+
+#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
+
+/* some bl->props field just changed */
+static int atmel_bl_update_status(struct backlight_device *bl)
+{
+	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
+	int			power = sinfo->bl_power;
+	int			brightness = bl->props.brightness;
+
+	/* REVISIT there may be a meaningful difference between
+	 * fb_blank and power ... there seem to be some cases
+	 * this doesn't handle correctly.
+	 */
+	if (bl->props.fb_blank != sinfo->bl_power)
+		power = bl->props.fb_blank;
+	else if (bl->props.power != sinfo->bl_power)
+		power = bl->props.power;
+
+	if (brightness < 0 && power == FB_BLANK_UNBLANK)
+		brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+	else if (power != FB_BLANK_UNBLANK)
+		brightness = 0;
+
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
+			brightness ? contrast_ctr : 0);
+
+	bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
+
+	return 0;
+}
+
+static int atmel_bl_get_brightness(struct backlight_device *bl)
+{
+	struct atmel_lcdfb_info *sinfo = bl_get_data(bl);
+
+	return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+}
+
+static struct backlight_ops atmel_lcdc_bl_ops = {
+	.update_status = atmel_bl_update_status,
+	.get_brightness = atmel_bl_get_brightness,
+};
+
+static void init_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	struct backlight_device	*bl;
+
+	sinfo->bl_power = FB_BLANK_UNBLANK;
+
+	if (sinfo->backlight)
+		return;
+
+	bl = backlight_device_register("backlight", &sinfo->pdev->dev,
+			sinfo, &atmel_lcdc_bl_ops);
+	if (IS_ERR(sinfo->backlight)) {
+		dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n",
+				PTR_ERR(bl));
+		return;
+	}
+	sinfo->backlight = bl;
+
+	bl->props.power = FB_BLANK_UNBLANK;
+	bl->props.fb_blank = FB_BLANK_UNBLANK;
+	bl->props.max_brightness = 0xff;
+	bl->props.brightness = atmel_bl_get_brightness(bl);
+}
+
+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	if (sinfo->backlight)
+		backlight_device_unregister(sinfo->backlight);
+}
+
+#else
+
+static void init_backlight(struct atmel_lcdfb_info *sinfo)
+{
+	dev_warn(&sinfo->pdev->dev, "backlight control is not available\n");
+}
+
+static void exit_backlight(struct atmel_lcdfb_info *sinfo)
+{
+}
+
+#endif
+
+static void init_contrast(struct atmel_lcdfb_info *sinfo)
+{
+	/* have some default contrast/backlight settings */
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+
+	if (sinfo->lcdcon_is_backlight)
+		init_backlight(sinfo);
+}
+
 
 static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
 	.type		= FB_TYPE_PACKED_PIXELS,
@@ -203,6 +305,26 @@
 	var->transp.offset = var->transp.length = 0;
 	var->xoffset = var->yoffset = 0;
 
+	/* Saturate vertical and horizontal timings at maximum values */
+	var->vsync_len = min_t(u32, var->vsync_len,
+			(ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1);
+	var->upper_margin = min_t(u32, var->upper_margin,
+			ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET);
+	var->lower_margin = min_t(u32, var->lower_margin,
+			ATMEL_LCDC_VFP);
+	var->right_margin = min_t(u32, var->right_margin,
+			(ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1);
+	var->hsync_len = min_t(u32, var->hsync_len,
+			(ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1);
+	var->left_margin = min_t(u32, var->left_margin,
+			ATMEL_LCDC_HBP + 1);
+
+	/* Some parameters can't be zero */
+	var->vsync_len = max_t(u32, var->vsync_len, 1);
+	var->right_margin = max_t(u32, var->right_margin, 1);
+	var->hsync_len = max_t(u32, var->hsync_len, 1);
+	var->left_margin = max_t(u32, var->left_margin, 1);
+
 	switch (var->bits_per_pixel) {
 	case 1:
 	case 2:
@@ -370,10 +492,6 @@
 	/* Disable all interrupts */
 	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
 
-	/* Set contrast */
-	value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE;
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value);
-	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
 	/* ...wait for DMA engine to become idle... */
 	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
 		msleep(10);
@@ -577,6 +695,7 @@
 		sinfo->default_monspecs = pdata_sinfo->default_monspecs;
 		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
 		sinfo->guard_time = pdata_sinfo->guard_time;
+		sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight;
 	} else {
 		dev_err(dev, "cannot get default configuration\n");
 		goto free_info;
@@ -670,6 +789,9 @@
 		goto release_mem;
 	}
 
+	/* Initialize PWM for contrast or backlight ("off") */
+	init_contrast(sinfo);
+
 	/* interrupt */
 	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
 	if (ret) {
@@ -721,6 +843,7 @@
 unregister_irqs:
 	free_irq(sinfo->irq_base, info);
 unmap_mmio:
+	exit_backlight(sinfo);
 	iounmap(sinfo->mmio);
 release_mem:
  	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
@@ -755,6 +878,7 @@
 	if (!sinfo)
 		return 0;
 
+	exit_backlight(sinfo);
 	if (sinfo->atmel_lcdfb_power_control)
 		sinfo->atmel_lcdfb_power_control(0);
 	unregister_framebuffer(info);
@@ -781,6 +905,9 @@
 
 static struct platform_driver atmel_lcdfb_driver = {
 	.remove		= __exit_p(atmel_lcdfb_remove),
+
+// FIXME need suspend, resume
+
 	.driver		= {
 		.name	= "atmel_lcdfb",
 		.owner	= THIS_MODULE,
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 9609a6c..924e255 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -50,6 +50,19 @@
 	  To have support for your specific LCD panel you will have to
 	  select the proper drivers which depend on this option.
 
+config BACKLIGHT_ATMEL_LCDC
+	bool "Atmel LCDC Contrast-as-Backlight control"
+	depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL
+	default y if MACH_SAM9261EK || MACH_SAM9263EK
+	help
+	  This provides a backlight control internal to the Atmel LCDC
+	  driver.  If the LCD "contrast control" on your board is wired
+	  so it controls the backlight brightness, select this option to
+	  export this as a PWM-based backlight control.
+
+	  If in doubt, it's safe to enable this option; it doesn't kick
+	  in unless the board's description says it's wired that way.
+
 config BACKLIGHT_CORGI
 	tristate "Generic (aka Sharp Corgi) Backlight Driver"
 	depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index c8e7427..0ce791e 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -498,8 +498,7 @@
 
 static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id)
 {
-
-	/*struct bfin_bf54xfb_info *info = (struct bfin_bf54xfb_info *)dev_id;*/
+	/*struct bfin_bf54xfb_info *info = dev_id;*/
 
 	u16 status = bfin_read_EPPI0_STATUS();
 
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 308850d..69864b1 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -63,7 +63,7 @@
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	struct fb_fillrect region;
 
-	region.color = attr_bgcol_ec(bgshift, vc);
+	region.color = attr_bgcol_ec(bgshift, vc, info);
 	region.dx = sx * vc->vc_font.width;
 	region.dy = sy * vc->vc_font.height;
 	region.width = width * vc->vc_font.width;
@@ -213,7 +213,7 @@
 	unsigned int bs = info->var.yres - bh;
 	struct fb_fillrect region;
 
-	region.color = attr_bgcol_ec(bgshift, vc);
+	region.color = attr_bgcol_ec(bgshift, vc, info);
 	region.rop = ROP_COPY;
 
 	if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 0f32f4a..0222824 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -84,7 +84,7 @@
 #ifdef CONFIG_MAC
 #include <asm/macints.h>
 #endif
-#if defined(__mc68000__) || defined(CONFIG_APUS)
+#if defined(__mc68000__)
 #include <asm/machdep.h>
 #include <asm/setup.h>
 #endif
@@ -147,7 +147,7 @@
 static int info_idx = -1;
 
 /* console rotation */
-static int rotate;
+static int initial_rotation;
 static int fbcon_has_sysfs;
 
 static const struct consw fb_con;
@@ -334,10 +334,7 @@
 	switch (depth) {
 	case 1:
 	{
-		int col = ~(0xfff << (max(info->var.green.length,
-					  max(info->var.red.length,
-					      info->var.blue.length)))) & 0xff;
-
+		int col = mono_col(info);
 		/* 0 or 1 */
 		int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0;
 		int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col;
@@ -537,9 +534,9 @@
 		if (!strncmp(options, "rotate:", 7)) {
 			options += 7;
 			if (*options)
-				rotate = simple_strtoul(options, &options, 0);
-			if (rotate > 3)
-				rotate = 0;
+				initial_rotation = simple_strtoul(options, &options, 0);
+			if (initial_rotation > 3)
+				initial_rotation = 0;
 		}
 	}
 	return 1;
@@ -989,7 +986,7 @@
 	ops->graphics = 1;
 	ops->cur_rotate = -1;
 	info->fbcon_par = ops;
-	p->con_rotate = rotate;
+	p->con_rotate = initial_rotation;
 	set_blitting_type(vc, info);
 
 	if (info->fix.type != FB_TYPE_TEXT) {
@@ -1176,7 +1173,7 @@
 		con_copy_unimap(vc, svc);
 
 	ops = info->fbcon_par;
-	p->con_rotate = rotate;
+	p->con_rotate = initial_rotation;
 	set_blitting_type(vc, info);
 
 	cols = vc->vc_cols;
@@ -2795,7 +2792,7 @@
 {
 	struct fb_info *info = registered_fb[con2fb_map[fg_console]];
 	struct fbcon_ops *ops = info->fbcon_par;
-	struct display *p = &fb_display[fg_console];
+	struct display *disp = &fb_display[fg_console];
 	int offset, limit, scrollback_old;
 
 	if (softback_top) {
@@ -2833,7 +2830,7 @@
 			logo_shown = FBCON_LOGO_CANSHOW;
 		}
 		fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
-		fbcon_redraw_softback(vc, p, lines);
+		fbcon_redraw_softback(vc, disp, lines);
 		fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK);
 		return 0;
 	}
@@ -2855,9 +2852,9 @@
 
 	fbcon_cursor(vc, CM_ERASE);
 
-	offset = p->yscroll - scrollback_current;
-	limit = p->vrows;
-	switch (p->scrollmode) {
+	offset = disp->yscroll - scrollback_current;
+	limit = disp->vrows;
+	switch (disp->scrollmode) {
 	case SCROLL_WRAP_MOVE:
 		info->var.vmode |= FB_VMODE_YWRAP;
 		break;
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 8e6ef4b..3706307 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -93,10 +93,6 @@
 	(((s) >> (fgshift)) & 0x0f)
 #define attr_bgcol(bgshift,s)    \
 	(((s) >> (bgshift)) & 0x0f)
-#define	attr_bgcol_ec(bgshift,vc) \
-	((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0)
-#define attr_fgcol_ec(fgshift,vc) \
-	((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0)
 
 /* Monochrome */
 #define attr_bold(s) \
@@ -108,6 +104,49 @@
 #define attr_blink(s) \
 	((s) & 0x8000)
 	
+#define mono_col(info)							\
+	(~(0xfff << (max((info)->var.green.length,			\
+			 max((info)->var.red.length,			\
+			     (info)->var.blue.length)))) & 0xff)
+
+static inline int attr_col_ec(int shift, struct vc_data *vc,
+			      struct fb_info *info, int is_fg)
+{
+	int is_mono01;
+	int col;
+	int fg;
+	int bg;
+
+	if (!vc)
+		return 0;
+
+	if (vc->vc_can_do_color)
+		return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char)
+			: attr_bgcol(shift,vc->vc_video_erase_char);
+
+	if (!info)
+		return 0;
+
+	col = mono_col(info);
+	is_mono01 = info->fix.visual == FB_VISUAL_MONO01;
+
+	if (attr_reverse(vc->vc_video_erase_char)) {
+		fg = is_mono01 ? col : 0;
+		bg = is_mono01 ? 0 : col;
+	}
+	else {
+		fg = is_mono01 ? 0 : col;
+		bg = is_mono01 ? col : 0;
+	}
+
+	return is_fg ? fg : bg;
+}
+
+#define attr_bgcol_ec(bgshift,vc,info)		\
+	attr_col_ec(bgshift,vc,info,0);
+#define attr_fgcol_ec(fgshift,vc,info)		\
+	attr_col_ec(fgshift,vc,info,1);
+
 /* Font */
 #define REFCOUNT(fd)	(((int *)(fd))[-1])
 #define FNTSIZE(fd)	(((int *)(fd))[-2])
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c
index 825e6d6..bdf913e 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -84,7 +84,7 @@
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	u32 vyres = GETVYRES(ops->p->scrollmode, info);
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.dx = sy * vc->vc_font.height;
 	region.dy = vyres - ((sx + width) * vc->vc_font.width);
 	region.height = width * vc->vc_font.width;
@@ -198,7 +198,7 @@
 	struct fb_fillrect region;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.rop = ROP_COPY;
 
 	if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index c637e63..a6819b9 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -70,7 +70,7 @@
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.dx = vxres - ((sy + height) * vc->vc_font.height);
 	region.dy = sx *  vc->vc_font.width;
 	region.height = width * vc->vc_font.width;
@@ -182,7 +182,7 @@
 	struct fb_fillrect region;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.rop = ROP_COPY;
 
 	if (rw && !bottom_only) {
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index 1473506..d9b5d6e 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -71,7 +71,7 @@
 	u32 vyres = GETVYRES(ops->p->scrollmode, info);
 	u32 vxres = GETVXRES(ops->p->scrollmode, info);
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.dy = vyres - ((sy + height) * vc->vc_font.height);
 	region.dx = vxres - ((sx + width) *  vc->vc_font.width);
 	region.width = width * vc->vc_font.width;
@@ -228,7 +228,7 @@
 	struct fb_fillrect region;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 
-	region.color = attr_bgcol_ec(bgshift,vc);
+	region.color = attr_bgcol_ec(bgshift,vc,info);
 	region.rop = ROP_COPY;
 
 	if (rw && !bottom_only) {
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 96979c3..d0c03fd 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#if defined(__mc68000__) || defined(CONFIG_APUS)
+#if defined(__mc68000__)
 #include <asm/setup.h>
 #endif
 #include <linux/font.h>
@@ -120,7 +120,7 @@
     for(i=0; i<num_fonts; i++) {
 	f = fonts[i];
 	c = f->pref;
-#if defined(__mc68000__) || defined(CONFIG_APUS)
+#if defined(__mc68000__)
 #ifdef CONFIG_FONT_PEARL_8x8
 	if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX)
 	    c = 100;
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
index d981fe4..0056a41 100644
--- a/drivers/video/console/tileblit.c
+++ b/drivers/video/console/tileblit.c
@@ -40,8 +40,8 @@
 
 	rect.index = vc->vc_video_erase_char &
 		((vc->vc_hi_font_mask) ? 0x1ff : 0xff);
-	rect.fg = attr_fgcol_ec(fgshift, vc);
-	rect.bg = attr_bgcol_ec(bgshift, vc);
+	rect.fg = attr_fgcol_ec(fgshift, vc, info);
+	rect.bg = attr_bgcol_ec(bgshift, vc, info);
 	rect.sx = sx;
 	rect.sy = sy;
 	rect.width = width;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index f65bcd3..6df29a6 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1153,8 +1153,6 @@
 
 	/* if 512 char mode is already enabled don't re-enable it. */
 	if ((set) && (ch512 != vga_512_chars)) {
-		int i;	
-		
 		/* attribute controller */
 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
 			struct vc_data *c = vc_cons[i].d;
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c
index a0c5d9d..0f8cfb9 100644
--- a/drivers/video/fb_defio.c
+++ b/drivers/video/fb_defio.c
@@ -25,8 +25,8 @@
 #include <linux/pagemap.h>
 
 /* this is to find and return the vmalloc-ed fb pages */
-static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma,
-					unsigned long vaddr, int *type)
+static int fb_deferred_io_fault(struct vm_area_struct *vma,
+				struct vm_fault *vmf)
 {
 	unsigned long offset;
 	struct page *page;
@@ -34,18 +34,17 @@
 	/* info->screen_base is in System RAM */
 	void *screen_base = (void __force *) info->screen_base;
 
-	offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+	offset = vmf->pgoff << PAGE_SHIFT;
 	if (offset >= info->fix.smem_len)
-		return NOPAGE_SIGBUS;
+		return VM_FAULT_SIGBUS;
 
 	page = vmalloc_to_page(screen_base + offset);
 	if (!page)
-		return NOPAGE_OOM;
+		return VM_FAULT_SIGBUS;
 
 	get_page(page);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return page;
+	vmf->page = page;
+	return 0;
 }
 
 int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync)
@@ -84,7 +83,7 @@
 }
 
 static struct vm_operations_struct fb_deferred_io_vm_ops = {
-	.nopage   	= fb_deferred_io_nopage,
+	.fault		= fb_deferred_io_fault,
 	.page_mkwrite	= fb_deferred_io_mkwrite,
 };
 
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h
index cdafbe1..a2a0618 100644
--- a/drivers/video/fb_draw.h
+++ b/drivers/video/fb_draw.h
@@ -91,6 +91,7 @@
 		val = comp(val >> 2, val << 2, REV_PIXELS_MASK2);
 	if (bswapmask & 3)
 		val = comp(val >> 4, val << 4, REV_PIXELS_MASK4);
+	return val;
 }
 
 static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask)
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 4ba9c08..052e180 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
  *
  * Credits:
- * 
+ *
  * The EDID Parser is a conglomeration from the following sources:
  *
  *   1. SciTech SNAP Graphics Architecture
@@ -12,13 +12,13 @@
  *
  *   2. XFree86 4.3.0, interpret_edid.c
  *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
- * 
- *   3. John Fremlin <vii@users.sourceforge.net> and 
+ *
+ *   3. John Fremlin <vii@users.sourceforge.net> and
  *      Ani Joshi <ajoshi@unixbox.com>
- *  
+ *
  * Generalized Timing Formula is derived from:
  *
- *      GTF Spreadsheet by Andy Morrish (1/5/97) 
+ *      GTF Spreadsheet by Andy Morrish (1/5/97)
  *      available at http://www.vesa.org
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -36,7 +36,7 @@
 #endif
 #include "edid.h"
 
-/* 
+/*
  * EDID parser
  */
 
@@ -160,8 +160,8 @@
 	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
 		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
 			brokendb[i].model == model) {
- 			fix = brokendb[i].fix;
- 			break;
+			fix = brokendb[i].fix;
+			break;
 		}
 	}
 
@@ -323,7 +323,7 @@
 	       (flags & DPMS_SUSPEND)    ? "yes" : "no",
 	       (flags & DPMS_STANDBY)    ? "yes" : "no");
 }
-	
+
 static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
 {
 	int tmp;
@@ -365,7 +365,7 @@
 	tmp += 512;
 	specs->chroma.bluey = tmp/1024;
 	DPRINTK("BlueY:    0.%03d\n", specs->chroma.bluey);
-	
+
 	tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
 	tmp *= 1000;
 	tmp += 512;
@@ -383,7 +383,7 @@
 			      struct fb_videomode *mode)
 {
 	struct fb_var_screeninfo *var;
-	
+
 	var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
 
 	if (var) {
@@ -451,11 +451,11 @@
 
 	c = block[1];
 	if (c&0x80) {
- 		mode[num++] = vesa_modes[9];
+		mode[num++] = vesa_modes[9];
 		DPRINTK("      800x600@72Hz\n");
 	}
 	if (c&0x40) {
- 		mode[num++] = vesa_modes[10];
+		mode[num++] = vesa_modes[10];
 		DPRINTK("      800x600@75Hz\n");
 	}
 	if (c&0x20) {
@@ -495,7 +495,7 @@
 static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
 {
 	int xres, yres = 0, refresh, ratio, i;
-	
+
 	xres = (block[0] + 31) * 8;
 	if (xres <= 256)
 		return 0;
@@ -519,7 +519,7 @@
 
 	DPRINTK("      %dx%d@%dHz\n", xres, yres, refresh);
 	for (i = 0; i < VESA_MODEDB_SIZE; i++) {
-		if (vesa_modes[i].xres == xres && 
+		if (vesa_modes[i].xres == xres &&
 		    vesa_modes[i].yres == yres &&
 		    vesa_modes[i].refresh == refresh) {
 			*mode = vesa_modes[i];
@@ -536,13 +536,13 @@
 {
 	int j, num = 0;
 
-	for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) 
+	for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
 		num += get_std_timing(block, &mode[num]);
 
 	return num;
 }
 
-static void get_detailed_timing(unsigned char *block, 
+static void get_detailed_timing(unsigned char *block,
 				struct fb_videomode *mode)
 {
 	mode->xres = H_ACTIVE;
@@ -553,7 +553,7 @@
 	mode->right_margin = H_SYNC_OFFSET;
 	mode->left_margin = (H_ACTIVE + H_BLANKING) -
 		(H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
-	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - 
+	mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
 		V_SYNC_WIDTH;
 	mode->lower_margin = V_SYNC_OFFSET;
 	mode->hsync_len = H_SYNC_WIDTH;
@@ -597,7 +597,7 @@
 	if (mode == NULL)
 		return NULL;
 
-	if (edid == NULL || !edid_checksum(edid) || 
+	if (edid == NULL || !edid_checksum(edid) ||
 	    !edid_check_header(edid)) {
 		kfree(mode);
 		return NULL;
@@ -632,7 +632,7 @@
 		if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
 			num += get_dst_timing(block + 5, &mode[num]);
 	}
-	
+
 	/* Yikes, EDID data is totally useless */
 	if (!num) {
 		kfree(mode);
@@ -686,7 +686,7 @@
 	/* estimate monitor limits based on modes supported */
 	if (retval) {
 		struct fb_videomode *modes, *mode;
-		int num_modes, i, hz, hscan, pixclock;
+		int num_modes, hz, hscan, pixclock;
 		int vtotal, htotal;
 
 		modes = fb_create_modedb(edid, &num_modes);
@@ -713,7 +713,7 @@
 			hscan = (pixclock + htotal / 2) / htotal;
 			hscan = (hscan + 500) / 1000 * 1000;
 			hz = (hscan + vtotal / 2) / vtotal;
-			
+
 			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
 				specs->dclkmax = pixclock;
 
@@ -966,8 +966,8 @@
 	DPRINTK("========================================\n");
 }
 
-/* 
- * VESA Generalized Timing Formula (GTF) 
+/*
+ * VESA Generalized Timing Formula (GTF)
  */
 
 #define FLYBACK                     550
@@ -996,7 +996,7 @@
  * @hfreq: horizontal freq
  *
  * DESCRIPTION:
- * vblank = right_margin + vsync_len + left_margin 
+ * vblank = right_margin + vsync_len + left_margin
  *
  *    given: right_margin = 1 (V_FRONTPORCH)
  *           vsync_len    = 3
@@ -1010,12 +1010,12 @@
 {
 	u32 vblank;
 
-	vblank = (hfreq * FLYBACK)/1000; 
+	vblank = (hfreq * FLYBACK)/1000;
 	vblank = (vblank + 500)/1000;
 	return (vblank + V_FRONTPORCH);
 }
 
-/** 
+/**
  * fb_get_hblank_by_freq - get horizontal blank time given hfreq
  * @hfreq: horizontal freq
  * @xres: horizontal resolution in pixels
@@ -1031,7 +1031,7 @@
  *
  * where: C = ((offset - scale factor) * blank_scale)
  *            -------------------------------------- + scale factor
- *                        256 
+ *                        256
  *        M = blank_scale * gradient
  *
  */
@@ -1039,7 +1039,7 @@
 {
 	u32 c_val, m_val, duty_cycle, hblank;
 
-	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + 
+	c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
 		 H_SCALEFACTOR) * 1000;
 	m_val = (H_BLANKSCALE * H_GRADIENT)/256;
 	m_val = (m_val * 1000000)/hfreq;
@@ -1048,7 +1048,7 @@
 	return (hblank);
 }
 
-/** 
+/**
  * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
  * @dclk: pixelclock in Hz
  * @xres: horizontal resolution in pixels
@@ -1061,7 +1061,7 @@
  *
  * duty cycle = percent of htotal assigned to inactive display
  * duty cycle = C - (M * h_period)
- * 
+ *
  * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
  *                   -----------------------------------------------
  *                                    2 * M
@@ -1077,11 +1077,11 @@
 	h_period = 100 - C_VAL;
 	h_period *= h_period;
 	h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
-	h_period *=10000; 
+	h_period *= 10000;
 
 	h_period = int_sqrt(h_period);
 	h_period -= (100 - C_VAL) * 100;
-	h_period *= 1000; 
+	h_period *= 1000;
 	h_period /= 2 * M_VAL;
 
 	duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
@@ -1089,7 +1089,7 @@
 	hblank &= ~15;
 	return (hblank);
 }
-	
+
 /**
  * fb_get_hfreq - estimate hsync
  * @vfreq: vertical refresh rate
@@ -1100,13 +1100,13 @@
  *          (yres + front_port) * vfreq * 1000000
  * hfreq = -------------------------------------
  *          (1000000 - (vfreq * FLYBACK)
- * 
+ *
  */
 
 static u32 fb_get_hfreq(u32 vfreq, u32 yres)
 {
 	u32 divisor, hfreq;
-	
+
 	divisor = (1000000 - (vfreq * FLYBACK))/1000;
 	hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
 	return (hfreq/divisor);
@@ -1117,7 +1117,7 @@
 	timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
 	timings->vblank = fb_get_vblank(timings->hfreq);
 	timings->vtotal = timings->vactive + timings->vblank;
-	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 
+	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
 						 timings->hactive);
 	timings->htotal = timings->hactive + timings->hblank;
 	timings->dclk = timings->htotal * timings->hfreq;
@@ -1128,7 +1128,7 @@
 	timings->vblank = fb_get_vblank(timings->hfreq);
 	timings->vtotal = timings->vactive + timings->vblank;
 	timings->vfreq = timings->hfreq/timings->vtotal;
-	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 
+	timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
 						 timings->hactive);
 	timings->htotal = timings->hactive + timings->hblank;
 	timings->dclk = timings->htotal * timings->hfreq;
@@ -1136,7 +1136,7 @@
 
 static void fb_timings_dclk(struct __fb_timings *timings)
 {
-	timings->hblank = fb_get_hblank_by_dclk(timings->dclk, 
+	timings->hblank = fb_get_hblank_by_dclk(timings->dclk,
 						timings->hactive);
 	timings->htotal = timings->hactive + timings->hblank;
 	timings->hfreq = timings->dclk/timings->htotal;
@@ -1156,29 +1156,29 @@
  * @info: pointer to fb_info
  *
  * DESCRIPTION:
- * Calculates video mode based on monitor specs using VESA GTF. 
- * The GTF is best for VESA GTF compliant monitors but is 
+ * Calculates video mode based on monitor specs using VESA GTF.
+ * The GTF is best for VESA GTF compliant monitors but is
  * specifically formulated to work for older monitors as well.
  *
- * If @flag==0, the function will attempt to maximize the 
+ * If @flag==0, the function will attempt to maximize the
  * refresh rate.  Otherwise, it will calculate timings based on
- * the flag and accompanying value.  
+ * the flag and accompanying value.
  *
- * If FB_IGNOREMON bit is set in @flags, monitor specs will be 
+ * If FB_IGNOREMON bit is set in @flags, monitor specs will be
  * ignored and @var will be filled with the calculated timings.
  *
  * All calculations are based on the VESA GTF Spreadsheet
  * available at VESA's public ftp (http://www.vesa.org).
- * 
+ *
  * NOTES:
  * The timings generated by the GTF will be different from VESA
  * DMT.  It might be a good idea to keep a table of standard
  * VESA modes as well.  The GTF may also not work for some displays,
  * such as, and especially, analog TV.
- *   
+ *
  * REQUIRES:
  * A valid info->monspecs, otherwise 'safe numbers' will be used.
- */ 
+ */
 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
 {
 	struct __fb_timings *timings;
@@ -1191,7 +1191,7 @@
 	if (!timings)
 		return -ENOMEM;
 
-	/* 
+	/*
 	 * If monspecs are invalid, use values that are enough
 	 * for 640x480@60
 	 */
@@ -1214,7 +1214,7 @@
 
 	timings->hactive = var->xres;
 	timings->vactive = var->yres;
-	if (var->vmode & FB_VMODE_INTERLACED) { 
+	if (var->vmode & FB_VMODE_INTERLACED) {
 		timings->vactive /= 2;
 		interlace = 2;
 	}
@@ -1250,9 +1250,9 @@
 		break;
 	default:
 		err = -EINVAL;
-		
-	} 
-	
+
+	}
+
 	if (err || (!(flags & FB_IGNOREMON) &&
 	    (timings->vfreq < vfmin || timings->vfreq > vfmax ||
 	     timings->hfreq < hfmin || timings->hfreq > hfmax ||
@@ -1269,7 +1269,7 @@
 		var->upper_margin = (timings->vblank * interlace)/dscan -
 			(var->vsync_len + var->lower_margin);
 	}
-	
+
 	kfree(timings);
 	return err;
 }
@@ -1291,7 +1291,7 @@
 	return -EINVAL;
 }
 #endif /* CONFIG_FB_MODE_HELPERS */
-	
+
 /*
  * fb_validate_mode - validates var against monitor capabilities
  * @var: pointer to fb_var_screeninfo
@@ -1309,7 +1309,7 @@
 	u32 hfreq, vfreq, htotal, vtotal, pixclock;
 	u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
 
-	/* 
+	/*
 	 * If monspecs are invalid, use values that are enough
 	 * for 640x480@60
 	 */
@@ -1333,10 +1333,10 @@
 	if (!var->pixclock)
 		return -EINVAL;
 	pixclock = PICOS2KHZ(var->pixclock) * 1000;
-	   
-	htotal = var->xres + var->right_margin + var->hsync_len + 
+
+	htotal = var->xres + var->right_margin + var->hsync_len +
 		var->left_margin;
-	vtotal = var->yres + var->lower_margin + var->vsync_len + 
+	vtotal = var->yres + var->lower_margin + var->vsync_len +
 		var->upper_margin;
 
 	if (var->vmode & FB_VMODE_INTERLACED)
@@ -1349,7 +1349,7 @@
 
 	vfreq = hfreq/vtotal;
 
-	return (vfreq < vfmin || vfreq > vfmax || 
+	return (vfreq < vfmin || vfreq > vfmax ||
 		hfreq < hfmin || hfreq > hfmax ||
 		pixclock < dclkmin || pixclock > dclkmax) ?
 		-EINVAL : 0;
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
index 583185f..eb6b881 100644
--- a/drivers/video/geode/lxfb_core.c
+++ b/drivers/video/geode/lxfb_core.c
@@ -34,7 +34,7 @@
  * we try to make it something sane - 640x480-60 is sane
  */
 
-const struct fb_videomode geode_modedb[] __initdata = {
+static const struct fb_videomode geode_modedb[] __initdata = {
 	/* 640x480-60 */
 	{ NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
 	  FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index b18486a..2eb4fb1 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -207,7 +207,8 @@
 #define HPFB_FBOMSB	0x5d	/* Frame buffer offset		*/
 #define HPFB_FBOLSB	0x5f
 
-static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base)
+static int __devinit hpfb_init_one(unsigned long phys_base,
+				   unsigned long virt_base)
 {
 	unsigned long fboff, fb_width, fb_height, fb_start;
 
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 1a7d778..1d13dd0 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1476,7 +1476,7 @@
 	struct i810fb_par *par = info->par;
 	u8 __iomem *mmio = par->mmio_start_virtual;
 
-	if (!par->dev_flags & LOCKUP)
+	if (!(par->dev_flags & LOCKUP))
 		return -ENXIO;
 
 	if (cursor->image.width > 64 || cursor->image.height > 64)
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index b87ea21..3a81060 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -400,6 +400,7 @@
         info = kzalloc(size, GFP_ATOMIC);
         if (!info) {
                 printk("igafb_init: can't alloc fb_info\n");
+		 pci_dev_put(pdev);
                 return -ENOMEM;
         }
 
@@ -409,12 +410,14 @@
 	if ((addr = pdev->resource[0].start) == 0) {
                 printk("igafb_init: no memory start\n");
 		kfree(info);
+		pci_dev_put(pdev);
 		return -ENXIO;
 	}
 
 	if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) {
                 printk("igafb_init: can't remap %lx[2M]\n", addr);
 		kfree(info);
+		pci_dev_put(pdev);
 		return -ENXIO;
 	}
 
@@ -449,6 +452,7 @@
                 printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start);
 		iounmap((void *)info->screen_base);
 		kfree(info);
+		pci_dev_put(pdev);
 		return -ENXIO;
 	}
 
@@ -466,6 +470,7 @@
 		iounmap((void *)par->io_base);
 		iounmap(info->screen_base);
 		kfree(info);
+		pci_dev_put(pdev);
 		return -ENOMEM;
 	}
 
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 5f6fb7d..fa1fff5 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -1971,7 +1971,7 @@
 static irqreturn_t intelfbhw_irq(int irq, void *dev_id)
 {
 	u16 tmp;
-	struct intelfb_info *dinfo = (struct intelfb_info *)dev_id;
+	struct intelfb_info *dinfo = dev_id;
 
 	spin_lock(&dinfo->int_lock);
 
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 4b6a99b..5246b04 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -2066,40 +2066,49 @@
 
 	switch (info->fix.accel) {
 	case FB_ACCEL_NEOMAGIC_NM2070:
-		sprintf(info->fix.id, "MagicGraph 128");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128");
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2090:
-		sprintf(info->fix.id, "MagicGraph 128V");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128V");
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2093:
-		sprintf(info->fix.id, "MagicGraph 128ZV");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128ZV");
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2097:
-		sprintf(info->fix.id, "MagicGraph 128ZV+");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128ZV+");
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2160:
-		sprintf(info->fix.id, "MagicGraph 128XD");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 128XD");
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2200:
-		sprintf(info->fix.id, "MagicGraph 256AV");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256AV");
 		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
 		               FBINFO_HWACCEL_COPYAREA |
                 	       FBINFO_HWACCEL_FILLRECT;
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2230:
-		sprintf(info->fix.id, "MagicGraph 256AV+");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256AV+");
 		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
 		               FBINFO_HWACCEL_COPYAREA |
                 	       FBINFO_HWACCEL_FILLRECT;
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2360:
-		sprintf(info->fix.id, "MagicGraph 256ZX");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256ZX");
 		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
 		               FBINFO_HWACCEL_COPYAREA |
                 	       FBINFO_HWACCEL_FILLRECT;
 		break;
 	case FB_ACCEL_NEOMAGIC_NM2380:
-		sprintf(info->fix.id, "MagicGraph 256XL+");
+		snprintf(info->fix.id, sizeof(info->fix.id),
+				"MagicGraph 256XL+");
 		info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
 		               FBINFO_HWACCEL_COPYAREA |
                 	       FBINFO_HWACCEL_FILLRECT;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 30e14eb..74517b1 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -849,9 +849,27 @@
 	if (!mode_valid && info->monspecs.modedb_len)
 		return -EINVAL;
 
+	/*
+	 * If we're on a flat panel, check if the mode is outside of the
+	 * panel dimensions. If so, cap it and try for the next best mode
+	 * before bailing out.
+	 */
 	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
-					      par->fpHeight < var->yres))
-		return -EINVAL;
+					      par->fpHeight < var->yres)) {
+		const struct fb_videomode *mode;
+
+		var->xres = par->fpWidth;
+		var->yres = par->fpHeight;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (!mode) {
+			printk(KERN_ERR PFX "mode out of range of flat "
+			       "panel dimensions\n");
+			return -EINVAL;
+		}
+
+		fb_videomode_to_var(var, mode);
+	}
 
 	if (var->yres_virtual < var->yres)
 		var->yres_virtual = var->yres;
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 5591dfb..30181b5 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1159,6 +1159,11 @@
 	u32 fgx, bgx;
 	const u32 *src = (const u32 *)image->data;
 	u32 xres = (info->var.xres + 31) & ~31;
+	int raster_mode = 1; /* invert bits */
+
+#ifdef __LITTLE_ENDIAN
+	raster_mode |= 3 << 7; /* reverse byte order */
+#endif
 
 	if (info->state != FBINFO_STATE_RUNNING)
 		return;
@@ -1208,9 +1213,8 @@
 		pm2_WR(par, PM2R_RENDER,
 			PM2F_RENDER_RECTANGLE |
 			PM2F_INCREASE_X | PM2F_INCREASE_Y);
-		/* BitMapPackEachScanline & invert bits and byte order*/
-		/* force background */
-		pm2_WR(par, PM2R_RASTERIZER_MODE,  (1 << 9) | 1 | (3 << 7));
+		/* BitMapPackEachScanline */
+		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9));
 		pm2_WR(par, PM2R_CONSTANT_COLOR, fgx);
 		pm2_WR(par, PM2R_RENDER,
 			PM2F_RENDER_RECTANGLE |
@@ -1224,8 +1228,7 @@
 			PM2F_RENDER_RECTANGLE |
 			PM2F_RENDER_FASTFILL |
 			PM2F_INCREASE_X | PM2F_INCREASE_Y);
-		/* invert bits and byte order*/
-		pm2_WR(par, PM2R_RASTERIZER_MODE,  1 | (3 << 7));
+		pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode);
 		pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx);
 		pm2_WR(par, PM2R_RENDER,
 			PM2F_RENDER_RECTANGLE |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 0706599..5dba8cd 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -1227,7 +1227,7 @@
 
 /* mmio register are already mapped when this function is called */
 /* the pm3fb_fix.smem_start is also set */
-static unsigned long pm3fb_size_memory(struct pm3_par *par)
+static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par)
 {
 	unsigned long	memsize = 0;
 	unsigned long	tempBypass, i, temp1, temp2;
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c
index a864438..6515ec1 100644
--- a/drivers/video/pmag-aa-fb.c
+++ b/drivers/video/pmag-aa-fb.c
@@ -150,7 +150,7 @@
 {
 	struct aafb_info *info = (struct aafb_info *)disp->fb_info;
 	struct aafb_cursor *c = &info->cursor;
-	u8 fgc = ~attr_bgcol_ec(disp, disp->conp);
+	u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info);
 
 	if (width > 64 || height > 64 || width < 0 || height < 0)
 		return -EINVAL;
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 044a423..dc3af1c 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -57,8 +57,6 @@
 #define GPU_ALIGN_UP(x)				_ALIGN_UP((x), 64)
 #define GPU_MAX_LINE_LENGTH			(65536 - 64)
 
-#define PS3FB_FULL_MODE_BIT			0x80
-
 #define GPU_INTR_STATUS_VSYNC_0			0	/* vsync on head A */
 #define GPU_INTR_STATUS_VSYNC_1			1	/* vsync on head B */
 #define GPU_INTR_STATUS_FLIP_0			3	/* flip head A */
@@ -118,8 +116,6 @@
 	unsigned int irq_no;
 
 	u64 context_handle, memory_handle;
-	void *xdr_ea;
-	size_t xdr_size;
 	struct gpu_driver_info *dinfo;
 
 	u64 vblank_count;	/* frame count */
@@ -136,42 +132,19 @@
 struct ps3fb_par {
 	u32 pseudo_palette[16];
 	int mode_id, new_mode_id;
-	int res_index;
 	unsigned int num_frames;	/* num of frame buffers */
 	unsigned int width;
 	unsigned int height;
-	unsigned long full_offset;	/* start of fullscreen DDR fb */
-	unsigned long fb_offset;	/* start of actual DDR fb */
-	unsigned long pan_offset;
+	unsigned int ddr_line_length;
+	unsigned int ddr_frame_size;
+	unsigned int xdr_frame_size;
+	unsigned int full_offset;	/* start of fullscreen DDR fb */
+	unsigned int fb_offset;		/* start of actual DDR fb */
+	unsigned int pan_offset;
 };
 
-struct ps3fb_res_table {
-	u32 xres;
-	u32 yres;
-	u32 xoff;
-	u32 yoff;
-	u32 type;
-};
-#define PS3FB_RES_FULL 1
-static const struct ps3fb_res_table ps3fb_res[] = {
-	/* res_x,y   margin_x,y  full */
-	{  720,  480,  72,  48 , 0},
-	{  720,  576,  72,  58 , 0},
-	{ 1280,  720,  78,  38 , 0},
-	{ 1920, 1080, 116,  58 , 0},
-	/* full mode */
-	{  720,  480,   0,   0 , PS3FB_RES_FULL},
-	{  720,  576,   0,   0 , PS3FB_RES_FULL},
-	{ 1280,  720,   0,   0 , PS3FB_RES_FULL},
-	{ 1920, 1080,   0,   0 , PS3FB_RES_FULL},
-	/* vesa: normally full mode */
-	{ 1280,  768,   0,   0 , 0},
-	{ 1280, 1024,   0,   0 , 0},
-	{ 1920, 1200,   0,   0 , 0},
-	{    0,    0,   0,   0 , 0} };
 
-/* default resolution */
-#define GPU_RES_INDEX	0		/* 720 x 480 */
+#define FIRST_NATIVE_MODE_INDEX	10
 
 static const struct fb_videomode ps3fb_modedb[] = {
     /* 60 Hz broadcast modes (modes "1" to "5") */
@@ -211,7 +184,7 @@
         "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5,
         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
     },    {
-        /* 1080 */
+        /* 1080i */
         "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5,
         FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
     },    {
@@ -220,24 +193,7 @@
         FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
     },
 
-    /* VESA modes (modes "11" to "13") */
-    {
-	/* WXGA */
-	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
-	0, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    }, {
-	/* SXGA */
-	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
-	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    }, {
-	/* WUXGA */
-	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
-	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
-	FB_MODE_IS_VESA
-    },
-
+    [FIRST_NATIVE_MODE_INDEX] =
     /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */
     {
 	/* 480if */
@@ -276,12 +232,30 @@
 	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
     }, {
 	/* 1080if */
-	"1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
+	"1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5,
 	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
     }, {
 	/* 1080pf */
 	"1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5,
 	FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
+    },
+
+    /* VESA modes (modes "11" to "13") */
+    {
+	/* WXGA */
+	"wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6,
+	0, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* SXGA */
+	"sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+	FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
+    }, {
+	/* WUXGA */
+	"wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6,
+	FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED,
+	FB_MODE_IS_VESA
     }
 };
 
@@ -289,110 +263,188 @@
 #define HEAD_A
 #define HEAD_B
 
-#define X_OFF(i)	(ps3fb_res[i].xoff)	/* left/right margin (pixel) */
-#define Y_OFF(i)	(ps3fb_res[i].yoff)	/* top/bottom margin (pixel) */
-#define WIDTH(i)	(ps3fb_res[i].xres)	/* width of FB */
-#define HEIGHT(i)	(ps3fb_res[i].yres)	/* height of FB */
 #define BPP		4			/* number of bytes per pixel */
 
-/* Start of the virtual frame buffer (relative to fullscreen ) */
-#define VP_OFF(i)	((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP)
-
 
 static int ps3fb_mode;
 module_param(ps3fb_mode, int, 0);
 
 static char *mode_option __devinitdata;
 
-static int ps3fb_get_res_table(u32 xres, u32 yres, int mode)
+static int ps3fb_cmp_mode(const struct fb_videomode *vmode,
+			  const struct fb_var_screeninfo *var)
 {
-	int full_mode;
-	unsigned int i;
-	u32 x, y, f;
+	long xres, yres, left_margin, right_margin, upper_margin, lower_margin;
+	long dx, dy;
 
-	full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0;
-	for (i = 0;; i++) {
-		x = ps3fb_res[i].xres;
-		y = ps3fb_res[i].yres;
-		f = ps3fb_res[i].type;
+	/* maximum values */
+	if (var->xres > vmode->xres || var->yres > vmode->yres ||
+	    var->pixclock > vmode->pixclock ||
+	    var->hsync_len > vmode->hsync_len ||
+	    var->vsync_len > vmode->vsync_len)
+		return -1;
 
-		if (!x) {
-			pr_debug("ERROR: ps3fb_get_res_table()\n");
-			return -1;
-		}
+	/* progressive/interlaced must match */
+	if ((var->vmode & FB_VMODE_MASK) != vmode->vmode)
+		return -1;
 
-		if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL)
-			continue;
+	/* minimum resolution */
+	xres = max(var->xres, 1U);
+	yres = max(var->yres, 1U);
 
-		if (x == xres && (yres == 0 || y == yres))
-			break;
+	/* minimum margins */
+	left_margin = max(var->left_margin, vmode->left_margin);
+	right_margin = max(var->right_margin, vmode->right_margin);
+	upper_margin = max(var->upper_margin, vmode->upper_margin);
+	lower_margin = max(var->lower_margin, vmode->lower_margin);
 
-		x = x - 2 * ps3fb_res[i].xoff;
-		y = y - 2 * ps3fb_res[i].yoff;
-		if (x == xres && (yres == 0 || y == yres))
-			break;
-	}
-	return i;
+	/* resolution + margins may not exceed native parameters */
+	dx = ((long)vmode->left_margin + (long)vmode->xres +
+	      (long)vmode->right_margin) -
+	     (left_margin + xres + right_margin);
+	if (dx < 0)
+		return -1;
+
+	dy = ((long)vmode->upper_margin + (long)vmode->yres +
+	      (long)vmode->lower_margin) -
+	     (upper_margin + yres + lower_margin);
+	if (dy < 0)
+		return -1;
+
+	/* exact match */
+	if (!dx && !dy)
+		return 0;
+
+	/* resolution difference */
+	return (vmode->xres - xres) * (vmode->yres - yres);
 }
 
-static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var,
+static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id)
+{
+	return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1];
+}
+
+static const struct fb_videomode *ps3fb_vmode(int id)
+{
+	u32 mode = id & PS3AV_MODE_MASK;
+
+	if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA)
+		return NULL;
+
+	if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) {
+		/* Non-fullscreen broadcast mode */
+		return &ps3fb_modedb[mode - 1];
+	}
+
+	return ps3fb_native_vmode(mode);
+}
+
+static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var,
 				    u32 *ddr_line_length, u32 *xdr_line_length)
 {
-	unsigned int i, mode;
+	unsigned int id, best_id;
+	int diff, best_diff;
+	const struct fb_videomode *vmode;
+	long gap;
 
-	for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++)
-		if (var->xres == ps3fb_modedb[i].xres &&
-		    var->yres == ps3fb_modedb[i].yres &&
-		    var->pixclock == ps3fb_modedb[i].pixclock &&
-		    var->hsync_len == ps3fb_modedb[i].hsync_len &&
-		    var->vsync_len == ps3fb_modedb[i].vsync_len &&
-		    var->left_margin == ps3fb_modedb[i].left_margin &&
-		    var->right_margin == ps3fb_modedb[i].right_margin &&
-		    var->upper_margin == ps3fb_modedb[i].upper_margin &&
-		    var->lower_margin == ps3fb_modedb[i].lower_margin &&
-		    var->sync == ps3fb_modedb[i].sync &&
-		    (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode)
-			goto found;
+	best_id = 0;
+	best_diff = INT_MAX;
+	pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__,
+		 var->left_margin, var->xres, var->right_margin,
+		 var->upper_margin, var->yres, var->lower_margin);
+	for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) {
+		vmode = ps3fb_native_vmode(id);
+		diff = ps3fb_cmp_mode(vmode, var);
+		pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n",
+			 __func__, id, vmode->left_margin, vmode->xres,
+			 vmode->right_margin, vmode->upper_margin,
+			 vmode->yres, vmode->lower_margin, diff);
+		if (diff < 0)
+			continue;
+		if (diff < best_diff) {
+			best_id = id;
+			if (!diff)
+				break;
+			best_diff = diff;
+		}
+	}
 
-	pr_debug("ps3fb_find_mode: mode not found\n");
-	return 0;
+	if (!best_id) {
+		pr_debug("%s: no suitable mode found\n", __func__);
+		return 0;
+	}
 
-found:
-	/* Cropped broadcast modes use the full line length */
-	*ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP;
+	id = best_id;
+	vmode = ps3fb_native_vmode(id);
+
+	*ddr_line_length = vmode->xres * BPP;
+
+	/* minimum resolution */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+
+	/* minimum virtual resolution */
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	/* minimum margins */
+	if (var->left_margin < vmode->left_margin)
+		var->left_margin = vmode->left_margin;
+	if (var->right_margin < vmode->right_margin)
+		var->right_margin = vmode->right_margin;
+	if (var->upper_margin < vmode->upper_margin)
+		var->upper_margin = vmode->upper_margin;
+	if (var->lower_margin < vmode->lower_margin)
+		var->lower_margin = vmode->lower_margin;
+
+	/* extra margins */
+	gap = ((long)vmode->left_margin + (long)vmode->xres +
+	       (long)vmode->right_margin) -
+	      ((long)var->left_margin + (long)var->xres +
+	       (long)var->right_margin);
+	if (gap > 0) {
+		var->left_margin += gap/2;
+		var->right_margin += (gap+1)/2;
+		pr_debug("%s: rounded up H to %u [%u] %u\n", __func__,
+			 var->left_margin, var->xres, var->right_margin);
+	}
+
+	gap = ((long)vmode->upper_margin + (long)vmode->yres +
+	       (long)vmode->lower_margin) -
+	      ((long)var->upper_margin + (long)var->yres +
+	       (long)var->lower_margin);
+	if (gap > 0) {
+		var->upper_margin += gap/2;
+		var->lower_margin += (gap+1)/2;
+		pr_debug("%s: rounded up V to %u [%u] %u\n", __func__,
+			 var->upper_margin, var->yres, var->lower_margin);
+	}
+
+	/* fixed fields */
+	var->pixclock = vmode->pixclock;
+	var->hsync_len = vmode->hsync_len;
+	var->vsync_len = vmode->vsync_len;
+	var->sync = vmode->sync;
 
 	if (ps3_compare_firmware_version(1, 9, 0) >= 0) {
-		*xdr_line_length = GPU_ALIGN_UP(max(var->xres,
-						    var->xres_virtual) * BPP);
+		*xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP);
 		if (*xdr_line_length > GPU_MAX_LINE_LENGTH)
 			*xdr_line_length = GPU_MAX_LINE_LENGTH;
 	} else
 		*xdr_line_length = *ddr_line_length;
 
-	/* Full broadcast modes have the full mode bit set */
-	mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1;
-
-	pr_debug("ps3fb_find_mode: mode %u\n", mode);
-
-	return mode;
-}
-
-static const struct fb_videomode *ps3fb_default_mode(int id)
-{
-	u32 mode = id & PS3AV_MODE_MASK;
-	u32 flags;
-
-	if (mode < 1 || mode > 13)
-		return NULL;
-
-	flags = id & ~PS3AV_MODE_MASK;
-
-	if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) {
-		/* Full broadcast mode */
-		return &ps3fb_modedb[mode + 12];
+	if (vmode->sync & FB_SYNC_BROADCAST) {
+		/* Full broadcast modes have the full mode bit set */
+		if (vmode->xres == var->xres && vmode->yres == var->yres)
+			id |= PS3AV_MODE_FULL;
 	}
 
-	return &ps3fb_modedb[mode - 1];
+	pr_debug("%s: mode %u\n", __func__, id);
+	return id;
 }
 
 static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
@@ -439,8 +491,7 @@
 static int ps3fb_sync(struct fb_info *info, u32 frame)
 {
 	struct ps3fb_par *par = info->par;
-	int i, error = 0;
-	u32 ddr_line_length, xdr_line_length;
+	int error = 0;
 	u64 ddr_base, xdr_base;
 
 	if (frame > par->num_frames - 1) {
@@ -450,16 +501,13 @@
 		goto out;
 	}
 
-	i = par->res_index;
-	xdr_line_length = info->fix.line_length;
-	ddr_line_length = ps3fb_res[i].xres * BPP;
-	xdr_base = frame * info->var.yres_virtual * xdr_line_length;
-	ddr_base = frame * ps3fb_res[i].yres * ddr_line_length;
+	xdr_base = frame * par->xdr_frame_size;
+	ddr_base = frame * par->ddr_frame_size;
 
 	ps3fb_sync_image(info->device, ddr_base + par->full_offset,
 			 ddr_base + par->fb_offset, xdr_base + par->pan_offset,
-			 par->width, par->height, ddr_line_length,
-			 xdr_line_length);
+			 par->width, par->height, par->ddr_line_length,
+			 info->fix.line_length);
 
 out:
 	return error;
@@ -498,22 +546,11 @@
 	u32 xdr_line_length, ddr_line_length;
 	int mode;
 
-	dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres,
-		info->var.xres);
-	dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres,
-		info->var.yres);
-
-	/* FIXME For now we do exact matches only */
 	mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length);
 	if (!mode)
 		return -EINVAL;
 
 	/* Virtual screen */
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-
 	if (var->xres_virtual > xdr_line_length / BPP) {
 		dev_dbg(info->device,
 			"Horizontal virtual screen size too large\n");
@@ -559,7 +596,7 @@
 	}
 
 	/* Memory limit */
-	if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) {
+	if (var->yres_virtual * xdr_line_length > info->fix.smem_len) {
 		dev_dbg(info->device, "Not enough memory\n");
 		return -ENOMEM;
 	}
@@ -578,39 +615,38 @@
 {
 	struct ps3fb_par *par = info->par;
 	unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines;
-	int i;
-	unsigned long offset;
+	unsigned int ddr_xoff, ddr_yoff, offset;
+	const struct fb_videomode *vmode;
 	u64 dst;
 
-	dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n",
-		info->var.xres, info->var.xres_virtual,
-		info->var.yres, info->var.yres_virtual, info->var.pixclock);
-
 	mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length);
 	if (!mode)
 		return -EINVAL;
 
-	i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode);
-	par->res_index = i;
+	vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK);
 
-	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
-	info->fix.smem_len = ps3fb.xdr_size;
 	info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0;
 	info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0;
 	info->fix.line_length = xdr_line_length;
 
-	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
+	par->ddr_line_length = ddr_line_length;
+	par->ddr_frame_size = vmode->yres * ddr_line_length;
+	par->xdr_frame_size = info->var.yres_virtual * xdr_line_length;
 
-	par->num_frames = ps3fb.xdr_size /
-			  max(ps3fb_res[i].yres * ddr_line_length,
-			      info->var.yres_virtual * xdr_line_length);
+	par->num_frames = info->fix.smem_len /
+			  max(par->ddr_frame_size, par->xdr_frame_size);
 
 	/* Keep the special bits we cannot set using fb_var_screeninfo */
 	par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode;
 
 	par->width = info->var.xres;
 	par->height = info->var.yres;
-	offset = VP_OFF(i);
+
+	/* Start of the virtual frame buffer (relative to fullscreen) */
+	ddr_xoff = info->var.left_margin - vmode->left_margin;
+	ddr_yoff = info->var.upper_margin - vmode->upper_margin;
+	offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP;
+
 	par->fb_offset = GPU_ALIGN_UP(offset);
 	par->full_offset = par->fb_offset - offset;
 	par->pan_offset = info->var.yoffset * xdr_line_length +
@@ -625,16 +661,16 @@
 	}
 
 	/* Clear XDR frame buffer memory */
-	memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size);
+	memset((void __force *)info->screen_base, 0, info->fix.smem_len);
 
 	/* Clear DDR frame buffer memory */
-	lines = ps3fb_res[i].yres * par->num_frames;
+	lines = vmode->yres * par->num_frames;
 	if (par->full_offset)
 		lines++;
-	maxlines = ps3fb.xdr_size / ddr_line_length;
+	maxlines = info->fix.smem_len / ddr_line_length;
 	for (dst = 0; lines; dst += maxlines * ddr_line_length) {
 		unsigned int l = min(lines, maxlines);
-		ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l,
+		ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l,
 				 ddr_line_length, ddr_line_length);
 		lines -= l;
 	}
@@ -797,7 +833,7 @@
 	case PS3FB_IOCTL_SETMODE:
 		{
 			struct ps3fb_par *par = info->par;
-			const struct fb_videomode *mode;
+			const struct fb_videomode *vmode;
 			struct fb_var_screeninfo var;
 
 			if (copy_from_user(&val, argp, sizeof(val)))
@@ -810,10 +846,10 @@
 			}
 			dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val);
 			retval = -EINVAL;
-			mode = ps3fb_default_mode(val);
-			if (mode) {
+			vmode = ps3fb_vmode(val);
+			if (vmode) {
 				var = info->var;
-				fb_videomode_to_var(&var, mode);
+				fb_videomode_to_var(&var, vmode);
 				acquire_console_sem();
 				info->flags |= FBINFO_MISC_USEREVENT;
 				/* Force, in case only special bits changed */
@@ -975,10 +1011,9 @@
 			__func__, status);
 		return -ENXIO;
 	}
-	dev_dbg(dev,
-		"video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n",
-		ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar,
-		virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size);
+	dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n",
+		ps3fb_videomemory.address, GPU_IOIF, xdr_lpar,
+		ps3fb_videomemory.size);
 
 	status = lv1_gpu_context_attribute(ps3fb.context_handle,
 					   L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP,
@@ -1055,14 +1090,14 @@
 	struct fb_info *info;
 	struct ps3fb_par *par;
 	int retval = -ENOMEM;
-	u32 xres, yres;
 	u64 ddr_lpar = 0;
 	u64 lpar_dma_control = 0;
 	u64 lpar_driver_info = 0;
 	u64 lpar_reports = 0;
 	u64 lpar_reports_size = 0;
 	u64 xdr_lpar;
-	int status, res_index;
+	void *fb_start;
+	int status;
 	struct task_struct *task;
 	unsigned long max_ps3fb_size;
 
@@ -1080,14 +1115,7 @@
 
 	if (!ps3fb_mode)
 		ps3fb_mode = ps3av_get_mode();
-	dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode);
-
-	if (ps3fb_mode > 0 &&
-	    !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) {
-		res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode);
-		dev_dbg(&dev->core, "res_index:%d\n", res_index);
-	} else
-		res_index = GPU_RES_INDEX;
+	dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode);
 
 	atomic_set(&ps3fb.f_count, -1);	/* fbcon opens ps3fb */
 	atomic_set(&ps3fb.ext_flip, 0);	/* for flip with vsync */
@@ -1124,7 +1152,7 @@
 	}
 
 	/* vsync interrupt */
-	ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024);
+	ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
 	if (!ps3fb.dinfo) {
 		dev_err(&dev->core, "%s: ioremap failed\n", __func__);
 		goto err_gpu_context_free;
@@ -1134,22 +1162,10 @@
 	if (retval)
 		goto err_iounmap_dinfo;
 
-	/* XDR frame buffer */
-	ps3fb.xdr_ea = ps3fb_videomemory.address;
-	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea));
-
 	/* Clear memory to prevent kernel info leakage into userspace */
-	memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size);
+	memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size);
 
-	/*
-	 * The GPU command buffer is at the start of video memory
-	 * As we don't use the full command buffer, we can put the actual
-	 * frame buffer at offset GPU_FB_START and save some precious XDR
-	 * memory
-	 */
-	ps3fb.xdr_ea += GPU_FB_START;
-	ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START;
-
+	xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address));
 	retval = ps3fb_xdr_settings(xdr_lpar, &dev->core);
 	if (retval)
 		goto err_free_irq;
@@ -1161,15 +1177,22 @@
 	par = info->par;
 	par->mode_id = ~ps3fb_mode;	/* != ps3fb_mode, to trigger change */
 	par->new_mode_id = ps3fb_mode;
-	par->res_index = res_index;
 	par->num_frames = 1;
 
-	info->screen_base = (char __iomem *)ps3fb.xdr_ea;
 	info->fbops = &ps3fb_ops;
-
 	info->fix = ps3fb_fix;
-	info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea);
-	info->fix.smem_len = ps3fb.xdr_size;
+
+	/*
+	 * The GPU command buffer is at the start of video memory
+	 * As we don't use the full command buffer, we can put the actual
+	 * frame buffer at offset GPU_FB_START and save some precious XDR
+	 * memory
+	 */
+	fb_start = ps3fb_videomemory.address + GPU_FB_START;
+	info->screen_base = (char __force __iomem *)fb_start;
+	info->fix.smem_start = virt_to_abs(fb_start);
+	info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START;
+
 	info->pseudo_palette = par->pseudo_palette;
 	info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
 		      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
@@ -1180,7 +1203,7 @@
 
 	if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb,
 			  ARRAY_SIZE(ps3fb_modedb),
-			  ps3fb_default_mode(par->new_mode_id), 32)) {
+			  ps3fb_vmode(par->new_mode_id), 32)) {
 		retval = -EINVAL;
 		goto err_fb_dealloc;
 	}
@@ -1194,9 +1217,9 @@
 
 	dev->core.driver_data = info;
 
-	dev_info(info->device, "%s %s, using %lu KiB of video memory\n",
+	dev_info(info->device, "%s %s, using %u KiB of video memory\n",
 		 dev_driver_string(info->dev), info->dev->bus_id,
-		 ps3fb.xdr_size >> 10);
+		 info->fix.smem_len >> 10);
 
 	task = kthread_run(ps3fbd, info, DEVICE_NAME);
 	if (IS_ERR(task)) {
@@ -1219,7 +1242,7 @@
 	free_irq(ps3fb.irq_no, &dev->core);
 	ps3_irq_plug_destroy(ps3fb.irq_no);
 err_iounmap_dinfo:
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	iounmap((u8 __force __iomem *)ps3fb.dinfo);
 err_gpu_context_free:
 	lv1_gpu_context_free(ps3fb.context_handle);
 err_gpu_memory_free:
@@ -1254,7 +1277,7 @@
 		framebuffer_release(info);
 		info = dev->core.driver_data = NULL;
 	}
-	iounmap((u8 __iomem *)ps3fb.dinfo);
+	iounmap((u8 __force __iomem *)ps3fb.dinfo);
 
 	status = lv1_gpu_context_free(ps3fb.context_handle);
 	if (status)
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index b3c31d9..71fa6ed 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -110,6 +110,11 @@
 
 /* useful functions */
 
+static int is_s3c2412(struct s3c2410fb_info *fbi)
+{
+	return (fbi->drv_type == DRV_S3C2412);
+}
+
 /* s3c2410fb_set_lcdaddr
  *
  * initialise lcd controller address pointers
@@ -501,7 +506,7 @@
 {
 	unsigned long flags;
 	unsigned long irqen;
-	void __iomem *regs = fbi->io;
+	void __iomem *irq_base = fbi->irq_base;
 
 	local_irq_save(flags);
 
@@ -511,9 +516,9 @@
 		fbi->palette_ready = 1;
 
 		/* enable IRQ */
-		irqen = readl(regs + S3C2410_LCDINTMSK);
+		irqen = readl(irq_base + S3C24XX_LCDINTMSK);
 		irqen &= ~S3C2410_LCDINT_FRSYNC;
-		writel(irqen, regs + S3C2410_LCDINTMSK);
+		writel(irqen, irq_base + S3C24XX_LCDINTMSK);
 	}
 
 	local_irq_restore(flags);
@@ -594,15 +599,17 @@
 static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
 {
 	struct s3c2410fb_info *fbi = info->par;
-	void __iomem *regs = fbi->io;
+	void __iomem *tpal_reg = fbi->io;
 
 	dprintk("blank(mode=%d, info=%p)\n", blank_mode, info);
 
+	tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
+
 	if (blank_mode == FB_BLANK_UNBLANK)
-		writel(0x0, regs + S3C2410_TPAL);
+		writel(0x0, tpal_reg);
 	else {
 		dprintk("setting TPAL to output 0x000000\n");
-		writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL);
+		writel(S3C2410_TPAL_EN, tpal_reg);
 	}
 
 	return 0;
@@ -663,7 +670,7 @@
 	dma_addr_t map_dma;
 	unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
 
-	dprintk("map_video_memory(fbi=%p)\n", fbi);
+	dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
 
 	info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
 						   &map_dma, GFP_KERNEL);
@@ -672,7 +679,7 @@
 		/* prevent initial garbage on screen */
 		dprintk("map_video_memory: clear %p:%08x\n",
 			info->screen_base, map_size);
-		memset(info->screen_base, 0xf0, map_size);
+		memset(info->screen_base, 0x00, map_size);
 
 		info->fix.smem_start = map_dma;
 
@@ -709,6 +716,16 @@
 	struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;
 	unsigned long flags;
 	void __iomem *regs = fbi->io;
+	void __iomem *tpal;
+	void __iomem *lpcsel;
+
+	if (is_s3c2412(fbi)) {
+		tpal = regs + S3C2412_TPAL;
+		lpcsel = regs + S3C2412_TCONSEL;
+	} else {
+		tpal = regs + S3C2410_TPAL;
+		lpcsel = regs + S3C2410_LPCSEL;
+	}
 
 	/* Initialise LCD with values from haret */
 
@@ -724,12 +741,12 @@
 	local_irq_restore(flags);
 
 	dprintk("LPCSEL    = 0x%08lx\n", mach_info->lpcsel);
-	writel(mach_info->lpcsel, regs + S3C2410_LPCSEL);
+	writel(mach_info->lpcsel, lpcsel);
 
-	dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL));
+	dprintk("replacing TPAL %08x\n", readl(tpal));
 
 	/* ensure temporary palette disabled */
-	writel(0x00, regs + S3C2410_TPAL);
+	writel(0x00, tpal);
 
 	return 0;
 }
@@ -763,15 +780,15 @@
 static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
 {
 	struct s3c2410fb_info *fbi = dev_id;
-	void __iomem *regs = fbi->io;
-	unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND);
+	void __iomem *irq_base = fbi->irq_base;
+	unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND);
 
 	if (lcdirq & S3C2410_LCDINT_FRSYNC) {
 		if (fbi->palette_ready)
 			s3c2410fb_write_palette(fbi);
 
-		writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND);
-		writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND);
+		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND);
+		writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND);
 	}
 
 	return IRQ_HANDLED;
@@ -779,7 +796,8 @@
 
 static char driver_name[] = "s3c2410fb";
 
-static int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __init s3c24xxfb_probe(struct platform_device *pdev,
+				  enum s3c_drv_type drv_type)
 {
 	struct s3c2410fb_info *info;
 	struct s3c2410fb_display *display;
@@ -799,6 +817,12 @@
 		return -EINVAL;
 	}
 
+	if (mach_info->default_display >= mach_info->num_displays) {
+		dev_err(&pdev->dev, "default is %d but only %d displays\n",
+			mach_info->default_display, mach_info->num_displays);
+		return -EINVAL;
+	}
+
 	display = mach_info->displays + mach_info->default_display;
 
 	irq = platform_get_irq(pdev, 0);
@@ -815,6 +839,7 @@
 
 	info = fbinfo->par;
 	info->dev = &pdev->dev;
+	info->drv_type = drv_type;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
@@ -838,6 +863,8 @@
 		goto release_mem;
 	}
 
+	info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
+
 	dprintk("devinit\n");
 
 	strcpy(fbinfo->fix.id, driver_name);
@@ -946,6 +973,16 @@
 	return ret;
 }
 
+static int __init s3c2410fb_probe(struct platform_device *pdev)
+{
+	return s3c24xxfb_probe(pdev, DRV_S3C2410);
+}
+
+static int __init s3c2412fb_probe(struct platform_device *pdev)
+{
+	return s3c24xxfb_probe(pdev, DRV_S3C2412);
+}
+
 /* s3c2410fb_stop_lcd
  *
  * shutdown the lcd controller
@@ -1047,14 +1084,31 @@
 	},
 };
 
+static struct platform_driver s3c2412fb_driver = {
+	.probe		= s3c2412fb_probe,
+	.remove		= s3c2410fb_remove,
+	.suspend	= s3c2410fb_suspend,
+	.resume		= s3c2410fb_resume,
+	.driver		= {
+		.name	= "s3c2412-lcd",
+		.owner	= THIS_MODULE,
+	},
+};
+
 int __init s3c2410fb_init(void)
 {
-	return platform_driver_register(&s3c2410fb_driver);
+	int ret = platform_driver_register(&s3c2410fb_driver);
+
+	if (ret == 0)
+		ret = platform_driver_register(&s3c2412fb_driver);;
+
+	return ret;
 }
 
 static void __exit s3c2410fb_cleanup(void)
 {
 	platform_driver_unregister(&s3c2410fb_driver);
+	platform_driver_unregister(&s3c2412fb_driver);
 }
 
 module_init(s3c2410fb_init);
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h
index 6ce5dc26..dbb73b9 100644
--- a/drivers/video/s3c2410fb.h
+++ b/drivers/video/s3c2410fb.h
@@ -25,13 +25,20 @@
 #ifndef __S3C2410FB_H
 #define __S3C2410FB_H
 
+enum s3c_drv_type {
+	DRV_S3C2410,
+	DRV_S3C2412,
+};
+
 struct s3c2410fb_info {
 	struct device		*dev;
 	struct clk		*clk;
 
 	struct resource		*mem;
 	void __iomem		*io;
+	void __iomem		*irq_base;
 
+	enum s3c_drv_type	drv_type;
 	struct s3c2410fb_hw	regs;
 
 	unsigned int		palette_ready;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 93ae747..7380362 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -427,7 +427,7 @@
 
 	monitor->feature = buffer[0x18];
 
-	if(!buffer[0x14] & 0x80) {
+	if(!(buffer[0x14] & 0x80)) {
 		if(!(buffer[0x14] & 0x08)) {
 			printk(KERN_INFO
 				"sisfb: WARNING: Monitor does not support separate syncs\n");
@@ -4621,9 +4621,9 @@
 
 	while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) {
 		temp = pdev->vendor;
-		pci_dev_put(pdev);
 		if(temp == pcivendor) {
 			ret = 1;
+			pci_dev_put(pdev);
 			break;
 		}
 	}
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 58f200c..e83dfba 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -641,6 +641,7 @@
 {
 	unsigned long control;
 	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
+	struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
 
 	control = readl(ctrl_reg);
 
@@ -657,26 +658,34 @@
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 
-		control |= SM501_DC_PANEL_CONTROL_BIAS;	/* VBIASEN */
-		writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
+		if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) {
+			control |= SM501_DC_PANEL_CONTROL_BIAS;	/* VBIASEN */
+			writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
 
-		control |= SM501_DC_PANEL_CONTROL_FPEN;
-		writel(control, ctrl_reg);
-
+		if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) {
+			control |= SM501_DC_PANEL_CONTROL_FPEN;
+			writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
 	} else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) {
 		/* disable panel power */
+		if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) {
+			control &= ~SM501_DC_PANEL_CONTROL_FPEN;
+			writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
 
-		control &= ~SM501_DC_PANEL_CONTROL_FPEN;
-		writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
-
-		control &= ~SM501_DC_PANEL_CONTROL_BIAS;
-		writel(control, ctrl_reg);
-		sm501fb_sync_regs(fbi);
-		mdelay(10);
+		if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) {
+			control &= ~SM501_DC_PANEL_CONTROL_BIAS;
+			writel(control, ctrl_reg);
+			sm501fb_sync_regs(fbi);
+			mdelay(10);
+		}
 
 		control &= ~SM501_DC_PANEL_CONTROL_DATA;
 		writel(control, ctrl_reg);
@@ -1267,6 +1276,7 @@
 {
 	struct resource	*res;
 	struct device *dev;
+	int k;
 	int ret;
 
 	info->dev = dev = &pdev->dev;
@@ -1328,6 +1338,13 @@
 
 	info->fbmem_len = (res->end - res->start)+1;
 
+	/* clear framebuffer memory - avoids garbage data on unused fb */
+	memset(info->fbmem, 0, info->fbmem_len);
+
+	/* clear palette ram - undefined at power on */
+	for (k = 0; k < (256 * 3); k++)
+		writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+
 	/* enable display controller */
 	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
 
@@ -1681,6 +1698,15 @@
 	if (par->screen.size == 0)
 		return 0;
 
+	/* blank the relevant interface to ensure unit power minimised */
+	(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
+
+	/* tell console/fb driver we are suspending */
+
+	acquire_console_sem();
+	fb_set_suspend(fbi, 1);
+	release_console_sem();
+
 	/* backup copies in case chip is powered down over suspend */
 
 	par->store_fb = vmalloc(par->screen.size);
@@ -1700,12 +1726,6 @@
 
 	memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size);
 	memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size);
-	/* blank the relevant interface to ensure unit power minimised */
-	(par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi);
-
-	acquire_console_sem();
-	fb_set_suspend(fbi, 1);
-	release_console_sem();
 
 	return 0;
 
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 057bdd5..71e179e 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1342,7 +1342,7 @@
 }
 
 #ifndef MODULE
-static void tdfxfb_setup(char *options)
+static void __init tdfxfb_setup(char *options)
 {
 	char *this_opt;
 
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index a14ef89..be27b9c 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -2003,12 +2003,12 @@
 
 module_exit(uvesafb_exit);
 
-static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
+static int param_get_scroll(char *buffer, struct kernel_param *kp)
 {
 	return 0;
 }
 
-static inline int param_set_scroll(const char *val, struct kernel_param *kp)
+static int param_set_scroll(const char *val, struct kernel_param *kp)
 {
 	ypan = 0;
 
@@ -2022,11 +2022,11 @@
 	return 0;
 }
 
-#define param_check_scroll(name, p) __param_check(name, p, void);
+#define param_check_scroll(name, p) __param_check(name, p, void)
 
 module_param_named(scroll, ypan, scroll, 0);
 MODULE_PARM_DESC(scroll,
-	"Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'");
+	"Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'");
 module_param_named(vgapal, pmi_setpal, invbool, 0);
 MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
 module_param_named(pmipal, pmi_setpal, bool, 0);
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index 1c65666..2aa71eb 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -651,7 +651,7 @@
 		return -EINVAL;
 	}
 
-	pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F);
+	pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40);
 	mem = pitch * var->yres_virtual;
 	if (mem > vinfo->vram_contig_size) {
 		return -ENOMEM;
@@ -785,8 +785,7 @@
 	int clock;
 
 	vinfo->bytes_per_pixel = var->bits_per_pixel >> 3;
-	vinfo->stride =
-	    __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F);
+	vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40);
 	info->fix.line_length = vinfo->stride;
 
 	if (!subsys)
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 8236d44..c449309 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -42,5 +42,15 @@
 	  in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
 	  hx4700.
 
+config W1_MASTER_GPIO
+	tristate "GPIO 1-wire busmaster"
+	depends on GENERIC_GPIO
+	help
+	  Say Y here if you want to communicate with your 1-wire devices using
+	  GPIO pins. This driver uses the GPIO API to control the wire.
+
+	  This support is also available as a module.  If so, the module
+	  will be called w1-gpio.ko.
+
 endmenu
 
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index 11551b3..1420b5b 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_W1_MASTER_DS2490)		+= ds2490.o
 obj-$(CONFIG_W1_MASTER_DS2482)		+= ds2482.o
 obj-$(CONFIG_W1_MASTER_DS1WM)		+= ds1wm.o
+obj-$(CONFIG_W1_MASTER_GPIO)		+= w1-gpio.o
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
new file mode 100644
index 0000000..9e1138a
--- /dev/null
+++ b/drivers/w1/masters/w1-gpio.c
@@ -0,0 +1,124 @@
+/*
+ * w1-gpio - GPIO w1 bus master driver
+ *
+ * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi>
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/w1-gpio.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+
+#include <asm/gpio.h>
+
+static void w1_gpio_write_bit_dir(void *data, u8 bit)
+{
+	struct w1_gpio_platform_data *pdata = data;
+
+	if (bit)
+		gpio_direction_input(pdata->pin);
+	else
+		gpio_direction_output(pdata->pin, 0);
+}
+
+static void w1_gpio_write_bit_val(void *data, u8 bit)
+{
+	struct w1_gpio_platform_data *pdata = data;
+
+	gpio_set_value(pdata->pin, bit);
+}
+
+static u8 w1_gpio_read_bit(void *data)
+{
+	struct w1_gpio_platform_data *pdata = data;
+
+	return gpio_get_value(pdata->pin);
+}
+
+static int __init w1_gpio_probe(struct platform_device *pdev)
+{
+	struct w1_bus_master *master;
+	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+	int err;
+
+	if (!pdata)
+		return -ENXIO;
+
+	master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL);
+	if (!master)
+		return -ENOMEM;
+
+	err = gpio_request(pdata->pin, "w1");
+	if (err)
+		goto free_master;
+
+	master->data = pdata;
+	master->read_bit = w1_gpio_read_bit;
+
+	if (pdata->is_open_drain) {
+		gpio_direction_output(pdata->pin, 1);
+		master->write_bit = w1_gpio_write_bit_val;
+	} else {
+		gpio_direction_input(pdata->pin);
+		master->write_bit = w1_gpio_write_bit_dir;
+	}
+
+	err = w1_add_master_device(master);
+	if (err)
+		goto free_gpio;
+
+	platform_set_drvdata(pdev, master);
+
+	return 0;
+
+ free_gpio:
+	gpio_free(pdata->pin);
+ free_master:
+	kfree(master);
+
+	return err;
+}
+
+static int __exit w1_gpio_remove(struct platform_device *pdev)
+{
+	struct w1_bus_master *master = platform_get_drvdata(pdev);
+	struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+	w1_remove_master_device(master);
+	gpio_free(pdata->pin);
+	kfree(master);
+
+	return 0;
+}
+
+static struct platform_driver w1_gpio_driver = {
+	.driver = {
+		.name	= "w1-gpio",
+		.owner	= THIS_MODULE,
+	},
+	.remove	= __exit_p(w1_gpio_remove),
+};
+
+static int __init w1_gpio_init(void)
+{
+	return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe);
+}
+
+static void __exit w1_gpio_exit(void)
+{
+	platform_driver_unregister(&w1_gpio_driver);
+}
+
+module_init(w1_gpio_init);
+module_exit(w1_gpio_exit);
+
+MODULE_DESCRIPTION("GPIO w1 bus master driver");
+MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 112f4ec..fb28aca 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -92,6 +92,7 @@
 	int			(*convert)(u8 rom[9]);
 };
 
+/* The return value is millidegrees Centigrade. */
 static inline int w1_DS18B20_convert_temp(u8 rom[9]);
 static inline int w1_DS18S20_convert_temp(u8 rom[9]);
 
@@ -113,7 +114,7 @@
 static inline int w1_DS18B20_convert_temp(u8 rom[9])
 {
 	s16 t = (rom[1] << 8) | rom[0];
-	t /= 16;
+	t = t*1000/16;
 	return t;
 }
 
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 33e5031..7293c9b 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -675,7 +675,6 @@
 	struct w1_slave *sl;
 	struct list_head *ent;
 	struct w1_reg_num *tmp;
-	int family_found = 0;
 	struct w1_master *dev;
 	u64 rn_le = cpu_to_le64(rn);
 
@@ -698,9 +697,6 @@
 		    sl->reg_num.crc == tmp->crc) {
 			set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 			break;
-		} else if (sl->reg_num.family == tmp->family) {
-			family_found = 1;
-			break;
 		}
 
 		slave_count++;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index e48a630..e63067d 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -534,7 +534,6 @@
 	if (err)
 		panic("Cannot register bdev pseudo-fs");
 	bd_mnt = kern_mount(&bd_type);
-	err = PTR_ERR(bd_mnt);
 	if (IS_ERR(bd_mnt))
 		panic("Cannot create bdev pseudo-fs");
 	blockdev_superblock = bd_mnt->mnt_sb;	/* For writeback */
diff --git a/fs/compat.c b/fs/compat.c
index 69baca5..ee80ff3 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -2083,51 +2083,6 @@
 
 #ifdef CONFIG_EPOLL
 
-#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
-asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
-			struct compat_epoll_event __user *event)
-{
-	long err = 0;
-	struct compat_epoll_event user;
-	struct epoll_event __user *kernel = NULL;
-
-	if (event) {
-		if (copy_from_user(&user, event, sizeof(user)))
-			return -EFAULT;
-		kernel = compat_alloc_user_space(sizeof(struct epoll_event));
-		err |= __put_user(user.events, &kernel->events);
-		err |= __put_user(user.data, &kernel->data);
-	}
-
-	return err ? err : sys_epoll_ctl(epfd, op, fd, kernel);
-}
-
-
-asmlinkage long compat_sys_epoll_wait(int epfd,
-			struct compat_epoll_event __user *events,
-			int maxevents, int timeout)
-{
-	long i, ret, err = 0;
-	struct epoll_event __user *kbuf;
-	struct epoll_event ev;
-
-	if ((maxevents <= 0) ||
-			(maxevents > (INT_MAX / sizeof(struct epoll_event))))
-		return -EINVAL;
-	kbuf = compat_alloc_user_space(sizeof(struct epoll_event) * maxevents);
-	ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
-	for (i = 0; i < ret; i++) {
-		err |= __get_user(ev.events, &kbuf[i].events);
-		err |= __get_user(ev.data, &kbuf[i].data);
-		err |= __put_user(ev.events, &events->events);
-		err |= __put_user_unaligned(ev.data, &events->data);
-		events++;
-	}
-
-	return err ? -EFAULT: ret;
-}
-#endif	/* CONFIG_HAS_COMPAT_EPOLL_EVENT */
-
 #ifdef TIF_RESTORE_SIGMASK
 asmlinkage long compat_sys_epoll_pwait(int epfd,
 			struct compat_epoll_event __user *events,
@@ -2153,11 +2108,7 @@
 		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
 	}
 
-#ifdef CONFIG_HAS_COMPAT_EPOLL_EVENT
-	err = compat_sys_epoll_wait(epfd, events, maxevents, timeout);
-#else
 	err = sys_epoll_wait(epfd, events, maxevents, timeout);
-#endif
 
 	/*
 	 * If we changed the signal mask, we need to restore the original one.
diff --git a/fs/dcache.c b/fs/dcache.c
index d9ca1e5..44f6cf2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -89,7 +89,7 @@
 	if (dentry->d_op && dentry->d_op->d_release)
 		dentry->d_op->d_release(dentry);
 	/* if dentry was never inserted into hash, immediate free is OK */
-	if (dentry->d_hash.pprev == NULL)
+	if (hlist_unhashed(&dentry->d_hash))
 		__d_free(dentry);
 	else
 		call_rcu(&dentry->d_u.d_rcu, d_callback);
@@ -1408,9 +1408,6 @@
 	if (atomic_read(&dentry->d_count) == 1) {
 		dentry_iput(dentry);
 		fsnotify_nameremove(dentry, isdir);
-
-		/* remove this and other inotify debug checks after 2.6.18 */
-		dentry->d_flags &= ~DCACHE_INOTIFY_PARENT_WATCHED;
 		return;
 	}
 
diff --git a/fs/dquot.c b/fs/dquot.c
index cee7c6f..def4e96 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -696,9 +696,8 @@
 /* This routine is guarded by dqonoff_mutex mutex */
 static void add_dquot_ref(struct super_block *sb, int type)
 {
-	struct inode *inode;
+	struct inode *inode, *old_inode = NULL;
 
-restart:
 	spin_lock(&inode_lock);
 	list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
 		if (!atomic_read(&inode->i_writecount))
@@ -711,12 +710,18 @@
 		__iget(inode);
 		spin_unlock(&inode_lock);
 
+		iput(old_inode);
 		sb->dq_op->initialize(inode, type);
-		iput(inode);
-		/* As we may have blocked we had better restart... */
-		goto restart;
+		/* We hold a reference to 'inode' so it couldn't have been
+		 * removed from s_inodes list while we dropped the inode_lock.
+		 * We cannot iput the inode now as we can be holding the last
+		 * reference and we cannot iput it under inode_lock. So we
+		 * keep the reference and iput it later. */
+		old_inode = inode;
+		spin_lock(&inode_lock);
 	}
 	spin_unlock(&inode_lock);
+	iput(old_inode);
 }
 
 /* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index f8ef0af..a066e10 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -355,8 +355,11 @@
 	}
 	/* Consider doing this once, when the file is opened */
 	mutex_lock(&crypt_stat->cs_tfm_mutex);
-	rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
-				     crypt_stat->key_size);
+	if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
+		rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
+					     crypt_stat->key_size);
+		crypt_stat->flags |= ECRYPTFS_KEY_SET;
+	}
 	if (rc) {
 		ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
 				rc);
@@ -376,11 +379,10 @@
  *
  * Convert an eCryptfs page index into a lower byte offset
  */
-void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
-				      struct ecryptfs_crypt_stat *crypt_stat)
+static void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
+					     struct ecryptfs_crypt_stat *crypt_stat)
 {
-	(*offset) = ((crypt_stat->extent_size
-		      * crypt_stat->num_header_extents_at_front)
+	(*offset) = (crypt_stat->num_header_bytes_at_front
 		     + (crypt_stat->extent_size * extent_num));
 }
 
@@ -842,15 +844,13 @@
 	set_extent_mask_and_shift(crypt_stat);
 	crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
 	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-		crypt_stat->num_header_extents_at_front = 0;
+		crypt_stat->num_header_bytes_at_front = 0;
 	else {
 		if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)
-			crypt_stat->num_header_extents_at_front =
-				(ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE
-				 / crypt_stat->extent_size);
+			crypt_stat->num_header_bytes_at_front =
+				ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 		else
-			crypt_stat->num_header_extents_at_front =
-				(PAGE_CACHE_SIZE / crypt_stat->extent_size);
+			crypt_stat->num_header_bytes_at_front =	PAGE_CACHE_SIZE;
 	}
 }
 
@@ -1128,7 +1128,7 @@
 
 struct ecryptfs_cipher_code_str_map_elem {
 	char cipher_str[16];
-	u16 cipher_code;
+	u8 cipher_code;
 };
 
 /* Add support for additional ciphers by adding elements here. The
@@ -1152,10 +1152,10 @@
  *
  * Returns zero on no match, or the cipher code on match
  */
-u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat)
+u8 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat)
 {
 	int i;
-	u16 code = 0;
+	u8 code = 0;
 	struct ecryptfs_cipher_code_str_map_elem *map =
 		ecryptfs_cipher_code_str_map;
 
@@ -1187,7 +1187,7 @@
  *
  * Returns zero on success
  */
-int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code)
+int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code)
 {
 	int rc = 0;
 	int i;
@@ -1236,7 +1236,8 @@
 
 	header_extent_size = (u32)crypt_stat->extent_size;
 	num_header_extents_at_front =
-		(u16)crypt_stat->num_header_extents_at_front;
+		(u16)(crypt_stat->num_header_bytes_at_front
+		      / crypt_stat->extent_size);
 	header_extent_size = cpu_to_be32(header_extent_size);
 	memcpy(virt, &header_extent_size, 4);
 	virt += 4;
@@ -1311,40 +1312,16 @@
 static int
 ecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,
 				    struct dentry *ecryptfs_dentry,
-				    char *page_virt)
+				    char *virt)
 {
-	int current_header_page;
-	int header_pages;
 	int rc;
 
-	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,
-				  0, PAGE_CACHE_SIZE);
-	if (rc) {
+	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
+				  0, crypt_stat->num_header_bytes_at_front);
+	if (rc)
 		printk(KERN_ERR "%s: Error attempting to write header "
 		       "information to lower file; rc = [%d]\n", __FUNCTION__,
 		       rc);
-		goto out;
-	}
-	header_pages = ((crypt_stat->extent_size
-			 * crypt_stat->num_header_extents_at_front)
-			/ PAGE_CACHE_SIZE);
-	memset(page_virt, 0, PAGE_CACHE_SIZE);
-	current_header_page = 1;
-	while (current_header_page < header_pages) {
-		loff_t offset;
-
-		offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT);
-		if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,
-					       page_virt, offset,
-					       PAGE_CACHE_SIZE))) {
-			printk(KERN_ERR "%s: Error attempting to write header "
-			       "information to lower file; rc = [%d]\n",
-			       __FUNCTION__, rc);
-			goto out;
-		}
-		current_header_page++;
-	}
-out:
 	return rc;
 }
 
@@ -1370,15 +1347,13 @@
  * retrieved via a prompt.  Exactly what happens at this point should
  * be policy-dependent.
  *
- * TODO: Support header information spanning multiple pages
- *
  * Returns zero on success; non-zero on error
  */
 int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
 {
 	struct ecryptfs_crypt_stat *crypt_stat =
 		&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
-	char *page_virt;
+	char *virt;
 	size_t size = 0;
 	int rc = 0;
 
@@ -1389,40 +1364,39 @@
 			goto out;
 		}
 	} else {
+		printk(KERN_WARNING "%s: Encrypted flag not set\n",
+		       __FUNCTION__);
 		rc = -EINVAL;
-		ecryptfs_printk(KERN_WARNING,
-				"Called with crypt_stat->encrypted == 0\n");
 		goto out;
 	}
 	/* Released in this function */
-	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER);
-	if (!page_virt) {
-		ecryptfs_printk(KERN_ERR, "Out of memory\n");
+	virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL);
+	if (!virt) {
+		printk(KERN_ERR "%s: Out of memory\n", __FUNCTION__);
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat,
-  					 ecryptfs_dentry);
+	rc = ecryptfs_write_headers_virt(virt, &size, crypt_stat,
+					 ecryptfs_dentry);
 	if (unlikely(rc)) {
-		ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");
-		memset(page_virt, 0, PAGE_CACHE_SIZE);
+		printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n",
+		       __FUNCTION__, rc);
 		goto out_free;
 	}
 	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
 		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,
-						      crypt_stat, page_virt,
-						      size);
+						      crypt_stat, virt, size);
 	else
 		rc = ecryptfs_write_metadata_to_contents(crypt_stat,
-							 ecryptfs_dentry,
-							 page_virt);
+							 ecryptfs_dentry, virt);
 	if (rc) {
-		printk(KERN_ERR "Error writing metadata out to lower file; "
-		       "rc = [%d]\n", rc);
+		printk(KERN_ERR "%s: Error writing metadata out to lower file; "
+		       "rc = [%d]\n", __FUNCTION__, rc);
 		goto out_free;
 	}
 out_free:
-	kmem_cache_free(ecryptfs_header_cache_0, page_virt);
+	memset(virt, 0, crypt_stat->num_header_bytes_at_front);
+	kfree(virt);
 out:
 	return rc;
 }
@@ -1442,16 +1416,16 @@
 	virt += sizeof(u32);
 	memcpy(&num_header_extents_at_front, virt, sizeof(u16));
 	num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
-	crypt_stat->num_header_extents_at_front =
-		(int)num_header_extents_at_front;
+	crypt_stat->num_header_bytes_at_front =
+		(((size_t)num_header_extents_at_front
+		  * (size_t)header_extent_size));
 	(*bytes_read) = (sizeof(u32) + sizeof(u16));
 	if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE)
-	    && ((crypt_stat->extent_size
-		 * crypt_stat->num_header_extents_at_front)
+	    && (crypt_stat->num_header_bytes_at_front
 		< ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) {
 		rc = -EINVAL;
-		printk(KERN_WARNING "Invalid number of header extents: [%zd]\n",
-		       crypt_stat->num_header_extents_at_front);
+		printk(KERN_WARNING "Invalid header size: [%zd]\n",
+		       crypt_stat->num_header_bytes_at_front);
 	}
 	return rc;
 }
@@ -1466,7 +1440,8 @@
  */
 static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
 {
-	crypt_stat->num_header_extents_at_front = 2;
+	crypt_stat->num_header_bytes_at_front =
+		ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 }
 
 /**
@@ -1552,9 +1527,10 @@
 	size = ecryptfs_getxattr_lower(lower_dentry, ECRYPTFS_XATTR_NAME,
 				       page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE);
 	if (size < 0) {
-		printk(KERN_ERR "Error attempting to read the [%s] "
-		       "xattr from the lower file; return value = [%zd]\n",
-		       ECRYPTFS_XATTR_NAME, size);
+		if (unlikely(ecryptfs_verbosity > 0))
+			printk(KERN_INFO "Error attempting to read the [%s] "
+			       "xattr from the lower file; return value = "
+			       "[%zd]\n", ECRYPTFS_XATTR_NAME, size);
 		rc = -EINVAL;
 		goto out;
 	}
@@ -1802,7 +1778,7 @@
 }
 
 struct kmem_cache *ecryptfs_key_tfm_cache;
-struct list_head key_tfm_list;
+static struct list_head key_tfm_list;
 struct mutex key_tfm_list_mutex;
 
 int ecryptfs_init_crypto(void)
@@ -1812,6 +1788,11 @@
 	return 0;
 }
 
+/**
+ * ecryptfs_destroy_crypto - free all cached key_tfms on key_tfm_list
+ *
+ * Called only at module unload time
+ */
 int ecryptfs_destroy_crypto(void)
 {
 	struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp;
@@ -1835,6 +1816,8 @@
 	struct ecryptfs_key_tfm *tmp_tfm;
 	int rc = 0;
 
+	BUG_ON(!mutex_is_locked(&key_tfm_list_mutex));
+
 	tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL);
 	if (key_tfm != NULL)
 		(*key_tfm) = tmp_tfm;
@@ -1861,13 +1844,50 @@
 			(*key_tfm) = NULL;
 		goto out;
 	}
-	mutex_lock(&key_tfm_list_mutex);
 	list_add(&tmp_tfm->key_tfm_list, &key_tfm_list);
-	mutex_unlock(&key_tfm_list_mutex);
 out:
 	return rc;
 }
 
+/**
+ * ecryptfs_tfm_exists - Search for existing tfm for cipher_name.
+ * @cipher_name: the name of the cipher to search for
+ * @key_tfm: set to corresponding tfm if found
+ *
+ * Searches for cached key_tfm matching @cipher_name
+ * Must be called with &key_tfm_list_mutex held
+ * Returns 1 if found, with @key_tfm set
+ * Returns 0 if not found, with @key_tfm set to NULL
+ */
+int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm)
+{
+	struct ecryptfs_key_tfm *tmp_key_tfm;
+
+	BUG_ON(!mutex_is_locked(&key_tfm_list_mutex));
+
+	list_for_each_entry(tmp_key_tfm, &key_tfm_list, key_tfm_list) {
+		if (strcmp(tmp_key_tfm->cipher_name, cipher_name) == 0) {
+			if (key_tfm)
+				(*key_tfm) = tmp_key_tfm;
+			return 1;
+		}
+	}
+	if (key_tfm)
+		(*key_tfm) = NULL;
+	return 0;
+}
+
+/**
+ * ecryptfs_get_tfm_and_mutex_for_cipher_name
+ *
+ * @tfm: set to cached tfm found, or new tfm created
+ * @tfm_mutex: set to mutex for cached tfm found, or new tfm created
+ * @cipher_name: the name of the cipher to search for and/or add
+ *
+ * Sets pointers to @tfm & @tfm_mutex matching @cipher_name.
+ * Searches for cached item first, and creates new if not found.
+ * Returns 0 on success, non-zero if adding new cipher failed
+ */
 int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
 					       struct mutex **tfm_mutex,
 					       char *cipher_name)
@@ -1877,22 +1897,17 @@
 
 	(*tfm) = NULL;
 	(*tfm_mutex) = NULL;
+
 	mutex_lock(&key_tfm_list_mutex);
-	list_for_each_entry(key_tfm, &key_tfm_list, key_tfm_list) {
-		if (strcmp(key_tfm->cipher_name, cipher_name) == 0) {
-			(*tfm) = key_tfm->key_tfm;
-			(*tfm_mutex) = &key_tfm->key_tfm_mutex;
-			mutex_unlock(&key_tfm_list_mutex);
+	if (!ecryptfs_tfm_exists(cipher_name, &key_tfm)) {
+		rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
+		if (rc) {
+			printk(KERN_ERR "Error adding new key_tfm to list; "
+					"rc = [%d]\n", rc);
 			goto out;
 		}
 	}
 	mutex_unlock(&key_tfm_list_mutex);
-	rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0);
-	if (rc) {
-		printk(KERN_ERR "Error adding new key_tfm to list; rc = [%d]\n",
-		       rc);
-		goto out;
-	}
 	(*tfm) = key_tfm->key_tfm;
 	(*tfm_mutex) = &key_tfm->key_tfm_mutex;
 out:
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index ce7a5d4..5007f78 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -234,10 +234,11 @@
 #define ECRYPTFS_KEY_VALID          0x00000080
 #define ECRYPTFS_METADATA_IN_XATTR  0x00000100
 #define ECRYPTFS_VIEW_AS_ENCRYPTED  0x00000200
+#define ECRYPTFS_KEY_SET            0x00000400
 	u32 flags;
 	unsigned int file_version;
 	size_t iv_bytes;
-	size_t num_header_extents_at_front;
+	size_t num_header_bytes_at_front;
 	size_t extent_size; /* Data extent size; default is 4096 */
 	size_t key_size;
 	size_t extent_shift;
@@ -322,7 +323,6 @@
 	unsigned char cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
 };
 
-extern struct list_head key_tfm_list;
 extern struct mutex key_tfm_list_mutex;
 
 /**
@@ -521,11 +521,9 @@
 extern struct kmem_cache *ecryptfs_dentry_info_cache;
 extern struct kmem_cache *ecryptfs_inode_info_cache;
 extern struct kmem_cache *ecryptfs_sb_info_cache;
-extern struct kmem_cache *ecryptfs_header_cache_0;
 extern struct kmem_cache *ecryptfs_header_cache_1;
 extern struct kmem_cache *ecryptfs_header_cache_2;
 extern struct kmem_cache *ecryptfs_xattr_cache;
-extern struct kmem_cache *ecryptfs_lower_page_cache;
 extern struct kmem_cache *ecryptfs_key_record_cache;
 extern struct kmem_cache *ecryptfs_key_sig_cache;
 extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
@@ -562,8 +560,8 @@
 					     struct inode *ecryptfs_inode);
 int ecryptfs_read_and_validate_xattr_region(char *page_virt,
 					    struct dentry *ecryptfs_dentry);
-u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
-int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code);
+u8 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat);
+int ecryptfs_cipher_code_to_string(char *str, u8 cipher_code);
 void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_generate_key_packet_set(char *dest_base,
 				     struct ecryptfs_crypt_stat *crypt_stat,
@@ -576,8 +574,6 @@
 int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode);
 int ecryptfs_inode_set(struct inode *inode, void *lower_inode);
 void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode);
-ssize_t ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
-			  size_t size);
 ssize_t
 ecryptfs_getxattr_lower(struct dentry *lower_dentry, const char *name,
 			void *value, size_t size);
@@ -623,6 +619,7 @@
 			 size_t key_size);
 int ecryptfs_init_crypto(void);
 int ecryptfs_destroy_crypto(void);
+int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm);
 int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
 					       struct mutex **tfm_mutex,
 					       char *cipher_name);
@@ -631,8 +628,6 @@
 				      char *sig);
 int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
 			 int num_zeros);
-void ecryptfs_lower_offset_for_extent(loff_t *offset, loff_t extent_num,
-				      struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
 			 loff_t offset, size_t size);
 int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
@@ -646,8 +641,6 @@
 				     pgoff_t page_index,
 				     size_t offset_in_page, size_t size,
 				     struct inode *ecryptfs_inode);
-int ecryptfs_read(char *data, loff_t offset, size_t size,
-		  struct file *ecryptfs_file);
 struct page *ecryptfs_get_locked_page(struct file *file, loff_t index);
 
 #endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index c98c469..2b8f5ed 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -209,9 +209,10 @@
 			if (!(mount_crypt_stat->flags
 			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
 				rc = -EIO;
-				printk(KERN_WARNING "Attempt to read file that "
+				printk(KERN_WARNING "Either the lower file "
 				       "is not in a valid eCryptfs format, "
-				       "and plaintext passthrough mode is not "
+				       "or the key could not be retrieved. "
+				       "Plaintext passthrough mode is not "
 				       "enabled; returning -EIO\n");
 				mutex_unlock(&crypt_stat->cs_mutex);
 				goto out_free;
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 5a71918..edd1e44 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -365,8 +365,7 @@
 		dentry->d_sb)->mount_crypt_stat;
 	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
 		if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-			file_size = ((crypt_stat->extent_size
-				      * crypt_stat->num_header_extents_at_front)
+			file_size = (crypt_stat->num_header_bytes_at_front
 				     + i_size_read(lower_dentry->d_inode));
 		else
 			file_size = i_size_read(lower_dentry->d_inode);
@@ -685,7 +684,7 @@
  * @crypt_stat: Crypt_stat associated with file
  * @upper_size: Size of the upper file
  *
- * Calculate the requried size of the lower file based on the
+ * Calculate the required size of the lower file based on the
  * specified size of the upper file. This calculation is based on the
  * number of headers in the underlying file and the extent size.
  *
@@ -697,8 +696,7 @@
 {
 	loff_t lower_size;
 
-	lower_size = (crypt_stat->extent_size
-		      * crypt_stat->num_header_extents_at_front);
+	lower_size = crypt_stat->num_header_bytes_at_front;
 	if (upper_size != 0) {
 		loff_t num_extents;
 
@@ -875,11 +873,11 @@
 			if (!(mount_crypt_stat->flags
 			      & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
 				rc = -EIO;
-				printk(KERN_WARNING "Attempt to read file that "
+				printk(KERN_WARNING "Either the lower file "
 				       "is not in a valid eCryptfs format, "
-				       "and plaintext passthrough mode is not "
+				       "or the key could not be retrieved. "
+				       "Plaintext passthrough mode is not "
 				       "enabled; returning -EIO\n");
-
 				mutex_unlock(&crypt_stat->cs_mutex);
 				goto out;
 			}
@@ -954,7 +952,7 @@
 	return rc;
 }
 
-ssize_t
+static ssize_t
 ecryptfs_getxattr(struct dentry *dentry, const char *name, void *value,
 		  size_t size)
 {
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index f458c1f..682b1b2 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -189,7 +189,7 @@
 }
 
 static int
-parse_tag_65_packet(struct ecryptfs_session_key *session_key, u16 *cipher_code,
+parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code,
 		    struct ecryptfs_message *msg)
 {
 	size_t i = 0;
@@ -275,7 +275,7 @@
 
 
 static int
-write_tag_66_packet(char *signature, size_t cipher_code,
+write_tag_66_packet(char *signature, u8 cipher_code,
 		    struct ecryptfs_crypt_stat *crypt_stat, char **packet,
 		    size_t *packet_len)
 {
@@ -428,7 +428,7 @@
 decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
 				  struct ecryptfs_crypt_stat *crypt_stat)
 {
-	u16 cipher_code = 0;
+	u8 cipher_code = 0;
 	struct ecryptfs_msg_ctx *msg_ctx;
 	struct ecryptfs_message *msg = NULL;
 	char *auth_tok_sig;
@@ -1537,7 +1537,7 @@
 	struct scatterlist dst_sg;
 	struct scatterlist src_sg;
 	struct mutex *tfm_mutex = NULL;
-	size_t cipher_code;
+	u8 cipher_code;
 	size_t packet_size_length;
 	size_t max_packet_size;
 	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 0249aa4..778c420 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -117,7 +117,7 @@
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
 {
 	struct ecryptfs_inode_info *inode_info =
 		ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
@@ -226,17 +226,15 @@
 	return rc;
 }
 
-enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig, ecryptfs_opt_debug,
-       ecryptfs_opt_ecryptfs_debug, ecryptfs_opt_cipher,
-       ecryptfs_opt_ecryptfs_cipher, ecryptfs_opt_ecryptfs_key_bytes,
+enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
+       ecryptfs_opt_cipher, ecryptfs_opt_ecryptfs_cipher,
+       ecryptfs_opt_ecryptfs_key_bytes,
        ecryptfs_opt_passthrough, ecryptfs_opt_xattr_metadata,
        ecryptfs_opt_encrypted_view, ecryptfs_opt_err };
 
 static match_table_t tokens = {
 	{ecryptfs_opt_sig, "sig=%s"},
 	{ecryptfs_opt_ecryptfs_sig, "ecryptfs_sig=%s"},
-	{ecryptfs_opt_debug, "debug=%u"},
-	{ecryptfs_opt_ecryptfs_debug, "ecryptfs_debug=%u"},
 	{ecryptfs_opt_cipher, "cipher=%s"},
 	{ecryptfs_opt_ecryptfs_cipher, "ecryptfs_cipher=%s"},
 	{ecryptfs_opt_ecryptfs_key_bytes, "ecryptfs_key_bytes=%u"},
@@ -313,7 +311,6 @@
 	substring_t args[MAX_OPT_ARGS];
 	int token;
 	char *sig_src;
-	char *debug_src;
 	char *cipher_name_dst;
 	char *cipher_name_src;
 	char *cipher_key_bytes_src;
@@ -341,16 +338,6 @@
 			}
 			sig_set = 1;
 			break;
-		case ecryptfs_opt_debug:
-		case ecryptfs_opt_ecryptfs_debug:
-			debug_src = args[0].from;
-			ecryptfs_verbosity =
-				(int)simple_strtol(debug_src, &debug_src,
-						   0);
-			ecryptfs_printk(KERN_DEBUG,
-					"Verbosity set to [%d]" "\n",
-					ecryptfs_verbosity);
-			break;
 		case ecryptfs_opt_cipher:
 		case ecryptfs_opt_ecryptfs_cipher:
 			cipher_name_src = args[0].from;
@@ -423,9 +410,13 @@
 	if (!cipher_key_bytes_set) {
 		mount_crypt_stat->global_default_cipher_key_size = 0;
 	}
-	rc = ecryptfs_add_new_key_tfm(
-		NULL, mount_crypt_stat->global_default_cipher_name,
-		mount_crypt_stat->global_default_cipher_key_size);
+	mutex_lock(&key_tfm_list_mutex);
+	if (!ecryptfs_tfm_exists(mount_crypt_stat->global_default_cipher_name,
+				 NULL))
+		rc = ecryptfs_add_new_key_tfm(
+			NULL, mount_crypt_stat->global_default_cipher_name,
+			mount_crypt_stat->global_default_cipher_key_size);
+	mutex_unlock(&key_tfm_list_mutex);
 	if (rc) {
 		printk(KERN_ERR "Error attempting to initialize cipher with "
 		       "name = [%s] and key size = [%td]; rc = [%d]\n",
@@ -654,11 +645,6 @@
 		.size = sizeof(struct ecryptfs_sb_info),
 	},
 	{
-		.cache = &ecryptfs_header_cache_0,
-		.name = "ecryptfs_headers_0",
-		.size = PAGE_CACHE_SIZE,
-	},
-	{
 		.cache = &ecryptfs_header_cache_1,
 		.name = "ecryptfs_headers_1",
 		.size = PAGE_CACHE_SIZE,
@@ -821,6 +807,10 @@
 		       "rc = [%d]\n", rc);
 		goto out_release_messaging;
 	}
+	if (ecryptfs_verbosity > 0)
+		printk(KERN_CRIT "eCryptfs verbosity set to %d. Secret values "
+			"will be written to the syslog!\n", ecryptfs_verbosity);
+
 	goto out;
 out_release_messaging:
 	ecryptfs_release_messaging(ecryptfs_transport);
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 0535412..dc74b18 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -34,8 +34,6 @@
 #include <linux/scatterlist.h>
 #include "ecryptfs_kernel.h"
 
-struct kmem_cache *ecryptfs_lower_page_cache;
-
 /**
  * ecryptfs_get_locked_page
  *
@@ -102,13 +100,14 @@
 			    struct ecryptfs_crypt_stat *crypt_stat)
 {
 	size_t written;
-	int save_num_header_extents_at_front =
-		crypt_stat->num_header_extents_at_front;
+	size_t save_num_header_bytes_at_front =
+		crypt_stat->num_header_bytes_at_front;
 
-	crypt_stat->num_header_extents_at_front = 1;
+	crypt_stat->num_header_bytes_at_front =
+		ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 	ecryptfs_write_header_metadata(page_virt + 20, crypt_stat, &written);
-	crypt_stat->num_header_extents_at_front =
-		save_num_header_extents_at_front;
+	crypt_stat->num_header_bytes_at_front =
+		save_num_header_bytes_at_front;
 }
 
 /**
@@ -134,8 +133,11 @@
 		loff_t view_extent_num = ((((loff_t)page->index)
 					   * num_extents_per_page)
 					  + extent_num_in_page);
+		size_t num_header_extents_at_front =
+			(crypt_stat->num_header_bytes_at_front
+			 / crypt_stat->extent_size);
 
-		if (view_extent_num < crypt_stat->num_header_extents_at_front) {
+		if (view_extent_num < num_header_extents_at_front) {
 			/* This is a header extent */
 			char *page_virt;
 
@@ -157,9 +159,8 @@
 		} else {
 			/* This is an encrypted data extent */
 			loff_t lower_offset =
-				((view_extent_num -
-				  crypt_stat->num_header_extents_at_front)
-				 * crypt_stat->extent_size);
+				((view_extent_num * crypt_stat->extent_size)
+				 - crypt_stat->num_header_bytes_at_front);
 
 			rc = ecryptfs_read_lower_page_segment(
 				page, (lower_offset >> PAGE_CACHE_SHIFT),
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 948f576..0c49286 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -293,6 +293,7 @@
 	return rc;
 }
 
+#if 0
 /**
  * ecryptfs_read
  * @data: The virtual address into which to write the data read (and
@@ -371,3 +372,4 @@
 out:
 	return rc;
 }
+#endif  /*  0  */
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index 4859c4e..c27ac2b 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -156,32 +156,38 @@
 /**
  * ecryptfs_show_options
  *
- * Prints the directory we are currently mounted over.
- * Returns zero on success; non-zero otherwise
+ * Prints the mount options for a given superblock.
+ * Returns zero; does not fail.
  */
 static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt)
 {
 	struct super_block *sb = mnt->mnt_sb;
-	struct dentry *lower_root_dentry = ecryptfs_dentry_to_lower(sb->s_root);
-	struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(sb->s_root);
-	char *tmp_page;
-	char *path;
-	int rc = 0;
+	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
+		&ecryptfs_superblock_to_private(sb)->mount_crypt_stat;
+	struct ecryptfs_global_auth_tok *walker;
 
-	tmp_page = (char *)__get_free_page(GFP_KERNEL);
-	if (!tmp_page) {
-		rc = -ENOMEM;
-		goto out;
+	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
+	list_for_each_entry(walker,
+			    &mount_crypt_stat->global_auth_tok_list,
+			    mount_crypt_stat_list) {
+		seq_printf(m, ",ecryptfs_sig=%s", walker->sig);
 	}
-	path = d_path(lower_root_dentry, lower_mnt, tmp_page, PAGE_SIZE);
-	if (IS_ERR(path)) {
-		rc = PTR_ERR(path);
-		goto out;
-	}
-	seq_printf(m, ",dir=%s", path);
-	free_page((unsigned long)tmp_page);
-out:
-	return rc;
+	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
+
+	seq_printf(m, ",ecryptfs_cipher=%s",
+		mount_crypt_stat->global_default_cipher_name);
+
+	if (mount_crypt_stat->global_default_cipher_key_size)
+		seq_printf(m, ",ecryptfs_key_bytes=%zd",
+			   mount_crypt_stat->global_default_cipher_key_size);
+	if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)
+		seq_printf(m, ",ecryptfs_passthrough");
+	if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)
+		seq_printf(m, ",ecryptfs_xattr_metadata");
+	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)
+		seq_printf(m, ",ecryptfs_encrypted_view");
+
+	return 0;
 }
 
 const struct super_operations ecryptfs_sops = {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 2ce19c0..a9f130c 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/anon_inodes.h>
 #include <linux/eventfd.h>
+#include <linux/syscalls.h>
 
 struct eventfd_ctx {
 	wait_queue_head_t wqh;
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 377ad17..e7b2baf 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -69,9 +69,53 @@
 	return desc + offset;
 }
 
+static int ext2_valid_block_bitmap(struct super_block *sb,
+					struct ext2_group_desc *desc,
+					unsigned int block_group,
+					struct buffer_head *bh)
+{
+	ext2_grpblk_t offset;
+	ext2_grpblk_t next_zero_bit;
+	ext2_fsblk_t bitmap_blk;
+	ext2_fsblk_t group_first_block;
+
+	group_first_block = ext2_group_first_block_no(sb, block_group);
+
+	/* check whether block bitmap block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+	offset = bitmap_blk - group_first_block;
+	if (!ext2_test_bit(offset, bh->b_data))
+		/* bad block bitmap */
+		goto err_out;
+
+	/* check whether the inode bitmap block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
+	offset = bitmap_blk - group_first_block;
+	if (!ext2_test_bit(offset, bh->b_data))
+		/* bad block bitmap */
+		goto err_out;
+
+	/* check whether the inode table block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_table);
+	offset = bitmap_blk - group_first_block;
+	next_zero_bit = ext2_find_next_zero_bit(bh->b_data,
+				offset + EXT2_SB(sb)->s_itb_per_group,
+				offset);
+	if (next_zero_bit >= offset + EXT2_SB(sb)->s_itb_per_group)
+		/* good bitmap for inode tables */
+		return 1;
+
+err_out:
+	ext2_error(sb, __FUNCTION__,
+			"Invalid block bitmap - "
+			"block_group = %d, block = %lu",
+			block_group, bitmap_blk);
+	return 0;
+}
+
 /*
- * Read the bitmap for a given block_group, reading into the specified 
- * slot in the superblock's bitmap cache.
+ * Read the bitmap for a given block_group,and validate the
+ * bits for block/inode/inode tables are set in the bitmaps
  *
  * Return buffer_head on success or NULL in case of failure.
  */
@@ -80,17 +124,36 @@
 {
 	struct ext2_group_desc * desc;
 	struct buffer_head * bh = NULL;
-	
-	desc = ext2_get_group_desc (sb, block_group, NULL);
+	ext2_fsblk_t bitmap_blk;
+
+	desc = ext2_get_group_desc(sb, block_group, NULL);
 	if (!desc)
-		goto error_out;
-	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
-	if (!bh)
-		ext2_error (sb, "read_block_bitmap",
+		return NULL;
+	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+	bh = sb_getblk(sb, bitmap_blk);
+	if (unlikely(!bh)) {
+		ext2_error(sb, __FUNCTION__,
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %u",
 			    block_group, le32_to_cpu(desc->bg_block_bitmap));
-error_out:
+		return NULL;
+	}
+	if (likely(bh_uptodate_or_lock(bh)))
+		return bh;
+
+	if (bh_submit_read(bh) < 0) {
+		brelse(bh);
+		ext2_error(sb, __FUNCTION__,
+			    "Cannot read block bitmap - "
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
+		return NULL;
+	}
+	if (!ext2_valid_block_bitmap(sb, desc, block_group, bh)) {
+		brelse(bh);
+		return NULL;
+	}
+
 	return bh;
 }
 
@@ -474,11 +537,13 @@
 	    in_range (block, le32_to_cpu(desc->bg_inode_table),
 		      sbi->s_itb_per_group) ||
 	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
-		      sbi->s_itb_per_group))
+		      sbi->s_itb_per_group)) {
 		ext2_error (sb, "ext2_free_blocks",
 			    "Freeing blocks in system zones - "
 			    "Block = %lu, count = %lu",
 			    block, count);
+		goto error_return;
+	}
 
 	for (i = 0, group_freed = 0; i < count; i++) {
 		if (!ext2_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
@@ -1250,8 +1315,8 @@
 	smp_rmb();
 
 	/*
-	 * Now search the rest of the groups.  We assume that 
-	 * i and gdp correctly point to the last group visited.
+	 * Now search the rest of the groups.  We assume that
+	 * group_no and gdp correctly point to the last group visited.
 	 */
 	for (bgi = 0; bgi < ngroups; bgi++) {
 		group_no++;
@@ -1311,11 +1376,13 @@
 	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
 		      EXT2_SB(sb)->s_itb_per_group) ||
 	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
-		      EXT2_SB(sb)->s_itb_per_group))
+		      EXT2_SB(sb)->s_itb_per_group)) {
 		ext2_error(sb, "ext2_new_blocks",
 			    "Allocating block in system zone - "
 			    "blocks from "E2FSBLK", length %lu",
 			    ret_block, num);
+		goto out;
+	}
 
 	performed_allocation = 1;
 
@@ -1466,9 +1533,6 @@
  */
 unsigned long ext2_bg_num_gdb(struct super_block *sb, int group)
 {
-	if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
-	    !ext2_group_sparse(group))
-		return 0;
-	return EXT2_SB(sb)->s_gdb_count;
+	return ext2_bg_has_super(sb, group) ? EXT2_SB(sb)->s_gdb_count : 0;
 }
 
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index d868e26..8dededd 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -703,7 +703,7 @@
 	.llseek		= generic_file_llseek,
 	.read		= generic_read_dir,
 	.readdir	= ext2_readdir,
-	.ioctl		= ext2_ioctl,
+	.unlocked_ioctl = ext2_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index c87ae29..bb9948c 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -139,8 +139,7 @@
 		struct page **pagep, void **fsdata);
 
 /* ioctl.c */
-extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
-		       unsigned long);
+extern long ext2_ioctl(struct file *, unsigned int, unsigned long);
 extern long ext2_compat_ioctl(struct file *, unsigned int, unsigned long);
 
 /* namei.c */
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index c051798..5f2fa9c 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -48,7 +48,7 @@
 	.write		= do_sync_write,
 	.aio_read	= generic_file_aio_read,
 	.aio_write	= generic_file_aio_write,
-	.ioctl		= ext2_ioctl,
+	.unlocked_ioctl = ext2_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
@@ -65,7 +65,7 @@
 	.llseek		= generic_file_llseek,
 	.read		= xip_file_read,
 	.write		= xip_file_write,
-	.ioctl		= ext2_ioctl,
+	.unlocked_ioctl = ext2_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ext2_compat_ioctl,
 #endif
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index b1ab32a..03978ec 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -286,15 +286,12 @@
  *	ext2_find_goal - find a prefered place for allocation.
  *	@inode: owner
  *	@block:  block we want
- *	@chain:  chain of indirect blocks
  *	@partial: pointer to the last triple within a chain
  *
  *	Returns preferred place for a block (the goal).
  */
 
-static inline int ext2_find_goal(struct inode *inode,
-				 long block,
-				 Indirect chain[4],
+static inline int ext2_find_goal(struct inode *inode, long block,
 				 Indirect *partial)
 {
 	struct ext2_block_alloc_info *block_i;
@@ -569,7 +566,6 @@
  *
  * `handle' can be NULL if create == 0.
  *
- * The BKL may not be held on entry here.  Be sure to take it early.
  * return > 0, # of blocks mapped or allocated.
  * return = 0, if plain lookup failed.
  * return < 0, error case.
@@ -639,7 +635,7 @@
 	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
 		ext2_init_block_alloc_info(inode);
 
-	goal = ext2_find_goal(inode, iblock, chain, partial);
+	goal = ext2_find_goal(inode, iblock, partial);
 
 	/* the number of blocks need to allocate for [d,t]indirect blocks */
 	indirect_blks = (chain + depth) - partial - 1;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 320b2cb..b8ea11f 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -17,9 +17,9 @@
 #include <asm/uaccess.h>
 
 
-int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
-		unsigned long arg)
+long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	struct inode *inode = filp->f_dentry->d_inode;
 	struct ext2_inode_info *ei = EXT2_I(inode);
 	unsigned int flags;
 	unsigned short rsv_window_size;
@@ -141,9 +141,6 @@
 #ifdef CONFIG_COMPAT
 long ext2_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct inode *inode = file->f_path.dentry->d_inode;
-	int ret;
-
 	/* These are just misnamed, they actually get/put from/to user an int */
 	switch (cmd) {
 	case EXT2_IOC32_GETFLAGS:
@@ -161,9 +158,6 @@
 	default:
 		return -ENOIOCTLCMD;
 	}
-	lock_kernel();
-	ret = ext2_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
-	unlock_kernel();
-	return ret;
+	return ext2_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
 }
 #endif
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 6abaf75..1ba18b7 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -234,16 +234,16 @@
 	    le16_to_cpu(es->s_def_resgid) != EXT2_DEF_RESGID) {
 		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
 	}
-	if (test_opt(sb, ERRORS_CONT)) {
+	if (test_opt(sb, ERRORS_RO)) {
 		int def_errors = le16_to_cpu(es->s_errors);
 
 		if (def_errors == EXT2_ERRORS_PANIC ||
-		    def_errors == EXT2_ERRORS_RO) {
-			seq_puts(seq, ",errors=continue");
+		    def_errors == EXT2_ERRORS_CONTINUE) {
+			seq_puts(seq, ",errors=remount-ro");
 		}
 	}
-	if (test_opt(sb, ERRORS_RO))
-		seq_puts(seq, ",errors=remount-ro");
+	if (test_opt(sb, ERRORS_CONT))
+		seq_puts(seq, ",errors=continue");
 	if (test_opt(sb, ERRORS_PANIC))
 		seq_puts(seq, ",errors=panic");
 	if (test_opt(sb, NO_UID32))
@@ -617,27 +617,24 @@
 	return res;
 }
 
-static int ext2_check_descriptors (struct super_block * sb)
+static int ext2_check_descriptors(struct super_block *sb)
 {
 	int i;
-	int desc_block = 0;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	unsigned long first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
 	unsigned long last_block;
-	struct ext2_group_desc * gdp = NULL;
 
 	ext2_debug ("Checking group descriptors");
 
-	for (i = 0; i < sbi->s_groups_count; i++)
-	{
+	for (i = 0; i < sbi->s_groups_count; i++) {
+		struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL);
+
 		if (i == sbi->s_groups_count - 1)
 			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
 		else
 			last_block = first_block +
 				(EXT2_BLOCKS_PER_GROUP(sb) - 1);
 
-		if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
-			gdp = (struct ext2_group_desc *) sbi->s_group_desc[desc_block++]->b_data;
 		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
 		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
 		{
@@ -667,7 +664,6 @@
 			return 0;
 		}
 		first_block += EXT2_BLOCKS_PER_GROUP(sb);
-		gdp++;
 	}
 	return 1;
 }
@@ -820,10 +816,10 @@
 	
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
-	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_RO)
-		set_opt(sbi->s_mount_opt, ERRORS_RO);
-	else
+	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
 		set_opt(sbi->s_mount_opt, ERRORS_CONT);
+	else
+		set_opt(sbi->s_mount_opt, ERRORS_RO);
 
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
@@ -868,8 +864,7 @@
 
 	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
 
-	if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) ||
-				  (sb->s_blocksize != blocksize))) {
+	if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) {
 		if (!silent)
 			printk("XIP: Unsupported blocksize\n");
 		goto failed_mount;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index a8ba7e8..a757130 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -80,13 +80,57 @@
 	return desc + offset;
 }
 
+static int ext3_valid_block_bitmap(struct super_block *sb,
+					struct ext3_group_desc *desc,
+					unsigned int block_group,
+					struct buffer_head *bh)
+{
+	ext3_grpblk_t offset;
+	ext3_grpblk_t next_zero_bit;
+	ext3_fsblk_t bitmap_blk;
+	ext3_fsblk_t group_first_block;
+
+	group_first_block = ext3_group_first_block_no(sb, block_group);
+
+	/* check whether block bitmap block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+	offset = bitmap_blk - group_first_block;
+	if (!ext3_test_bit(offset, bh->b_data))
+		/* bad block bitmap */
+		goto err_out;
+
+	/* check whether the inode bitmap block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_bitmap);
+	offset = bitmap_blk - group_first_block;
+	if (!ext3_test_bit(offset, bh->b_data))
+		/* bad block bitmap */
+		goto err_out;
+
+	/* check whether the inode table block number is set */
+	bitmap_blk = le32_to_cpu(desc->bg_inode_table);
+	offset = bitmap_blk - group_first_block;
+	next_zero_bit = ext3_find_next_zero_bit(bh->b_data,
+				offset + EXT3_SB(sb)->s_itb_per_group,
+				offset);
+	if (next_zero_bit >= offset + EXT3_SB(sb)->s_itb_per_group)
+		/* good bitmap for inode tables */
+		return 1;
+
+err_out:
+	ext3_error(sb, __FUNCTION__,
+			"Invalid block bitmap - "
+			"block_group = %d, block = %lu",
+			block_group, bitmap_blk);
+	return 0;
+}
+
 /**
  * read_block_bitmap()
  * @sb:			super block
  * @block_group:	given block group
  *
- * Read the bitmap for a given block_group, reading into the specified
- * slot in the superblock's bitmap cache.
+ * Read the bitmap for a given block_group,and validate the
+ * bits for block/inode/inode tables are set in the bitmaps
  *
  * Return buffer_head on success or NULL in case of failure.
  */
@@ -95,17 +139,35 @@
 {
 	struct ext3_group_desc * desc;
 	struct buffer_head * bh = NULL;
+	ext3_fsblk_t bitmap_blk;
 
-	desc = ext3_get_group_desc (sb, block_group, NULL);
+	desc = ext3_get_group_desc(sb, block_group, NULL);
 	if (!desc)
-		goto error_out;
-	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
-	if (!bh)
-		ext3_error (sb, "read_block_bitmap",
+		return NULL;
+	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
+	bh = sb_getblk(sb, bitmap_blk);
+	if (unlikely(!bh)) {
+		ext3_error(sb, __FUNCTION__,
 			    "Cannot read block bitmap - "
 			    "block_group = %d, block_bitmap = %u",
 			    block_group, le32_to_cpu(desc->bg_block_bitmap));
-error_out:
+		return NULL;
+	}
+	if (likely(bh_uptodate_or_lock(bh)))
+		return bh;
+
+	if (bh_submit_read(bh) < 0) {
+		brelse(bh);
+		ext3_error(sb, __FUNCTION__,
+			    "Cannot read block bitmap - "
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
+		return NULL;
+	}
+	if (!ext3_valid_block_bitmap(sb, desc, block_group, bh)) {
+		brelse(bh);
+		return NULL;
+	}
 	return bh;
 }
 /*
@@ -468,11 +530,13 @@
 	    in_range (block, le32_to_cpu(desc->bg_inode_table),
 		      sbi->s_itb_per_group) ||
 	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
-		      sbi->s_itb_per_group))
+		      sbi->s_itb_per_group)) {
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks in system zones - "
 			    "Block = "E3FSBLK", count = %lu",
 			    block, count);
+		goto error_return;
+	}
 
 	/*
 	 * We are about to start releasing blocks in the bitmap,
@@ -1508,7 +1572,7 @@
 
 	/*
 	 * Now search the rest of the groups.  We assume that
-	 * i and gdp correctly point to the last group visited.
+	 * group_no and gdp correctly point to the last group visited.
 	 */
 	for (bgi = 0; bgi < ngroups; bgi++) {
 		group_no++;
@@ -1575,11 +1639,13 @@
 	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
 		      EXT3_SB(sb)->s_itb_per_group) ||
 	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
-		      EXT3_SB(sb)->s_itb_per_group))
+		      EXT3_SB(sb)->s_itb_per_group)) {
 		ext3_error(sb, "ext3_new_block",
 			    "Allocating block in system zone - "
 			    "blocks from "E3FSBLK", length %lu",
 			     ret_block, num);
+		goto out;
+	}
 
 	performed_allocation = 1;
 
@@ -1782,11 +1848,7 @@
 
 static unsigned long ext3_bg_num_gdb_nometa(struct super_block *sb, int group)
 {
-	if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
-				EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
-			!ext3_group_sparse(group))
-		return 0;
-	return EXT3_SB(sb)->s_gdb_count;
+	return ext3_bg_has_super(sb, group) ? EXT3_SB(sb)->s_gdb_count : 0;
 }
 
 /**
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0775354..8a9ce2d 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -439,16 +439,14 @@
  *	ext3_find_goal - find a prefered place for allocation.
  *	@inode: owner
  *	@block:  block we want
- *	@chain:  chain of indirect blocks
  *	@partial: pointer to the last triple within a chain
- *	@goal:	place to store the result.
  *
  *	Normally this function find the prefered place for block allocation,
- *	stores it in *@goal and returns zero.
+ *	returns it.
  */
 
 static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block,
-		Indirect chain[4], Indirect *partial)
+				   Indirect *partial)
 {
 	struct ext3_block_alloc_info *block_i;
 
@@ -884,7 +882,7 @@
 	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
 		ext3_init_block_alloc_info(inode);
 
-	goal = ext3_find_goal(inode, iblock, chain, partial);
+	goal = ext3_find_goal(inode, iblock, partial);
 
 	/* the number of blocks need to allocate for [d,t]indirect blocks */
 	indirect_blks = (chain + depth) - partial - 1;
@@ -941,55 +939,45 @@
 	return err;
 }
 
-#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
+/* Maximum number of blocks we map for direct IO at once. */
+#define DIO_MAX_BLOCKS 4096
+/*
+ * Number of credits we need for writing DIO_MAX_BLOCKS:
+ * We need sb + group descriptor + bitmap + inode -> 4
+ * For B blocks with A block pointers per block we need:
+ * 1 (triple ind.) + (B/A/A + 2) (doubly ind.) + (B/A + 2) (indirect).
+ * If we plug in 4096 for B and 256 for A (for 1KB block size), we get 25.
+ */
+#define DIO_CREDITS 25
 
 static int ext3_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
 	handle_t *handle = ext3_journal_current_handle();
-	int ret = 0;
+	int ret = 0, started = 0;
 	unsigned max_blocks = bh_result->b_size >> inode->i_blkbits;
 
-	if (!create)
-		goto get_block;		/* A read */
-
-	if (max_blocks == 1)
-		goto get_block;		/* A single block get */
-
-	if (handle->h_transaction->t_state == T_LOCKED) {
-		/*
-		 * Huge direct-io writes can hold off commits for long
-		 * periods of time.  Let this commit run.
-		 */
-		ext3_journal_stop(handle);
-		handle = ext3_journal_start(inode, DIO_CREDITS);
-		if (IS_ERR(handle))
+	if (create && !handle) {	/* Direct IO write... */
+		if (max_blocks > DIO_MAX_BLOCKS)
+			max_blocks = DIO_MAX_BLOCKS;
+		handle = ext3_journal_start(inode, DIO_CREDITS +
+				2 * EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb));
+		if (IS_ERR(handle)) {
 			ret = PTR_ERR(handle);
-		goto get_block;
-	}
-
-	if (handle->h_buffer_credits <= EXT3_RESERVE_TRANS_BLOCKS) {
-		/*
-		 * Getting low on buffer credits...
-		 */
-		ret = ext3_journal_extend(handle, DIO_CREDITS);
-		if (ret > 0) {
-			/*
-			 * Couldn't extend the transaction.  Start a new one.
-			 */
-			ret = ext3_journal_restart(handle, DIO_CREDITS);
+			goto out;
 		}
+		started = 1;
 	}
 
-get_block:
-	if (ret == 0) {
-		ret = ext3_get_blocks_handle(handle, inode, iblock,
+	ret = ext3_get_blocks_handle(handle, inode, iblock,
 					max_blocks, bh_result, create, 0);
-		if (ret > 0) {
-			bh_result->b_size = (ret << inode->i_blkbits);
-			ret = 0;
-		}
+	if (ret > 0) {
+		bh_result->b_size = (ret << inode->i_blkbits);
+		ret = 0;
 	}
+	if (started)
+		ext3_journal_stop(handle);
+out:
 	return ret;
 }
 
@@ -1680,7 +1668,8 @@
  * if the machine crashes during the write.
  *
  * If the O_DIRECT write is intantiating holes inside i_size and the machine
- * crashes then stale disk data _may_ be exposed inside the file.
+ * crashes then stale disk data _may_ be exposed inside the file. But current
+ * VFS code falls back into buffered path in that case so we are safe.
  */
 static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
 			const struct iovec *iov, loff_t offset,
@@ -1689,7 +1678,7 @@
 	struct file *file = iocb->ki_filp;
 	struct inode *inode = file->f_mapping->host;
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	handle_t *handle = NULL;
+	handle_t *handle;
 	ssize_t ret;
 	int orphan = 0;
 	size_t count = iov_length(iov, nr_segs);
@@ -1697,17 +1686,21 @@
 	if (rw == WRITE) {
 		loff_t final_size = offset + count;
 
-		handle = ext3_journal_start(inode, DIO_CREDITS);
-		if (IS_ERR(handle)) {
-			ret = PTR_ERR(handle);
-			goto out;
-		}
 		if (final_size > inode->i_size) {
+			/* Credits for sb + inode write */
+			handle = ext3_journal_start(inode, 2);
+			if (IS_ERR(handle)) {
+				ret = PTR_ERR(handle);
+				goto out;
+			}
 			ret = ext3_orphan_add(handle, inode);
-			if (ret)
-				goto out_stop;
+			if (ret) {
+				ext3_journal_stop(handle);
+				goto out;
+			}
 			orphan = 1;
 			ei->i_disksize = inode->i_size;
+			ext3_journal_stop(handle);
 		}
 	}
 
@@ -1715,18 +1708,21 @@
 				 offset, nr_segs,
 				 ext3_get_block, NULL);
 
-	/*
-	 * Reacquire the handle: ext3_get_block() can restart the transaction
-	 */
-	handle = ext3_journal_current_handle();
-
-out_stop:
-	if (handle) {
+	if (orphan) {
 		int err;
 
-		if (orphan && inode->i_nlink)
+		/* Credits for sb + inode write */
+		handle = ext3_journal_start(inode, 2);
+		if (IS_ERR(handle)) {
+			/* This is really bad luck. We've written the data
+			 * but cannot extend i_size. Bail out and pretend
+			 * the write failed... */
+			ret = PTR_ERR(handle);
+			goto out;
+		}
+		if (inode->i_nlink)
 			ext3_orphan_del(handle, inode);
-		if (orphan && ret > 0) {
+		if (ret > 0) {
 			loff_t end = offset + ret;
 			if (end > inode->i_size) {
 				ei->i_disksize = end;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4ab6f76..92b83b0 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -860,14 +860,10 @@
 	int nblocks, i, err;
 	struct inode *dir = dentry->d_parent->d_inode;
 	int namelen;
-	const u8 *name;
-	unsigned blocksize;
 
 	*res_dir = NULL;
 	sb = dir->i_sb;
-	blocksize = sb->s_blocksize;
 	namelen = dentry->d_name.len;
-	name = dentry->d_name.name;
 	if (namelen > EXT3_NAME_LEN)
 		return NULL;
 	if (is_dx(dir)) {
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index f3675cc..343677e 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -575,16 +575,16 @@
 	    le16_to_cpu(es->s_def_resgid) != EXT3_DEF_RESGID) {
 		seq_printf(seq, ",resgid=%u", sbi->s_resgid);
 	}
-	if (test_opt(sb, ERRORS_CONT)) {
+	if (test_opt(sb, ERRORS_RO)) {
 		int def_errors = le16_to_cpu(es->s_errors);
 
 		if (def_errors == EXT3_ERRORS_PANIC ||
-		    def_errors == EXT3_ERRORS_RO) {
-			seq_puts(seq, ",errors=continue");
+		    def_errors == EXT3_ERRORS_CONTINUE) {
+			seq_puts(seq, ",errors=remount-ro");
 		}
 	}
-	if (test_opt(sb, ERRORS_RO))
-		seq_puts(seq, ",errors=remount-ro");
+	if (test_opt(sb, ERRORS_CONT))
+		seq_puts(seq, ",errors=continue");
 	if (test_opt(sb, ERRORS_PANIC))
 		seq_puts(seq, ",errors=panic");
 	if (test_opt(sb, NO_UID32))
@@ -1252,28 +1252,24 @@
 }
 
 /* Called at mount-time, super-block is locked */
-static int ext3_check_descriptors (struct super_block * sb)
+static int ext3_check_descriptors(struct super_block *sb)
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
 	ext3_fsblk_t last_block;
-	struct ext3_group_desc * gdp = NULL;
-	int desc_block = 0;
 	int i;
 
 	ext3_debug ("Checking group descriptors");
 
-	for (i = 0; i < sbi->s_groups_count; i++)
-	{
+	for (i = 0; i < sbi->s_groups_count; i++) {
+		struct ext3_group_desc *gdp = ext3_get_group_desc(sb, i, NULL);
+
 		if (i == sbi->s_groups_count - 1)
 			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
 		else
 			last_block = first_block +
 				(EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
-		if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
-			gdp = (struct ext3_group_desc *)
-					sbi->s_group_desc[desc_block++]->b_data;
 		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
 		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
 		{
@@ -1306,7 +1302,6 @@
 			return 0;
 		}
 		first_block += EXT3_BLOCKS_PER_GROUP(sb);
-		gdp++;
 	}
 
 	sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb));
@@ -1583,10 +1578,10 @@
 
 	if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_PANIC)
 		set_opt(sbi->s_mount_opt, ERRORS_PANIC);
-	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_RO)
-		set_opt(sbi->s_mount_opt, ERRORS_RO);
-	else
+	else if (le16_to_cpu(sbi->s_es->s_errors) == EXT3_ERRORS_CONTINUE)
 		set_opt(sbi->s_mount_opt, ERRORS_CONT);
+	else
+		set_opt(sbi->s_mount_opt, ERRORS_RO);
 
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index ac75ea9..0737e05 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1700,7 +1700,7 @@
 
 	/*
 	 * Now search the rest of the groups.  We assume that
-	 * i and gdp correctly point to the last group visited.
+	 * group_no and gdp correctly point to the last group visited.
 	 */
 	for (bgi = 0; bgi < ngroups; bgi++) {
 		group_no++;
@@ -2011,11 +2011,7 @@
 static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
 					ext4_group_t group)
 {
-	if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-				EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
-			!ext4_group_sparse(group))
-		return 0;
-	return EXT4_SB(sb)->s_gdb_count;
+	return ext4_bg_has_super(sb, group) ? EXT4_SB(sb)->s_gdb_count : 0;
 }
 
 /**
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 05c4145..0e9055c 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -429,16 +429,13 @@
  *	ext4_find_goal - find a prefered place for allocation.
  *	@inode: owner
  *	@block:  block we want
- *	@chain:  chain of indirect blocks
  *	@partial: pointer to the last triple within a chain
- *	@goal:	place to store the result.
  *
  *	Normally this function find the prefered place for block allocation,
- *	stores it in *@goal and returns zero.
+ *	returns it.
  */
-
 static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block,
-		Indirect chain[4], Indirect *partial)
+		Indirect *partial)
 {
 	struct ext4_block_alloc_info *block_i;
 
@@ -839,7 +836,7 @@
 	if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info))
 		ext4_init_block_alloc_info(inode);
 
-	goal = ext4_find_goal(inode, iblock, chain, partial);
+	goal = ext4_find_goal(inode, iblock, partial);
 
 	/* the number of blocks need to allocate for [d,t]indirect blocks */
 	indirect_blks = (chain + depth) - partial - 1;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 055a0cd..c89bb87 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1458,7 +1458,7 @@
 }
 
 /* Called at mount-time, super-block is locked */
-static int ext4_check_descriptors (struct super_block * sb)
+static int ext4_check_descriptors(struct super_block *sb)
 {
 	struct ext4_sb_info *sbi = EXT4_SB(sb);
 	ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
@@ -1466,8 +1466,6 @@
 	ext4_fsblk_t block_bitmap;
 	ext4_fsblk_t inode_bitmap;
 	ext4_fsblk_t inode_table;
-	struct ext4_group_desc * gdp = NULL;
-	int desc_block = 0;
 	int flexbg_flag = 0;
 	ext4_group_t i;
 
@@ -1476,17 +1474,15 @@
 
 	ext4_debug ("Checking group descriptors");
 
-	for (i = 0; i < sbi->s_groups_count; i++)
-	{
+	for (i = 0; i < sbi->s_groups_count; i++) {
+		struct ext4_group_desc *gdp = ext4_get_group_desc(sb, i, NULL);
+
 		if (i == sbi->s_groups_count - 1 || flexbg_flag)
 			last_block = ext4_blocks_count(sbi->s_es) - 1;
 		else
 			last_block = first_block +
 				(EXT4_BLOCKS_PER_GROUP(sb) - 1);
 
-		if ((i % EXT4_DESC_PER_BLOCK(sb)) == 0)
-			gdp = (struct ext4_group_desc *)
-					sbi->s_group_desc[desc_block++]->b_data;
 		block_bitmap = ext4_block_bitmap(sb, gdp);
 		if (block_bitmap < first_block || block_bitmap > last_block)
 		{
@@ -1524,8 +1520,6 @@
 		}
 		if (!flexbg_flag)
 			first_block += EXT4_BLOCKS_PER_GROUP(sb);
-		gdp = (struct ext4_group_desc *)
-			((__u8 *)gdp + EXT4_DESC_SIZE(sb));
 	}
 
 	ext4_free_blocks_count_set(sbi->s_es, ext4_count_free_blocks(sb));
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..c614175 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -155,6 +155,42 @@
 	return err;
 }
 
+static int check_mode(const struct msdos_sb_info *sbi, mode_t mode)
+{
+	mode_t req = mode & ~S_IFMT;
+
+	/*
+	 * Of the r and x bits, all (subject to umask) must be present. Of the
+	 * w bits, either all (subject to umask) or none must be present.
+	 */
+
+	if (S_ISREG(mode)) {
+		req &= ~sbi->options.fs_fmask;
+
+		if ((req & (S_IRUGO | S_IXUGO)) !=
+		    ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask))
+			return -EPERM;
+
+		if ((req & S_IWUGO) != 0 &&
+		    (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask))
+			return -EPERM;
+	} else if (S_ISDIR(mode)) {
+		req &= ~sbi->options.fs_dmask;
+
+		if ((req & (S_IRUGO | S_IXUGO)) !=
+		    ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask))
+			return -EPERM;
+
+		if ((req & S_IWUGO) != 0 &&
+		    (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask))
+			return -EPERM;
+	} else {
+		return -EPERM;
+	}
+
+	return 0;
+}
+
 int fat_notify_change(struct dentry *dentry, struct iattr *attr)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
@@ -186,9 +222,7 @@
 	if (((attr->ia_valid & ATTR_UID) &&
 	     (attr->ia_uid != sbi->options.fs_uid)) ||
 	    ((attr->ia_valid & ATTR_GID) &&
-	     (attr->ia_gid != sbi->options.fs_gid)) ||
-	    ((attr->ia_valid & ATTR_MODE) &&
-	     (attr->ia_mode & ~MSDOS_VALID_MODE)))
+	     (attr->ia_gid != sbi->options.fs_gid)))
 		error = -EPERM;
 
 	if (error) {
@@ -196,6 +230,13 @@
 			error = 0;
 		goto out;
 	}
+
+	if (attr->ia_valid & ATTR_MODE) {
+		error = check_mode(sbi, attr->ia_mode);
+		if (error != 0 && !sbi->options.quiet)
+			goto out;
+	}
+
 	error = inode_setattr(inode, attr);
 	if (error)
 		goto out;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 920a576e..24c0aaa 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1295,10 +1295,8 @@
 
 		fsinfo = (struct fat_boot_fsinfo *)fsinfo_bh->b_data;
 		if (!IS_FSINFO(fsinfo)) {
-			printk(KERN_WARNING
-			       "FAT: Did not find valid FSINFO signature.\n"
-			       "     Found signature1 0x%08x signature2 0x%08x"
-			       " (sector = %lu)\n",
+			printk(KERN_WARNING "FAT: Invalid FSINFO signature: "
+			       "0x%08x, 0x%08x (sector = %lu)\n",
 			       le32_to_cpu(fsinfo->signature1),
 			       le32_to_cpu(fsinfo->signature2),
 			       sbi->fsinfo_sector);
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 308f2b6..61f2351 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -55,9 +55,8 @@
 	fsinfo = (struct fat_boot_fsinfo *)bh->b_data;
 	/* Sanity check */
 	if (!IS_FSINFO(fsinfo)) {
-		printk(KERN_ERR "FAT: Did not find valid FSINFO signature.\n"
-		       "     Found signature1 0x%08x signature2 0x%08x"
-		       " (sector = %lu)\n",
+		printk(KERN_ERR "FAT: Invalid FSINFO signature: "
+		       "0x%08x, 0x%08x (sector = %lu)\n",
 		       le32_to_cpu(fsinfo->signature1),
 		       le32_to_cpu(fsinfo->signature2),
 		       sbi->fsinfo_sector);
diff --git a/fs/file.c b/fs/file.c
index c5575de..5110acb1 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -24,6 +24,8 @@
 	struct fdtable *next;
 };
 
+int sysctl_nr_open __read_mostly = 1024*1024;
+
 /*
  * We use this list to defer free fdtables that have vmalloced
  * sets/arrays. By keeping a per-cpu list, we avoid having to embed
@@ -147,8 +149,8 @@
 	nr /= (1024 / sizeof(struct file *));
 	nr = roundup_pow_of_two(nr + 1);
 	nr *= (1024 / sizeof(struct file *));
-	if (nr > NR_OPEN)
-		nr = NR_OPEN;
+	if (nr > sysctl_nr_open)
+		nr = sysctl_nr_open;
 
 	fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL);
 	if (!fdt)
@@ -233,7 +235,7 @@
 	if (nr < fdt->max_fds)
 		return 0;
 	/* Can we expand? */
-	if (nr >= NR_OPEN)
+	if (nr >= sysctl_nr_open)
 		return -EMFILE;
 
 	/* All good, so we try */
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 0b30640..db80ce9 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -515,8 +515,7 @@
 	might_sleep();
 	spin_lock(&sb_lock);
 restart:
-	sb = sb_entry(super_blocks.prev);
-	for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
+	list_for_each_entry_reverse(sb, &super_blocks, s_list) {
 		if (sb_has_dirty_inodes(sb)) {
 			/* we're making our own get_super here */
 			sb->s_count++;
@@ -581,10 +580,8 @@
 {
 	struct super_block *sb;
 	spin_lock(&sb_lock);
-	sb = sb_entry(super_blocks.prev);
-	for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
+	list_for_each_entry_reverse(sb, &super_blocks, s_list)
 		sb->s_syncing = val;
-	}
 	spin_unlock(&sb_lock);
 }
 
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index db534bcde..af639807 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -201,6 +201,55 @@
 	}
 }
 
+static unsigned len_args(unsigned numargs, struct fuse_arg *args)
+{
+	unsigned nbytes = 0;
+	unsigned i;
+
+	for (i = 0; i < numargs; i++)
+		nbytes += args[i].size;
+
+	return nbytes;
+}
+
+static u64 fuse_get_unique(struct fuse_conn *fc)
+{
+	fc->reqctr++;
+	/* zero is special */
+	if (fc->reqctr == 0)
+		fc->reqctr = 1;
+
+	return fc->reqctr;
+}
+
+static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
+{
+	req->in.h.unique = fuse_get_unique(fc);
+	req->in.h.len = sizeof(struct fuse_in_header) +
+		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
+	list_add_tail(&req->list, &fc->pending);
+	req->state = FUSE_REQ_PENDING;
+	if (!req->waiting) {
+		req->waiting = 1;
+		atomic_inc(&fc->num_waiting);
+	}
+	wake_up(&fc->waitq);
+	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
+}
+
+static void flush_bg_queue(struct fuse_conn *fc)
+{
+	while (fc->active_background < FUSE_MAX_BACKGROUND &&
+	       !list_empty(&fc->bg_queue)) {
+		struct fuse_req *req;
+
+		req = list_entry(fc->bg_queue.next, struct fuse_req, list);
+		list_del(&req->list);
+		fc->active_background++;
+		queue_request(fc, req);
+	}
+}
+
 /*
  * This function is called when a request is finished.  Either a reply
  * has arrived or it was aborted (and not yet sent) or some error
@@ -229,6 +278,8 @@
 			clear_bdi_congested(&fc->bdi, WRITE);
 		}
 		fc->num_background--;
+		fc->active_background--;
+		flush_bg_queue(fc);
 	}
 	spin_unlock(&fc->lock);
 	wake_up(&req->waitq);
@@ -320,42 +371,6 @@
 	}
 }
 
-static unsigned len_args(unsigned numargs, struct fuse_arg *args)
-{
-	unsigned nbytes = 0;
-	unsigned i;
-
-	for (i = 0; i < numargs; i++)
-		nbytes += args[i].size;
-
-	return nbytes;
-}
-
-static u64 fuse_get_unique(struct fuse_conn *fc)
- {
- 	fc->reqctr++;
- 	/* zero is special */
- 	if (fc->reqctr == 0)
- 		fc->reqctr = 1;
-
-	return fc->reqctr;
-}
-
-static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
-{
-	req->in.h.unique = fuse_get_unique(fc);
-	req->in.h.len = sizeof(struct fuse_in_header) +
-		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
-	list_add_tail(&req->list, &fc->pending);
-	req->state = FUSE_REQ_PENDING;
-	if (!req->waiting) {
-		req->waiting = 1;
-		atomic_inc(&fc->num_waiting);
-	}
-	wake_up(&fc->waitq);
-	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
-}
-
 void request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
 	req->isreply = 1;
@@ -375,20 +390,26 @@
 	spin_unlock(&fc->lock);
 }
 
+static void request_send_nowait_locked(struct fuse_conn *fc,
+				       struct fuse_req *req)
+{
+	req->background = 1;
+	fc->num_background++;
+	if (fc->num_background == FUSE_MAX_BACKGROUND)
+		fc->blocked = 1;
+	if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
+		set_bdi_congested(&fc->bdi, READ);
+		set_bdi_congested(&fc->bdi, WRITE);
+	}
+	list_add_tail(&req->list, &fc->bg_queue);
+	flush_bg_queue(fc);
+}
+
 static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
 {
 	spin_lock(&fc->lock);
 	if (fc->connected) {
-		req->background = 1;
-		fc->num_background++;
-		if (fc->num_background == FUSE_MAX_BACKGROUND)
-			fc->blocked = 1;
-		if (fc->num_background == FUSE_CONGESTION_THRESHOLD) {
-			set_bdi_congested(&fc->bdi, READ);
-			set_bdi_congested(&fc->bdi, WRITE);
-		}
-
-		queue_request(fc, req);
+		request_send_nowait_locked(fc, req);
 		spin_unlock(&fc->lock);
 	} else {
 		req->out.h.error = -ENOTCONN;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 80d2f52..f56f91b 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -416,6 +416,7 @@
 	fuse_put_request(fc, forget_req);
 	d_instantiate(entry, inode);
 	fuse_change_entry_timeout(entry, &outentry);
+	fuse_invalidate_attr(dir);
 	file = lookup_instantiate_filp(nd, entry, generic_file_open);
 	if (IS_ERR(file)) {
 		ff->fh = outopen.fh;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index bb05d22..676b0bc 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -77,8 +77,8 @@
 
 static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 {
-	dput(req->dentry);
-	mntput(req->vfsmount);
+	dput(req->misc.release.dentry);
+	mntput(req->misc.release.vfsmount);
 	fuse_put_request(fc, req);
 }
 
@@ -86,7 +86,8 @@
 {
 	if (atomic_dec_and_test(&ff->count)) {
 		struct fuse_req *req = ff->reserved_req;
-		struct fuse_conn *fc = get_fuse_conn(req->dentry->d_inode);
+		struct inode *inode = req->misc.release.dentry->d_inode;
+		struct fuse_conn *fc = get_fuse_conn(inode);
 		req->end = fuse_release_end;
 		request_send_background(fc, req);
 		kfree(ff);
@@ -137,7 +138,7 @@
 void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode)
 {
 	struct fuse_req *req = ff->reserved_req;
-	struct fuse_release_in *inarg = &req->misc.release_in;
+	struct fuse_release_in *inarg = &req->misc.release.in;
 
 	inarg->fh = ff->fh;
 	inarg->flags = flags;
@@ -153,13 +154,14 @@
 	struct fuse_file *ff = file->private_data;
 	if (ff) {
 		struct fuse_conn *fc = get_fuse_conn(inode);
+		struct fuse_req *req = ff->reserved_req;
 
 		fuse_release_fill(ff, get_node_id(inode), file->f_flags,
 				  isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
 
 		/* Hold vfsmount and dentry until release is finished */
-		ff->reserved_req->vfsmount = mntget(file->f_path.mnt);
-		ff->reserved_req->dentry = dget(file->f_path.dentry);
+		req->misc.release.vfsmount = mntget(file->f_path.mnt);
+		req->misc.release.dentry = dget(file->f_path.dentry);
 
 		spin_lock(&fc->lock);
 		list_del(&ff->write_entry);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 3ab8a30..67aaf6e 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -215,7 +215,11 @@
 	/** Data for asynchronous requests */
 	union {
 		struct fuse_forget_in forget_in;
-		struct fuse_release_in release_in;
+		struct {
+			struct fuse_release_in in;
+			struct vfsmount *vfsmount;
+			struct dentry *dentry;
+		} release;
 		struct fuse_init_in init_in;
 		struct fuse_init_out init_out;
 		struct fuse_read_in read_in;
@@ -238,12 +242,6 @@
 	/** File used in the request (or NULL) */
 	struct fuse_file *ff;
 
-	/** vfsmount used in release */
-	struct vfsmount *vfsmount;
-
-	/** dentry used in release */
-	struct dentry *dentry;
-
 	/** Request completion callback */
 	void (*end)(struct fuse_conn *, struct fuse_req *);
 
@@ -298,6 +296,12 @@
 	/** Number of requests currently in the background */
 	unsigned num_background;
 
+	/** Number of background requests currently queued for userspace */
+	unsigned active_background;
+
+	/** The list of background requests set aside for later queuing */
+	struct list_head bg_queue;
+
 	/** Pending interrupts */
 	struct list_head interrupts;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e5e80d1..c90f633 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -465,6 +465,7 @@
 		INIT_LIST_HEAD(&fc->processing);
 		INIT_LIST_HEAD(&fc->io);
 		INIT_LIST_HEAD(&fc->interrupts);
+		INIT_LIST_HEAD(&fc->bg_queue);
 		atomic_set(&fc->num_waiting, 0);
 		fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 		fc->bdi.unplug_io_fn = default_unplug_io_fn;
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index f8452a0..4129cdb 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -52,9 +52,9 @@
 		rec = (e + b) / 2;
 		len = hfs_brec_lenoff(bnode, rec, &off);
 		keylen = hfs_brec_keylen(bnode, rec);
-		if (keylen == HFS_BAD_KEYLEN) {
+		if (keylen == 0) {
 			res = -EINVAL;
-			goto done;
+			goto fail;
 		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
 		cmpval = bnode->tree->keycmp(fd->key, fd->search_key);
@@ -71,9 +71,9 @@
 	if (rec != e && e >= 0) {
 		len = hfs_brec_lenoff(bnode, e, &off);
 		keylen = hfs_brec_keylen(bnode, e);
-		if (keylen == HFS_BAD_KEYLEN) {
+		if (keylen == 0) {
 			res = -EINVAL;
-			goto done;
+			goto fail;
 		}
 		hfs_bnode_read(bnode, fd->key, off, keylen);
 	}
@@ -83,6 +83,7 @@
 	fd->keylength = keylen;
 	fd->entryoffset = off + keylen;
 	fd->entrylength = len - keylen;
+fail:
 	return res;
 }
 
@@ -206,7 +207,7 @@
 
 	len = hfs_brec_lenoff(bnode, fd->record, &off);
 	keylen = hfs_brec_keylen(bnode, fd->record);
-	if (keylen == HFS_BAD_KEYLEN) {
+	if (keylen == 0) {
 		res = -EINVAL;
 		goto out;
 	}
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 8626ee3..878bf25 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -49,14 +49,14 @@
 			if (retval > node->tree->max_key_len + 2) {
 				printk(KERN_ERR "hfs: keylen %d too large\n",
 					retval);
-				retval = HFS_BAD_KEYLEN;
+				retval = 0;
 			}
 		} else {
 			retval = (hfs_bnode_read_u8(node, recoff) | 1) + 1;
 			if (retval > node->tree->max_key_len + 1) {
 				printk(KERN_ERR "hfs: keylen %d too large\n",
 					retval);
-				retval = HFS_BAD_KEYLEN;
+				retval = 0;
 			}
 		}
 	}
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 110dd35..24cf6fc 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -81,15 +81,23 @@
 		goto fail_page;
 	if (!tree->node_count)
 		goto fail_page;
-	if ((id == HFS_EXT_CNID) && (tree->max_key_len != HFS_MAX_EXT_KEYLEN)) {
-		printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
-			tree->max_key_len);
-		goto fail_page;
-	}
-	if ((id == HFS_CAT_CNID) && (tree->max_key_len != HFS_MAX_CAT_KEYLEN)) {
-		printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
-			tree->max_key_len);
-		goto fail_page;
+	switch (id) {
+	case HFS_EXT_CNID:
+		if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) {
+			printk(KERN_ERR "hfs: invalid extent max_key_len %d\n",
+				tree->max_key_len);
+			goto fail_page;
+		}
+		break;
+	case HFS_CAT_CNID:
+		if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) {
+			printk(KERN_ERR "hfs: invalid catalog max_key_len %d\n",
+				tree->max_key_len);
+			goto fail_page;
+		}
+		break;
+	default:
+		BUG();
 	}
 
 	tree->node_size_shift = ffs(size) - 1;
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index c6aae61..6f194d0 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -28,8 +28,6 @@
 #define HFS_MAX_NAMELEN		128
 #define HFS_MAX_VALENCE		32767U
 
-#define HFS_BAD_KEYLEN		0xFF
-
 /* Meanings of the drAtrb field of the MDB,
  * Reference: _Inside Macintosh: Files_ p. 2-61
  */
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 16cbd90..32de44e 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -6,7 +6,7 @@
  * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains hfs_read_super(), some of the super_ops and
- * init_module() and cleanup_module().	The remaining super_ops are in
+ * init_hfs_fs() and exit_hfs_fs().  The remaining super_ops are in
  * inode.c since they deal with inodes.
  *
  * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
diff --git a/fs/inotify.c b/fs/inotify.c
index 2c5b921..690e725 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -168,20 +168,14 @@
 		struct dentry *child;
 
 		list_for_each_entry(child, &alias->d_subdirs, d_u.d_child) {
-			if (!child->d_inode) {
-				WARN_ON(child->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
+			if (!child->d_inode)
 				continue;
-			}
+
 			spin_lock(&child->d_lock);
-			if (watched) {
-				WARN_ON(child->d_flags &
-						DCACHE_INOTIFY_PARENT_WATCHED);
+			if (watched)
 				child->d_flags |= DCACHE_INOTIFY_PARENT_WATCHED;
-			} else {
-				WARN_ON(!(child->d_flags &
-					DCACHE_INOTIFY_PARENT_WATCHED));
-				child->d_flags&=~DCACHE_INOTIFY_PARENT_WATCHED;
-			}
+			else
+				child->d_flags &=~DCACHE_INOTIFY_PARENT_WATCHED;
 			spin_unlock(&child->d_lock);
 		}
 	}
@@ -253,7 +247,6 @@
 	if (!inode)
 		return;
 
-	WARN_ON(entry->d_flags & DCACHE_INOTIFY_PARENT_WATCHED);
 	spin_lock(&entry->d_lock);
 	parent = entry->d_parent;
 	if (parent->d_inode && inotify_inode_watched(parent->d_inode))
@@ -627,6 +620,7 @@
 		      struct inode *inode, u32 mask)
 {
 	int ret = 0;
+	int newly_watched;
 
 	/* don't allow invalid bits: we don't want flags set */
 	mask &= IN_ALL_EVENTS | IN_ONESHOT;
@@ -653,12 +647,18 @@
 	 */
 	watch->inode = igrab(inode);
 
-	if (!inotify_inode_watched(inode))
-		set_dentry_child_flags(inode, 1);
-
 	/* Add the watch to the handle's and the inode's list */
+	newly_watched = !inotify_inode_watched(inode);
 	list_add(&watch->h_list, &ih->watches);
 	list_add(&watch->i_list, &inode->inotify_watches);
+	/*
+	 * Set child flags _after_ adding the watch, so there is no race
+	 * windows where newly instantiated children could miss their parent's
+	 * watched flag.
+	 */
+	if (newly_watched)
+		set_dentry_child_flags(inode, 1);
+
 out:
 	mutex_unlock(&ih->mutex);
 	mutex_unlock(&inode->inotify_mutex);
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 5e00933..a336c97 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -79,6 +79,7 @@
 	atomic_t		count;		/* reference count */
 	struct user_struct	*user;		/* user who opened this dev */
 	struct inotify_handle	*ih;		/* inotify handle */
+	struct fasync_struct    *fa;            /* async notification */
 	unsigned int		queue_size;	/* size of the queue (bytes) */
 	unsigned int		event_count;	/* number of pending events */
 	unsigned int		max_events;	/* maximum number of events */
@@ -248,6 +249,19 @@
 }
 
 /*
+ * inotify_dev_get_last_event - return the last event in the given dev's queue
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static inline struct inotify_kernel_event *
+inotify_dev_get_last_event(struct inotify_device *dev)
+{
+	if (list_empty(&dev->events))
+		return NULL;
+	return list_entry(dev->events.prev, struct inotify_kernel_event, list);
+}
+
+/*
  * inotify_dev_queue_event - event handler registered with core inotify, adds
  * a new event to the given device
  *
@@ -273,7 +287,7 @@
 		put_inotify_watch(w); /* final put */
 
 	/* coalescing: drop this event if it is a dupe of the previous */
-	last = inotify_dev_get_event(dev);
+	last = inotify_dev_get_last_event(dev);
 	if (last && last->event.mask == mask && last->event.wd == wd &&
 			last->event.cookie == cookie) {
 		const char *lastname = last->name;
@@ -302,6 +316,7 @@
 	dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
 	list_add_tail(&kevent->list, &dev->events);
 	wake_up_interruptible(&dev->wq);
+	kill_fasync(&dev->fa, SIGIO, POLL_IN);
 
 out:
 	mutex_unlock(&dev->ev_mutex);
@@ -490,6 +505,13 @@
 	return ret;
 }
 
+static int inotify_fasync(int fd, struct file *file, int on)
+{
+	struct inotify_device *dev = file->private_data;
+
+	return fasync_helper(fd, file, on, &dev->fa) >= 0 ? 0 : -EIO;
+}
+
 static int inotify_release(struct inode *ignored, struct file *file)
 {
 	struct inotify_device *dev = file->private_data;
@@ -502,6 +524,9 @@
 		inotify_dev_event_dequeue(dev);
 	mutex_unlock(&dev->ev_mutex);
 
+	if (file->f_flags & FASYNC)
+		inotify_fasync(-1, file, 0);
+
 	/* free this device: the put matching the get in inotify_init() */
 	put_inotify_dev(dev);
 
@@ -530,6 +555,7 @@
 static const struct file_operations inotify_fops = {
 	.poll           = inotify_poll,
 	.read           = inotify_read,
+	.fasync         = inotify_fasync,
 	.release        = inotify_release,
 	.unlocked_ioctl = inotify_ioctl,
 	.compat_ioctl	= inotify_ioctl,
@@ -577,6 +603,7 @@
 		goto out_free_dev;
 	}
 	dev->ih = ih;
+	dev->fa = NULL;
 
 	filp->f_op = &inotify_fops;
 	filp->f_path.mnt = mntget(inotify_mnt);
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 5d14243..3943a89 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -1457,7 +1457,7 @@
  * Aborts hard --- we mark the abort as occurred, but do _nothing_ else,
  * and don't attempt to make any other journal updates.
  */
-void __journal_abort_hard(journal_t *journal)
+static void __journal_abort_hard(journal_t *journal)
 {
 	transaction_t *transaction;
 	char b[BDEVNAME_SIZE];
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index c5d9694..2b8edf4 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -354,7 +354,7 @@
 		struct buffer_head *	obh;
 		struct buffer_head *	nbh;
 
-		cond_resched();		/* We're under lock_kernel() */
+		cond_resched();
 
 		/* If we already know where to stop the log traversal,
 		 * check right now that we haven't gone past the end of
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
index 9216806..d36356f 100644
--- a/fs/jbd2/recovery.c
+++ b/fs/jbd2/recovery.c
@@ -397,7 +397,7 @@
 		struct buffer_head *	obh;
 		struct buffer_head *	nbh;
 
-		cond_resched();		/* We're under lock_kernel() */
+		cond_resched();
 
 		/* If we already know where to stop the log traversal,
 		 * check right now that we haven't gone past the end of
diff --git a/fs/namei.c b/fs/namei.c
index 73e2e66..241cff4 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2188,6 +2188,7 @@
 
 	/* We don't d_delete() NFS sillyrenamed files--they still exist. */
 	if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
+		fsnotify_link_count(dentry->d_inode);
 		d_delete(dentry);
 	}
 
@@ -2360,7 +2361,7 @@
 	error = dir->i_op->link(old_dentry, dir, new_dentry);
 	mutex_unlock(&old_dentry->d_inode->i_mutex);
 	if (!error)
-		fsnotify_create(dir, new_dentry);
+		fsnotify_link(dir, old_dentry->d_inode, new_dentry);
 	return error;
 }
 
diff --git a/fs/namespace.c b/fs/namespace.c
index 61bf376..e9c10cd 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -25,18 +25,21 @@
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/ramfs.h>
+#include <linux/log2.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include "pnode.h"
 #include "internal.h"
 
+#define HASH_SHIFT ilog2(PAGE_SIZE / sizeof(struct list_head))
+#define HASH_SIZE (1UL << HASH_SHIFT)
+
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
 static int event;
 
 static struct list_head *mount_hashtable __read_mostly;
-static int hash_mask __read_mostly, hash_bits __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
 static struct rw_semaphore namespace_sem;
 
@@ -48,8 +51,8 @@
 {
 	unsigned long tmp = ((unsigned long)mnt / L1_CACHE_BYTES);
 	tmp += ((unsigned long)dentry / L1_CACHE_BYTES);
-	tmp = tmp + (tmp >> hash_bits);
-	return tmp & hash_mask;
+	tmp = tmp + (tmp >> HASH_SHIFT);
+	return tmp & (HASH_SIZE - 1);
 }
 
 struct vfsmount *alloc_vfsmnt(const char *name)
@@ -1813,9 +1816,7 @@
 
 void __init mnt_init(void)
 {
-	struct list_head *d;
-	unsigned int nr_hash;
-	int i;
+	unsigned u;
 	int err;
 
 	init_rwsem(&namespace_sem);
@@ -1828,35 +1829,11 @@
 	if (!mount_hashtable)
 		panic("Failed to allocate mount hash table\n");
 
-	/*
-	 * Find the power-of-two list-heads that can fit into the allocation..
-	 * We don't guarantee that "sizeof(struct list_head)" is necessarily
-	 * a power-of-two.
-	 */
-	nr_hash = PAGE_SIZE / sizeof(struct list_head);
-	hash_bits = 0;
-	do {
-		hash_bits++;
-	} while ((nr_hash >> hash_bits) != 0);
-	hash_bits--;
+	printk("Mount-cache hash table entries: %lu\n", HASH_SIZE);
 
-	/*
-	 * Re-calculate the actual number of entries and the mask
-	 * from the number of bits we can fit.
-	 */
-	nr_hash = 1UL << hash_bits;
-	hash_mask = nr_hash - 1;
+	for (u = 0; u < HASH_SIZE; u++)
+		INIT_LIST_HEAD(&mount_hashtable[u]);
 
-	printk("Mount-cache hash table entries: %d\n", nr_hash);
-
-	/* And initialize the newly allocated array */
-	d = mount_hashtable;
-	i = nr_hash;
-	do {
-		INIT_LIST_HEAD(d);
-		d++;
-		i--;
-	} while (i);
 	err = sysfs_init();
 	if (err)
 		printk(KERN_WARNING "%s: sysfs_init error: %d\n",
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index e1cb70c..eff1f18 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -987,7 +987,7 @@
 static int __init init_ncp_fs(void)
 {
 	int err;
-	DPRINTK("ncpfs: init_module called\n");
+	DPRINTK("ncpfs: init_ncp_fs called\n");
 
 	err = init_inodecache();
 	if (err)
@@ -1004,7 +1004,7 @@
 
 static void __exit exit_ncp_fs(void)
 {
-	DPRINTK("ncpfs: cleanup_module called\n");
+	DPRINTK("ncpfs: exit_ncp_fs called\n");
 	unregister_filesystem(&ncp_fs_type);
 	destroy_inodecache();
 }
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index a99acd8..cb5f0a3 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -198,7 +198,7 @@
 
 config SGI_PARTITION
 	bool "SGI partition support" if PARTITION_ADVANCED
-	default y if (SGI_IP22 || SGI_IP27 || ((MACH_JAZZ || SNI_RM) && !CPU_LITTLE_ENDIAN))
+	default y if DEFAULT_SGI_PARTITION
 	help
 	  Say Y here if you would like to be able to read the hard disk
 	  partition table format used by SGI machines.
diff --git a/fs/pnode.c b/fs/pnode.c
index 89940f2..05ba692 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -83,6 +83,8 @@
 		mnt->mnt_master = NULL;
 		if (type == MS_UNBINDABLE)
 			mnt->mnt_flags |= MNT_UNBINDABLE;
+		else
+			mnt->mnt_flags &= ~MNT_UNBINDABLE;
 	}
 }
 
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 51288db..2686592 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -29,6 +29,7 @@
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 #include <linux/pagemap.h>
+#include <linux/interrupt.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -64,7 +65,6 @@
  */
 extern int get_hardware_list(char *);
 extern int get_stram_list(char *);
-extern int get_filesystem_list(char *);
 extern int get_exec_domain_list(char *);
 extern int get_dma_list(char *);
 
@@ -84,10 +84,15 @@
 {
 	int a, b, c;
 	int len;
+	unsigned long seq;
 
-	a = avenrun[0] + (FIXED_1/200);
-	b = avenrun[1] + (FIXED_1/200);
-	c = avenrun[2] + (FIXED_1/200);
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		a = avenrun[0] + (FIXED_1/200);
+		b = avenrun[1] + (FIXED_1/200);
+		c = avenrun[2] + (FIXED_1/200);
+	} while (read_seqretry(&xtime_lock, seq));
+
 	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
 		LOAD_INT(a), LOAD_FRAC(a),
 		LOAD_INT(b), LOAD_FRAC(b),
@@ -599,7 +604,6 @@
 }
 
 
-extern int show_interrupts(struct seq_file *f, void *v); /* In arch code */
 static struct seq_operations int_seq_ops = {
 	.start = int_seq_start,
 	.next  = int_seq_next,
diff --git a/fs/reiserfs/prints.c b/fs/reiserfs/prints.c
index 5e7388b..740bb8c 100644
--- a/fs/reiserfs/prints.c
+++ b/fs/reiserfs/prints.c
@@ -575,6 +575,8 @@
 					printk
 					    ("Block %llu contains unformatted data\n",
 					     (unsigned long long)bh->b_blocknr);
+
+	va_end(args);
 }
 
 static char print_tb_buf[2048];
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 1597f6b..a5bd23c 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -1084,7 +1084,7 @@
 }
 
 /* This is the implementation for the xattr plugin infrastructure */
-static struct list_head xattr_handlers = LIST_HEAD_INIT(xattr_handlers);
+static LIST_HEAD(xattr_handlers);
 static DEFINE_RWLOCK(handler_lock);
 
 static struct reiserfs_xattr_handler *find_xattr_handler_prefix(const char
diff --git a/fs/select.c b/fs/select.c
index 47f4792..5633fe9 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -739,7 +739,7 @@
 			timeout_jiffies = -1;
 		else
 #endif
-			timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+			timeout_jiffies = msecs_to_jiffies(timeout_msecs) + 1;
 	} else {
 		/* Infinite (< 0) or no (0) timeout */
 		timeout_jiffies = timeout_msecs;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 2d3e107..cb2b63a 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/anon_inodes.h>
 #include <linux/signalfd.h>
+#include <linux/syscalls.h>
 
 struct signalfd_ctx {
 	sigset_t sigmask;
diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c
index e48bd82..e37fe4d 100644
--- a/fs/smbfs/sock.c
+++ b/fs/smbfs/sock.c
@@ -329,9 +329,8 @@
 	msg.msg_control = NULL;
 
 	/* Dont repeat bytes and count available bufferspace */
-	rlen = smb_move_iov(&p, &num, iov, req->rq_bytes_recvd);
-	if (req->rq_rlen < rlen)
-		rlen = req->rq_rlen;
+	rlen = min_t(int, smb_move_iov(&p, &num, iov, req->rq_bytes_recvd),
+			(req->rq_rlen - req->rq_bytes_recvd));
 
 	result = kernel_recvmsg(sock, &msg, p, num, rlen, flags);
 
diff --git a/fs/utimes.c b/fs/utimes.c
index b9912ec..e5588cd 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/utime.h>
+#include <linux/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
index 04006c1..efd9a5e 100644
--- a/include/asm-arm/arch-iop13xx/adma.h
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -247,7 +247,7 @@
 }
 
 static inline void
-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)
 {
 	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
 	union {
@@ -257,13 +257,13 @@
 
 	u_desc_ctrl.value = 0;
 	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 	hw_desc->crc_addr = 0;
 }
 
 static inline void
-iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)
 {
 	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
 	union {
@@ -274,14 +274,15 @@
 	u_desc_ctrl.value = 0;
 	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
 	u_desc_ctrl.field.block_fill_en = 1;
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 	hw_desc->crc_addr = 0;
 }
 
 /* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
 static inline void
-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,
+		  unsigned long flags)
 {
 	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
 	union {
@@ -292,7 +293,7 @@
 	u_desc_ctrl.value = 0;
 	u_desc_ctrl.field.src_select = src_cnt - 1;
 	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 	hw_desc->crc_addr = 0;
 
@@ -301,7 +302,8 @@
 
 /* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
 static inline int
-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
+		       unsigned long flags)
 {
 	struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
 	union {
@@ -314,7 +316,7 @@
 	u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
 	u_desc_ctrl.field.zero_result = 1;
 	u_desc_ctrl.field.status_write_back_en = 1;
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 	hw_desc->crc_addr = 0;
 
diff --git a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
index 76fe5f6..bd85484 100644
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h
@@ -147,7 +147,16 @@
 
 #define S3C2412_FRCPAT(x)	S3C2410_LCDREG(0xB4 + ((x)*4))
 
+/* general registers */
+
+/* base of the LCD registers, where INTPND, INTSRC and then INTMSK
+ * are available. */
+
+#define S3C2410_LCDINTBASE	S3C2410_LCDREG(0x54)
+#define S3C2412_LCDINTBASE	S3C2410_LCDREG(0x24)
+
+#define S3C24XX_LCDINTPND	(0x00)
+#define S3C24XX_LCDSRCPND	(0x04)
+#define S3C24XX_LCDINTMSK	(0x08)
+
 #endif /* ___ASM_ARCH_REGS_LCD_H */
-
-
-
diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h
index ba1dca8..7380373 100644
--- a/include/asm-arm/arch-s3c2410/spi-gpio.h
+++ b/include/asm-arm/arch-s3c2410/spi-gpio.h
@@ -13,9 +13,6 @@
 #ifndef __ASM_ARCH_SPIGPIO_H
 #define __ASM_ARCH_SPIGPIO_H __FILE__
 
-struct s3c2410_spigpio_info;
-struct spi_board_info;
-
 struct s3c2410_spigpio_info {
 	unsigned long		 pin_clk;
 	unsigned long		 pin_mosi;
@@ -23,9 +20,6 @@
 
 	int			 bus_num;
 
-	unsigned long		 board_size;
-	struct spi_board_info	*board_info;
-
 	void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
 };
 
diff --git a/include/asm-arm/arch-s3c2410/spi.h b/include/asm-arm/arch-s3c2410/spi.h
index 4029a1a..7ca0ed9 100644
--- a/include/asm-arm/arch-s3c2410/spi.h
+++ b/include/asm-arm/arch-s3c2410/spi.h
@@ -13,15 +13,9 @@
 #ifndef __ASM_ARCH_SPI_H
 #define __ASM_ARCH_SPI_H __FILE__
 
-struct s3c2410_spi_info;
-struct spi_board_info;
-
 struct s3c2410_spi_info {
 	unsigned long		 pin_cs;	/* simple gpio cs */
 
-	unsigned long		 board_size;
-	struct spi_board_info	*board_info;
-
 	void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol);
 };
 
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
index 10834b5..5c529e6 100644
--- a/include/asm-arm/hardware/iop3xx-adma.h
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -414,7 +414,7 @@
 }
 
 static inline void
-iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, unsigned long flags)
 {
 	struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
 	union {
@@ -425,14 +425,14 @@
 	u_desc_ctrl.value = 0;
 	u_desc_ctrl.field.mem_to_mem_en = 1;
 	u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 	hw_desc->upper_pci_src_addr = 0;
 	hw_desc->crc_addr = 0;
 }
 
 static inline void
-iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, unsigned long flags)
 {
 	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
 	union {
@@ -443,12 +443,13 @@
 	u_desc_ctrl.value = 0;
 	u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
 	u_desc_ctrl.field.dest_write_en = 1;
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 }
 
 static inline u32
-iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
+iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt,
+		     unsigned long flags)
 {
 	int i, shift;
 	u32 edcr;
@@ -509,21 +510,23 @@
 
 	u_desc_ctrl.field.dest_write_en = 1;
 	u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 
 	return u_desc_ctrl.value;
 }
 
 static inline void
-iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt,
+		  unsigned long flags)
 {
-	iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
+	iop3xx_desc_init_xor(desc->hw_desc, src_cnt, flags);
 }
 
 /* return the number of operations */
 static inline int
-iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt,
+		       unsigned long flags)
 {
 	int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
 	struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
@@ -538,10 +541,10 @@
 	for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
 		i += slots_per_op, j++) {
 		iter = iop_hw_desc_slot_idx(hw_desc, i);
-		u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
+		u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, flags);
 		u_desc_ctrl.field.dest_write_en = 0;
 		u_desc_ctrl.field.zero_result_en = 1;
-		u_desc_ctrl.field.int_en = int_en;
+		u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 		iter->desc_ctrl = u_desc_ctrl.value;
 
 		/* for the subsequent descriptors preserve the store queue
@@ -559,7 +562,8 @@
 }
 
 static inline void
-iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt,
+		       unsigned long flags)
 {
 	struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
 	union {
@@ -591,7 +595,7 @@
 	}
 
 	u_desc_ctrl.field.dest_write_en = 0;
-	u_desc_ctrl.field.int_en = int_en;
+	u_desc_ctrl.field.int_en = flags & DMA_PREP_INTERRUPT;
 	hw_desc->desc_ctrl = u_desc_ctrl.value;
 }
 
diff --git a/include/asm-avr32/delay.h b/include/asm-avr32/delay.h
index cc3b2e3..a0ed9a9 100644
--- a/include/asm-avr32/delay.h
+++ b/include/asm-avr32/delay.h
@@ -12,7 +12,7 @@
 
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long xloops);
 extern void __delay(unsigned long loops);
 
 #define udelay(n) (__builtin_constant_p(n) ? \
diff --git a/include/asm-avr32/timex.h b/include/asm-avr32/timex.h
index 5e44ecb..187dcf3 100644
--- a/include/asm-avr32/timex.h
+++ b/include/asm-avr32/timex.h
@@ -34,7 +34,6 @@
 	return 0;
 }
 
-extern int read_current_timer(unsigned long *timer_value);
-#define ARCH_HAS_READ_CURRENT_TIMER	1
+#define ARCH_HAS_READ_CURRENT_TIMER
 
 #endif /* __ASM_AVR32_TIMEX_H */
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
index 1601d62f..574fe56 100644
--- a/include/asm-blackfin/io.h
+++ b/include/asm-blackfin/io.h
@@ -188,8 +188,6 @@
 #define page_to_phys(page)      ((page - mem_map) << PAGE_SHIFT)
 #define page_to_bus(page)       ((page - mem_map) << PAGE_SHIFT)
 
-#define mm_ptov(vaddr)		((void *) (vaddr))
-#define mm_vtop(vaddr)		((unsigned long) (vaddr))
 #define phys_to_virt(vaddr)	((void *) (vaddr))
 #define virt_to_phys(vaddr)	((unsigned long) (vaddr))
 
diff --git a/include/asm-generic/cputime.h b/include/asm-generic/cputime.h
index 09204e4..1c1fa42 100644
--- a/include/asm-generic/cputime.h
+++ b/include/asm-generic/cputime.h
@@ -18,6 +18,7 @@
 #define cputime_lt(__a, __b)		((__a) <  (__b))
 #define cputime_le(__a, __b)		((__a) <= (__b))
 #define cputime_to_jiffies(__ct)	(__ct)
+#define cputime_to_scaled(__ct)		(__ct)
 #define jiffies_to_cputime(__hz)	(__hz)
 
 typedef u64 cputime64_t;
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 962cad7..8feeae1 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -8,8 +8,6 @@
 extern char __bss_start[], __bss_stop[];
 extern char __init_begin[], __init_end[];
 extern char _sinittext[], _einittext[];
-extern char _sextratext[] __attribute__((weak));
-extern char _eextratext[] __attribute__((weak));
 extern char _end[];
 extern char __per_cpu_start[], __per_cpu_end[];
 extern char __kprobes_text_start[], __kprobes_text_end[];
diff --git a/include/asm-h8300/io.h b/include/asm-h8300/io.h
index 7543a57..26dc6cc 100644
--- a/include/asm-h8300/io.h
+++ b/include/asm-h8300/io.h
@@ -302,8 +302,6 @@
 /*
  * Macros used for converting between virtual and physical mappings.
  */
-#define mm_ptov(vaddr)		((void *) (vaddr))
-#define mm_vtop(vaddr)		((unsigned long) (vaddr))
 #define phys_to_virt(vaddr)	((void *) (vaddr))
 #define virt_to_phys(vaddr)	((unsigned long) (vaddr))
 
diff --git a/include/asm-h8300/virtconvert.h b/include/asm-h8300/virtconvert.h
index ee7d5ea..19cfd62 100644
--- a/include/asm-h8300/virtconvert.h
+++ b/include/asm-h8300/virtconvert.h
@@ -10,8 +10,6 @@
 #include <asm/setup.h>
 #include <asm/page.h>
 
-#define mm_ptov(vaddr)		((void *) (vaddr))
-#define mm_vtop(vaddr)		((unsigned long) (vaddr))
 #define phys_to_virt(vaddr)	((void *) (vaddr))
 #define virt_to_phys(vaddr)	((unsigned long) (vaddr))
 
diff --git a/include/asm-m32r/delay.h b/include/asm-m32r/delay.h
index 164448d..9dd9e99 100644
--- a/include/asm-m32r/delay.h
+++ b/include/asm-m32r/delay.h
@@ -12,7 +12,7 @@
 
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long xloops);
 extern void __delay(unsigned long loops);
 
 #define udelay(n) (__builtin_constant_p(n) ? \
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 778a4c5..0b604f0 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -107,8 +107,6 @@
 /* 64-bit machines, beware!  SRB. */
 #define SIZEOF_PTR_LOG2			       2
 
-#define mm_end_of_chunk(addr, len)	0
-
 extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
 
 /*
diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
index 653d9b2..6adef1e 100644
--- a/include/asm-m68knommu/io.h
+++ b/include/asm-m68knommu/io.h
@@ -172,8 +172,6 @@
 /*
  * Macros used for converting between virtual and physical mappings.
  */
-#define mm_ptov(vaddr)		((void *) (vaddr))
-#define mm_vtop(vaddr)		((unsigned long) (vaddr))
 #define phys_to_virt(vaddr)	((void *) (vaddr))
 #define virt_to_phys(vaddr)	((unsigned long) (vaddr))
 
diff --git a/include/asm-powerpc/cputime.h b/include/asm-powerpc/cputime.h
index 3108044..f42e623 100644
--- a/include/asm-powerpc/cputime.h
+++ b/include/asm-powerpc/cputime.h
@@ -52,12 +52,26 @@
  * Convert cputime <-> jiffies
  */
 extern u64 __cputime_jiffies_factor;
+DECLARE_PER_CPU(unsigned long, cputime_last_delta);
+DECLARE_PER_CPU(unsigned long, cputime_scaled_last_delta);
 
 static inline unsigned long cputime_to_jiffies(const cputime_t ct)
 {
 	return mulhdu(ct, __cputime_jiffies_factor);
 }
 
+/* Estimate the scaled cputime by scaling the real cputime based on
+ * the last scaled to real ratio */
+static inline cputime_t cputime_to_scaled(const cputime_t ct)
+{
+	if (cpu_has_feature(CPU_FTR_SPURR) &&
+	    per_cpu(cputime_last_delta, smp_processor_id()))
+		return ct *
+			per_cpu(cputime_scaled_last_delta, smp_processor_id())/
+			per_cpu(cputime_last_delta, smp_processor_id());
+	return ct;
+}
+
 static inline cputime_t jiffies_to_cputime(const unsigned long jif)
 {
 	cputime_t ct;
diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h
index 7a4374b..a7e06e2 100644
--- a/include/asm-powerpc/dma.h
+++ b/include/asm-powerpc/dma.h
@@ -93,16 +93,6 @@
  *
  */
 
-/* see prep_setup_arch() for detailed informations */
-#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP)
-extern long ppc_cs4232_dma, ppc_cs4232_dma2;
-#define SND_DMA1 ppc_cs4232_dma
-#define SND_DMA2 ppc_cs4232_dma2
-#else
-#define SND_DMA1 -1
-#define SND_DMA2 -1
-#endif
-
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
 #define IO_DMA2_BASE	0xC0	/* 16 bit master DMA, ch 4(=slave input)..7 */
@@ -269,24 +259,15 @@
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
 		break;
 	case 5:
-		if (SND_DMA1 == 5 || SND_DMA2 == 5)
-			dma_outb(pagenr, DMA_LO_PAGE_5);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
 		break;
 	case 6:
-		if (SND_DMA1 == 6 || SND_DMA2 == 6)
-			dma_outb(pagenr, DMA_LO_PAGE_6);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
 		break;
 	case 7:
-		if (SND_DMA1 == 7 || SND_DMA2 == 7)
-			dma_outb(pagenr, DMA_LO_PAGE_7);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
 		break;
 	}
@@ -302,12 +283,6 @@
 			 ((dmanr & 3) << 1) + IO_DMA1_BASE);
 		dma_outb((phys >> 8) & 0xff,
 			 ((dmanr & 3) << 1) + IO_DMA1_BASE);
-	} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
-		dma_outb(phys & 0xff,
-			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
-		dma_outb((phys >> 8) & 0xff,
-			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
-		dma_outb((dmanr & 3), DMA2_EXT_REG);
 	} else {
 		dma_outb((phys >> 1) & 0xff,
 			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
@@ -334,11 +309,6 @@
 			 ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
 		dma_outb((count >> 8) & 0xff,
 			 ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
-	} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
-		dma_outb(count & 0xff,
-			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
-		dma_outb((count >> 8) & 0xff,
-			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
 	} else {
 		dma_outb((count >> 1) & 0xff,
 			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
@@ -368,8 +338,7 @@
 	count = 1 + dma_inb(io_port);
 	count += dma_inb(io_port) << 8;
 
-	return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2)
-	    ? count : (count << 1);
+	return (dmanr <= 3) ? count : (count << 1);
 }
 
 /* These are in kernel/dma.c: */
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index f6dfce0..748b35a 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -115,8 +115,6 @@
 	u64 system_time;		/* accumulated system TB ticks */
 	u64 startpurr;			/* PURR/TB value snapshot */
 	u64 startspurr;			/* SPURR value snapshot */
-	u64 purrdelta;			/* FIXME: document */
-	u64 spurrdelta;			/* FIXME: document */
 };
 
 extern struct paca_struct paca[];
diff --git a/include/asm-powerpc/ps3av.h b/include/asm-powerpc/ps3av.h
index 967930b..fda9871 100644
--- a/include/asm-powerpc/ps3av.h
+++ b/include/asm-powerpc/ps3av.h
@@ -310,19 +310,25 @@
 #define PS3AV_MONITOR_TYPE_HDMI			1	/* HDMI */
 #define PS3AV_MONITOR_TYPE_DVI			2	/* DVI */
 
-#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_60	2	/* 480p */
-#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60	1	/* 480i */
-#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_50	7	/* 576p */
-#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50	6	/* 576i */
-
-#define PS3AV_REGION_60				0x01
-#define PS3AV_REGION_50				0x02
-#define PS3AV_REGION_RGB			0x10
-
-#define get_status(buf)				(((__u32 *)buf)[2])
-#define PS3AV_HDR_SIZE				4	/* version + size */
 
 /* for video mode */
+enum ps3av_mode_num {
+	PS3AV_MODE_AUTO				= 0,
+	PS3AV_MODE_480I				= 1,
+	PS3AV_MODE_480P				= 2,
+	PS3AV_MODE_720P60			= 3,
+	PS3AV_MODE_1080I60			= 4,
+	PS3AV_MODE_1080P60			= 5,
+	PS3AV_MODE_576I				= 6,
+	PS3AV_MODE_576P				= 7,
+	PS3AV_MODE_720P50			= 8,
+	PS3AV_MODE_1080I50			= 9,
+	PS3AV_MODE_1080P50			= 10,
+	PS3AV_MODE_WXGA				= 11,
+	PS3AV_MODE_SXGA				= 12,
+	PS3AV_MODE_WUXGA			= 13,
+};
+
 #define PS3AV_MODE_MASK				0x000F
 #define PS3AV_MODE_HDCP_OFF			0x1000	/* Retail PS3 product doesn't support this */
 #define PS3AV_MODE_DITHER			0x0800
@@ -333,6 +339,19 @@
 #define PS3AV_MODE_RGB				0x0020
 
 
+#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_60	PS3AV_MODE_480P
+#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60	PS3AV_MODE_480I
+#define PS3AV_DEFAULT_HDMI_MODE_ID_REG_50	PS3AV_MODE_576P
+#define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50	PS3AV_MODE_576I
+
+#define PS3AV_REGION_60				0x01
+#define PS3AV_REGION_50				0x02
+#define PS3AV_REGION_RGB			0x10
+
+#define get_status(buf)				(((__u32 *)buf)[2])
+#define PS3AV_HDR_SIZE				4	/* version + size */
+
+
 /** command packet structure **/
 struct ps3av_send_hdr {
 	u16 version;
@@ -713,8 +732,6 @@
 extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32);
 extern int ps3av_get_auto_mode(void);
 extern int ps3av_get_mode(void);
-extern int ps3av_get_scanmode(int);
-extern int ps3av_get_refresh_rate(int);
 extern int ps3av_video_mode2res(u32, u32 *, u32 *);
 extern int ps3av_video_mute(int);
 extern int ps3av_audio_mute(int);
diff --git a/include/asm-s390/cputime.h b/include/asm-s390/cputime.h
index 4b3ef7c..133ce05 100644
--- a/include/asm-s390/cputime.h
+++ b/include/asm-s390/cputime.h
@@ -54,6 +54,7 @@
 #define cputime_lt(__a, __b)		((__a) <  (__b))
 #define cputime_le(__a, __b)		((__a) <= (__b))
 #define cputime_to_jiffies(__ct)	(__div((__ct), 1000000 / HZ))
+#define cputime_to_scaled(__ct)		(__ct)
 #define jiffies_to_cputime(__hz)	((cputime_t)(__hz) * (1000000 / HZ))
 
 #define cputime64_zero			(0ULL)
diff --git a/include/asm-sh/delay.h b/include/asm-sh/delay.h
index 031db84..d5d4640 100644
--- a/include/asm-sh/delay.h
+++ b/include/asm-sh/delay.h
@@ -12,7 +12,7 @@
 
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long xloops);
 extern void __delay(unsigned long loops);
 
 #ifdef CONFIG_SUPERH32
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 0decdf7..2338a02 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -327,11 +327,13 @@
 #define __NR_epoll_pwait	309
 #define __NR_utimensat		310
 #define __NR_signalfd		311
-#define __NR_timerfd		312
+#define __NR_timerfd_create	312
 #define __NR_eventfd		313
 #define __NR_fallocate		314
+#define __NR_timerfd_settime	315
+#define __NR_timerfd_gettime	316
 
-#define NR_SYSCALLS		315
+#define NR_SYSCALLS		317
 
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
  * it never had the plain ones and there is no value to adding those
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index c299b85..b6ece22 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -16,7 +16,7 @@
 /* BIO layer definitions. */
 extern unsigned long kern_base, kern_size;
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
-#define BIO_VMERGE_BOUNDARY	8192
+#define BIO_VMERGE_BOUNDARY	0
 
 static inline u8 _inb(unsigned long addr)
 {
diff --git a/include/asm-sparc64/timex.h b/include/asm-sparc64/timex.h
index 2a5e4eb..c622535 100644
--- a/include/asm-sparc64/timex.h
+++ b/include/asm-sparc64/timex.h
@@ -14,10 +14,6 @@
 typedef unsigned long cycles_t;
 #define get_cycles()	tick_ops->get_tick()
 
-#define ARCH_HAS_READ_CURRENT_TIMER	1
-#define read_current_timer(timer_val_p) 	\
-({	*timer_val_p = tick_ops->get_tick();	\
-	0;					\
-})
+#define ARCH_HAS_READ_CURRENT_TIMER
 
 #endif
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index cb751b4..77559da 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -329,11 +329,13 @@
 #define __NR_epoll_pwait	309
 #define __NR_utimensat		310
 #define __NR_signalfd		311
-#define __NR_timerfd		312
+#define __NR_timerfd_create	312
 #define __NR_eventfd		313
 #define __NR_fallocate		314
+#define __NR_timerfd_settime	315
+#define __NR_timerfd_gettime	316
 
-#define NR_SYSCALLS		315
+#define NR_SYSCALLS		317
 
 #ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
diff --git a/include/asm-v850/io.h b/include/asm-v850/io.h
index cc364fc..cdad251 100644
--- a/include/asm-v850/io.h
+++ b/include/asm-v850/io.h
@@ -122,8 +122,6 @@
 #endif
 
 /* Conversion between virtual and physical mappings.  */
-#define mm_ptov(addr)		((void *)__phys_to_virt (addr))
-#define mm_vtop(addr)		((unsigned long)__virt_to_phys (addr))
 #define phys_to_virt(addr)	((void *)__phys_to_virt (addr))
 #define virt_to_phys(addr)	((unsigned long)__virt_to_phys (addr))
 
diff --git a/include/asm-x86/delay.h b/include/asm-x86/delay.h
index d11d47f..409a649 100644
--- a/include/asm-x86/delay.h
+++ b/include/asm-x86/delay.h
@@ -13,7 +13,7 @@
 
 extern void __udelay(unsigned long usecs);
 extern void __ndelay(unsigned long nsecs);
-extern void __const_udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long xloops);
 extern void __delay(unsigned long loops);
 
 /* 0x10c7 is 2**32 / 1000000 (rounded up) */
diff --git a/include/asm-x86/timex.h b/include/asm-x86/timex.h
index 27cfd6c..43e5a78 100644
--- a/include/asm-x86/timex.h
+++ b/include/asm-x86/timex.h
@@ -14,7 +14,6 @@
 #endif
 #define CLOCK_TICK_RATE	PIT_TICK_RATE
 
-extern int read_current_timer(unsigned long *timer_value);
-#define ARCH_HAS_READ_CURRENT_TIMER	1
+#define ARCH_HAS_READ_CURRENT_TIMER
 
 #endif
diff --git a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
index 22eb936..0260c3e 100644
--- a/include/linux/ac97_codec.h
+++ b/include/linux/ac97_codec.h
@@ -326,11 +326,7 @@
 #define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */
 };
 
-extern int ac97_read_proc (char *page_out, char **start, off_t off,
-			   int count, int *eof, void *data);
 extern int ac97_probe_codec(struct ac97_codec *);
-extern unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate);
-extern unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate);
 
 extern struct ac97_codec *ac97_alloc_codec(void);
 extern void ac97_release_codec(struct ac97_codec *codec);
@@ -363,7 +359,4 @@
 	int type;               /* quirk type above */
 };
 
-struct pci_dev;
-extern int ac97_tune_hardware(struct pci_dev *pdev, struct ac97_quirk *quirk, int override);
-
 #endif /* _AC97_CODEC_H_ */
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 302eb72..e8cae54 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -173,7 +173,11 @@
 static inline u32 jiffies_to_AHZ(unsigned long x)
 {
 #if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0
+# if HZ < AHZ
+	return x * (AHZ / HZ);
+# else
 	return x / (HZ / AHZ);
+# endif
 #else
         u64 tmp = (u64)x * TICK_NSEC;
         do_div(tmp, (NSEC_PER_SEC / AHZ));
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
index bdca3f1..eb640f0 100644
--- a/include/linux/async_tx.h
+++ b/include/linux/async_tx.h
@@ -47,7 +47,6 @@
  * address is an implied source, whereas the asynchronous case it must be listed
  * as a source.  The destination address must be the first address in the source
  * array.
- * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
  * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
  * dependency chain
  * @ASYNC_TX_DEP_ACK: ack the dependency descriptor.  Useful for chaining.
@@ -55,7 +54,6 @@
 enum async_tx_flags {
 	ASYNC_TX_XOR_ZERO_DST	 = (1 << 0),
 	ASYNC_TX_XOR_DROP_DST	 = (1 << 1),
-	ASYNC_TX_ASSUME_COHERENT = (1 << 2),
 	ASYNC_TX_ACK		 = (1 << 3),
 	ASYNC_TX_DEP_ACK	 = (1 << 4),
 };
@@ -64,9 +62,15 @@
 void async_tx_issue_pending_all(void);
 enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
+#ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL
+#include <asm/async_tx.h>
+#else
+#define async_tx_find_channel(dep, type, dst, dst_count, src, src_count, len) \
+	 __async_tx_find_channel(dep, type)
 struct dma_chan *
-async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+__async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
 	enum dma_transaction_type tx_type);
+#endif /* CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL */
 #else
 static inline void async_tx_issue_pending_all(void)
 {
@@ -88,7 +92,8 @@
 
 static inline struct dma_chan *
 async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
-	enum dma_transaction_type tx_type)
+	enum dma_transaction_type tx_type, struct page **dst, int dst_count,
+	struct page **src, int src_count, size_t len)
 {
 	return NULL;
 }
diff --git a/include/linux/pata_platform.h b/include/linux/ata_platform.h
similarity index 75%
rename from include/linux/pata_platform.h
rename to include/linux/ata_platform.h
index 6a7a92d..b856a2a 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/ata_platform.h
@@ -1,5 +1,5 @@
-#ifndef __LINUX_PATA_PLATFORM_H
-#define __LINUX_PATA_PLATFORM_H
+#ifndef __LINUX_ATA_PLATFORM_H
+#define __LINUX_ATA_PLATFORM_H
 
 struct pata_platform_info {
 	/*
@@ -24,4 +24,11 @@
 
 extern int __devexit __pata_platform_remove(struct device *dev);
 
-#endif /* __LINUX_PATA_PLATFORM_H */
+/*
+ * Marvell SATA private data
+ */
+struct mv_sata_platform_data {
+	int	n_ports; /* number of sata ports */
+};
+
+#endif /* __LINUX_ATA_PLATFORM_H */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index ae0a483..a671dbf 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -257,16 +257,8 @@
 /*
  * epoll (fs/eventpoll.c) compat bits follow ...
  */
-#ifndef CONFIG_HAS_COMPAT_EPOLL_EVENT
 struct epoll_event;
 #define compat_epoll_event	epoll_event
-#else
-asmlinkage long compat_sys_epoll_ctl(int epfd, int op, int fd,
-			struct compat_epoll_event __user *event);
-asmlinkage long compat_sys_epoll_wait(int epfd,
-			struct compat_epoll_event __user *events,
-			int maxevents, int timeout);
-#endif
 asmlinkage long compat_sys_epoll_pwait(int epfd,
 			struct compat_epoll_event __user *events,
 			int maxevents, int timeout,
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 5c84bf8..acbb364 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -95,6 +95,15 @@
 #define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
 
 /**
+ * enum dma_prep_flags - DMA flags to augment operation preparation
+ * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
+ * 	this transaction
+ */
+enum dma_prep_flags {
+	DMA_PREP_INTERRUPT = (1 << 0),
+};
+
+/**
  * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
  * See linux/cpumask.h
  */
@@ -209,8 +218,6 @@
  *	descriptors
  * @chan: target channel for this operation
  * @tx_submit: set the prepared descriptor(s) to be executed by the engine
- * @tx_set_dest: set a destination address in a hardware descriptor
- * @tx_set_src: set a source address in a hardware descriptor
  * @callback: routine to call after this operation is complete
  * @callback_param: general parameter to pass to the callback routine
  * ---async_tx api specific fields---
@@ -227,10 +234,6 @@
 	struct list_head tx_list;
 	struct dma_chan *chan;
 	dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
-	void (*tx_set_dest)(dma_addr_t addr,
-		struct dma_async_tx_descriptor *tx, int index);
-	void (*tx_set_src)(dma_addr_t addr,
-		struct dma_async_tx_descriptor *tx, int index);
 	dma_async_tx_callback callback;
 	void *callback_param;
 	struct list_head depend_list;
@@ -279,15 +282,17 @@
 	void (*device_free_chan_resources)(struct dma_chan *chan);
 
 	struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
-		struct dma_chan *chan, size_t len, int int_en);
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags);
 	struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
-		struct dma_chan *chan, unsigned int src_cnt, size_t len,
-		int int_en);
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+		unsigned int src_cnt, size_t len, unsigned long flags);
 	struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
-		struct dma_chan *chan, unsigned int src_cnt, size_t len,
-		u32 *result, int int_en);
+		struct dma_chan *chan, dma_addr_t *src,	unsigned int src_cnt,
+		size_t len, u32 *result, unsigned long flags);
 	struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
-		struct dma_chan *chan, int value, size_t len, int int_en);
+		struct dma_chan *chan, dma_addr_t dest, int value, size_t len,
+		unsigned long flags);
 	struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
 		struct dma_chan *chan);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 56bd421..109734b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -21,7 +21,7 @@
 
 /* Fixed constants first: */
 #undef NR_OPEN
-#define NR_OPEN (1024*1024)	/* Absolute upper limit on fd num */
+extern int sysctl_nr_open;
 #define INR_OPEN 1024		/* Initial setting for nfile rlimits */
 
 #define BLOCK_SIZE_BITS 10
@@ -977,7 +977,6 @@
 extern struct list_head super_blocks;
 extern spinlock_t sb_lock;
 
-#define sb_entry(list)	list_entry((list), struct super_block, s_list)
 #define S_BIAS (1<<30)
 struct super_block {
 	struct list_head	s_list;		/* Keep this first */
@@ -1279,8 +1278,10 @@
  *
  * Two bits are used for locking and completion notification, I_LOCK and I_SYNC.
  *
- * I_DIRTY_SYNC		Inode itself is dirty.
- * I_DIRTY_DATASYNC	Data-related inode changes pending
+ * I_DIRTY_SYNC		Inode is dirty, but doesn't have to be written on
+ *			fdatasync().  i_atime is the usual cause.
+ * I_DIRTY_DATASYNC	Inode is dirty and must be written on fdatasync(), f.e.
+ *			because i_size changed.
  * I_DIRTY_PAGES	Inode has dirty pages.  Inode itself may be clean.
  * I_NEW		get_new_inode() sets i_state to I_LOCK|I_NEW.  Both
  *			are cleared by unlock_new_inode(), called from iget().
@@ -1312,8 +1313,6 @@
  *			purpose reduces latency and prevents some filesystem-
  *			specific deadlocks.
  *
- * Q: Why does I_DIRTY_DATASYNC exist?  It appears as if it could be replaced
- *    by (I_DIRTY_SYNC|I_DIRTY_PAGES).
  * Q: What is the difference between I_WILL_FREE and I_FREEING?
  * Q: igrab() only checks on (I_FREEING|I_WILL_FREE).  Should it also check on
  *    I_CLEAR?  If not, why?
@@ -2113,6 +2112,7 @@
 int proc_nr_files(struct ctl_table *table, int write, struct file *filp,
 		  void __user *buffer, size_t *lenp, loff_t *ppos);
 
+int get_filesystem_list(char * buf);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_FS_H */
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 2bd31fa..d4b7c4a 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -92,6 +92,14 @@
 }
 
 /*
+ * fsnotify_link_count - inode's link count changed
+ */
+static inline void fsnotify_link_count(struct inode *inode)
+{
+	inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL);
+}
+
+/*
  * fsnotify_create - 'name' was linked in
  */
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
@@ -103,6 +111,20 @@
 }
 
 /*
+ * fsnotify_link - new hardlink in 'inode' directory
+ * Note: We have to pass also the linked inode ptr as some filesystems leave
+ *   new_dentry->d_inode NULL and instantiate inode pointer later
+ */
+static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
+{
+	inode_dir_notify(dir, DN_CREATE);
+	inotify_inode_queue_event(dir, IN_CREATE, 0, new_dentry->d_name.name,
+				  inode);
+	fsnotify_link_count(inode);
+	audit_inode_child(new_dentry->d_name.name, new_dentry, dir);
+}
+
+/*
  * fsnotify_mkdir - directory 'name' was created
  */
 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
diff --git a/include/linux/hash.h b/include/linux/hash.h
index acf17bb..06d25c1 100644
--- a/include/linux/hash.h
+++ b/include/linux/hash.h
@@ -1,6 +1,6 @@
 #ifndef _LINUX_HASH_H
 #define _LINUX_HASH_H
-/* Fast hashing routine for a long.
+/* Fast hashing routine for ints,  longs and pointers.
    (C) 2002 William Lee Irwin III, IBM */
 
 /*
@@ -13,23 +13,30 @@
  * them can use shifts and additions instead of multiplications for
  * machines where multiplications are slow.
  */
-#if BITS_PER_LONG == 32
+
+#include <asm/types.h>
+
 /* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
-#define GOLDEN_RATIO_PRIME 0x9e370001UL
-#elif BITS_PER_LONG == 64
+#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
 /*  2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
-#define GOLDEN_RATIO_PRIME 0x9e37fffffffc0001UL
+#define GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001UL
+
+#if BITS_PER_LONG == 32
+#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_32
+#define hash_long(val, bits) hash_32(val, bits)
+#elif BITS_PER_LONG == 64
+#define hash_long(val, bits) hash_64(val, bits)
+#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_PRIME_64
 #else
-#error Define GOLDEN_RATIO_PRIME for your wordsize.
+#error Wordsize not 32 or 64
 #endif
 
-static inline unsigned long hash_long(unsigned long val, unsigned int bits)
+static inline u64 hash_64(u64 val, unsigned int bits)
 {
-	unsigned long hash = val;
+	u64 hash = val;
 
-#if BITS_PER_LONG == 64
 	/*  Sigh, gcc can't optimise this alone like it does for 32 bits. */
-	unsigned long n = hash;
+	u64 n = hash;
 	n <<= 18;
 	hash -= n;
 	n <<= 33;
@@ -42,15 +49,20 @@
 	hash += n;
 	n <<= 2;
 	hash += n;
-#else
-	/* On some cpus multiply is faster, on others gcc will do shifts */
-	hash *= GOLDEN_RATIO_PRIME;
-#endif
 
 	/* High bits are more random, so use them. */
-	return hash >> (BITS_PER_LONG - bits);
+	return hash >> (64 - bits);
 }
-	
+
+static inline u32 hash_32(u32 val, unsigned int bits)
+{
+	/* On some cpus multiply is faster, on others gcc will do shifts */
+	u32 hash = val * GOLDEN_RATIO_PRIME_32;
+
+	/* High bits are more random, so use them. */
+	return hash >> (32 - bits);
+}
+
 static inline unsigned long hash_ptr(void *ptr, unsigned int bits)
 {
 	return hash_long((unsigned long)ptr, bits);
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index db390c5..6115545 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -26,13 +26,6 @@
 #include <linux/netdevice.h>
 #include <linux/hdlc/ioctl.h>
 
-
-/* Used by all network devices here, pointed to by netdev_priv(dev) */
-struct hdlc_device_desc {
-	int (*netif_rx)(struct sk_buff *skb);
-	struct net_device_stats stats;
-};
-
 /* This structure is a private property of HDLC protocols.
    Hardware drivers have no interest here */
 
@@ -44,12 +37,15 @@
 	void (*detach)(struct net_device *dev);
 	int (*ioctl)(struct net_device *dev, struct ifreq *ifr);
 	__be16 (*type_trans)(struct sk_buff *skb, struct net_device *dev);
+	int (*netif_rx)(struct sk_buff *skb);
 	struct module *module;
 	struct hdlc_proto *next; /* next protocol in the list */
 };
 
 
+/* Pointed to by dev->priv */
 typedef struct hdlc_device {
+	struct net_device_stats stats;
 	/* used by HDLC layer to take control over HDLC device from hw driver*/
 	int (*attach)(struct net_device *dev,
 		      unsigned short encoding, unsigned short parity);
@@ -83,18 +79,11 @@
 
 struct net_device *alloc_hdlcdev(void *priv);
 
-
-static __inline__ struct hdlc_device_desc* dev_to_desc(struct net_device *dev)
+static inline struct hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-	return netdev_priv(dev);
+	return dev->priv;
 }
 
-static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
-{
-	return netdev_priv(dev) + sizeof(struct hdlc_device_desc);
-}
-
-
 static __inline__ void debug_frame(const struct sk_buff *skb)
 {
 	int i;
@@ -116,13 +105,13 @@
 void hdlc_close(struct net_device *dev);
 
 int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
-			 int (*rx)(struct sk_buff *skb), size_t size);
+			 size_t size);
 /* May be used by hardware driver to gain control over HDLC device */
 void detach_hdlc_protocol(struct net_device *dev);
 
 static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
 {
-	return &dev_to_desc(dev)->stats;
+	return &dev_to_hdlc(dev)->stats;
 }
 
 
diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca953x.h
similarity index 92%
rename from include/linux/i2c/pca9539.h
rename to include/linux/i2c/pca953x.h
index 611d84a..3c73612 100644
--- a/include/linux/i2c/pca9539.h
+++ b/include/linux/i2c/pca953x.h
@@ -1,6 +1,6 @@
 /* platform data for the PCA9539 16-bit I/O expander driver */
 
-struct pca9539_platform_data {
+struct pca953x_platform_data {
 	/* number of the first GPIO */
 	unsigned	gpio_base;
 
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 34f40ef..79504b2 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -327,7 +327,7 @@
  * 
  * Returns error if the skb is not of VLAN type
  */
-static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+static inline int __vlan_get_tag(const struct sk_buff *skb, unsigned short *tag)
 {
 	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
 
@@ -347,7 +347,8 @@
  * 
  * Returns error if @skb->cb[] is not set correctly
  */
-static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short *tag)
+static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
+					 unsigned short *tag)
 {
 	struct vlan_skb_tx_cookie *cookie;
 
@@ -370,7 +371,7 @@
  * 
  * Returns error if the skb is not VLAN tagged
  */
-static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
+static inline int vlan_get_tag(const struct sk_buff *skb, unsigned short *tag)
 {
 	if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
 		return __vlan_hwaccel_get_tag(skb, tag);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c3db4a0..dea7598 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -444,4 +444,6 @@
 }
 #endif
 
+int show_interrupts(struct seq_file *p, void *v);
+
 #endif
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index d0ecc8e..9cb2855 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -507,7 +507,6 @@
   struct ktermios	normal_termios;  /* For saving termios structs     */
   struct ktermios	callout_termios;
   wait_queue_head_t	open_wait, close_wait;
-  struct semaphore      write_sem;
   spinlock_t	        readlock;
 } modem_info;
 
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index d9ecd13..b18fd3b 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -33,7 +33,6 @@
 #include <linux/lockdep.h>
 
 #include <asm/semaphore.h>
-#endif
 
 #define journal_oom_retry 1
 
@@ -84,7 +83,6 @@
 
 #define JFS_MIN_JOURNAL_BLOCKS 1024
 
-#ifdef __KERNEL__
 
 /**
  * typedef handle_t - The handle_t type represents a single atomic update being performed by some process.
@@ -924,7 +922,6 @@
 extern int	   journal_wipe       (journal_t *, int);
 extern int	   journal_skip_recovery	(journal_t *);
 extern void	   journal_update_superblock	(journal_t *, int);
-extern void	   __journal_abort_hard	(journal_t *);
 extern void	   journal_abort      (journal_t *, int);
 extern int	   journal_errno      (journal_t *);
 extern void	   journal_ack_err    (journal_t *);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index ff356b2..18222f2 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -35,7 +35,7 @@
 #define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
 #define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
 #define PTR_ALIGN(p, a)		((typeof(p))ALIGN((unsigned long)(p), (a)))
-#define IS_ALIGNED(x,a)		(((x) % ((typeof(x))(a))) == 0)
+#define IS_ALIGNED(x, a)		(((x) & ((typeof(x))(a) - 1)) == 0)
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 6168c0a..4a6ce82 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -152,8 +152,10 @@
 struct kretprobe {
 	struct kprobe kp;
 	kretprobe_handler_t handler;
+	kretprobe_handler_t entry_handler;
 	int maxactive;
 	int nmissed;
+	size_t data_size;
 	struct hlist_head free_instances;
 	struct hlist_head used_instances;
 };
@@ -164,6 +166,7 @@
 	struct kretprobe *rp;
 	kprobe_opcode_t *ret_addr;
 	struct task_struct *task;
+	char data[0];
 };
 
 struct kretprobe_blackpoint {
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 4374c42..bc5a8d0 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -457,7 +457,6 @@
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
 	unsigned int		tag;
 	unsigned int		n_elem;
-	unsigned int		n_iter;
 	unsigned int		mapped_n_elem;
 
 	int			dma_dir;
@@ -1367,7 +1366,6 @@
 	qc->nbytes = qc->raw_nbytes = qc->curbytes = 0;
 	qc->n_elem = 0;
 	qc->mapped_n_elem = 0;
-	qc->n_iter = 0;
 	qc->err_mask = 0;
 	qc->pad_len = 0;
 	qc->last_sg = NULL;
diff --git a/include/linux/log2.h b/include/linux/log2.h
index c8cf5e8..25b8086 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -190,4 +190,20 @@
 	__rounddown_pow_of_two(n)		\
  )
 
+/**
+ * order_base_2 - calculate the (rounded up) base 2 order of the argument
+ * @n: parameter
+ *
+ * The first few values calculated by this routine:
+ *  ob2(0) = 0
+ *  ob2(1) = 0
+ *  ob2(2) = 1
+ *  ob2(3) = 2
+ *  ob2(4) = 2
+ *  ob2(5) = 3
+ *  ... and so on.
+ */
+
+#define order_base_2(n) ilog2(roundup_pow_of_two(n))
+
 #endif /* _LINUX_LOG2_H */
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 26a0a103..46169a7 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -76,6 +76,7 @@
 enum {
 	LO_FLAGS_READ_ONLY	= 1,
 	LO_FLAGS_USE_AOPS	= 2,
+	LO_FLAGS_AUTOCLEAR	= 4,
 };
 
 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */
diff --git a/include/linux/lp.h b/include/linux/lp.h
index 7059b6b..0df024b 100644
--- a/include/linux/lp.h
+++ b/include/linux/lp.h
@@ -99,7 +99,7 @@
 #ifdef __KERNEL__
 
 #include <linux/wait.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 /* Magic numbers for defining port-device mappings */
 #define LP_PARPORT_UNSPEC -4
@@ -145,7 +145,7 @@
 #endif
 	wait_queue_head_t waitq;
 	unsigned int last_error;
-	struct semaphore port_mutex;
+	struct mutex port_mutex;
 	wait_queue_head_t dataq;
 	long timeout;
 	unsigned int best_mode;
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 39d3283..df6dd79a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1765,6 +1765,7 @@
 #define PCI_DEVICE_ID_QUATECH_DSC100	0x0020
 #define PCI_DEVICE_ID_QUATECH_ESC100D	0x0050
 #define PCI_DEVICE_ID_QUATECH_ESC100M	0x0060
+#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
 
 #define PCI_VENDOR_ID_SEALEVEL		0x135e
 #define PCI_DEVICE_ID_SEALEVEL_U530	0x7101
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 50faa0e..1ac9697 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -54,7 +54,7 @@
 #ifdef CONFIG_SMP
 
 struct percpu_data {
-	void *ptrs[NR_CPUS];
+	void *ptrs[1];
 };
 
 #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index 40fac8c..28dfc61c 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -348,6 +348,7 @@
 	FLOW_KEY_RTCLASSID,
 	FLOW_KEY_SKUID,
 	FLOW_KEY_SKGID,
+	FLOW_KEY_VLAN_TAG,
 	__FLOW_KEY_MAX,
 };
 
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index b9339d8..cd6332b 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -258,6 +258,7 @@
 #else
 #define pnp_device_is_isapnp(dev) 0
 #endif
+extern struct mutex pnp_res_mutex;
 
 #ifdef CONFIG_PNPBIOS
 extern struct pnp_protocol pnpbios_protocol;
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 515bff0..6ab8071 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -204,6 +204,41 @@
 }
 #endif	/* arch_has_block_step */
 
+#ifndef arch_ptrace_stop_needed
+/**
+ * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called
+ * @code:	current->exit_code value ptrace will stop with
+ * @info:	siginfo_t pointer (or %NULL) for signal ptrace will stop with
+ *
+ * This is called with the siglock held, to decide whether or not it's
+ * necessary to release the siglock and call arch_ptrace_stop() with the
+ * same @code and @info arguments.  It can be defined to a constant if
+ * arch_ptrace_stop() is never required, or always is.  On machines where
+ * this makes sense, it should be defined to a quick test to optimize out
+ * calling arch_ptrace_stop() when it would be superfluous.  For example,
+ * if the thread has not been back to user mode since the last stop, the
+ * thread state might indicate that nothing needs to be done.
+ */
+#define arch_ptrace_stop_needed(code, info)	(0)
+#endif
+
+#ifndef arch_ptrace_stop
+/**
+ * arch_ptrace_stop - Do machine-specific work before stopping for ptrace
+ * @code:	current->exit_code value ptrace will stop with
+ * @info:	siginfo_t pointer (or %NULL) for signal ptrace will stop with
+ *
+ * This is called with no locks held when arch_ptrace_stop_needed() has
+ * just returned nonzero.  It is allowed to block, e.g. for user memory
+ * access.  The arch can have machine-specific work to be done before
+ * ptrace stops.  On ia64, register backing store gets written back to user
+ * memory here.  Since this can be costly (requires dropping the siglock),
+ * we only do it when the arch requires it for this particular stop, as
+ * indicated by arch_ptrace_stop_needed().
+ */
+#define arch_ptrace_stop(code, info)		do { } while (0)
+#endif
+
 #endif
 
 #endif
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 306a1d1a..e51b531 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -244,6 +244,8 @@
 	 */
 	unsigned long daemon_lastrun; /* jiffies of last run */
 	unsigned long daemon_sleep; /* how many seconds between updates? */
+	unsigned long last_end_sync; /* when we lasted called end_sync to
+				      * update bitmap with resync progress */
 
 	atomic_t pending_writes; /* pending writes to the bitmap file */
 	wait_queue_head_t write_wait;
@@ -275,6 +277,7 @@
 int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int degraded);
 void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
 void bitmap_close_sync(struct bitmap *bitmap);
+void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector);
 
 void bitmap_unplug(struct bitmap *bitmap);
 void bitmap_daemon_work(struct bitmap *bitmap);
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index dcb7292..85a068b 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -81,6 +81,8 @@
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
 #define	BarriersNotsupp	5		/* BIO_RW_BARRIER is not supported */
+#define	AllReserved	6		/* If whole device is reserved for
+					 * one array */
 
 	int desc_nr;			/* descriptor index in the superblock */
 	int raid_disk;			/* role of device in array */
@@ -130,6 +132,9 @@
 					minor_version,
 					patch_version;
 	int				persistent;
+	int 				external;	/* metadata is
+							 * managed externally */
+	char				metadata_type[17]; /* externally set*/
 	int				chunk_size;
 	time_t				ctime, utime;
 	int				level, layout;
@@ -216,6 +221,8 @@
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
 	sector_t			recovery_cp;
+	sector_t			resync_max;	/* resync should pause
+							 * when it gets here */
 
 	spinlock_t			write_lock;
 	wait_queue_head_t		sb_wait;	/* for waiting on superblock updates */
@@ -306,23 +313,17 @@
  * iterates through some rdev ringlist. It's safe to remove the
  * current 'rdev'. Dont touch 'tmp' though.
  */
-#define ITERATE_RDEV_GENERIC(head,rdev,tmp)				\
+#define rdev_for_each_list(rdev, tmp, list)				\
 									\
-	for ((tmp) = (head).next;					\
+	for ((tmp) = (list).next;					\
 		(rdev) = (list_entry((tmp), mdk_rdev_t, same_set)),	\
-			(tmp) = (tmp)->next, (tmp)->prev != &(head)	\
+			(tmp) = (tmp)->next, (tmp)->prev != &(list)	\
 		; )
 /*
  * iterates through the 'same array disks' ringlist
  */
-#define ITERATE_RDEV(mddev,rdev,tmp)					\
-	ITERATE_RDEV_GENERIC((mddev)->disks,rdev,tmp)
-
-/*
- * Iterates through 'pending RAID disks'
- */
-#define ITERATE_RDEV_PENDING(rdev,tmp)					\
-	ITERATE_RDEV_GENERIC(pending_raid_disks,rdev,tmp)
+#define rdev_for_each(rdev, tmp, mddev)				\
+	rdev_for_each_list(rdev, tmp, (mddev)->disks)
 
 typedef struct mdk_thread_s {
 	void			(*run) (mddev_t *mddev);
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index d32c14d..37a642c 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -174,10 +174,13 @@
  * code.
  */
 
-#define rcu_assign_pointer(p, v)	({ \
-						smp_wmb(); \
-						(p) = (v); \
-					})
+#define rcu_assign_pointer(p, v) \
+	({ \
+		if (!__builtin_constant_p(v) || \
+		    ((v) != NULL)) \
+			smp_wmb(); \
+		(p) = (v); \
+	})
 
 /**
  * synchronize_sched - block until all CPUs have exited any non-preemptive
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9c13be3..7c8ca05 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -810,7 +810,7 @@
 
 struct io_context;			/* See blkdev.h */
 #define NGROUPS_SMALL		32
-#define NGROUPS_PER_BLOCK	((int)(PAGE_SIZE / sizeof(gid_t)))
+#define NGROUPS_PER_BLOCK	((unsigned int)(PAGE_SIZE / sizeof(gid_t)))
 struct group_info {
 	int ngroups;
 	atomic_t usage;
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 0ae3388..7e09514 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -371,6 +371,8 @@
 	(!siginmask(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \
 	 (t)->sighand->action[(signr)-1].sa.sa_handler == SIG_DFL)
 
+void signals_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 9e3aaad..932a9ef 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -70,6 +70,8 @@
 #define SM501FB_FLAG_DISABLE_AT_EXIT	(1<<1)
 #define SM501FB_FLAG_USE_HWCURSOR	(1<<2)
 #define SM501FB_FLAG_USE_HWACCEL	(1<<3)
+#define SM501FB_FLAG_PANEL_USE_FPEN	(1<<4)
+#define SM501FB_FLAG_PANEL_USE_VBIASEN	(1<<5)
 
 struct sm501_platdata_fbsub {
 	struct fb_videomode	*def_mode;
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index e18f5c2..9d5da8b 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -373,6 +373,15 @@
 	if (sdev->bus->bustype == SSB_BUSTYPE_PCI)
 		pci_set_power_state(sdev->bus->host_pci, state);
 }
+#else
+static inline void ssb_pcihost_unregister(struct pci_driver *driver)
+{
+}
+
+static inline
+void ssb_pcihost_set_power_state(struct ssb_device *sdev, pci_power_t state)
+{
+}
 #endif /* CONFIG_SSB_PCIHOST */
 
 
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 24c6a2b..8ea3e71 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -244,6 +244,8 @@
 /* Don't use! Compatibility define for existing users. */
 #define tickadj	(500/HZ ? : 1)
 
+int read_current_timer(unsigned long *timer_val);
+
 #endif /* KERNEL */
 
 #endif /* LINUX_TIMEX_H */
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 402de89..5824a97 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -74,7 +74,6 @@
 
 struct tty_bufhead {
 	struct delayed_work work;
-	struct semaphore pty_sem;
 	spinlock_t lock;
 	struct tty_buffer *head;	/* Queue head */
 	struct tty_buffer *tail;	/* Active buffer */
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index feb5e99..9448ffb 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -77,6 +77,7 @@
 void reset_vc(struct vc_data *vc);
 extern int unbind_con_driver(const struct consw *csw, int first, int last,
 			     int deflt);
+int vty_init(void);
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
diff --git a/include/linux/w1-gpio.h b/include/linux/w1-gpio.h
new file mode 100644
index 0000000..9797fec
--- /dev/null
+++ b/include/linux/w1-gpio.h
@@ -0,0 +1,23 @@
+/*
+ * w1-gpio interface to platform code
+ *
+ * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi>
+ *
+ * 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.
+ */
+#ifndef _LINUX_W1_GPIO_H
+#define _LINUX_W1_GPIO_H
+
+/**
+ * struct w1_gpio_platform_data - Platform-dependent data for w1-gpio
+ * @pin: GPIO pin to use
+ * @is_open_drain: GPIO pin is configured as open drain
+ */
+struct w1_gpio_platform_data {
+	unsigned int pin;
+	unsigned int is_open_drain:1;
+};
+
+#endif /* _LINUX_W1_GPIO_H */
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
index 4eea637..336c20d 100644
--- a/include/video/atmel_lcdc.h
+++ b/include/video/atmel_lcdc.h
@@ -22,7 +22,7 @@
 #ifndef __ATMEL_LCDC_H__
 #define __ATMEL_LCDC_H__
 
- /* LCD Controller info data structure */
+ /* LCD Controller info data structure, stored in device platform_data */
 struct atmel_lcdfb_info {
 	spinlock_t		lock;
 	struct fb_info		*info;
@@ -33,7 +33,14 @@
 	struct platform_device	*pdev;
 	struct clk		*bus_clk;
 	struct clk		*lcdc_clk;
-	unsigned int		default_bpp;
+
+#ifdef CONFIG_BACKLIGHT_ATMEL_LCDC
+	struct backlight_device	*backlight;
+	u8			bl_power;
+#endif
+	bool			lcdcon_is_backlight;
+
+	u8			default_bpp;
 	unsigned int		default_lcdcon2;
 	unsigned int		default_dmacon;
 	void (*atmel_lcdfb_power_control)(int on);
@@ -115,20 +122,20 @@
 #define		ATMEL_LCDC_MEMOR_LITTLE		(1 << 31)
 
 #define ATMEL_LCDC_TIM1		0x0808
-#define	ATMEL_LCDC_VFP		(0xff <<  0)
+#define	ATMEL_LCDC_VFP		(0xffU <<  0)
 #define	ATMEL_LCDC_VBP_OFFSET		8
-#define	ATMEL_LCDC_VBP		(0xff <<  ATMEL_LCDC_VBP_OFFSET)
+#define	ATMEL_LCDC_VBP		(0xffU <<  ATMEL_LCDC_VBP_OFFSET)
 #define	ATMEL_LCDC_VPW_OFFSET		16
-#define	ATMEL_LCDC_VPW		(0x3f << ATMEL_LCDC_VPW_OFFSET)
+#define	ATMEL_LCDC_VPW		(0x3fU << ATMEL_LCDC_VPW_OFFSET)
 #define	ATMEL_LCDC_VHDLY_OFFSET		24
-#define	ATMEL_LCDC_VHDLY	(0xf  << ATMEL_LCDC_VHDLY_OFFSET)
+#define	ATMEL_LCDC_VHDLY	(0xfU  << ATMEL_LCDC_VHDLY_OFFSET)
 
 #define ATMEL_LCDC_TIM2		0x080c
-#define	ATMEL_LCDC_HBP		(0xff  <<  0)
+#define	ATMEL_LCDC_HBP		(0xffU  <<  0)
 #define	ATMEL_LCDC_HPW_OFFSET		8
-#define	ATMEL_LCDC_HPW		(0x3f  <<  ATMEL_LCDC_HPW_OFFSET)
+#define	ATMEL_LCDC_HPW		(0x3fU  <<  ATMEL_LCDC_HPW_OFFSET)
 #define	ATMEL_LCDC_HFP_OFFSET		21
-#define	ATMEL_LCDC_HFP		(0x7ff << ATMEL_LCDC_HFP_OFFSET)
+#define	ATMEL_LCDC_HFP		(0x7ffU << ATMEL_LCDC_HFP_OFFSET)
 
 #define ATMEL_LCDC_LCDFRMCFG	0x0810
 #define	ATMEL_LCDC_LINEVAL	(0x7ff <<  0)
diff --git a/init/calibrate.c b/init/calibrate.c
index 2d3d73b..ecb3822 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -7,8 +7,7 @@
 #include <linux/jiffies.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-
-#include <asm/timex.h>
+#include <linux/timex.h>
 
 unsigned long preset_lpj;
 static int __init lpj_setup(char *str)
@@ -29,7 +28,7 @@
 #define DELAY_CALIBRATION_TICKS			((HZ < 100) ? 1 : (HZ/100))
 #define MAX_DIRECT_CALIBRATION_RETRIES		5
 
-static unsigned long __devinit calibrate_delay_direct(void)
+static unsigned long __cpuinit calibrate_delay_direct(void)
 {
 	unsigned long pre_start, start, post_start;
 	unsigned long pre_end, end, post_end;
@@ -102,7 +101,7 @@
 	return 0;
 }
 #else
-static unsigned long __devinit calibrate_delay_direct(void) {return 0;}
+static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
 #endif
 
 /*
@@ -112,7 +111,7 @@
  */
 #define LPS_PREC 8
 
-void __devinit calibrate_delay(void)
+void __cpuinit calibrate_delay(void)
 {
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 1161dfd..f865731 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -11,6 +11,7 @@
 #include <linux/mount.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/fs.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -18,8 +19,6 @@
 
 #include "do_mounts.h"
 
-extern int get_filesystem_list(char * buf);
-
 int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
 
 int root_mountflags = MS_RDONLY | MS_SILENT;
diff --git a/init/initramfs.c b/init/initramfs.c
index 1db02a0..d53fee8 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -503,7 +503,6 @@
 __setup("retain_initrd", retain_initrd_param);
 
 extern char __initramfs_start[], __initramfs_end[];
-#ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/initrd.h>
 #include <linux/kexec.h>
 
@@ -539,15 +538,12 @@
 	initrd_end = 0;
 }
 
-#endif
-
 static int __init populate_rootfs(void)
 {
 	char *err = unpack_to_rootfs(__initramfs_start,
 			 __initramfs_end - __initramfs_start, 0);
 	if (err)
 		panic(err);
-#ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start) {
 #ifdef CONFIG_BLK_DEV_RAM
 		int fd;
@@ -579,7 +575,6 @@
 		free_initrd();
 #endif
 	}
-#endif
 	return 0;
 }
 rootfs_initcall(populate_rootfs);
diff --git a/init/main.c b/init/main.c
index cb81ed1..c691f5f 100644
--- a/init/main.c
+++ b/init/main.c
@@ -57,6 +57,7 @@
 #include <linux/device.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/signal.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -83,7 +84,6 @@
 extern void fork_init(unsigned long);
 extern void mca_init(void);
 extern void sbus_init(void);
-extern void signals_init(void);
 extern void pidhash_init(void);
 extern void pidmap_init(void);
 extern void prio_tree_init(void);
diff --git a/ipc/msg.c b/ipc/msg.c
index fdf3db5..ec0c724 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -105,6 +105,7 @@
 void msg_exit_ns(struct ipc_namespace *ns)
 {
 	struct msg_queue *msq;
+	struct kern_ipc_perm *perm;
 	int next_id;
 	int total, in_use;
 
@@ -113,10 +114,11 @@
 	in_use = msg_ids(ns).in_use;
 
 	for (total = 0, next_id = 0; total < in_use; next_id++) {
-		msq = idr_find(&msg_ids(ns).ipcs_idr, next_id);
-		if (msq == NULL)
+		perm = idr_find(&msg_ids(ns).ipcs_idr, next_id);
+		if (perm == NULL)
 			continue;
-		ipc_lock_by_ptr(&msq->q_perm);
+		ipc_lock_by_ptr(perm);
+		msq = container_of(perm, struct msg_queue, q_perm);
 		freeque(ns, msq);
 		total++;
 	}
@@ -144,6 +146,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check_down(&msg_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct msg_queue *)ipcp;
+
 	return container_of(ipcp, struct msg_queue, q_perm);
 }
 
@@ -155,6 +160,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock(&msg_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct msg_queue *)ipcp;
+
 	return container_of(ipcp, struct msg_queue, q_perm);
 }
 
@@ -163,6 +171,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check(&msg_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct msg_queue *)ipcp;
+
 	return container_of(ipcp, struct msg_queue, q_perm);
 }
 
diff --git a/ipc/sem.c b/ipc/sem.c
index 35952c0..d65e285 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -143,6 +143,7 @@
 void sem_exit_ns(struct ipc_namespace *ns)
 {
 	struct sem_array *sma;
+	struct kern_ipc_perm *perm;
 	int next_id;
 	int total, in_use;
 
@@ -151,10 +152,11 @@
 	in_use = sem_ids(ns).in_use;
 
 	for (total = 0, next_id = 0; total < in_use; next_id++) {
-		sma = idr_find(&sem_ids(ns).ipcs_idr, next_id);
-		if (sma == NULL)
+		perm = idr_find(&sem_ids(ns).ipcs_idr, next_id);
+		if (perm == NULL)
 			continue;
-		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_lock_by_ptr(perm);
+		sma = container_of(perm, struct sem_array, sem_perm);
 		freeary(ns, sma);
 		total++;
 	}
@@ -181,6 +183,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct sem_array *)ipcp;
+
 	return container_of(ipcp, struct sem_array, sem_perm);
 }
 
@@ -192,6 +197,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock(&sem_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct sem_array *)ipcp;
+
 	return container_of(ipcp, struct sem_array, sem_perm);
 }
 
@@ -200,6 +208,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check(&sem_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct sem_array *)ipcp;
+
 	return container_of(ipcp, struct sem_array, sem_perm);
 }
 
diff --git a/ipc/shm.c b/ipc/shm.c
index 3818fae..65c3a29 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -111,6 +111,7 @@
 void shm_exit_ns(struct ipc_namespace *ns)
 {
 	struct shmid_kernel *shp;
+	struct kern_ipc_perm *perm;
 	int next_id;
 	int total, in_use;
 
@@ -119,10 +120,11 @@
 	in_use = shm_ids(ns).in_use;
 
 	for (total = 0, next_id = 0; total < in_use; next_id++) {
-		shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
-		if (shp == NULL)
+		perm = idr_find(&shm_ids(ns).ipcs_idr, next_id);
+		if (perm == NULL)
 			continue;
-		ipc_lock_by_ptr(&shp->shm_perm);
+		ipc_lock_by_ptr(perm);
+		shp = container_of(perm, struct shmid_kernel, shm_perm);
 		do_shm_rmid(ns, shp);
 		total++;
 	}
@@ -149,6 +151,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_down(&shm_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct shmid_kernel *)ipcp;
+
 	return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -158,6 +163,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check_down(&shm_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct shmid_kernel *)ipcp;
+
 	return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -169,6 +177,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct shmid_kernel *)ipcp;
+
 	return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
@@ -177,6 +188,9 @@
 {
 	struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id);
 
+	if (IS_ERR(ipcp))
+		return (struct shmid_kernel *)ipcp;
+
 	return container_of(ipcp, struct shmid_kernel, shm_perm);
 }
 
diff --git a/ipc/util.c b/ipc/util.c
index 1aa0ebf..76c1f34 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -802,8 +802,8 @@
 /*
  * This routine locks the ipc structure found at least at position pos.
  */
-struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
-					loff_t *new_pos)
+static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
+					      loff_t *new_pos)
 {
 	struct kern_ipc_perm *ipc;
 	int total, id;
diff --git a/kernel/exit.c b/kernel/exit.c
index 9d3d0f0..eb9934a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1590,8 +1590,6 @@
 					goto repeat;
 				if (retval != 0) /* He released the lock.  */
 					goto end;
-			} else if (p->exit_state == EXIT_DEAD) {
-				continue;
 			} else if (p->exit_state == EXIT_ZOMBIE) {
 				/*
 				 * Eligible but we cannot release it yet:
@@ -1606,7 +1604,7 @@
 				/* He released the lock.  */
 				if (retval != 0)
 					goto end;
-			} else {
+			} else if (p->exit_state != EXIT_DEAD) {
 check_continued:
 				/*
 				 * It's running now, so it might later
diff --git a/kernel/fork.c b/kernel/fork.c
index 2b55b74..3995297 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1399,7 +1399,7 @@
 	return ERR_PTR(retval);
 }
 
-noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
+noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
 {
 	memset(regs, 0, sizeof(struct pt_regs));
 	return regs;
@@ -1510,7 +1510,7 @@
 		if (!(clone_flags & CLONE_STOPPED))
 			wake_up_new_task(p, clone_flags);
 		else
-			p->state = TASK_STOPPED;
+			__set_task_state(p, TASK_STOPPED);
 
 		if (unlikely (trace)) {
 			current->ptrace_message = nr;
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 7dadc71..f091d13 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -53,14 +53,6 @@
 	return 0;
 }
 
-static inline int is_kernel_extratext(unsigned long addr)
-{
-	if (addr >= (unsigned long)_sextratext
-	    && addr <= (unsigned long)_eextratext)
-		return 1;
-	return 0;
-}
-
 static inline int is_kernel_text(unsigned long addr)
 {
 	if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)
@@ -80,8 +72,7 @@
 	if (all_var)
 		return is_kernel(addr);
 
-	return is_kernel_text(addr) || is_kernel_inittext(addr) ||
-		is_kernel_extratext(addr);
+	return is_kernel_text(addr) || is_kernel_inittext(addr);
 }
 
 /* expand a compressed symbol data into the resulting uncompressed string,
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d0493ea..7a86e64 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -699,6 +699,12 @@
 				 struct kretprobe_instance, uflist);
 		ri->rp = rp;
 		ri->task = current;
+
+		if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+			spin_unlock_irqrestore(&kretprobe_lock, flags);
+			return 0;
+		}
+
 		arch_prepare_kretprobe(ri, regs);
 
 		/* XXX(hch): why is there no hlist_move_head? */
@@ -745,7 +751,8 @@
 	INIT_HLIST_HEAD(&rp->used_instances);
 	INIT_HLIST_HEAD(&rp->free_instances);
 	for (i = 0; i < rp->maxactive; i++) {
-		inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
+		inst = kmalloc(sizeof(struct kretprobe_instance) +
+			       rp->data_size, GFP_KERNEL);
 		if (inst == NULL) {
 			free_rp_inst(rp);
 			return -ENOMEM;
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 4253f47..643360d 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -4,6 +4,7 @@
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
 #include <linux/vmalloc.h>
+#include <linux/reboot.h>
 
 /*
  *	Notifier list for kernel code which wants to be called
diff --git a/kernel/params.c b/kernel/params.c
index 42fe5e6..e28c706 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -272,7 +272,7 @@
 		       unsigned int min, unsigned int max,
 		       void *elem, int elemsize,
 		       int (*set)(const char *, struct kernel_param *kp),
-		       int *num)
+		       unsigned int *num)
 {
 	int ret;
 	struct kernel_param kp;
diff --git a/kernel/printk.c b/kernel/printk.c
index 29ae1e99..4a09062 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -93,16 +93,16 @@
  */
 static DEFINE_SPINLOCK(logbuf_lock);
 
-#define LOG_BUF_MASK	(log_buf_len-1)
+#define LOG_BUF_MASK (log_buf_len-1)
 #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
 
 /*
  * The indices into log_buf are not constrained to log_buf_len - they
  * must be masked before subscripting
  */
-static unsigned long log_start;	/* Index into log_buf: next char to be read by syslog() */
-static unsigned long con_start;	/* Index into log_buf: next char to be sent to consoles */
-static unsigned long log_end;	/* Index into log_buf: most-recently-written-char + 1 */
+static unsigned log_start;	/* Index into log_buf: next char to be read by syslog() */
+static unsigned con_start;	/* Index into log_buf: next char to be sent to consoles */
+static unsigned log_end;	/* Index into log_buf: most-recently-written-char + 1 */
 
 /*
  *	Array of consoles built from command line options (console=)
@@ -128,17 +128,17 @@
 static char __log_buf[__LOG_BUF_LEN];
 static char *log_buf = __log_buf;
 static int log_buf_len = __LOG_BUF_LEN;
-static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
+static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
 
 static int __init log_buf_len_setup(char *str)
 {
-	unsigned long size = memparse(str, &str);
+	unsigned size = memparse(str, &str);
 	unsigned long flags;
 
 	if (size)
 		size = roundup_pow_of_two(size);
 	if (size > log_buf_len) {
-		unsigned long start, dest_idx, offset;
+		unsigned start, dest_idx, offset;
 		char *new_log_buf;
 
 		new_log_buf = alloc_bootmem(size);
@@ -295,7 +295,7 @@
  */
 int do_syslog(int type, char __user *buf, int len)
 {
-	unsigned long i, j, limit, count;
+	unsigned i, j, limit, count;
 	int do_clear = 0;
 	char c;
 	int error = 0;
@@ -436,7 +436,7 @@
 /*
  * Call the console drivers on a range of log_buf
  */
-static void __call_console_drivers(unsigned long start, unsigned long end)
+static void __call_console_drivers(unsigned start, unsigned end)
 {
 	struct console *con;
 
@@ -463,8 +463,8 @@
 /*
  * Write out chars from start to end - 1 inclusive
  */
-static void _call_console_drivers(unsigned long start,
-				unsigned long end, int msg_log_level)
+static void _call_console_drivers(unsigned start,
+				unsigned end, int msg_log_level)
 {
 	if ((msg_log_level < console_loglevel || ignore_loglevel) &&
 			console_drivers && start != end) {
@@ -484,12 +484,12 @@
  * log_buf[start] to log_buf[end - 1].
  * The console_sem must be held.
  */
-static void call_console_drivers(unsigned long start, unsigned long end)
+static void call_console_drivers(unsigned start, unsigned end)
 {
-	unsigned long cur_index, start_print;
+	unsigned cur_index, start_print;
 	static int msg_level = -1;
 
-	BUG_ON(((long)(start - end)) > 0);
+	BUG_ON(((int)(start - end)) > 0);
 
 	cur_index = start;
 	start_print = start;
@@ -790,7 +790,7 @@
 	return -ENOSYS;
 }
 
-static void call_console_drivers(unsigned long start, unsigned long end)
+static void call_console_drivers(unsigned start, unsigned end)
 {
 }
 
@@ -983,8 +983,8 @@
 void release_console_sem(void)
 {
 	unsigned long flags;
-	unsigned long _con_start, _log_end;
-	unsigned long wake_klogd = 0;
+	unsigned _con_start, _log_end;
+	unsigned wake_klogd = 0;
 
 	if (console_suspended) {
 		up(&secondary_console_sem);
@@ -1275,7 +1275,7 @@
 int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
 {
 	static DEFINE_SPINLOCK(ratelimit_lock);
-	static unsigned long toks = 10 * 5 * HZ;
+	static unsigned toks = 10 * 5 * HZ;
 	static unsigned long last_msg;
 	static int missed;
 	unsigned long flags;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index b0d4ab4..628b03a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -20,6 +20,7 @@
 #include <linux/signal.h>
 #include <linux/audit.h>
 #include <linux/pid_namespace.h>
+#include <linux/syscalls.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -53,7 +54,7 @@
 	spin_lock(&child->sighand->siglock);
 	if (task_is_traced(child)) {
 		if (child->signal->flags & SIGNAL_STOP_STOPPED) {
-			child->state = TASK_STOPPED;
+			__set_task_state(child, TASK_STOPPED);
 		} else {
 			signal_wake_up(child, 1);
 		}
@@ -103,18 +104,16 @@
 	    && child->signal != NULL) {
 		ret = 0;
 		spin_lock_irq(&child->sighand->siglock);
-		if (task_is_stopped(child)) {
+		if (task_is_stopped(child))
 			child->state = TASK_TRACED;
-		} else if (!task_is_traced(child) && !kill) {
+		else if (!task_is_traced(child) && !kill)
 			ret = -ESRCH;
-		}
 		spin_unlock_irq(&child->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
 
-	if (!ret && !kill) {
+	if (!ret && !kill)
 		wait_task_inactive(child);
-	}
 
 	/* All systems go.. */
 	return ret;
diff --git a/kernel/relay.c b/kernel/relay.c
index 7c03733..d080b9d 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -37,37 +37,31 @@
 }
 
 /*
- * nopage() vm_op implementation for relay file mapping.
+ * fault() vm_op implementation for relay file mapping.
  */
-static struct page *relay_buf_nopage(struct vm_area_struct *vma,
-				     unsigned long address,
-				     int *type)
+static int relay_buf_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct page *page;
 	struct rchan_buf *buf = vma->vm_private_data;
-	unsigned long offset = address - vma->vm_start;
+	pgoff_t pgoff = vmf->pgoff;
 
-	if (address > vma->vm_end)
-		return NOPAGE_SIGBUS; /* Disallow mremap */
 	if (!buf)
-		return NOPAGE_OOM;
+		return VM_FAULT_OOM;
 
-	page = vmalloc_to_page(buf->start + offset);
+	page = vmalloc_to_page(buf->start + (pgoff << PAGE_SHIFT));
 	if (!page)
-		return NOPAGE_OOM;
+		return VM_FAULT_SIGBUS;
 	get_page(page);
+	vmf->page = page;
 
-	if (type)
-		*type = VM_FAULT_MINOR;
-
-	return page;
+	return 0;
 }
 
 /*
  * vm_ops for relay file mappings.
  */
 static struct vm_operations_struct relay_file_mmap_ops = {
-	.nopage = relay_buf_nopage,
+	.fault = relay_buf_fault,
 	.close = relay_file_mmap_close,
 };
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 6a5f97c..5d30ff5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1578,6 +1578,17 @@
 }
 
 /*
+ * Return nonzero if there is a SIGKILL that should be waking us up.
+ * Called with the siglock held.
+ */
+static int sigkill_pending(struct task_struct *tsk)
+{
+	return ((sigismember(&tsk->pending.signal, SIGKILL) ||
+		 sigismember(&tsk->signal->shared_pending.signal, SIGKILL)) &&
+		!unlikely(sigismember(&tsk->blocked, SIGKILL)));
+}
+
+/*
  * This must be called with current->sighand->siglock held.
  *
  * This should be the path for all ptrace stops.
@@ -1590,6 +1601,26 @@
  */
 static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
 {
+	int killed = 0;
+
+	if (arch_ptrace_stop_needed(exit_code, info)) {
+		/*
+		 * The arch code has something special to do before a
+		 * ptrace stop.  This is allowed to block, e.g. for faults
+		 * on user stack pages.  We can't keep the siglock while
+		 * calling arch_ptrace_stop, so we must release it now.
+		 * To preserve proper semantics, we must do this before
+		 * any signal bookkeeping like checking group_stop_count.
+		 * Meanwhile, a SIGKILL could come in before we retake the
+		 * siglock.  That must prevent us from sleeping in TASK_TRACED.
+		 * So after regaining the lock, we must check for SIGKILL.
+		 */
+		spin_unlock_irq(&current->sighand->siglock);
+		arch_ptrace_stop(exit_code, info);
+		spin_lock_irq(&current->sighand->siglock);
+		killed = sigkill_pending(current);
+	}
+
 	/*
 	 * If there is a group stop in progress,
 	 * we must participate in the bookkeeping.
@@ -1601,11 +1632,11 @@
 	current->exit_code = exit_code;
 
 	/* Let the debugger run.  */
-	set_current_state(TASK_TRACED);
+	__set_current_state(TASK_TRACED);
 	spin_unlock_irq(&current->sighand->siglock);
 	try_to_freeze();
 	read_lock(&tasklist_lock);
-	if (may_ptrace_stop()) {
+	if (!unlikely(killed) && may_ptrace_stop()) {
 		do_notify_parent_cldstop(current, CLD_TRAPPED);
 		read_unlock(&tasklist_lock);
 		schedule();
diff --git a/kernel/srcu.c b/kernel/srcu.c
index 3507cabe..b0aeeaf 100644
--- a/kernel/srcu.c
+++ b/kernel/srcu.c
@@ -74,7 +74,7 @@
  * severe errors when invoked on an active srcu_struct.  That said, it
  * can be useful as an error check at cleanup time.
  */
-int srcu_readers_active(struct srcu_struct *sp)
+static int srcu_readers_active(struct srcu_struct *sp)
 {
 	return srcu_readers_active_idx(sp, 0) + srcu_readers_active_idx(sp, 1);
 }
@@ -255,4 +255,3 @@
 EXPORT_SYMBOL_GPL(srcu_read_unlock);
 EXPORT_SYMBOL_GPL(synchronize_srcu);
 EXPORT_SYMBOL_GPL(srcu_batches_completed);
-EXPORT_SYMBOL_GPL(srcu_readers_active);
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 51b5ee5..6f4e0e1 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -29,7 +29,6 @@
 static enum stopmachine_state stopmachine_state;
 static unsigned int stopmachine_num_threads;
 static atomic_t stopmachine_thread_ack;
-static DECLARE_MUTEX(stopmachine_mutex);
 
 static int stopmachine(void *cpu)
 {
@@ -170,6 +169,7 @@
 struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
 				       unsigned int cpu)
 {
+	static DEFINE_MUTEX(stopmachine_mutex);
 	struct stop_machine_data smdata;
 	struct task_struct *p;
 
@@ -177,7 +177,7 @@
 	smdata.data = data;
 	init_completion(&smdata.done);
 
-	down(&stopmachine_mutex);
+	mutex_lock(&stopmachine_mutex);
 
 	/* If they don't care which CPU fn runs on, bind to any online one. */
 	if (cpu == NR_CPUS)
@@ -193,7 +193,7 @@
 		wake_up_process(p);
 		wait_for_completion(&smdata.done);
 	}
-	up(&stopmachine_mutex);
+	mutex_unlock(&stopmachine_mutex);
 	return p;
 }
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 53de35f..e3c08d4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1145,16 +1145,16 @@
     struct group_info *group_info)
 {
 	int i;
-	int count = group_info->ngroups;
+	unsigned int count = group_info->ngroups;
 
 	for (i = 0; i < group_info->nblocks; i++) {
-		int cp_count = min(NGROUPS_PER_BLOCK, count);
-		int off = i * NGROUPS_PER_BLOCK;
-		int len = cp_count * sizeof(*grouplist);
+		unsigned int cp_count = min(NGROUPS_PER_BLOCK, count);
+		unsigned int len = cp_count * sizeof(*grouplist);
 
-		if (copy_to_user(grouplist+off, group_info->blocks[i], len))
+		if (copy_to_user(grouplist, group_info->blocks[i], len))
 			return -EFAULT;
 
+		grouplist += NGROUPS_PER_BLOCK;
 		count -= cp_count;
 	}
 	return 0;
@@ -1165,16 +1165,16 @@
     gid_t __user *grouplist)
 {
 	int i;
-	int count = group_info->ngroups;
+	unsigned int count = group_info->ngroups;
 
 	for (i = 0; i < group_info->nblocks; i++) {
-		int cp_count = min(NGROUPS_PER_BLOCK, count);
-		int off = i * NGROUPS_PER_BLOCK;
-		int len = cp_count * sizeof(*grouplist);
+		unsigned int cp_count = min(NGROUPS_PER_BLOCK, count);
+		unsigned int len = cp_count * sizeof(*grouplist);
 
-		if (copy_from_user(group_info->blocks[i], grouplist+off, len))
+		if (copy_from_user(group_info->blocks[i], grouplist, len))
 			return -EFAULT;
 
+		grouplist += NGROUPS_PER_BLOCK;
 		count -= cp_count;
 	}
 	return 0;
@@ -1472,7 +1472,7 @@
 	if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
 	    !capable(CAP_SYS_RESOURCE))
 		return -EPERM;
-	if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN)
+	if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
 		return -EPERM;
 
 	retval = security_task_setrlimit(resource, &new_rlim);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5e2ad5b..86daaa2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1203,6 +1203,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nr_open",
+		.data		= &sysctl_nr_open,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= FS_DENTRY,
 		.procname	= "dentry-state",
 		.data		= &dentry_stat,
diff --git a/kernel/test_kprobes.c b/kernel/test_kprobes.c
index 88cdb10..06b6395 100644
--- a/kernel/test_kprobes.c
+++ b/kernel/test_kprobes.c
@@ -135,6 +135,12 @@
 #ifdef CONFIG_KRETPROBES
 static u32 krph_val;
 
+static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+	krph_val = (rand1 / div_factor);
+	return 0;
+}
+
 static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
 	unsigned long ret = regs_return_value(regs);
@@ -144,13 +150,19 @@
 		printk(KERN_ERR "Kprobe smoke test failed: "
 				"incorrect value in kretprobe handler\n");
 	}
+	if (krph_val == 0) {
+		handler_errors++;
+		printk(KERN_ERR "Kprobe smoke test failed: "
+				"call to kretprobe entry handler failed\n");
+	}
 
-	krph_val = (rand1 / div_factor);
+	krph_val = rand1;
 	return 0;
 }
 
 static struct kretprobe rp = {
 	.handler	= return_handler,
+	.entry_handler  = entry_handler,
 	.kp.symbol_name = "kprobe_target"
 };
 
@@ -167,7 +179,7 @@
 
 	ret = kprobe_target(rand1);
 	unregister_kretprobe(&rp);
-	if (krph_val == 0) {
+	if (krph_val != rand1) {
 		printk(KERN_ERR "Kprobe smoke test failed: "
 				"kretprobe handler not called\n");
 		handler_errors++;
diff --git a/kernel/time.c b/kernel/time.c
index 4064c05..33af3e5 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -566,7 +566,11 @@
 clock_t jiffies_to_clock_t(long x)
 {
 #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+# if HZ < USER_HZ
+	return x * (USER_HZ / HZ);
+# else
 	return x / (HZ / USER_HZ);
+# endif
 #else
 	u64 tmp = (u64)x * TICK_NSEC;
 	do_div(tmp, (NSEC_PER_SEC / USER_HZ));
@@ -599,7 +603,14 @@
 u64 jiffies_64_to_clock_t(u64 x)
 {
 #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
+# if HZ < USER_HZ
+	x *= USER_HZ;
+	do_div(x, HZ);
+# elif HZ > USER_HZ
 	do_div(x, HZ / USER_HZ);
+# else
+	/* Nothing to do */
+# endif
 #else
 	/*
 	 * There are better ways that don't overflow early,
@@ -611,7 +622,6 @@
 #endif
 	return x;
 }
-
 EXPORT_SYMBOL(jiffies_64_to_clock_t);
 
 u64 nsec_to_clock_t(u64 x)
@@ -646,7 +656,6 @@
 	} while (read_seqretry(&xtime_lock, seq));
 	return ret;
 }
-
 EXPORT_SYMBOL(get_jiffies_64);
 #endif
 
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 6e9259a..81afb39 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -363,15 +363,13 @@
 static ssize_t
 sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
 {
-	char *curr = buf;
+	ssize_t count = 0;
 
 	spin_lock_irq(&clocksource_lock);
-	curr += sprintf(curr, "%s ", curr_clocksource->name);
+	count = snprintf(buf, PAGE_SIZE, "%s\n", curr_clocksource->name);
 	spin_unlock_irq(&clocksource_lock);
 
-	curr += sprintf(curr, "\n");
-
-	return curr - buf;
+	return count;
 }
 
 /**
@@ -439,17 +437,20 @@
 sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
 {
 	struct clocksource *src;
-	char *curr = buf;
+	ssize_t count = 0;
 
 	spin_lock_irq(&clocksource_lock);
 	list_for_each_entry(src, &clocksource_list, list) {
-		curr += sprintf(curr, "%s ", src->name);
+		count += snprintf(buf + count,
+				  max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
+				  "%s ", src->name);
 	}
 	spin_unlock_irq(&clocksource_lock);
 
-	curr += sprintf(curr, "\n");
+	count += snprintf(buf + count,
+			  max((ssize_t)PAGE_SIZE - count, (ssize_t)0), "\n");
 
-	return curr - buf;
+	return count;
 }
 
 /*
diff --git a/kernel/timer.c b/kernel/timer.c
index 9fbb472..70b29b5 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -818,12 +818,14 @@
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 void account_process_tick(struct task_struct *p, int user_tick)
 {
+	cputime_t one_jiffy = jiffies_to_cputime(1);
+
 	if (user_tick) {
-		account_user_time(p, jiffies_to_cputime(1));
-		account_user_time_scaled(p, jiffies_to_cputime(1));
+		account_user_time(p, one_jiffy);
+		account_user_time_scaled(p, cputime_to_scaled(one_jiffy));
 	} else {
-		account_system_time(p, HARDIRQ_OFFSET, jiffies_to_cputime(1));
-		account_system_time_scaled(p, jiffies_to_cputime(1));
+		account_system_time(p, HARDIRQ_OFFSET, one_jiffy);
+		account_system_time_scaled(p, cputime_to_scaled(one_jiffy));
 	}
 }
 #endif
diff --git a/lib/extable.c b/lib/extable.c
index 463f456..179c087 100644
--- a/lib/extable.c
+++ b/lib/extable.c
@@ -57,10 +57,10 @@
 	while (first <= last) {
 		const struct exception_table_entry *mid;
 
-		mid = (last - first) / 2 + first;
+		mid = ((last - first) >> 1) + first;
 		/*
-		 * careful, the distance between entries can be
-		 * larger than 2GB:
+		 * careful, the distance between value and insn
+		 * can be larger than MAX_LONG:
 		 */
 		if (mid->insn < value)
 			first = mid + 1;
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
index eddc9b3..6c90fb9 100644
--- a/lib/smp_processor_id.c
+++ b/lib/smp_processor_id.c
@@ -42,7 +42,9 @@
 	if (!printk_ratelimit())
 		goto out_enable;
 
-	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] "
+			"code: %s/%d\n",
+			preempt_count() - 1, current->comm, current->pid);
 	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
 	dump_stack();
 
diff --git a/mm/allocpercpu.c b/mm/allocpercpu.c
index 00b0262..7e58322 100644
--- a/mm/allocpercpu.c
+++ b/mm/allocpercpu.c
@@ -98,7 +98,7 @@
  */
 void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask)
 {
-	void *pdata = kzalloc(sizeof(struct percpu_data), gfp);
+	void *pdata = kzalloc(nr_cpu_ids * sizeof(void *), gfp);
 	void *__pdata = __percpu_disguise(pdata);
 
 	if (unlikely(!pdata))
diff --git a/net/ipv4/ipvs/ip_vs_wrr.c b/net/ipv4/ipvs/ip_vs_wrr.c
index 749fa04..85c680a 100644
--- a/net/ipv4/ipvs/ip_vs_wrr.c
+++ b/net/ipv4/ipvs/ip_vs_wrr.c
@@ -22,6 +22,7 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/net.h>
 
 #include <net/ip_vs.h>
 
@@ -169,7 +170,7 @@
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_INFO("ip_vs_wrr_schedule(): "
+					IP_VS_ERR_RL("ip_vs_wrr_schedule(): "
 						   "no available servers\n");
 					dest = NULL;
 					goto out;
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index e77592d..45c7c0c 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -1,6 +1,5 @@
 config MAC80211
 	tristate "Generic IEEE 802.11 Networking Stack (mac80211)"
-	depends on EXPERIMENTAL
 	select CRYPTO
 	select CRYPTO_ECB
 	select CRYPTO_ARC4
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 8d76986..971b867 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -19,6 +19,7 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/ipv6.h>
+#include <linux/if_vlan.h>
 
 #include <net/pkt_cls.h>
 #include <net/ip.h>
@@ -270,6 +271,15 @@
 	return 0;
 }
 
+static u32 flow_get_vlan_tag(const struct sk_buff *skb)
+{
+	u16 uninitialized_var(tag);
+
+	if (vlan_get_tag(skb, &tag) < 0)
+		return 0;
+	return tag & VLAN_VID_MASK;
+}
+
 static u32 flow_key_get(const struct sk_buff *skb, int key)
 {
 	switch (key) {
@@ -305,6 +315,8 @@
 		return flow_get_skuid(skb);
 	case FLOW_KEY_SKGID:
 		return flow_get_skgid(skb);
+	case FLOW_KEY_VLAN_TAG:
+		return flow_get_vlan_tag(skb);
 	default:
 		WARN_ON(1);
 		return 0;
@@ -402,12 +414,13 @@
 
 	if (tb[TCA_FLOW_KEYS]) {
 		keymask = nla_get_u32(tb[TCA_FLOW_KEYS]);
-		if (fls(keymask) - 1 > FLOW_KEY_MAX)
-			return -EOPNOTSUPP;
 
 		nkeys = hweight32(keymask);
 		if (nkeys == 0)
 			return -EINVAL;
+
+		if (fls(keymask) - 1 > FLOW_KEY_MAX)
+			return -EOPNOTSUPP;
 	}
 
 	err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 9c2ec19..2a7e648 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -176,7 +176,7 @@
 
 META_COLLECTOR(int_vlan_tag)
 {
-	unsigned short tag;
+	unsigned short uninitialized_var(tag);
 	if (vlan_get_tag(skb, &tag) < 0)
 		*err = -1;
 	else
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index d716b76..340ad69 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -2,7 +2,7 @@
 
 #	Check the stack usage of functions
 #
-#	Copyright Joern Engel <joern@wh.fh-wedel.de>
+#	Copyright Joern Engel <joern@lazybastard.org>
 #	Inspired by Linus Torvalds
 #	Original idea maybe from Keith Owens
 #	s390 port and big speedup by Arnd Bergmann <arnd@bergmann-dalldorf.de>
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 1f11d84..c912137 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -31,17 +31,16 @@
 
 #define KSYM_NAME_LEN		128
 
-
 struct sym_entry {
 	unsigned long long addr;
 	unsigned int len;
+	unsigned int start_pos;
 	unsigned char *sym;
 };
 
-
 static struct sym_entry *table;
 static unsigned int table_size, table_cnt;
-static unsigned long long _text, _stext, _etext, _sinittext, _einittext, _sextratext, _eextratext;
+static unsigned long long _text, _stext, _etext, _sinittext, _einittext;
 static int all_symbols = 0;
 static char symbol_prefix_char = '\0';
 
@@ -99,10 +98,6 @@
 		_sinittext = s->addr;
 	else if (strcmp(sym, "_einittext") == 0)
 		_einittext = s->addr;
-	else if (strcmp(sym, "_sextratext") == 0)
-		_sextratext = s->addr;
-	else if (strcmp(sym, "_eextratext") == 0)
-		_eextratext = s->addr;
 	else if (toupper(stype) == 'A')
 	{
 		/* Keep these useful absolute symbols */
@@ -165,18 +160,18 @@
 	 * and inittext sections are discarded */
 	if (!all_symbols) {
 		if ((s->addr < _stext || s->addr > _etext)
-		    && (s->addr < _sinittext || s->addr > _einittext)
-		    && (s->addr < _sextratext || s->addr > _eextratext))
+		    && (s->addr < _sinittext || s->addr > _einittext))
 			return 0;
 		/* Corner case.  Discard any symbols with the same value as
-		 * _etext _einittext or _eextratext; they can move between pass
-		 * 1 and 2 when the kallsyms data are added.  If these symbols
-		 * move then they may get dropped in pass 2, which breaks the
-		 * kallsyms rules.
+		 * _etext _einittext; they can move between pass 1 and 2 when
+		 * the kallsyms data are added.  If these symbols move then
+		 * they may get dropped in pass 2, which breaks the kallsyms
+		 * rules.
 		 */
-		if ((s->addr == _etext && strcmp((char*)s->sym + offset, "_etext")) ||
-		    (s->addr == _einittext && strcmp((char*)s->sym + offset, "_einittext")) ||
-		    (s->addr == _eextratext && strcmp((char*)s->sym + offset, "_eextratext")))
+		if ((s->addr == _etext &&
+				strcmp((char *)s->sym + offset, "_etext")) ||
+		    (s->addr == _einittext &&
+				strcmp((char *)s->sym + offset, "_einittext")))
 			return 0;
 	}
 
@@ -202,8 +197,10 @@
 				exit (1);
 			}
 		}
-		if (read_symbol(in, &table[table_cnt]) == 0)
+		if (read_symbol(in, &table[table_cnt]) == 0) {
+			table[table_cnt].start_pos = table_cnt;
 			table_cnt++;
+		}
 	}
 }
 
@@ -506,6 +503,35 @@
 	optimize_result();
 }
 
+static int compare_symbols(const void *a, const void *b)
+{
+	const struct sym_entry *sa;
+	const struct sym_entry *sb;
+	int wa, wb;
+
+	sa = a;
+	sb = b;
+
+	/* sort by address first */
+	if (sa->addr > sb->addr)
+		return 1;
+	if (sa->addr < sb->addr)
+		return -1;
+
+	/* sort by "weakness" type */
+	wa = (sa->sym[0] == 'w') || (sa->sym[0] == 'W');
+	wb = (sb->sym[0] == 'w') || (sb->sym[0] == 'W');
+	if (wa != wb)
+		return wa - wb;
+
+	/* sort by initial order, so that other symbols are left undisturbed */
+	return sa->start_pos - sb->start_pos;
+}
+
+static void sort_symbols(void)
+{
+	qsort(table, table_cnt, sizeof(struct sym_entry), compare_symbols);
+}
 
 int main(int argc, char **argv)
 {
@@ -527,6 +553,7 @@
 		usage();
 
 	read_map(stdin);
+	sort_symbols();
 	optimize_token_table();
 	write_src();
 
diff --git a/security/Kconfig b/security/Kconfig
index 25ffe1b..5dfc206 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -104,6 +104,24 @@
 	  
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_DEFAULT_MMAP_MIN_ADDR
+        int "Low address space to protect from user allocation"
+        depends on SECURITY
+        default 0
+        help
+	  This is the portion of low virtual memory which should be protected
+	  from userspace allocation.  Keeping a user from writing to low pages
+	  can help reduce the impact of kernel NULL pointer bugs.
+
+	  For most users with lots of address space a value of 65536 is
+	  reasonable and should cause no problems.  Programs which use vm86
+	  functionality would either need additional permissions from either
+	  the LSM or the capabilities module or have this protection disabled.
+
+	  This value can be changed after boot using the
+	  /proc/sys/vm/mmap_min_addr tunable.
+
+
 source security/selinux/Kconfig
 source security/smack/Kconfig
 
diff --git a/security/security.c b/security/security.c
index b6c57a6..d15e56c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -23,7 +23,9 @@
 extern void security_fixup_ops(struct security_operations *ops);
 
 struct security_operations *security_ops;	/* Initialized to NULL */
-unsigned long mmap_min_addr;		/* 0 means no protection */
+
+/* amount of vm to protect from userspace access */
+unsigned long mmap_min_addr = CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR;
 
 static inline int verify(struct security_operations *ops)
 {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 23137c1..837ce42 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -107,7 +107,6 @@
 int security_get_permissions(char *class, char ***perms, int *nperms);
 int security_get_reject_unknown(void);
 int security_get_allow_unknown(void);
-int security_get_policycaps(int *len, int **values);
 
 #define SECURITY_FS_USE_XATTR		1 /* use xattr */
 #define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index fced6bc..f374186 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2246,39 +2246,6 @@
 }
 
 /**
- * security_get_policycaps - Query the loaded policy for its capabilities
- * @len: the number of capability bits
- * @values: the capability bit array
- *
- * Description:
- * Get an array of the policy capabilities in @values where each entry in
- * @values is either true (1) or false (0) depending the policy's support of
- * that feature.  The policy capabilities are defined by the
- * POLICYDB_CAPABILITY_* enums.  The size of the array is stored in @len and it
- * is up to the caller to free the array in @values.  Returns zero on success,
- * negative values on failure.
- *
- */
-int security_get_policycaps(int *len, int **values)
-{
-	int rc = -ENOMEM;
-	unsigned int iter;
-
-	POLICY_RDLOCK;
-
-	*values = kcalloc(POLICYDB_CAPABILITY_MAX, sizeof(int), GFP_ATOMIC);
-	if (*values == NULL)
-		goto out;
-	for (iter = 0; iter < POLICYDB_CAPABILITY_MAX; iter++)
-		(*values)[iter] = ebitmap_get_bit(&policydb.policycaps, iter);
-	*len = POLICYDB_CAPABILITY_MAX;
-
-out:
-	POLICY_RDUNLOCK;
-	return rc;
-}
-
-/**
  * security_policycap_supported - Check for a specific policy capability
  * @req_cap: capability
  *
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index f883c4b..1f86299 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -6,7 +6,6 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_SOUND_OSS)		+= sound.o
-obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o ad1848.o 
 
 # Please leave it as is, cause the link order is significant !
 
@@ -16,7 +15,6 @@
 obj-$(CONFIG_SOUND_PSS)		+= pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)	+= trix.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SSCAPE)	+= sscape.o ad1848.o mpu401.o
-obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o uart401.o
 obj-$(CONFIG_SOUND_MSS)		+= ad1848.o
 obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
@@ -27,19 +25,12 @@
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_VIDC)	+= vidc_mod.o
 obj-$(CONFIG_SOUND_WAVEARTIST)	+= waveartist.o
-
-obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
-ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
-  obj-$(CONFIG_SOUND_VIA82CXXX) += sound.o uart401.o
-endif
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)	+= msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)	+= vwsnd.o
-obj-$(CONFIG_SOUND_ICH)		+= i810_audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o
-obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
 
 obj-$(CONFIG_SOUND_WM97XX)	+= ac97_plugin_wm97xx.o
 
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index fef56ca..87a6726 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -189,42 +189,6 @@
 	{0x57454301, "Winbond 83971D",		&null_ops},
 };
 
-static const char *ac97_stereo_enhancements[] =
-{
-	/*   0 */ "No 3D Stereo Enhancement",
-	/*   1 */ "Analog Devices Phat Stereo",
-	/*   2 */ "Creative Stereo Enhancement",
-	/*   3 */ "National Semi 3D Stereo Enhancement",
-	/*   4 */ "YAMAHA Ymersion",
-	/*   5 */ "BBE 3D Stereo Enhancement",
-	/*   6 */ "Crystal Semi 3D Stereo Enhancement",
-	/*   7 */ "Qsound QXpander",
-	/*   8 */ "Spatializer 3D Stereo Enhancement",
-	/*   9 */ "SRS 3D Stereo Enhancement",
-	/*  10 */ "Platform Tech 3D Stereo Enhancement",
-	/*  11 */ "AKM 3D Audio",
-	/*  12 */ "Aureal Stereo Enhancement",
-	/*  13 */ "Aztech 3D Enhancement",
-	/*  14 */ "Binaura 3D Audio Enhancement",
-	/*  15 */ "ESS Technology Stereo Enhancement",
-	/*  16 */ "Harman International VMAx",
-	/*  17 */ "Nvidea 3D Stereo Enhancement",
-	/*  18 */ "Philips Incredible Sound",
-	/*  19 */ "Texas Instruments 3D Stereo Enhancement",
-	/*  20 */ "VLSI Technology 3D Stereo Enhancement",
-	/*  21 */ "TriTech 3D Stereo Enhancement",
-	/*  22 */ "Realtek 3D Stereo Enhancement",
-	/*  23 */ "Samsung 3D Stereo Enhancement",
-	/*  24 */ "Wolfson Microelectronics 3D Enhancement",
-	/*  25 */ "Delta Integration 3D Enhancement",
-	/*  26 */ "SigmaTel 3D Enhancement",
-	/*  27 */ "Winbond 3D Stereo Enhancement",
-	/*  28 */ "Rockwell 3D Stereo Enhancement",
-	/*  29 */ "Reserved 29",
-	/*  30 */ "Reserved 30",
-	/*  31 */ "Reserved 31"
-};
-
 /* this table has default mixer values for all OSS mixers. */
 static struct mixer_defaults {
 	int mixer;
@@ -614,83 +578,6 @@
 	return -EINVAL;
 }
 
-/* entry point for /proc/driver/controller_vendor/ac97/%d */
-int ac97_read_proc (char *page, char **start, off_t off,
-		    int count, int *eof, void *data)
-{
-	int len = 0, cap, extid, val, id1, id2;
-	struct ac97_codec *codec;
-	int is_ac97_20 = 0;
-
-	if ((codec = data) == NULL)
-		return -ENODEV;
-
-	id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
-	id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
-	len += sprintf (page+len, "Vendor name      : %s\n", codec->name);
-	len += sprintf (page+len, "Vendor id        : %04X %04X\n", id1, id2);
-
-	extid = codec->codec_read(codec, AC97_EXTENDED_ID);
-	extid &= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13));
-	len += sprintf (page+len, "AC97 Version     : %s\n",
-			extid ? "2.0 or later" : "1.0");
-	if (extid) is_ac97_20 = 1;
-
-	cap = codec->codec_read(codec, AC97_RESET);
-	len += sprintf (page+len, "Capabilities     :%s%s%s%s%s%s\n",
-			cap & 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
-			cap & 0x0002 ? " -reserved1-" : "",
-			cap & 0x0004 ? " -bass & treble-" : "",
-			cap & 0x0008 ? " -simulated stereo-" : "",
-			cap & 0x0010 ? " -headphone out-" : "",
-			cap & 0x0020 ? " -loudness-" : "");
-	val = cap & 0x00c0;
-	len += sprintf (page+len, "DAC resolutions  :%s%s%s\n",
-			" -16-bit-",
-			val & 0x0040 ? " -18-bit-" : "",
-			val & 0x0080 ? " -20-bit-" : "");
-	val = cap & 0x0300;
-	len += sprintf (page+len, "ADC resolutions  :%s%s%s\n",
-			" -16-bit-",
-			val & 0x0100 ? " -18-bit-" : "",
-			val & 0x0200 ? " -20-bit-" : "");
-	len += sprintf (page+len, "3D enhancement   : %s\n",
-			ac97_stereo_enhancements[(cap >> 10) & 0x1f]);
-
-	val = codec->codec_read(codec, AC97_GENERAL_PURPOSE);
-	len += sprintf (page+len, "POP path         : %s 3D\n"
-			"Sim. stereo      : %s\n"
-			"3D enhancement   : %s\n"
-			"Loudness         : %s\n"
-			"Mono output      : %s\n"
-			"MIC select       : %s\n"
-			"ADC/DAC loopback : %s\n",
-			val & 0x8000 ? "post" : "pre",
-			val & 0x4000 ? "on" : "off",
-			val & 0x2000 ? "on" : "off",
-			val & 0x1000 ? "on" : "off",
-			val & 0x0200 ? "MIC" : "MIX",
-			val & 0x0100 ? "MIC2" : "MIC1",
-			val & 0x0080 ? "on" : "off");
-
-	extid = codec->codec_read(codec, AC97_EXTENDED_ID);
-	cap = extid;
-	len += sprintf (page+len, "Ext Capabilities :%s%s%s%s%s%s%s\n",
-			cap & 0x0001 ? " -var rate PCM audio-" : "",
-			cap & 0x0002 ? " -2x PCM audio out-" : "",
-			cap & 0x0008 ? " -var rate MIC in-" : "",
-			cap & 0x0040 ? " -PCM center DAC-" : "",
-			cap & 0x0080 ? " -PCM surround DAC-" : "",
-			cap & 0x0100 ? " -PCM LFE DAC-" : "",
-			cap & 0x0200 ? " -slot/DAC mappings-" : "");
-	if (is_ac97_20) {
-		len += sprintf (page+len, "Front DAC rate   : %d\n",
-				codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE));
-	}
-
-	return len;
-}
-
 /**
  *	codec_id	-  Turn id1/id2 into a PnP string
  *	@id1: Vendor ID1
@@ -1313,176 +1200,5 @@
 #endif
 	
 
-EXPORT_SYMBOL(ac97_read_proc);
 EXPORT_SYMBOL(ac97_probe_codec);
 
-/*
- *	AC97 library support routines
- */	
- 
-/**
- *	ac97_set_dac_rate	-	set codec rate adaption
- *	@codec: ac97 code
- *	@rate: rate in hertz
- *
- *	Set the DAC rate. Assumes the codec supports VRA. The caller is
- *	expected to have checked this little detail.
- */
- 
-unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate)
-{
-	unsigned int new_rate = rate;
-	u32 dacp;
-	u32 mast_vol, phone_vol, mono_vol, pcm_vol;
-	u32 mute_vol = 0x8000;	/* The mute volume? */
-
-	if(rate != codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE))
-	{
-		/* Mute several registers */
-		mast_vol = codec->codec_read(codec, AC97_MASTER_VOL_STEREO);
-		mono_vol = codec->codec_read(codec, AC97_MASTER_VOL_MONO);
-		phone_vol = codec->codec_read(codec, AC97_HEADPHONE_VOL);
-		pcm_vol = codec->codec_read(codec, AC97_PCMOUT_VOL);
-		codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mute_vol);
-		codec->codec_write(codec, AC97_MASTER_VOL_MONO, mute_vol);
-		codec->codec_write(codec, AC97_HEADPHONE_VOL, mute_vol);
-		codec->codec_write(codec, AC97_PCMOUT_VOL, mute_vol);
-		
-		/* Power down the DAC */
-		dacp=codec->codec_read(codec, AC97_POWER_CONTROL);
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200);
-		/* Load the rate and read the effective rate */
-		codec->codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate);
-		new_rate=codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE);
-		/* Power it back up */
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp);
-
-		/* Restore volumes */
-		codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mast_vol);
-		codec->codec_write(codec, AC97_MASTER_VOL_MONO, mono_vol);
-		codec->codec_write(codec, AC97_HEADPHONE_VOL, phone_vol);
-		codec->codec_write(codec, AC97_PCMOUT_VOL, pcm_vol);
-	}
-	return new_rate;
-}
-
-EXPORT_SYMBOL(ac97_set_dac_rate);
-
-/**
- *	ac97_set_adc_rate	-	set codec rate adaption
- *	@codec: ac97 code
- *	@rate: rate in hertz
- *
- *	Set the ADC rate. Assumes the codec supports VRA. The caller is
- *	expected to have checked this little detail.
- */
-
-unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate)
-{
-	unsigned int new_rate = rate;
-	u32 dacp;
-
-	if(rate != codec->codec_read(codec, AC97_PCM_LR_ADC_RATE))
-	{
-		/* Power down the ADC */
-		dacp=codec->codec_read(codec, AC97_POWER_CONTROL);
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0100);
-		/* Load the rate and read the effective rate */
-		codec->codec_write(codec, AC97_PCM_LR_ADC_RATE, rate);
-		new_rate=codec->codec_read(codec, AC97_PCM_LR_ADC_RATE);
-		/* Power it back up */
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp);
-	}
-	return new_rate;
-}
-
-EXPORT_SYMBOL(ac97_set_adc_rate);
-
-static int swap_headphone(int remove_master)
-{
-	struct list_head *l;
-	struct ac97_codec *c;
-	
-	if (remove_master) {
-		mutex_lock(&codec_mutex);
-		list_for_each(l, &codecs)
-		{
-			c = list_entry(l, struct ac97_codec, list);
-			if (supported_mixer(c, SOUND_MIXER_PHONEOUT))
-				c->supported_mixers &= ~SOUND_MASK_PHONEOUT;
-		}
-		mutex_unlock(&codec_mutex);
-	} else
-		ac97_hw[SOUND_MIXER_PHONEOUT].offset = AC97_MASTER_VOL_STEREO;
-
-	/* Scale values already match */
-	ac97_hw[SOUND_MIXER_VOLUME].offset = AC97_MASTER_VOL_MONO;
-	return 0;
-}
-
-static int apply_quirk(int quirk)
-{
-	switch (quirk) {
-	case AC97_TUNE_NONE:
-		return 0;
-	case AC97_TUNE_HP_ONLY:
-		return swap_headphone(1);
-	case AC97_TUNE_SWAP_HP:
-		return swap_headphone(0);
-	case AC97_TUNE_SWAP_SURROUND:
-		return -ENOSYS; /* not yet implemented */
-	case AC97_TUNE_AD_SHARING:
-		return -ENOSYS; /* not yet implemented */
-	case AC97_TUNE_ALC_JACK:
-		return -ENOSYS; /* not yet implemented */
-	}
-	return -EINVAL;
-}
-
-/**
- *	ac97_tune_hardware - tune up the hardware
- *	@pdev: pci_dev pointer
- *	@quirk: quirk list
- *	@override: explicit quirk value (overrides if not AC97_TUNE_DEFAULT)
- *
- *	Do some workaround for each pci device, such as renaming of the
- *	headphone (true line-out) control as "Master".
- *	The quirk-list must be terminated with a zero-filled entry.
- *
- *	Returns zero if successful, or a negative error code on failure.
- */
-
-int ac97_tune_hardware(struct pci_dev *pdev, struct ac97_quirk *quirk, int override)
-{
-	int result;
-
-	if (!quirk)
-		return -EINVAL;
-
-	if (override != AC97_TUNE_DEFAULT) {
-		result = apply_quirk(override);
-		if (result < 0)
-			printk(KERN_ERR "applying quirk type %d failed (%d)\n", override, result);
-		return result;
-	}
-
-	for (; quirk->vendor; quirk++) {
-		if (quirk->vendor != pdev->subsystem_vendor)
-			continue;
-		if ((! quirk->mask && quirk->device == pdev->subsystem_device) ||
-		    quirk->device == (quirk->mask & pdev->subsystem_device)) {
-#ifdef DEBUG
-			printk("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, pdev->subsystem_device);
-#endif
-			result = apply_quirk(quirk->type);
-			if (result < 0)
-				printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result);
-			return result;
-		}
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(ac97_tune_hardware);
-
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
deleted file mode 100644
index 4d5cf05..0000000
--- a/sound/oss/btaudio.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
-    btaudio - bt878 audio dma driver for linux 2.4.x
-
-    (c) 2000-2002 Gerd Knorr <kraxel@bytesex.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/slab.h>
-#include <linux/kdev_t.h>
-#include <linux/mutex.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-
-/* mmio access */
-#define btwrite(dat,adr)    writel((dat), (bta->mmio+(adr)))
-#define btread(adr)         readl(bta->mmio+(adr))
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-/* registers (shifted because bta->mmio is long) */
-#define REG_INT_STAT      (0x100 >> 2)
-#define REG_INT_MASK      (0x104 >> 2)
-#define REG_GPIO_DMA_CTL  (0x10c >> 2)
-#define REG_PACKET_LEN    (0x110 >> 2)
-#define REG_RISC_STRT_ADD (0x114 >> 2)
-#define REG_RISC_COUNT    (0x120 >> 2)
-
-/* IRQ bits - REG_INT_(STAT|MASK) */
-#define IRQ_SCERR         (1 << 19)
-#define IRQ_OCERR         (1 << 18)
-#define IRQ_PABORT        (1 << 17)
-#define IRQ_RIPERR        (1 << 16)
-#define IRQ_PPERR         (1 << 15)
-#define IRQ_FDSR          (1 << 14)
-#define IRQ_FTRGT         (1 << 13)
-#define IRQ_FBUS          (1 << 12)
-#define IRQ_RISCI         (1 << 11)
-#define IRQ_OFLOW         (1 <<  3)
-
-#define IRQ_BTAUDIO       (IRQ_SCERR | IRQ_OCERR | IRQ_PABORT | IRQ_RIPERR |\
-			   IRQ_PPERR | IRQ_FDSR  | IRQ_FTRGT  | IRQ_FBUS   |\
-			   IRQ_RISCI)
-
-/* REG_GPIO_DMA_CTL bits */
-#define DMA_CTL_A_PWRDN   (1 << 26)
-#define DMA_CTL_DA_SBR    (1 << 14)
-#define DMA_CTL_DA_ES2    (1 << 13)
-#define DMA_CTL_ACAP_EN   (1 <<  4)
-#define DMA_CTL_RISC_EN   (1 <<  1)
-#define DMA_CTL_FIFO_EN   (1 <<  0)
-
-/* RISC instructions */
-#define RISC_WRITE        (0x01 << 28)
-#define RISC_JUMP         (0x07 << 28)
-#define RISC_SYNC         (0x08 << 28)
-
-/* RISC bits */
-#define RISC_WR_SOL       (1 << 27)
-#define RISC_WR_EOL       (1 << 26)
-#define RISC_IRQ          (1 << 24)
-#define RISC_SYNC_RESYNC  (1 << 15)
-#define RISC_SYNC_FM1     0x06
-#define RISC_SYNC_VRO     0x0c
-
-#define HWBASE_AD (448000)
-
-/* -------------------------------------------------------------- */
-
-struct btaudio {
-	/* linked list */
-	struct btaudio *next;
-
-	/* device info */
-	int            dsp_digital;
-	int            dsp_analog;
-	int            mixer_dev;
-	struct pci_dev *pci;
-	unsigned int   irq;
-	unsigned long  mem;
-	unsigned long  __iomem *mmio;
-
-	/* locking */
-	int            users;
-	struct mutex lock;
-
-	/* risc instructions */
-	unsigned int   risc_size;
-	unsigned long  *risc_cpu;
-	dma_addr_t     risc_dma;
-
-	/* audio data */
-	unsigned int   buf_size;
-	unsigned char  *buf_cpu;
-	dma_addr_t     buf_dma;
-
-	/* buffer setup */
-	int line_bytes;
-	int line_count;
-	int block_bytes;
-	int block_count;
-
-	/* read fifo management */
-	int recording;
-	int dma_block;
-	int read_offset;
-	int read_count;
-	wait_queue_head_t readq;
-
-	/* settings */
-	int gain[3];
-	int source;
-	int bits;
-	int decimation;
-	int mixcount;
-	int sampleshift;
-	int channels;
-	int analog;
-	int rate;
-};
-
-struct cardinfo {
-	char *name;
-	int rate;
-};
-
-static struct btaudio *btaudios;
-static unsigned int debug;
-static unsigned int irq_debug;
-
-/* -------------------------------------------------------------- */
-
-#define BUF_DEFAULT 128*1024
-#define BUF_MIN         8192
-
-static int alloc_buffer(struct btaudio *bta)
-{
-	if (NULL == bta->buf_cpu) {
-		for (bta->buf_size = BUF_DEFAULT; bta->buf_size >= BUF_MIN;
-		     bta->buf_size = bta->buf_size >> 1) {
-			bta->buf_cpu = pci_alloc_consistent
-				(bta->pci, bta->buf_size, &bta->buf_dma);
-			if (NULL != bta->buf_cpu)
-				break;
-		}
-		if (NULL == bta->buf_cpu)
-			return -ENOMEM;
-		memset(bta->buf_cpu,0,bta->buf_size);
-	}
-	if (NULL == bta->risc_cpu) {
-		bta->risc_size = PAGE_SIZE;
-		bta->risc_cpu = pci_alloc_consistent
-			(bta->pci, bta->risc_size, &bta->risc_dma);
-		if (NULL == bta->risc_cpu) {
-			pci_free_consistent(bta->pci, bta->buf_size, bta->buf_cpu, bta->buf_dma);
-			bta->buf_cpu = NULL;
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void free_buffer(struct btaudio *bta)
-{
-	if (NULL != bta->buf_cpu) {
-		pci_free_consistent(bta->pci, bta->buf_size,
-				    bta->buf_cpu, bta->buf_dma);
-		bta->buf_cpu = NULL;
-	}
-	if (NULL != bta->risc_cpu) {
-		pci_free_consistent(bta->pci, bta->risc_size,
-				    bta->risc_cpu, bta->risc_dma);
-		bta->risc_cpu = NULL;
-	}
-}
-
-static int make_risc(struct btaudio *bta)
-{
-	int rp, bp, line, block;
-	unsigned long risc;
-
-	bta->block_bytes = bta->buf_size >> 4;
-	bta->block_count = 1 << 4;
-	bta->line_bytes  = bta->block_bytes;
-	bta->line_count  = bta->block_count;
-	while (bta->line_bytes > 4095) {
-		bta->line_bytes >>= 1;
-		bta->line_count <<= 1;
-	}
-	if (bta->line_count > 255)
-		return -EINVAL;
-	if (debug)
-		printk(KERN_DEBUG
-		       "btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n",
-		       bta->buf_size,bta->block_bytes,bta->block_count,
-		       bta->line_bytes,bta->line_count);
-        rp = 0; bp = 0;
-	block = 0;
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_SYNC|RISC_SYNC_FM1);
-	bta->risc_cpu[rp++] = cpu_to_le32(0);
-	for (line = 0; line < bta->line_count; line++) {
-		risc  = RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL;
-		risc |= bta->line_bytes;
-		if (0 == (bp & (bta->block_bytes-1))) {
-			risc |= RISC_IRQ;
-			risc |= (block  & 0x0f) << 16;
-			risc |= (~block & 0x0f) << 20;
-			block++;
-		}
-		bta->risc_cpu[rp++] = cpu_to_le32(risc);
-		bta->risc_cpu[rp++] = cpu_to_le32(bta->buf_dma + bp);
-		bp += bta->line_bytes;
-	}
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_SYNC|RISC_SYNC_VRO);
-	bta->risc_cpu[rp++] = cpu_to_le32(0);
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_JUMP); 
-	bta->risc_cpu[rp++] = cpu_to_le32(bta->risc_dma);
-	return 0;
-}
-
-static int start_recording(struct btaudio *bta)
-{
-	int ret;
-
-	if (0 != (ret = alloc_buffer(bta)))
-		return ret;
-	if (0 != (ret = make_risc(bta)))
-		return ret;
-
-	btwrite(bta->risc_dma, REG_RISC_STRT_ADD);
-	btwrite((bta->line_count << 16) | bta->line_bytes,
-		REG_PACKET_LEN);
-	btwrite(IRQ_BTAUDIO, REG_INT_MASK);
-	if (bta->analog) {
-		btwrite(DMA_CTL_ACAP_EN |
-			DMA_CTL_RISC_EN |
-			DMA_CTL_FIFO_EN |
-			DMA_CTL_DA_ES2  |
-			((bta->bits == 8) ? DMA_CTL_DA_SBR : 0) |
-			(bta->gain[bta->source] << 28) |
-			(bta->source            << 24) |
-			(bta->decimation        <<  8),
-			REG_GPIO_DMA_CTL);
-	} else {
-		btwrite(DMA_CTL_ACAP_EN |
-			DMA_CTL_RISC_EN |
-			DMA_CTL_FIFO_EN |
-			DMA_CTL_DA_ES2  |
-			DMA_CTL_A_PWRDN |
-			(1 << 6)   |
-			((bta->bits == 8) ? DMA_CTL_DA_SBR : 0) |
-			(bta->gain[bta->source] << 28) |
-			(bta->source            << 24) |
-			(bta->decimation        <<  8),
-			REG_GPIO_DMA_CTL);
-	}
-	bta->dma_block = 0;
-	bta->read_offset = 0;
-	bta->read_count = 0;
-	bta->recording = 1;
-	if (debug)
-		printk(KERN_DEBUG "btaudio: recording started\n");
-	return 0;
-}
-
-static void stop_recording(struct btaudio *bta)
-{
-        btand(~15, REG_GPIO_DMA_CTL);
-	bta->recording = 0;
-	if (debug)
-		printk(KERN_DEBUG "btaudio: recording stopped\n");
-}
-
-
-/* -------------------------------------------------------------- */
-
-static int btaudio_mixer_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->mixer_dev == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-
-	if (debug)
-		printk("btaudio: open mixer [%d]\n",minor);
-	file->private_data = bta;
-	return 0;
-}
-
-static int btaudio_mixer_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static int btaudio_mixer_ioctl(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg)
-{
-	struct btaudio *bta = file->private_data;
-	int ret,val=0,i=0;
-	void __user *argp = (void __user *)arg;
-
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		memset(&info,0,sizeof(info));
-                strlcpy(info.id,"bt878",sizeof(info.id));
-                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
-                info.modify_counter = bta->mixcount;
-                if (copy_to_user(argp, &info, sizeof(info)))
-                        return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		memset(&info,0,sizeof(info));
-                strlcpy(info.id, "bt878", sizeof(info.id));
-                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
-                if (copy_to_user(argp, &info, sizeof(info)))
-                        return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int __user *)argp);
-
-	/* read */
-	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
-		if (get_user(val, (int __user *)argp))
-			return -EFAULT;
-
-	switch (cmd) {
-	case MIXER_READ(SOUND_MIXER_CAPS):
-		ret = SOUND_CAP_EXCL_INPUT;
-		break;
-	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = 0;
-		break;
-	case MIXER_READ(SOUND_MIXER_RECMASK):
-	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_LINE1|SOUND_MASK_LINE2|SOUND_MASK_LINE3;
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_RECSRC):
-		if (val & SOUND_MASK_LINE1 && bta->source != 0)
-			bta->source = 0;
-		else if (val & SOUND_MASK_LINE2 && bta->source != 1)
-			bta->source = 1;
-		else if (val & SOUND_MASK_LINE3 && bta->source != 2)
-			bta->source = 2;
-		btaor((bta->gain[bta->source] << 28) |
-		      (bta->source            << 24),
-		      0x0cffffff, REG_GPIO_DMA_CTL);
-	case MIXER_READ(SOUND_MIXER_RECSRC):
-		switch (bta->source) {
-		case 0:  ret = SOUND_MASK_LINE1; break;
-		case 1:  ret = SOUND_MASK_LINE2; break;
-		case 2:  ret = SOUND_MASK_LINE3; break;
-		default: ret = 0;
-		}
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_LINE1):
-	case MIXER_WRITE(SOUND_MIXER_LINE2):
-	case MIXER_WRITE(SOUND_MIXER_LINE3):
-		if (MIXER_WRITE(SOUND_MIXER_LINE1) == cmd)
-			i = 0;
-		if (MIXER_WRITE(SOUND_MIXER_LINE2) == cmd)
-			i = 1;
-		if (MIXER_WRITE(SOUND_MIXER_LINE3) == cmd)
-			i = 2;
-		bta->gain[i] = (val & 0xff) * 15 / 100;
-		if (bta->gain[i] > 15) bta->gain[i] = 15;
-		if (bta->gain[i] <  0) bta->gain[i] =  0;
-		if (i == bta->source)
-			btaor((bta->gain[bta->source]<<28),
-			      0x0fffffff, REG_GPIO_DMA_CTL);
-		ret  = bta->gain[i] * 100 / 15;
-		ret |= ret << 8;
-		break;
-
-	case MIXER_READ(SOUND_MIXER_LINE1):
-	case MIXER_READ(SOUND_MIXER_LINE2):
-	case MIXER_READ(SOUND_MIXER_LINE3):
-		if (MIXER_READ(SOUND_MIXER_LINE1) == cmd)
-			i = 0;
-		if (MIXER_READ(SOUND_MIXER_LINE2) == cmd)
-			i = 1;
-		if (MIXER_READ(SOUND_MIXER_LINE3) == cmd)
-			i = 2;
-		ret  = bta->gain[i] * 100 / 15;
-		ret |= ret << 8;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (put_user(ret, (int __user *)argp))
-		return -EFAULT;
-	return 0;
-}
-
-static const struct file_operations btaudio_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_mixer_open,
-	.release	= btaudio_mixer_release,
-	.ioctl		= btaudio_mixer_ioctl,
-};
-
-/* -------------------------------------------------------------- */
-
-static int btaudio_dsp_open(struct inode *inode, struct file *file,
-			    struct btaudio *bta, int analog)
-{
-	mutex_lock(&bta->lock);
-	if (bta->users)
-		goto busy;
-	bta->users++;
-	file->private_data = bta;
-
-	bta->analog = analog;
-	bta->dma_block = 0;
-	bta->read_offset = 0;
-	bta->read_count = 0;
-	bta->sampleshift = 0;
-
-	mutex_unlock(&bta->lock);
-	return 0;
-
- busy:
-	mutex_unlock(&bta->lock);
-	return -EBUSY;
-}
-
-static int btaudio_dsp_open_digital(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->dsp_digital == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-	
-	if (debug)
-		printk("btaudio: open digital dsp [%d]\n",minor);
-	return btaudio_dsp_open(inode,file,bta,0);
-}
-
-static int btaudio_dsp_open_analog(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->dsp_analog == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-
-	if (debug)
-		printk("btaudio: open analog dsp [%d]\n",minor);
-	return btaudio_dsp_open(inode,file,bta,1);
-}
-
-static int btaudio_dsp_release(struct inode *inode, struct file *file)
-{
-	struct btaudio *bta = file->private_data;
-
-	mutex_lock(&bta->lock);
-	if (bta->recording)
-		stop_recording(bta);
-	bta->users--;
-	mutex_unlock(&bta->lock);
-	return 0;
-}
-
-static ssize_t btaudio_dsp_read(struct file *file, char __user *buffer,
-				size_t swcount, loff_t *ppos)
-{
-	struct btaudio *bta = file->private_data;
-	int hwcount = swcount << bta->sampleshift;
-	int nsrc, ndst, err, ret = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&bta->readq, &wait);
-	mutex_lock(&bta->lock);
-	while (swcount > 0) {
-		if (0 == bta->read_count) {
-			if (!bta->recording) {
-				if (0 != (err = start_recording(bta))) {
-					if (0 == ret)
-						ret = err;
-					break;
-				}
-			}
-			if (file->f_flags & O_NONBLOCK) {
-				if (0 == ret)
-					ret = -EAGAIN;
-				break;
-			}
-			mutex_unlock(&bta->lock);
-			current->state = TASK_INTERRUPTIBLE;
-			schedule();
-			mutex_lock(&bta->lock);
-			if(signal_pending(current)) {
-				if (0 == ret)
-					ret = -EINTR;
-				break;
-			}
-		}
-		nsrc = (bta->read_count < hwcount) ? bta->read_count : hwcount;
-		if (nsrc > bta->buf_size - bta->read_offset)
-			nsrc = bta->buf_size - bta->read_offset;
-		ndst = nsrc >> bta->sampleshift;
-		
-		if ((bta->analog  && 0 == bta->sampleshift) ||
-		    (!bta->analog && 2 == bta->channels)) {
-			/* just copy */
-			if (copy_to_user(buffer + ret, bta->buf_cpu + bta->read_offset, nsrc)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-
-		} else if (!bta->analog) {
-			/* stereo => mono (digital audio) */
-			__s16 *src = (__s16*)(bta->buf_cpu + bta->read_offset);
-			__s16 __user *dst = (__s16 __user *)(buffer + ret);
-			__s16 avg;
-			int n = ndst>>1;
-			if (!access_ok(VERIFY_WRITE, dst, ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, dst++) {
-				avg  = (__s16)le16_to_cpu(*src) / 2; src++;
-				avg += (__s16)le16_to_cpu(*src) / 2; src++;
-				__put_user(cpu_to_le16(avg),dst);
-			}
-
-		} else if (8 == bta->bits) {
-			/* copy + byte downsampling (audio A/D) */
-			__u8 *src = bta->buf_cpu + bta->read_offset;
-			__u8 __user *dst = buffer + ret;
-			int n = ndst;
-			if (!access_ok(VERIFY_WRITE, dst, ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, src += (1 << bta->sampleshift), dst++)
-				__put_user(*src, dst);
-
-		} else {
-			/* copy + word downsampling (audio A/D) */
-			__u16 *src = (__u16*)(bta->buf_cpu + bta->read_offset);
-			__u16 __user *dst = (__u16 __user *)(buffer + ret);
-			int n = ndst>>1;
-			if (!access_ok(VERIFY_WRITE,dst,ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, src += (1 << bta->sampleshift), dst++)
-				__put_user(*src, dst);
-		}
-
-		ret     += ndst;
-		swcount -= ndst;
-		hwcount -= nsrc;
-		bta->read_count  -= nsrc;
-		bta->read_offset += nsrc;
-		if (bta->read_offset == bta->buf_size)
-			bta->read_offset = 0;
-	}
-	mutex_unlock(&bta->lock);
-	remove_wait_queue(&bta->readq, &wait);
-	current->state = TASK_RUNNING;
-	return ret;
-}
-
-static ssize_t btaudio_dsp_write(struct file *file, const char __user *buffer,
-				 size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-static int btaudio_dsp_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct btaudio *bta = file->private_data;
-	int s, i, ret, val = 0;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-	
-        switch (cmd) {
-        case OSS_GETVERSION:
-                return put_user(SOUND_VERSION, p);
-        case SNDCTL_DSP_GETCAPS:
-		return 0;
-
-        case SNDCTL_DSP_SPEED:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (bta->analog) {
-			for (s = 0; s < 16; s++)
-				if (val << s >= HWBASE_AD*4/15)
-					break;
-			for (i = 15; i >= 5; i--)
-				if (val << s <= HWBASE_AD*4/i)
-					break;
-			bta->sampleshift = s;
-			bta->decimation  = i;
-			if (debug)
-				printk(KERN_DEBUG "btaudio: rate: req=%d  "
-				       "dec=%d shift=%d hwrate=%d swrate=%d\n",
-				       val,i,s,(HWBASE_AD*4/i),(HWBASE_AD*4/i)>>s);
-		} else {
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			bta->decimation  = 0;
-		}
-		if (bta->recording) {
-			mutex_lock(&bta->lock);
-			stop_recording(bta);
-			start_recording(bta);
-			mutex_unlock(&bta->lock);
-		}
-		/* fall through */
-        case SOUND_PCM_READ_RATE:
-		if (bta->analog) {
-			return put_user(HWBASE_AD*4/bta->decimation>>bta->sampleshift, p);
-		} else {
-			return put_user(bta->rate, p);
-		}
-
-        case SNDCTL_DSP_STEREO:
-		if (!bta->analog) {
-			if (get_user(val, p))
-				return -EFAULT;
-			bta->channels    = (val > 0) ? 2 : 1;
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			if (debug)
-				printk(KERN_INFO
-				       "btaudio: stereo=%d channels=%d\n",
-				       val,bta->channels);
-		} else {
-			if (val == 1)
-				return -EFAULT;
-			else {
-				bta->channels = 1;
-				if (debug)
-					printk(KERN_INFO
-					       "btaudio: stereo=0 channels=1\n");
-			}
-		}
-		return put_user((bta->channels)-1, p);
-
-        case SNDCTL_DSP_CHANNELS:
-		if (!bta->analog) {
-			if (get_user(val, p))
-				return -EFAULT;
-			bta->channels    = (val > 1) ? 2 : 1;
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			if (debug)
-				printk(KERN_DEBUG
-				       "btaudio: val=%d channels=%d\n",
-				       val,bta->channels);
-		}
-		/* fall through */
-        case SOUND_PCM_READ_CHANNELS:
-		return put_user(bta->channels, p);
-		
-        case SNDCTL_DSP_GETFMTS: /* Returns a mask */
-		if (bta->analog)
-			return put_user(AFMT_S16_LE|AFMT_S8, p);
-		else
-			return put_user(AFMT_S16_LE, p);
-
-        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		if (get_user(val, p))
-			return -EFAULT;
-                if (val != AFMT_QUERY) {
-			if (bta->analog)
-				bta->bits = (val == AFMT_S8) ? 8 : 16;
-			else
-				bta->bits = 16;
-			if (bta->recording) {
-				mutex_lock(&bta->lock);
-				stop_recording(bta);
-				start_recording(bta);
-				mutex_unlock(&bta->lock);
-			}
-		}
-		if (debug)
-			printk(KERN_DEBUG "btaudio: fmt: bits=%d\n",bta->bits);
-                return put_user((bta->bits==16) ? AFMT_S16_LE : AFMT_S8,
-				p);
-		break;
-        case SOUND_PCM_READ_BITS:
-		return put_user(bta->bits, p);
-
-        case SNDCTL_DSP_NONBLOCK:
-                file->f_flags |= O_NONBLOCK;
-                return 0;
-
-        case SNDCTL_DSP_RESET:
-		if (bta->recording) {
-			mutex_lock(&bta->lock);
-			stop_recording(bta);
-			mutex_unlock(&bta->lock);
-		}
-		return 0;
-        case SNDCTL_DSP_GETBLKSIZE:
-		if (!bta->recording) {
-			if (0 != (ret = alloc_buffer(bta)))
-				return ret;
-			if (0 != (ret = make_risc(bta)))
-				return ret;
-		}
-		return put_user(bta->block_bytes>>bta->sampleshift,p);
-
-        case SNDCTL_DSP_SYNC:
-		/* NOP */
-		return 0;
-	case SNDCTL_DSP_GETISPACE:
-	{
-		audio_buf_info info;
-		if (!bta->recording)
-			return -EINVAL;
-		info.fragsize = bta->block_bytes>>bta->sampleshift;
-		info.fragstotal = bta->block_count;
-		info.bytes = bta->read_count;
-		info.fragments = info.bytes / info.fragsize;
-		if (debug)
-			printk(KERN_DEBUG "btaudio: SNDCTL_DSP_GETISPACE "
-			       "returns %d/%d/%d/%d\n",
-			       info.fragsize, info.fragstotal,
-			       info.bytes, info.fragments);
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-#if 0 /* TODO */
-        case SNDCTL_DSP_GETTRIGGER:
-        case SNDCTL_DSP_SETTRIGGER:
-        case SNDCTL_DSP_SETFRAGMENT:
-#endif
-	default:
-		return -EINVAL;
-	}
-}
-
-static unsigned int btaudio_dsp_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct btaudio *bta = file->private_data;
-	unsigned int mask = 0;
-
-	poll_wait(file, &bta->readq, wait);
-
-	if (0 != bta->read_count)
-		mask |= (POLLIN | POLLRDNORM);
-
-	return mask;
-}
-
-static const struct file_operations btaudio_digital_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_dsp_open_digital,
-	.release	= btaudio_dsp_release,
-	.read		= btaudio_dsp_read,
-	.write		= btaudio_dsp_write,
-	.ioctl		= btaudio_dsp_ioctl,
-	.poll		= btaudio_dsp_poll,
-};
-
-static const struct file_operations btaudio_analog_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_dsp_open_analog,
-	.release	= btaudio_dsp_release,
-	.read		= btaudio_dsp_read,
-	.write		= btaudio_dsp_write,
-	.ioctl		= btaudio_dsp_ioctl,
-	.poll		= btaudio_dsp_poll,
-};
-
-/* -------------------------------------------------------------- */
-
-static char *irq_name[] = { "", "", "", "OFLOW", "", "", "", "", "", "", "",
-			    "RISCI", "FBUS", "FTRGT", "FDSR", "PPERR",
-			    "RIPERR", "PABORT", "OCERR", "SCERR" };
-
-static irqreturn_t btaudio_irq(int irq, void *dev_id)
-{
-	int count = 0;
-	u32 stat,astat;
-	struct btaudio *bta = dev_id;
-	int handled = 0;
-
-	for (;;) {
-		count++;
-		stat  = btread(REG_INT_STAT);
-		astat = stat & btread(REG_INT_MASK);
-		if (!astat)
-			return IRQ_RETVAL(handled);
-		handled = 1;
-		btwrite(astat,REG_INT_STAT);
-
-		if (irq_debug) {
-			int i;
-			printk(KERN_DEBUG "btaudio: irq loop=%d risc=%x, bits:",
-			       count, stat>>28);
-			for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
-				if (stat & (1 << i))
-					printk(" %s",irq_name[i]);
-				if (astat & (1 << i))
-					printk("*");
-			}
-			printk("\n");
-		}
-		if (stat & IRQ_RISCI) {
-			int blocks;
-			blocks = (stat >> 28) - bta->dma_block;
-			if (blocks < 0)
-				blocks += bta->block_count;
-			bta->dma_block = stat >> 28;
-			if (bta->read_count + 2*bta->block_bytes > bta->buf_size) {
-				stop_recording(bta);
-				printk(KERN_INFO "btaudio: buffer overrun\n");
-			}
-			if (blocks > 0) {
-				bta->read_count += blocks * bta->block_bytes;
-				wake_up_interruptible(&bta->readq);
-			}
-		}
-		if (count > 10) {
-			printk(KERN_WARNING
-			       "btaudio: Oops - irq mask cleared\n");
-			btwrite(0, REG_INT_MASK);
-		}
-	}
-	return IRQ_NONE;
-}
-
-/* -------------------------------------------------------------- */
-
-static unsigned int dsp1 = -1;
-static unsigned int dsp2 = -1;
-static unsigned int mixer = -1;
-static int latency = -1;
-static int digital = 1;
-static int analog = 1;
-static int rate;
-
-#define BTA_OSPREY200 1
-
-static struct cardinfo cards[] = {
-	[0] = {
-		.name	= "default",
-		.rate	= 32000,
-	},
-	[BTA_OSPREY200] = {
-		.name	= "Osprey 200",
-		.rate	= 44100,
-	},
-};
-
-static int __devinit btaudio_probe(struct pci_dev *pci_dev,
-				   const struct pci_device_id *pci_id)
-{
-	struct btaudio *bta;
-	struct cardinfo *card = &cards[pci_id->driver_data];
-	unsigned char revision,lat;
-	int rc = -EBUSY;
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-	if (!request_mem_region(pci_resource_start(pci_dev,0),
-				pci_resource_len(pci_dev,0),
-				"btaudio")) {
-		return -EBUSY;
-	}
-
-	bta = kzalloc(sizeof(*bta),GFP_ATOMIC);
-	if (!bta) {
-		rc = -ENOMEM;
-		goto fail0;
-	}
-
-	bta->pci  = pci_dev;
-	bta->irq  = pci_dev->irq;
-	bta->mem  = pci_resource_start(pci_dev,0);
-	bta->mmio = ioremap(pci_resource_start(pci_dev,0),
-			    pci_resource_len(pci_dev,0));
-
-	bta->source     = 1;
-	bta->bits       = 8;
-	bta->channels   = 1;
-	if (bta->analog) {
-		bta->decimation  = 15;
-	} else {
-		bta->decimation  = 0;
-		bta->sampleshift = 1;
-	}
-
-	/* sample rate */
-	bta->rate = card->rate;
-	if (rate)
-		bta->rate = rate;
-	
-	mutex_init(&bta->lock);
-        init_waitqueue_head(&bta->readq);
-
-	if (-1 != latency) {
-		printk(KERN_INFO "btaudio: setting pci latency timer to %d\n",
-		       latency);
-		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
-	}
-        pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
-        pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
-        printk(KERN_INFO "btaudio: Bt%x (rev %d) at %02x:%02x.%x, ",
-	       pci_dev->device,revision,pci_dev->bus->number,
-	       PCI_SLOT(pci_dev->devfn),PCI_FUNC(pci_dev->devfn));
-        printk("irq: %d, latency: %d, mmio: 0x%lx\n",
-	       bta->irq, lat, bta->mem);
-	printk("btaudio: using card config \"%s\"\n", card->name);
-
-	/* init hw */
-        btwrite(0, REG_GPIO_DMA_CTL);
-        btwrite(0, REG_INT_MASK);
-        btwrite(~0U, REG_INT_STAT);
-	pci_set_master(pci_dev);
-
-	if ((rc = request_irq(bta->irq, btaudio_irq, IRQF_SHARED|IRQF_DISABLED,
-			      "btaudio",(void *)bta)) < 0) {
-		printk(KERN_WARNING
-		       "btaudio: can't request irq (rc=%d)\n",rc);
-		goto fail1;
-	}
-
-	/* register devices */
-	if (digital) {
-		rc = bta->dsp_digital =
-			register_sound_dsp(&btaudio_digital_dsp_fops,dsp1);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register digital dsp (rc=%d)\n",rc);
-			goto fail2;
-		}
-		printk(KERN_INFO "btaudio: registered device dsp%d [digital]\n",
-		       bta->dsp_digital >> 4);
-	}
-	if (analog) {
-		rc = bta->dsp_analog =
-			register_sound_dsp(&btaudio_analog_dsp_fops,dsp2);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register analog dsp (rc=%d)\n",rc);
-			goto fail3;
-		}
-		printk(KERN_INFO "btaudio: registered device dsp%d [analog]\n",
-		       bta->dsp_analog >> 4);
-		rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register mixer (rc=%d)\n",rc);
-			goto fail4;
-		}
-		printk(KERN_INFO "btaudio: registered device mixer%d\n",
-		       bta->mixer_dev >> 4);
-	}
-
-	/* hook into linked list */
-	bta->next = btaudios;
-	btaudios = bta;
-
-	pci_set_drvdata(pci_dev,bta);
-        return 0;
-
- fail4:
-	unregister_sound_dsp(bta->dsp_analog);
- fail3:
-	if (digital)
-		unregister_sound_dsp(bta->dsp_digital);
- fail2:
-        free_irq(bta->irq,bta);	
- fail1:
-	iounmap(bta->mmio);
-	kfree(bta);
- fail0:
-	release_mem_region(pci_resource_start(pci_dev,0),
-			   pci_resource_len(pci_dev,0));
-	return rc;
-}
-
-static void __devexit btaudio_remove(struct pci_dev *pci_dev)
-{
-	struct btaudio *bta = pci_get_drvdata(pci_dev);
-	struct btaudio *walk;
-
-	/* turn off all DMA / IRQs */
-        btand(~15, REG_GPIO_DMA_CTL);
-        btwrite(0, REG_INT_MASK);
-        btwrite(~0U, REG_INT_STAT);
-
-	/* unregister devices */
-	if (digital) {
-		unregister_sound_dsp(bta->dsp_digital);
-	}
-	if (analog) {
-		unregister_sound_dsp(bta->dsp_analog);
-		unregister_sound_mixer(bta->mixer_dev);
-	}
-
-	/* free resources */
-	free_buffer(bta);
-        free_irq(bta->irq,bta);
-	release_mem_region(pci_resource_start(pci_dev,0),
-			   pci_resource_len(pci_dev,0));
-	iounmap(bta->mmio);
-
-	/* remove from linked list */
-	if (bta == btaudios) {
-		btaudios = NULL;
-	} else {
-		for (walk = btaudios; walk->next != bta; walk = walk->next)
-			; /* if (NULL == walk->next) BUG(); */
-		walk->next = bta->next;
-	}
-
-	pci_set_drvdata(pci_dev, NULL);
-	kfree(bta);
-	return;
-}
-
-/* -------------------------------------------------------------- */
-
-static struct pci_device_id btaudio_pci_tbl[] = {
-        {
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= 0x0070,
-		.subdevice	= 0xff01,
-		.driver_data	= BTA_OSPREY200,
-	},{
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-	},{
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-        },{
-		/* --- end of list --- */
-	}
-};
-
-static struct pci_driver btaudio_pci_driver = {
-        .name		= "btaudio",
-        .id_table	= btaudio_pci_tbl,
-        .probe		= btaudio_probe,
-        .remove		=  __devexit_p(btaudio_remove),
-};
-
-static int btaudio_init_module(void)
-{
-	printk(KERN_INFO "btaudio: driver version 0.7 loaded [%s%s%s]\n",
-	       digital ? "digital" : "",
-	       analog && digital ? "+" : "",
-	       analog ? "analog" : "");
-	return pci_register_driver(&btaudio_pci_driver);
-}
-
-static void btaudio_cleanup_module(void)
-{
-	pci_unregister_driver(&btaudio_pci_driver);
-	return;
-}
-
-module_init(btaudio_init_module);
-module_exit(btaudio_cleanup_module);
-
-module_param(dsp1, int, S_IRUGO);
-module_param(dsp2, int, S_IRUGO);
-module_param(mixer, int, S_IRUGO);
-module_param(debug, int, S_IRUGO | S_IWUSR);
-module_param(irq_debug, int, S_IRUGO | S_IWUSR);
-module_param(digital, int, S_IRUGO);
-module_param(analog, int, S_IRUGO);
-module_param(rate, int, S_IRUGO);
-module_param(latency, int, S_IRUGO);
-MODULE_PARM_DESC(latency,"pci latency timer");
-
-MODULE_DEVICE_TABLE(pci, btaudio_pci_tbl);
-MODULE_DESCRIPTION("bt878 audio dma driver");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
deleted file mode 100644
index de40e21..0000000
--- a/sound/oss/cs4232.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- *	cs4232.c
- *
- * The low level driver for Crystal CS4232 based cards. The CS4232 is
- * a PnP compatible chip which contains a CS4231A codec, SB emulation,
- * a MPU401 compatible MIDI port, joystick and synthesizer and IDE CD-ROM 
- * interfaces. This is just a temporary driver until full PnP support
- * gets implemented. Just the WSS codec, FM synth and the MIDI ports are
- * supported. Other interfaces are left uninitialized.
- *
- * ifdef ...WAVEFRONT...
- * 
- *   Support is provided for initializing the WaveFront synth
- *   interface as well, which is logical device #4. Note that if
- *   you have a Tropez+ card, you probably don't need to setup
- *   the CS4232-supported MIDI interface, since it corresponds to
- *   the internal 26-pin header that's hard to access. Using this
- *   requires an additional IRQ, a resource none too plentiful in
- *   this environment. Just don't set module parameters mpuio and
- *   mpuirq, and the MIDI port will be left uninitialized. You can
- *   still use the ICS2115 hosted MIDI interface which corresponds
- *   to the 9-pin D connector on the back of the card.
- *
- * endif  ...WAVEFRONT...
- *
- * Supported chips are:
- *      CS4232
- *      CS4236
- *      CS4236B
- *
- * Note: You will need a PnP config setup to initialise some CS4232 boards
- * anyway.
- *
- * Changes
- *      John Rood               Added Bose Sound System Support.
- *      Toshio Spoor
- *	Alan Cox		Modularisation, Basic cleanups.
- *      Paul Barton-Davis	Separated MPU configuration, added
- *                                       Tropez+ (WaveFront) support
- *	Christoph Hellwig	Adapted to module_init/module_exit,
- * 					simple cleanups
- * 	Arnaldo C. de Melo	got rid of attach_uart401
- *	Bartlomiej Zolnierkiewicz
- *				Added some __init/__initdata/__exit
- *	Marcus Meissner		Added ISA PnP support.
- */
-
-#include <linux/pnp.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "sound_config.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-#define KEY_PORT	0x279	/* Same as LPT1 status port */
-#define CSN_NUM		0x99	/* Just a random number */
-#define INDEX_ADDRESS   0x00    /* (R0) Index Address Register */
-#define INDEX_DATA      0x01    /* (R1) Indexed Data Register */
-#define PIN_CONTROL     0x0a    /* (I10) Pin Control */
-#define ENABLE_PINS     0xc0    /* XCTRL0/XCTRL1 enable */
-
-static void CS_OUT(unsigned char a)
-{
-	outb(a, KEY_PORT);
-}
-
-#define CS_OUT2(a, b)		{CS_OUT(a);CS_OUT(b);}
-#define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
-
-static int __initdata bss       = 0;
-static int mpu_base, mpu_irq;
-static int synth_base, synth_irq;
-static int mpu_detected;
-
-static int probe_cs4232_mpu(struct address_info *hw_config)
-{
-	/*
-	 *	Just write down the config values.
-	 */
-
-	mpu_base = hw_config->io_base;
-	mpu_irq = hw_config->irq;
-
-	return 1;
-}
-
-static unsigned char crystal_key[] =	/* A 32 byte magic key sequence */
-{
-	0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
-	0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
-	0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
-	0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
-};
-
-static void sleep(unsigned howlong)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(howlong);
-}
-
-static void enable_xctrl(int baseio)
-{
-        unsigned char regd;
-                
-        /*
-         * Some IBM Aptiva's have the Bose Sound System. By default
-         * the Bose Amplifier is disabled. The amplifier will be 
-         * activated, by setting the XCTRL0 and XCTRL1 bits.
-         * Volume of the monitor bose speakers/woofer, can then
-         * be set by changing the PCM volume.
-         *
-         */
-                
-        printk("cs4232: enabling Bose Sound System Amplifier.\n");
-        
-        /* Switch to Pin Control Address */                   
-        regd = inb(baseio + INDEX_ADDRESS) & 0xe0;
-        outb(((unsigned char) (PIN_CONTROL | regd)), baseio + INDEX_ADDRESS );
-        
-        /* Activate the XCTRL0 and XCTRL1 Pins */
-        regd = inb(baseio + INDEX_DATA);
-        outb(((unsigned char) (ENABLE_PINS | regd)), baseio + INDEX_DATA );
-}
-
-static int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
-{
-	int i, n;
-	int base = hw_config->io_base, irq = hw_config->irq;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-	struct resource *ports;
-
-	if (base == -1 || irq == -1 || dma1 == -1) {
-		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
-		return 0;
-	}
-
-	/*
-	 * Verify that the I/O port range is free.
-	 */
-
-	ports = request_region(base, 4, "ad1848");
-	if (!ports) {
-		printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
-		return 0;
-	}
-	if (ad1848_detect(ports, NULL, hw_config->osp)) {
-		goto got_it;	/* The card is already active */
-	}
-	if (isapnp_configured) {
-		printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
-		goto fail;
-	}
-
-	/*
-	 * This version of the driver doesn't use the PnP method when configuring
-	 * the card but a simplified method defined by Crystal. This means that
-	 * just one CS4232 compatible device can exist on the system. Also this
-	 * method conflicts with possible PnP support in the OS. For this reason 
-	 * driver is just a temporary kludge.
-	 *
-	 * Also the Cirrus/Crystal method doesn't always work. Try ISA PnP first ;)
-	 */
-
-	/*
-	 * Repeat initialization few times since it doesn't always succeed in
-	 * first time.
-	 */
-
-	for (n = 0; n < 4; n++)
-	{	
-		/*
-		 *	Wake up the card by sending a 32 byte Crystal key to the key port.
-		 */
-		
-		for (i = 0; i < 32; i++)
-			CS_OUT(crystal_key[i]);
-
-		sleep(HZ / 10);
-
-		/*
-		 *	Now set the CSN (Card Select Number).
-		 */
-
-		CS_OUT2(0x06, CSN_NUM);
-
-		/*
-		 *	Then set some config bytes. First logical device 0 
-		 */
-
-		CS_OUT2(0x15, 0x00);	/* Select logical device 0 (WSS/SB/FM) */
-		CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff);	/* WSS base */
-
-		if (!request_region(0x388, 4, "FM"))	/* Not free */
-			CS_OUT3(0x48, 0x00, 0x00)	/* FM base off */
-		else {
-			release_region(0x388, 4);
-			CS_OUT3(0x48, 0x03, 0x88);	/* FM base 0x388 */
-		}
-
-		CS_OUT3(0x42, 0x00, 0x00);	/* SB base off */
-		CS_OUT2(0x22, irq);		/* SB+WSS IRQ */
-		CS_OUT2(0x2a, dma1);		/* SB+WSS DMA */
-
-		if (dma2 != -1)
-			CS_OUT2(0x25, dma2)	/* WSS DMA2 */
-		else
-			CS_OUT2(0x25, 4);	/* No WSS DMA2 */
-
-		CS_OUT2(0x33, 0x01);	/* Activate logical dev 0 */
-
-		sleep(HZ / 10);
-
-		/*
-		 * Initialize logical device 3 (MPU)
-		 */
-
-		if (mpu_base != 0 && mpu_irq != 0)
-		{
-			CS_OUT2(0x15, 0x03);	/* Select logical device 3 (MPU) */
-			CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff);	/* MPU base */
-			CS_OUT2(0x22, mpu_irq);	/* MPU IRQ */
-			CS_OUT2(0x33, 0x01);	/* Activate logical dev 3 */
-		}
-
-		if(synth_base != 0)
-		{
-		    CS_OUT2 (0x15, 0x04);	        /* logical device 4 (WaveFront) */
-		    CS_OUT3 (0x47, (synth_base >> 8) & 0xff,
-			     synth_base & 0xff);	/* base */
-		    CS_OUT2 (0x22, synth_irq);     	/* IRQ */
-		    CS_OUT2 (0x33, 0x01);	        /* Activate logical dev 4 */
-		}
-
-		/*
-		 * Finally activate the chip
-		 */
-		
-		CS_OUT(0x79);
-
-		sleep(HZ / 5);
-
-		/*
-		 * Then try to detect the codec part of the chip
-		 */
-
-		if (ad1848_detect(ports, NULL, hw_config->osp))
-			goto got_it;
-		
-		sleep(HZ);
-	}
-fail:
-	release_region(base, 4);
-	return 0;
-
-got_it:
-	if (dma2 == -1)
-		dma2 = dma1;
-
-	hw_config->slots[0] = ad1848_init("Crystal audio controller", ports,
-					  irq,
-					  dma1,		/* Playback DMA */
-					  dma2,		/* Capture DMA */
-					  0,
-					  hw_config->osp,
-					  THIS_MODULE);
-
-	if (hw_config->slots[0] != -1 &&
-		audio_devs[hw_config->slots[0]]->mixer_dev!=-1)
-	{	
-		/* Assume the mixer map is as suggested in the CS4232 databook */
-		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
-		AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
-		AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);		/* FM synth */
-	}
-	if (mpu_base != 0 && mpu_irq != 0)
-	{
-		static struct address_info hw_config2 = {
-			0
-		};		/* Ensure it's initialized */
-
-		hw_config2.io_base = mpu_base;
-		hw_config2.irq = mpu_irq;
-		hw_config2.dma = -1;
-		hw_config2.dma2 = -1;
-		hw_config2.always_detect = 0;
-		hw_config2.name = NULL;
-		hw_config2.driver_use_1 = 0;
-		hw_config2.driver_use_2 = 0;
-		hw_config2.card_subtype = 0;
-
-		if (probe_uart401(&hw_config2, THIS_MODULE))
-		{
-			mpu_detected = 1;
-		}
-		else
-		{
-			mpu_base = mpu_irq = 0;
-		}
-		hw_config->slots[1] = hw_config2.slots[1];
-	}
-	
-	if (bss)
-        	enable_xctrl(base);
-
-	return 1;
-}
-
-static void __devexit unload_cs4232(struct address_info *hw_config)
-{
-	int base = hw_config->io_base, irq = hw_config->irq;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-
-	if (dma2 == -1)
-		dma2 = dma1;
-
-	ad1848_unload(base,
-		      irq,
-		      dma1,	/* Playback DMA */
-		      dma2,	/* Capture DMA */
-		      0);
-
-	sound_unload_audiodev(hw_config->slots[0]);
-	if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
-	{
-		static struct address_info hw_config2 =
-		{
-			0
-		};		/* Ensure it's initialized */
-
-		hw_config2.io_base = mpu_base;
-		hw_config2.irq = mpu_irq;
-		hw_config2.dma = -1;
-		hw_config2.dma2 = -1;
-		hw_config2.always_detect = 0;
-		hw_config2.name = NULL;
-		hw_config2.driver_use_1 = 0;
-		hw_config2.driver_use_2 = 0;
-		hw_config2.card_subtype = 0;
-		hw_config2.slots[1] = hw_config->slots[1];
-
-		unload_uart401(&hw_config2);
-	}
-}
-
-static struct address_info cfg;
-static struct address_info cfg_mpu;
-
-static int __initdata io	= -1;
-static int __initdata irq	= -1;
-static int __initdata dma	= -1;
-static int __initdata dma2	= -1;
-static int __initdata mpuio	= -1;
-static int __initdata mpuirq	= -1;
-static int __initdata synthio	= -1;
-static int __initdata synthirq	= -1;
-static int __initdata isapnp	= 1;
-
-static unsigned int cs4232_devices;
-
-MODULE_DESCRIPTION("CS4232 based soundcard driver"); 
-MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); 
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io,"base I/O port for AD1848");
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq,"IRQ for AD1848 chip");
-module_param(dma, int, 0);
-MODULE_PARM_DESC(dma,"8 bit DMA for AD1848 chip");
-module_param(dma2, int, 0);
-MODULE_PARM_DESC(dma2,"16 bit DMA for AD1848 chip");
-module_param(mpuio, int, 0);
-MODULE_PARM_DESC(mpuio,"MPU 401 base address");
-module_param(mpuirq, int, 0);
-MODULE_PARM_DESC(mpuirq,"MPU 401 IRQ");
-module_param(synthio, int, 0);
-MODULE_PARM_DESC(synthio,"Maui WaveTable base I/O port");
-module_param(synthirq, int, 0);
-MODULE_PARM_DESC(synthirq,"Maui WaveTable IRQ");
-module_param(isapnp, bool, 0);
-MODULE_PARM_DESC(isapnp,"Enable ISAPnP probing (default 1)");
-module_param(bss, bool, 0);
-MODULE_PARM_DESC(bss,"Enable Bose Sound System Support (default 0)");
-
-/*
- *	Install a CS4232 based card. Need to have ad1848 and mpu401
- *	loaded ready.
- */
-
-/* All cs4232 based cards have the main ad1848 card either as CSC0000 or
- * CSC0100. */
-static const struct pnp_device_id cs4232_pnp_table[] = {
-	{ .id = "CSC0100", .driver_data = 0 },
-	{ .id = "CSC0000", .driver_data = 0 },
-	/* Guillemot Turtlebeach something appears to be cs4232 compatible
-	 * (untested) */
-	{ .id = "GIM0100", .driver_data = 0 },
-	{ .id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, cs4232_pnp_table);
-
-static int __init cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
-	struct address_info *isapnpcfg;
-
-	isapnpcfg = kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
-	if (!isapnpcfg)
-		return -ENOMEM;
-
-	isapnpcfg->irq		= pnp_irq(dev, 0);
-	isapnpcfg->dma		= pnp_dma(dev, 0);
-	isapnpcfg->dma2		= pnp_dma(dev, 1);
-	isapnpcfg->io_base	= pnp_port_start(dev, 0);
-	if (probe_cs4232(isapnpcfg,TRUE) == 0) {
-		printk(KERN_ERR "cs4232: ISA PnP card found, but not detected?\n");
-		kfree(isapnpcfg);
-		return -ENODEV;
-	}
-	pnp_set_drvdata(dev,isapnpcfg);
-	cs4232_devices++;
-	return 0;
-}
-
-static void __devexit cs4232_pnp_remove(struct pnp_dev *dev)
-{
-	struct address_info *cfg = pnp_get_drvdata(dev);
-	if (cfg) {
-		unload_cs4232(cfg);
-		kfree(cfg);
-	}
-}
-
-static struct pnp_driver cs4232_driver = {
-	.name		= "cs4232",
-	.id_table	= cs4232_pnp_table,
-	.probe		= cs4232_pnp_probe,
-	.remove		= __devexit_p(cs4232_pnp_remove),
-};
-
-static int __init init_cs4232(void)
-{
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
-	if(synthio == -1)
-		printk(KERN_INFO "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
-	else {
-		synth_base = synthio;
-		synth_irq =  synthirq;
-	}
-#else
-	if(synthio != -1)
-		printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n");
-#endif
-	cfg.irq = -1;
-
-	if (isapnp) {
-		pnp_register_driver(&cs4232_driver);
-		if (cs4232_devices)
-			return 0;
-	}
-
-	if(io==-1||irq==-1||dma==-1)
-	{
-		printk(KERN_ERR "cs4232: Must set io, irq and dma.\n");
-		return -ENODEV;
-	}
-
-	cfg.io_base = io;
-	cfg.irq = irq;
-	cfg.dma = dma;
-	cfg.dma2 = dma2;
-
-	cfg_mpu.io_base = -1;
-	cfg_mpu.irq = -1;
-
-	if (mpuio != -1 && mpuirq != -1) {
-		cfg_mpu.io_base = mpuio;
-		cfg_mpu.irq = mpuirq;
-		probe_cs4232_mpu(&cfg_mpu); /* Bug always returns 0 not OK -- AC */
-	}
-
-	if (probe_cs4232(&cfg,FALSE) == 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-static void __exit cleanup_cs4232(void)
-{
-	pnp_unregister_driver(&cs4232_driver);
-        if (cfg.irq != -1)
-		unload_cs4232(&cfg); /* Unloads global MPU as well, if needed */
-}
-
-module_init(init_cs4232);
-module_exit(cleanup_cs4232);
-
-#ifndef MODULE
-static int __init setup_cs4232(char *str)
-{
-	/* io, irq, dma, dma2 mpuio, mpuirq*/
-	int ints[7];
-
-	/* If we have isapnp cards, no need for options */
-	pnp_register_driver(&cs4232_driver);
-	if (cs4232_devices)
-		return 1;
-	
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma2	= ints[4];
-	mpuio	= ints[5];
-	mpuirq	= ints[6];
-
-	return 1;
-}
-
-__setup("cs4232=", setup_cs4232);
-#endif
diff --git a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
index 71b3134..3eb7827 100644
--- a/sound/oss/dmasound/Kconfig
+++ b/sound/oss/dmasound/Kconfig
@@ -14,7 +14,7 @@
 
 config DMASOUND_PAULA
 	tristate "Amiga DMA sound support"
-	depends on (AMIGA || APUS) && SOUND
+	depends on AMIGA && SOUND
 	select DMASOUND
 	help
 	  If you want to use the internal audio of your Amiga in Linux, answer
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
index 90fc058..202e810 100644
--- a/sound/oss/dmasound/dmasound_paula.c
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -91,10 +91,6 @@
      *  power LED are controlled by the same line.
      */
 
-#ifdef CONFIG_APUS
-#define mach_heartbeat	ppc_md.heartbeat
-#endif
-
 static void (*saved_heartbeat)(int) = NULL;
 
 static inline void disable_heartbeat(void)
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
deleted file mode 100644
index f5e31f1..0000000
--- a/sound/oss/i810_audio.c
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- *	Intel i810 and friends ICH driver for Linux
- *	Alan Cox <alan@redhat.com>
- *
- *  Built from:
- *	Low level code:  Zach Brown (original nonworking i810 OSS driver)
- *			 Jaroslav Kysela <perex@suse.cz> (working ALSA driver)
- *
- *	Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *	Extended by: Zach Brown <zab@redhat.com>  
- *			and others..
- *
- *  Hardware Provided By:
- *	Analog Devices (A major AC97 codec maker)
- *	Intel Corp  (you've probably heard of them already)
- *
- *  AC97 clues and assistance provided by
- *	Analog Devices
- *	Zach 'Fufu' Brown
- *	Jeff Garzik
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	Intel 810 theory of operation
- *
- *	The chipset provides three DMA channels that talk to an AC97
- *	CODEC (AC97 is a digital/analog mixer standard). At its simplest
- *	you get 48Khz audio with basic volume and mixer controls. At the
- *	best you get rate adaption in the codec. We set the card up so
- *	that we never take completion interrupts but instead keep the card
- *	chasing its tail around a ring buffer. This is needed for mmap
- *	mode audio and happens to work rather well for non-mmap modes too.
- *
- *	The board has one output channel for PCM audio (supported) and
- *	a stereo line in and mono microphone input. Again these are normally
- *	locked to 48Khz only. Right now recording is not finished.
- *
- *	There is no midi support, no synth support. Use timidity. To get
- *	esd working you need to use esd -r 48000 as it won't probe 48KHz
- *	by default. mpg123 can't handle 48Khz only audio so use xmms.
- *
- *	Fix The Sound On Dell
- *
- *	Not everyone uses 48KHz. We know of no way to detect this reliably
- *	and certainly not to get the right data. If your i810 audio sounds
- *	stupid you may need to investigate other speeds. According to Analog
- *	they tend to use a 14.318MHz clock which gives you a base rate of
- *	41194Hz.
- *
- *	This is available via the 'ftsodell=1' option. 
- *
- *	If you need to force a specific rate set the clocking= option
- *
- *	This driver is cursed. (Ben LaHaise)
- *
- *  ICH 3 caveats
- *	Intel errata #7 for ICH3 IO. We need to disable SMI stuff
- *	when codec probing. [Not Yet Done]
- *
- *  ICH 4 caveats
- *
- *	The ICH4 has the feature, that the codec ID doesn't have to be 
- *	congruent with the IO connection.
- * 
- *	Therefore, from driver version 0.23 on, there is a "codec ID" <->
- *	"IO register base offset" mapping (card->ac97_id_map) field.
- *   
- *	Juergen "George" Sawinski (jsaw) 
- */
- 
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/ac97_codec.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-#define DRIVER_VERSION "1.01"
-
-#define MODULOP2(a, b) ((a) & ((b) - 1))
-#define MASKP2(a, b) ((a) & ~((b) - 1))
-
-static int ftsodell;
-static int strict_clocking;
-static unsigned int clocking;
-static int spdif_locked;
-static int ac97_quirk = AC97_TUNE_DEFAULT;
-
-//#define DEBUG
-//#define DEBUG2
-//#define DEBUG_INTERRUPTS
-//#define DEBUG_MMAP
-//#define DEBUG_MMIO
-
-#define ADC_RUNNING	1
-#define DAC_RUNNING	2
-
-#define I810_FMT_16BIT	1
-#define I810_FMT_STEREO	2
-#define I810_FMT_MASK	3
-
-#define SPDIF_ON	0x0004
-#define SURR_ON		0x0010
-#define CENTER_LFE_ON	0x0020
-#define VOL_MUTED	0x8000
-
-/* the 810's array of pointers to data buffers */
-
-struct sg_item {
-#define BUSADDR_MASK	0xFFFFFFFE
-	u32 busaddr;	
-#define CON_IOC 	0x80000000 /* interrupt on completion */
-#define CON_BUFPAD	0x40000000 /* pad underrun with last sample, else 0 */
-#define CON_BUFLEN_MASK	0x0000ffff /* buffer length in samples */
-	u32 control;
-};
-
-/* an instance of the i810 channel */
-#define SG_LEN 32
-struct i810_channel 
-{
-	/* these sg guys should probably be allocated
-	   separately as nocache. Must be 8 byte aligned */
-	struct sg_item sg[SG_LEN];	/* 32*8 */
-	u32 offset;			/* 4 */
-	u32 port;			/* 4 */
-	u32 used;
-	u32 num;
-};
-
-/*
- * we have 3 separate dma engines.  pcm in, pcm out, and mic.
- * each dma engine has controlling registers.  These goofy
- * names are from the datasheet, but make it easy to write
- * code while leafing through it.
- *
- * ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2, 
- * mic in 2, s/pdif.   Of special interest is the fact that
- * the upper 3 DMA engines on the ICH4 *must* be accessed
- * via mmio access instead of pio access.
- */
-
-#define ENUM_ENGINE(PRE,DIG) 									\
-enum {												\
-	PRE##_BASE =	0x##DIG##0,		/* Base Address */				\
-	PRE##_BDBAR =	0x##DIG##0,		/* Buffer Descriptor list Base Address */	\
-	PRE##_CIV =	0x##DIG##4,		/* Current Index Value */			\
-	PRE##_LVI =	0x##DIG##5,		/* Last Valid Index */				\
-	PRE##_SR =	0x##DIG##6,		/* Status Register */				\
-	PRE##_PICB =	0x##DIG##8,		/* Position In Current Buffer */		\
-	PRE##_PIV =	0x##DIG##a,		/* Prefetched Index Value */			\
-	PRE##_CR =	0x##DIG##b		/* Control Register */				\
-}
-
-ENUM_ENGINE(OFF,0);	/* Offsets */
-ENUM_ENGINE(PI,0);	/* PCM In */
-ENUM_ENGINE(PO,1);	/* PCM Out */
-ENUM_ENGINE(MC,2);	/* Mic In */
-
-enum {
-	GLOB_CNT =	0x2c,			/* Global Control */
-	GLOB_STA = 	0x30,			/* Global Status */
-	CAS	 = 	0x34			/* Codec Write Semaphore Register */
-};
-
-ENUM_ENGINE(MC2,4);     /* Mic In 2 */
-ENUM_ENGINE(PI2,5);     /* PCM In 2 */
-ENUM_ENGINE(SP,6);      /* S/PDIF */
-
-enum {
-	SDM =           0x80                    /* SDATA_IN Map Register */
-};
-
-/* interrupts for a dma engine */
-#define DMA_INT_FIFO		(1<<4)  /* fifo under/over flow */
-#define DMA_INT_COMPLETE	(1<<3)  /* buffer read/write complete and ioc set */
-#define DMA_INT_LVI		(1<<2)  /* last valid done */
-#define DMA_INT_CELV		(1<<1)  /* last valid is current */
-#define DMA_INT_DCH		(1)	/* DMA Controller Halted (happens on LVI interrupts) */
-#define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI)
-
-/* interrupts for the whole chip */
-#define INT_SEC		(1<<11)
-#define INT_PRI		(1<<10)
-#define INT_MC		(1<<7)
-#define INT_PO		(1<<6)
-#define INT_PI		(1<<5)
-#define INT_MO		(1<<2)
-#define INT_NI		(1<<1)
-#define INT_GPI		(1<<0)
-#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
-
-/* magic numbers to protect our data structures */
-#define I810_CARD_MAGIC		0x5072696E /* "Prin" */
-#define I810_STATE_MAGIC	0x63657373 /* "cess" */
-#define I810_DMA_MASK		0xffffffff /* DMA buffer mask for pci_alloc_consist */
-#define NR_HW_CH		3
-
-/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
-#define NR_AC97                 4
-
-/* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */
-/* stream at a minimum for this card to be happy */
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-/* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift */
-/* values are one less than might be expected */
-static const unsigned sample_shift[] = { -1, 0, 0, 1 };
-
-enum {
-	ICH82801AA = 0,
-	ICH82901AB,
-	INTEL440MX,
-	INTELICH2,
-	INTELICH3,
-	INTELICH4,
-	INTELICH5,
-	SI7012,
-	NVIDIA_NFORCE,
-	AMD768,
-	AMD8111
-};
-
-static char * card_names[] = {
-	"Intel ICH 82801AA",
-	"Intel ICH 82901AB",
-	"Intel 440MX",
-	"Intel ICH2",
-	"Intel ICH3",
-	"Intel ICH4",
-	"Intel ICH5",
-	"SiS 7012",
-	"NVIDIA nForce Audio",
-	"AMD 768",
-	"AMD-8111 IOHub"
-};
-
-/* These are capabilities (and bugs) the chipsets _can_ have */
-static struct {
-	int16_t      nr_ac97;
-#define CAP_MMIO                 0x0001
-#define CAP_20BIT_AUDIO_SUPPORT  0x0002
-	u_int16_t flags;
-} card_cap[] = {
-	{  1, 0x0000 }, /* ICH82801AA */
-	{  1, 0x0000 }, /* ICH82901AB */
-	{  1, 0x0000 }, /* INTEL440MX */
-	{  1, 0x0000 }, /* INTELICH2 */
-	{  2, 0x0000 }, /* INTELICH3 */
- 	{  3, 0x0003 }, /* INTELICH4 */
-	{  3, 0x0003 }, /* INTELICH5 */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* SI7012 */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* NVIDIA_NFORCE */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* AMD768 */
-	/*@FIXME to be verified*/	{  3, 0x0001 }, /* AMD8111 */
-};
-
-static struct pci_device_id i810_pci_tbl [] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE (pci, i810_pci_tbl);
-
-#ifdef CONFIG_PM
-#define PM_SUSPENDED(card) (card->pm_suspended)
-#else
-#define PM_SUSPENDED(card) (0)
-#endif
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct i810_state {
-	unsigned int magic;
-	struct i810_card *card;	/* Card info */
-
-	/* single open lock mechanism, only used for recording */
-	struct mutex open_mutex;
-	wait_queue_head_t open_wait;
-
-	/* file mode */
-	mode_t open_mode;
-
-	/* virtual channel number */
-	int virt;
-
-#ifdef CONFIG_PM
-	unsigned int pm_saved_dac_rate,pm_saved_adc_rate;
-#endif
-	struct dmabuf {
-		/* wave sample stuff */
-		unsigned int rate;
-		unsigned char fmt, enable, trigger;
-
-		/* hardware channel */
-		struct i810_channel *read_channel;
-		struct i810_channel *write_channel;
-
-		/* OSS buffer management stuff */
-		void *rawbuf;
-		dma_addr_t dma_handle;
-		unsigned buforder;
-		unsigned numfrag;
-		unsigned fragshift;
-
-		/* our buffer acts like a circular ring */
-		unsigned hwptr;		/* where dma last started, updated by update_ptr */
-		unsigned swptr;		/* where driver last clear/filled, updated by read/write */
-		int count;		/* bytes to be consumed or been generated by dma machine */
-		unsigned total_bytes;	/* total bytes dmaed by hardware */
-
-		unsigned error;		/* number of over/underruns */
-		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */
-
-		/* redundant, but makes calculations easier */
-		/* what the hardware uses */
-		unsigned dmasize;
-		unsigned fragsize;
-		unsigned fragsamples;
-
-		/* what we tell the user to expect */
-		unsigned userfrags;
-		unsigned userfragsize;
-
-		/* OSS stuff */
-		unsigned mapped:1;
-		unsigned ready:1;
-		unsigned update_flag;
-		unsigned ossfragsize;
-		unsigned ossmaxfrags;
-		unsigned subdivision;
-	} dmabuf;
-};
-
-
-struct i810_card {
-	unsigned int magic;
-
-	/* We keep i810 cards in a linked list */
-	struct i810_card *next;
-
-	/* The i810 has a certain amount of cross channel interaction
-	   so we use a single per card lock */
-	spinlock_t lock;
-	
-	/* Control AC97 access serialization */
-	spinlock_t ac97_lock;
-
-	/* PCI device stuff */
-	struct pci_dev * pci_dev;
-	u16 pci_id;
-	u16 pci_id_internal; /* used to access card_cap[] */
-#ifdef CONFIG_PM	
-	u16 pm_suspended;
-	int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97];
-#endif
-	/* soundcore stuff */
-	int dev_audio;
-
-	/* structures for abstraction of hardware facilities, codecs, banks and channels*/
-	u16    ac97_id_map[NR_AC97];
-	struct ac97_codec *ac97_codec[NR_AC97];
-	struct i810_state *states[NR_HW_CH];
-	struct i810_channel *channel;	/* 1:1 to states[] but diff. lifetime */
-	dma_addr_t chandma;
-
-	u16 ac97_features;
-	u16 ac97_status;
-	u16 channels;
-	
-	/* hardware resources */
-	unsigned long ac97base;
-	unsigned long iobase;
-	u32 irq;
-
-	unsigned long ac97base_mmio_phys;
-	unsigned long iobase_mmio_phys;
-	u_int8_t __iomem *ac97base_mmio;
-	u_int8_t __iomem *iobase_mmio;
-
-	int           use_mmio;
-	
-	/* Function support */
-	struct i810_channel *(*alloc_pcm_channel)(struct i810_card *);
-	struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);
-	struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *);
-	void (*free_pcm_channel)(struct i810_card *, int chan);
-
-	/* We have a *very* long init time possibly, so use this to block */
-	/* attempts to open our devices before we are ready (stops oops'es) */
-	int initializing;
-};
-
-/* extract register offset from codec struct */
-#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
-
-#define I810_IOREAD(size, type, card, off)				\
-({									\
-	type val;							\
-	if (card->use_mmio)						\
-		val=read##size(card->iobase_mmio+off);			\
-	else								\
-		val=in##size(card->iobase+off);				\
-	val;								\
-})
-
-#define I810_IOREADL(card, off)		I810_IOREAD(l, u32, card, off)
-#define I810_IOREADW(card, off)		I810_IOREAD(w, u16, card, off)
-#define I810_IOREADB(card, off)		I810_IOREAD(b, u8,  card, off)
-
-#define I810_IOWRITE(size, val, card, off)				\
-({									\
-	if (card->use_mmio)						\
-		write##size(val, card->iobase_mmio+off);		\
-	else								\
-		out##size(val, card->iobase+off);			\
-})
-
-#define I810_IOWRITEL(val, card, off)	I810_IOWRITE(l, val, card, off)
-#define I810_IOWRITEW(val, card, off)	I810_IOWRITE(w, val, card, off)
-#define I810_IOWRITEB(val, card, off)	I810_IOWRITE(b, val, card, off)
-
-#define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN)
-#define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN)
-
-/* set LVI from CIV */
-#define CIV_TO_LVI(card, port, off) \
-	I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI)
-
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
-	{
-		.vendor = 0x0e11,
-		.device = 0x00b8,
-		.name = "Compaq Evo D510C",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x00d8,
-		.name = "Dell Precision 530",   /* AD1885 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x0126,
-		.name = "Dell Optiplex GX260",  /* AD1981A */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x012d,
-		.name = "Dell Precision 450",   /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{       /* FIXME: which codec? */
-		.vendor = 0x103c,
-		.device = 0x00c3,
-		.name = "Hewlett-Packard onboard",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x12f1,
-		.name = "HP xw8200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x3008,
-		.name = "HP xw4200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x10f1,
-		.device = 0x2665,
-		.name = "Fujitsu-Siemens Celsius",      /* AD1981? */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x10f1,
-		.device = 0x2885,
-		.name = "AMD64 Mobo",   /* ALC650 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x110a,
-		.device = 0x0056,
-		.name = "Fujitsu-Siemens Scenic",       /* AD1981? */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x11d4,
-		.device = 0x5375,
-		.name = "ADI AD1985 (discrete)",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1462,
-		.device = 0x5470,
-		.name = "MSI P4 ATX 645 Ultra",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1734,
-		.device = 0x0088,
-		.name = "Fujitsu-Siemens D1522",	/* AD1981 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4856,
-		.name = "Intel D845WN (82801BA)",
-		.type = AC97_TUNE_SWAP_HP
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4d44,
-		.name = "Intel D850EMV2",       /* AD1885 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4d56,
-		.name = "Intel ICH/AD1885",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x012d,
-		.name = "Dell Precision 450",   /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x3008,
-		.name = "HP xw4200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x12f1,
-		.name = "HP xw8200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{ } /* terminator */
-};
-
-static struct i810_card *devs = NULL;
-
-static int i810_open_mixdev(struct inode *inode, struct file *file);
-static int i810_ioctl_mixdev(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg);
-static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
-static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data);
-static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data);
-
-static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card)
-{
-	if(card->channel[1].used==1)
-		return NULL;
-	card->channel[1].used=1;
-	return &card->channel[1];
-}
-
-static struct i810_channel *i810_alloc_rec_pcm_channel(struct i810_card *card)
-{
-	if(card->channel[0].used==1)
-		return NULL;
-	card->channel[0].used=1;
-	return &card->channel[0];
-}
-
-static struct i810_channel *i810_alloc_rec_mic_channel(struct i810_card *card)
-{
-	if(card->channel[2].used==1)
-		return NULL;
-	card->channel[2].used=1;
-	return &card->channel[2];
-}
-
-static void i810_free_pcm_channel(struct i810_card *card, int channel)
-{
-	card->channel[channel].used=0;
-}
-
-static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate )
-{
-	unsigned long id = 0L;
-
-	id = (i810_ac97_get(codec, AC97_VENDOR_ID1) << 16);
-	id |= i810_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff;
-#ifdef DEBUG
-	printk ( "i810_audio: codec = %s, codec_id = 0x%08lx\n", codec->name, id);
-#endif
-	switch ( id ) {
-		case 0x41445361: /* AD1886 */
-			if (rate == 48000) {
-				return 1;
-			}
-			break;
-		default: /* all other codecs, until we know otherwiae */
-			if (rate == 48000 || rate == 44100 || rate == 32000) {
-				return 1;
-			}
-			break;
-	}
-	return (0);
-}
-
-/* i810_set_spdif_output
- * 
- *  Configure the S/PDIF output transmitter. When we turn on
- *  S/PDIF, we turn off the analog output. This may not be
- *  the right thing to do.
- *
- *  Assumptions:
- *     The DSP sample rate must already be set to a supported
- *     S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort.
- */
-static int i810_set_spdif_output(struct i810_state *state, int slots, int rate)
-{
-	int	vol;
-	int	aud_reg;
-	int	r = 0;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-
-	if(!codec->codec_ops->digital) {
-		state->card->ac97_status &= ~SPDIF_ON;
-	} else {
-		if ( slots == -1 ) { /* Turn off S/PDIF */
-			codec->codec_ops->digital(codec, 0, 0, 0);
-			/* If the volume wasn't muted before we turned on S/PDIF, unmute it */
-			if ( !(state->card->ac97_status & VOL_MUTED) ) {
-				aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
-				i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED));
-			}
-			state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON);
-			return 0;
-		}
-
-		vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
-		state->card->ac97_status = vol & VOL_MUTED;
-		
-		r = codec->codec_ops->digital(codec, slots, rate, 0);
-
-		if(r)
-			state->card->ac97_status |= SPDIF_ON;
-		else
-			state->card->ac97_status &= ~SPDIF_ON;
-
-		/* Mute the analog output */
-		/* Should this only mute the PCM volume??? */
-		i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED));
-	}
-	return r;
-}
-
-/* i810_set_dac_channels
- *
- *  Configure the codec's multi-channel DACs
- *
- *  The logic is backwards. Setting the bit to 1 turns off the DAC. 
- *
- *  What about the ICH? We currently configure it using the
- *  SNDCTL_DSP_CHANNELS ioctl.  If we're turnning on the DAC, 
- *  does that imply that we want the ICH set to support
- *  these channels?
- *  
- *  TODO:
- *    vailidate that the codec really supports these DACs
- *    before turning them on. 
- */
-static void i810_set_dac_channels(struct i810_state *state, int channel)
-{
-	int	aud_reg;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-	
-	/* No codec, no setup */
-	
-	if(codec == NULL)
-		return;
-
-	aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-	aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK;
-	state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON);
-
-	switch ( channel ) {
-		case 2: /* always enabled */
-			break;
-		case 4:
-			aud_reg &= ~AC97_EA_PRJ;
-			state->card->ac97_status |= SURR_ON;
-			break;
-		case 6:
-			aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK);
-			state->card->ac97_status |= SURR_ON | CENTER_LFE_ON;
-			break;
-		default:
-			break;
-	}
-	i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg);
-
-}
-
-
-/* set playback sample rate */
-static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate)
-{	
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 new_rate;
-	struct ac97_codec *codec=state->card->ac97_codec[0];
-	
-	if(!(state->card->ac97_features&0x0001))
-	{
-		dmabuf->rate = clocking;
-#ifdef DEBUG
-		printk("Asked for %d Hz, but ac97_features says we only do %dHz.  Sorry!\n",
-		       rate,clocking);
-#endif		       
-		return clocking;
-	}
-			
-	if (rate > 48000)
-		rate = 48000;
-	if (rate < 8000)
-		rate = 8000;
-	dmabuf->rate = rate;
-		
-	/*
-	 *	Adjust for misclocked crap
-	 */
-	rate = ( rate * clocking)/48000;
-	if(strict_clocking && rate < 8000) {
-		rate = 8000;
-		dmabuf->rate = (rate * 48000)/clocking;
-	}
-
-        new_rate=ac97_set_dac_rate(codec, rate);
-	if(new_rate != rate) {
-		dmabuf->rate = (new_rate * 48000)/clocking;
-	}
-#ifdef DEBUG
-	printk("i810_audio: called i810_set_dac_rate : asked for %d, got %d\n", rate, dmabuf->rate);
-#endif
-	rate = new_rate;
-	return dmabuf->rate;
-}
-
-/* set recording sample rate */
-static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 new_rate;
-	struct ac97_codec *codec=state->card->ac97_codec[0];
-	
-	if(!(state->card->ac97_features&0x0001))
-	{
-		dmabuf->rate = clocking;
-		return clocking;
-	}
-			
-	if (rate > 48000)
-		rate = 48000;
-	if (rate < 8000)
-		rate = 8000;
-	dmabuf->rate = rate;
-
-	/*
-	 *	Adjust for misclocked crap
-	 */
-	 
-	rate = ( rate * clocking)/48000;
-	if(strict_clocking && rate < 8000) {
-		rate = 8000;
-		dmabuf->rate = (rate * 48000)/clocking;
-	}
-
-	new_rate = ac97_set_adc_rate(codec, rate);
-	
-	if(new_rate != rate) {
-		dmabuf->rate = (new_rate * 48000)/clocking;
-		rate = new_rate;
-	}
-#ifdef DEBUG
-	printk("i810_audio: called i810_set_adc_rate : rate = %d/%d\n", dmabuf->rate, rate);
-#endif
-	return dmabuf->rate;
-}
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
-   called with spinlock held! */
-   
-static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned int civ, offset, port, port_picb, bytes = 2;
-	
-	if (!dmabuf->enable)
-		return 0;
-
-	if (rec)
-		port = dmabuf->read_channel->port;
-	else
-		port = dmabuf->write_channel->port;
-
-	if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) {
-		port_picb = port + OFF_SR;
-		bytes = 1;
-	} else
-		port_picb = port + OFF_PICB;
-
-	do {
-		civ = GET_CIV(state->card, port);
-		offset = I810_IOREADW(state->card, port_picb);
-		/* Must have a delay here! */ 
-		if(offset == 0)
-			udelay(1);
-		/* Reread both registers and make sure that that total
-		 * offset from the first reading to the second is 0.
-		 * There is an issue with SiS hardware where it will count
-		 * picb down to 0, then update civ to the next value,
-		 * then set the new picb to fragsize bytes.  We can catch
-		 * it between the civ update and the picb update, making
-		 * it look as though we are 1 fragsize ahead of where we
-		 * are.  The next to we get the address though, it will
-		 * be back in the right place, and we will suddenly think
-		 * we just went forward dmasize - fragsize bytes, causing
-		 * totally stupid *huge* dma overrun messages.  We are
-		 * assuming that the 1us delay is more than long enough
-		 * that we won't have to worry about the chip still being
-		 * out of sync with reality ;-)
-		 */
-	} while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb));
-		 
-	return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
-		% dmabuf->dmasize);
-}
-
-/* Stop recording (lock held) */
-static inline void __stop_adc(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_card *card = state->card;
-
-	dmabuf->enable &= ~ADC_RUNNING;
-	I810_IOWRITEB(0, card, PI_CR);
-	// wait for the card to acknowledge shutdown
-	while( I810_IOREADB(card, PI_CR) != 0 ) ;
-	// now clear any latent interrupt bits (like the halt bit)
-	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB );
-	else
-		I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR );
-	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA);
-}
-
-static void stop_adc(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__stop_adc(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static inline void __start_adc(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable &&
-	    (dmabuf->trigger & PCM_ENABLE_INPUT)) {
-		dmabuf->enable |= ADC_RUNNING;
-		// Interrupt enable, LVI enable, DMA enable
-		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR);
-	}
-}
-
-static void start_adc(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__start_adc(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void __stop_dac(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_card *card = state->card;
-
-	dmabuf->enable &= ~DAC_RUNNING;
-	I810_IOWRITEB(0, card, PO_CR);
-	// wait for the card to acknowledge shutdown
-	while( I810_IOREADB(card, PO_CR) != 0 ) ;
-	// now clear any latent interrupt bits (like the halt bit)
-	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB );
-	else
-		I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR );
-	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA);
-}
-
-static void stop_dac(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__stop_dac(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}	
-
-static inline void __start_dac(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable &&
-	    (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
-		dmabuf->enable |= DAC_RUNNING;
-		// Interrupt enable, LVI enable, DMA enable
-		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR);
-	}
-}
-static void start_dac(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__start_dac(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
-#define DMABUF_MINORDER 1
-
-/* allocate DMA buffer, playback and recording buffer should be allocated separately */
-static int alloc_dmabuf(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	void *rawbuf= NULL;
-	int order, size;
-	struct page *page, *pend;
-
-	/* If we don't have any oss frag params, then use our default ones */
-	if(dmabuf->ossmaxfrags == 0)
-		dmabuf->ossmaxfrags = 4;
-	if(dmabuf->ossfragsize == 0)
-		dmabuf->ossfragsize = (PAGE_SIZE<<DMABUF_DEFAULTORDER)/dmabuf->ossmaxfrags;
-	size = dmabuf->ossfragsize * dmabuf->ossmaxfrags;
-
-	if(dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size)
-		return 0;
-	/* alloc enough to satisfy the oss params */
-	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
-		if ( (PAGE_SIZE<<order) > size )
-			continue;
-		if ((rawbuf = pci_alloc_consistent(state->card->pci_dev,
-						   PAGE_SIZE << order,
-						   &dmabuf->dma_handle)))
-			break;
-	}
-	if (!rawbuf)
-		return -ENOMEM;
-
-
-#ifdef DEBUG
-	printk("i810_audio: allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, rawbuf);
-#endif
-
-	dmabuf->ready  = dmabuf->mapped = 0;
-	dmabuf->rawbuf = rawbuf;
-	dmabuf->buforder = order;
-	
-	/* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
-	pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
-	for (page = virt_to_page(rawbuf); page <= pend; page++)
-		SetPageReserved(page);
-
-	return 0;
-}
-
-/* free DMA buffer */
-static void dealloc_dmabuf(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *page, *pend;
-
-	if (dmabuf->rawbuf) {
-		/* undo marking the pages as reserved */
-		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
-		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
-			ClearPageReserved(page);
-		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,
-				    dmabuf->rawbuf, dmabuf->dma_handle);
-	}
-	dmabuf->rawbuf = NULL;
-	dmabuf->mapped = dmabuf->ready = 0;
-}
-
-static int prog_dmabuf(struct i810_state *state, unsigned rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_channel *c;
-	struct sg_item *sg;
-	unsigned long flags;
-	int ret;
-	unsigned fragint;
-	int i;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-	if(dmabuf->enable & DAC_RUNNING)
-		__stop_dac(state);
-	if(dmabuf->enable & ADC_RUNNING)
-		__stop_adc(state);
-	dmabuf->total_bytes = 0;
-	dmabuf->count = dmabuf->error = 0;
-	dmabuf->swptr = dmabuf->hwptr = 0;
-	spin_unlock_irqrestore(&state->card->lock, flags);
-
-	/* allocate DMA buffer, let alloc_dmabuf determine if we are already
-	 * allocated well enough or if we should replace the current buffer
-	 * (assuming one is already allocated, if it isn't, then allocate it).
-	 */
-	if ((ret = alloc_dmabuf(state)))
-		return ret;
-
-	/* FIXME: figure out all this OSS fragment stuff */
-	/* I did, it now does what it should according to the OSS API.  DL */
-	/* We may not have realloced our dmabuf, but the fragment size to
-	 * fragment number ratio may have changed, so go ahead and reprogram
-	 * things
-	 */
-	dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder;
-	dmabuf->numfrag = SG_LEN;
-	dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag;
-	dmabuf->fragsamples = dmabuf->fragsize >> 1;
-	dmabuf->fragshift = ffs(dmabuf->fragsize) - 1;
-	dmabuf->userfragsize = dmabuf->ossfragsize;
-	dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize;
-
-	memset(dmabuf->rawbuf, 0, dmabuf->dmasize);
-
-	if(dmabuf->ossmaxfrags == 4) {
-		fragint = 8;
-	} else if (dmabuf->ossmaxfrags == 8) {
-		fragint = 4;
-	} else if (dmabuf->ossmaxfrags == 16) {
-		fragint = 2;
-	} else {
-		fragint = 1;
-	}
-	/*
-	 *	Now set up the ring 
-	 */
-	if(dmabuf->read_channel)
-		c = dmabuf->read_channel;
-	else
-		c = dmabuf->write_channel;
-	while(c != NULL) {
-		sg=&c->sg[0];
-		/*
-		 *	Load up 32 sg entries and take an interrupt at half
-		 *	way (we might want more interrupts later..) 
-		 */
-	  
-		for(i=0;i<dmabuf->numfrag;i++)
-		{
-			sg->busaddr=(u32)dmabuf->dma_handle+dmabuf->fragsize*i;
-			// the card will always be doing 16bit stereo
-			sg->control=dmabuf->fragsamples;
-			if(state->card->pci_id == PCI_DEVICE_ID_SI_7012)
-				sg->control <<= 1;
-			sg->control|=CON_BUFPAD;
-			// set us up to get IOC interrupts as often as needed to
-			// satisfy numfrag requirements, no more
-			if( ((i+1) % fragint) == 0) {
-				sg->control|=CON_IOC;
-			}
-			sg++;
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
-		while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ;
-		I810_IOWRITEL((u32)state->card->chandma +
-		    c->num*sizeof(struct i810_channel),
-		    state->card, c->port+OFF_BDBAR);
-		CIV_TO_LVI(state->card, c->port, 0);
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if(c != dmabuf->write_channel)
-			c = dmabuf->write_channel;
-		else
-			c = NULL;
-	}
-	
-	/* set the ready flag for the dma buffer */
-	dmabuf->ready = 1;
-
-#ifdef DEBUG
-	printk("i810_audio: prog_dmabuf, sample rate = %d, format = %d,\n\tnumfrag = %d, "
-	       "fragsize = %d dmasize = %d\n",
-	       dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-	       dmabuf->fragsize, dmabuf->dmasize);
-#endif
-
-	return 0;
-}
-
-static void __i810_update_lvi(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int x, port;
-	int trigger;
-	int count, fragsize;
-	void (*start)(struct i810_state *);
-
-	count = dmabuf->count;
-	if (rec) {
-		port = dmabuf->read_channel->port;
-		trigger = PCM_ENABLE_INPUT;
-		start = __start_adc;
-		count = dmabuf->dmasize - count;
-	} else {
-		port = dmabuf->write_channel->port;
-		trigger = PCM_ENABLE_OUTPUT;
-		start = __start_dac;
-	}
-
-	/* Do not process partial fragments. */
-	fragsize = dmabuf->fragsize;
-	if (count < fragsize)
-		return;
-
-	/* if we are currently stopped, then our CIV is actually set to our
-	 * *last* sg segment and we are ready to wrap to the next.  However,
-	 * if we set our LVI to the last sg segment, then it won't wrap to
-	 * the next sg segment, it won't even get a start.  So, instead, when
-	 * we are stopped, we set both the LVI value and also we increment
-	 * the CIV value to the next sg segment to be played so that when
-	 * we call start, things will operate properly.  Since the CIV can't
-	 * be written to directly for this purpose, we set the LVI to CIV + 1
-	 * temporarily.  Once the engine has started we set the LVI to its
-	 * final value.
-	 */
-	if (!dmabuf->enable && dmabuf->ready) {
-		if (!(dmabuf->trigger & trigger))
-			return;
-
-		CIV_TO_LVI(state->card, port, 1);
-
-		start(state);
-		while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2))))
-			;
-	}
-
-	/* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
-	x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
-	x >>= dmabuf->fragshift;
-	I810_IOWRITEB(x, state->card, port + OFF_LVI);
-}
-
-static void i810_update_lvi(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-
-	if(!dmabuf->ready)
-		return;
-	spin_lock_irqsave(&state->card->lock, flags);
-	__i810_update_lvi(state, rec);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void i810_update_ptr(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned hwptr;
-	unsigned fragmask, dmamask;
-	int diff;
-
-	fragmask = MASKP2(~0, dmabuf->fragsize);
-	dmamask = MODULOP2(~0, dmabuf->dmasize);
-
-	/* error handling and process wake up for ADC */
-	if (dmabuf->enable == ADC_RUNNING) {
-		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 1) & fragmask;
-		diff = (hwptr - dmabuf->hwptr) & dmamask;
-#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
-		printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
-#endif
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count += diff;
-		if (dmabuf->count > dmabuf->dmasize) {
-			/* buffer underrun or buffer overrun */
-			/* this is normal for the end of a read */
-			/* only give an error if we went past the */
-			/* last valid sg entry */
-			if (GET_CIV(state->card, PI_BASE) !=
-			    GET_LVI(state->card, PI_BASE)) {
-				printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
-				dmabuf->error++;
-			}
-		}
-		if (diff)
-			wake_up(&dmabuf->wait);
-	}
-	/* error handling and process wake up for DAC */
-	if (dmabuf->enable == DAC_RUNNING) {
-		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 0) & fragmask;
-		diff = (hwptr - dmabuf->hwptr) & dmamask;
-#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
-		printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
-#endif
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count -= diff;
-		if (dmabuf->count < 0) {
-			/* buffer underrun or buffer overrun */
-			/* this is normal for the end of a write */
-			/* only give an error if we went past the */
-			/* last valid sg entry */
-			if (GET_CIV(state->card, PO_BASE) !=
-			    GET_LVI(state->card, PO_BASE)) {
-				printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
-				printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
-					"count %d\n",
-					GET_CIV(state->card, PO_BASE),
-					GET_LVI(state->card, PO_BASE),
-					dmabuf->hwptr, dmabuf->count);
-				dmabuf->error++;
-			}
-		}
-		if (diff)
-			wake_up(&dmabuf->wait);
-	}
-}
-
-static inline int i810_get_free_write_space(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int free;
-
-	i810_update_ptr(state);
-	// catch underruns during playback
-	if (dmabuf->count < 0) {
-		dmabuf->count = 0;
-		dmabuf->swptr = dmabuf->hwptr;
-	}
-	free = dmabuf->dmasize - dmabuf->count;
-	if(free < 0)
-		return(0);
-	return(free);
-}
-
-static inline int i810_get_available_read_data(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int avail;
-
-	i810_update_ptr(state);
-	// catch overruns during record
-	if (dmabuf->count > dmabuf->dmasize) {
-		dmabuf->count = dmabuf->dmasize;
-		dmabuf->swptr = dmabuf->hwptr;
-	}
-	avail = dmabuf->count;
-	if(avail < 0)
-		return(0);
-	return(avail);
-}
-
-static inline void fill_partial_frag(struct dmabuf *dmabuf)
-{
-	unsigned fragsize;
-	unsigned swptr, len;
-
-	fragsize = dmabuf->fragsize;
-	swptr = dmabuf->swptr;
-	len = fragsize - MODULOP2(dmabuf->swptr, fragsize);
-	if (len == fragsize)
-		return;
-
-	memset(dmabuf->rawbuf + swptr, '\0', len);
-	dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize);
-	dmabuf->count += len;
-}
-
-static int drain_dac(struct i810_state *state, int signals_allowed)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	unsigned long tmo;
-	int count;
-
-	if (!dmabuf->ready)
-		return 0;
-	if(dmabuf->mapped) {
-		stop_dac(state);
-		return 0;
-	}
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	fill_partial_frag(dmabuf);
-
-	/* 
-	 * This will make sure that our LVI is correct, that our
-	 * pointer is updated, and that the DAC is running.  We
-	 * have to force the setting of dmabuf->trigger to avoid
-	 * any possible deadlocks.
-	 */
-	dmabuf->trigger = PCM_ENABLE_OUTPUT;
-	__i810_update_lvi(state, 0);
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-
-	add_wait_queue(&dmabuf->wait, &wait);
-	for (;;) {
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		count = dmabuf->count;
-
-		/* It seems that we have to set the current state to
-		 * TASK_INTERRUPTIBLE every time to make the process
-		 * really go to sleep.  This also has to be *after* the
-		 * update_ptr() call because update_ptr is likely to
-		 * do a wake_up() which will unset this before we ever
-		 * try to sleep, resuling in a tight loop in this code
-		 * instead of actually sleeping and waiting for an
-		 * interrupt to wake us up!
-		 */
-		__set_current_state(signals_allowed ?
-				    TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (count <= 0)
-			break;
-
-                if (signal_pending(current) && signals_allowed) {
-                        break;
-                }
-
-		/*
-		 * set the timeout to significantly longer than it *should*
-		 * take for the DAC to drain the DMA buffer
-		 */
-		tmo = (count * HZ) / (dmabuf->rate);
-		if (!schedule_timeout(tmo >= 2 ? tmo : 2)){
-			printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n");
-			count = 0;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dmabuf->wait, &wait);
-	if(count > 0 && signal_pending(current) && signals_allowed)
-		return -ERESTARTSYS;
-	stop_dac(state);
-	return 0;
-}
-
-static void i810_channel_interrupt(struct i810_card *card)
-{
-	int i, count;
-	
-#ifdef DEBUG_INTERRUPTS
-	printk("CHANNEL ");
-#endif
-	for(i=0;i<NR_HW_CH;i++)
-	{
-		struct i810_state *state = card->states[i];
-		struct i810_channel *c;
-		struct dmabuf *dmabuf;
-		unsigned long port;
-		u16 status;
-		
-		if(!state)
-			continue;
-		if(!state->dmabuf.ready)
-			continue;
-		dmabuf = &state->dmabuf;
-		if(dmabuf->enable & DAC_RUNNING) {
-			c=dmabuf->write_channel;
-		} else if(dmabuf->enable & ADC_RUNNING) {
-			c=dmabuf->read_channel;
-		} else	/* This can occur going from R/W to close */
-			continue;
-		
-		port = c->port;
-
-		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			status = I810_IOREADW(card, port + OFF_PICB);
-		else
-			status = I810_IOREADW(card, port + OFF_SR);
-
-#ifdef DEBUG_INTERRUPTS
-		printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status);
-#endif
-		if(status & DMA_INT_COMPLETE)
-		{
-			/* only wake_up() waiters if this interrupt signals
-			 * us being beyond a userfragsize of data open or
-			 * available, and i810_update_ptr() does that for
-			 * us
-			 */
-			i810_update_ptr(state);
-#ifdef DEBUG_INTERRUPTS
-			printk("COMP %d ", dmabuf->hwptr /
-					dmabuf->fragsize);
-#endif
-		}
-		if(status & (DMA_INT_LVI | DMA_INT_DCH))
-		{
-			/* wake_up() unconditionally on LVI and DCH */
-			i810_update_ptr(state);
-			wake_up(&dmabuf->wait);
-#ifdef DEBUG_INTERRUPTS
-			if(status & DMA_INT_LVI)
-				printk("LVI ");
-			if(status & DMA_INT_DCH)
-				printk("DCH -");
-#endif
-			count = dmabuf->count;
-			if(dmabuf->enable & ADC_RUNNING)
-				count = dmabuf->dmasize - count;
-			if (count >= (int)dmabuf->fragsize) {
-				I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR);
-#ifdef DEBUG_INTERRUPTS
-				printk(" CONTINUE ");
-#endif
-			} else {
-				if (dmabuf->enable & DAC_RUNNING)
-					__stop_dac(state);
-				if (dmabuf->enable & ADC_RUNNING)
-					__stop_adc(state);
-				dmabuf->enable = 0;
-#ifdef DEBUG_INTERRUPTS
-				printk(" STOP ");
-#endif
-			}
-		}
-		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB);
-		else
-			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR);
-	}
-#ifdef DEBUG_INTERRUPTS
-	printk(")\n");
-#endif
-}
-
-static irqreturn_t i810_interrupt(int irq, void *dev_id)
-{
-	struct i810_card *card = dev_id;
-	u32 status;
-
-	spin_lock(&card->lock);
-
-	status = I810_IOREADL(card, GLOB_STA);
-
-	if(!(status & INT_MASK)) 
-	{
-		spin_unlock(&card->lock);
-		return IRQ_NONE;  /* not for us */
-	}
-
-	if(status & (INT_PO|INT_PI|INT_MC))
-		i810_channel_interrupt(card);
-
- 	/* clear 'em */
-	I810_IOWRITEL(status & INT_MASK, card, GLOB_STA);
-	spin_unlock(&card->lock);
-	return IRQ_HANDLED;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is
-   waiting to be copied to the user's buffer.  It is filled by the dma
-   machine and drained by this loop. */
-
-static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card=state ? state->card : NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned int swptr;
-	int cnt;
-	int pending;
-        DECLARE_WAITQUEUE(waita, current);
-
-#ifdef DEBUG2
-	printk("i810_audio: i810_read called, count = %d\n", count);
-#endif
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (dmabuf->enable & DAC_RUNNING)
-		return -ENODEV;
-	if (!dmabuf->read_channel) {
-		dmabuf->ready = 0;
-		dmabuf->read_channel = card->alloc_rec_pcm_channel(card);
-		if (!dmabuf->read_channel) {
-			return -EBUSY;
-		}
-	}
-	if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-		return ret;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	ret = 0;
-
-	pending = 0;
-
-        add_wait_queue(&dmabuf->wait, &waita);
-	while (count > 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        schedule();
-                        if (signal_pending(current)) {
-                                if (!ret) ret = -EAGAIN;
-                                break;
-                        }
-                        continue;
-                }
-		cnt = i810_get_available_read_data(state);
-		swptr = dmabuf->swptr;
-		// this is to make the copy_to_user simpler below
-		if(cnt > (dmabuf->dmasize - swptr))
-			cnt = dmabuf->dmasize - swptr;
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			unsigned long tmo;
-			/*
-			 * Don't let us deadlock.  The ADC won't start if
-			 * dmabuf->trigger isn't set.  A call to SETTRIGGER
-			 * could have turned it off after we set it to on
-			 * previously.
-			 */
-			dmabuf->trigger = PCM_ENABLE_INPUT;
-			/*
-			 * This does three things.  Updates LVI to be correct,
-			 * makes sure the ADC is running, and updates the
-			 * hwptr.
-			 */
-			i810_update_lvi(state,1);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
-				goto done;
-			}
-			/* Set the timeout to how long it would take to fill
-			 * two of our buffers.  If we haven't been woke up
-			 * by then, then we know something is wrong.
-			 */
-			tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4);
-			/* There are two situations when sleep_on_timeout returns, one is when
-			   the interrupt is serviced correctly and the process is waked up by
-			   ISR ON TIME. Another is when timeout is expired, which means that
-			   either interrupt is NOT serviced correctly (pending interrupt) or it
-			   is TOO LATE for the process to be scheduled to run (scheduler latency)
-			   which results in a (potential) buffer overrun. And worse, there is
-			   NOTHING we can do to prevent it. */
-			if (!schedule_timeout(tmo >= 2 ? tmo : 2)) {
-#ifdef DEBUG
-				printk(KERN_ERR "i810_audio: recording schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
-				/* a buffer overrun, we delay the recovery until next time the
-				   while loop begin and we REALLY have space to record */
-			}
-			if (signal_pending(current)) {
-				ret = ret ? ret : -ERESTARTSYS;
-				goto done;
-			}
-			continue;
-		}
-
-		if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
-			if (!ret) ret = -EFAULT;
-			goto done;
-		}
-
-		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
-
-		spin_lock_irqsave(&card->lock, flags);
-
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        continue;
-                }
-		dmabuf->swptr = swptr;
-		pending = dmabuf->count -= cnt;
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-	}
- done:
-	pending = dmabuf->dmasize - pending;
-	if (dmabuf->enable || pending >= dmabuf->userfragsize)
-		i810_update_lvi(state, 1);
-        set_current_state(TASK_RUNNING);
-        remove_wait_queue(&dmabuf->wait, &waita);
-
-	return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
-   the soundcard.  it is drained by the dma machine and filled by this loop. */
-static ssize_t i810_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card=state ? state->card : NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned int swptr = 0;
-	int pending;
-	int cnt;
-        DECLARE_WAITQUEUE(waita, current);
-
-#ifdef DEBUG2
-	printk("i810_audio: i810_write called, count = %d\n", count);
-#endif
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (dmabuf->enable & ADC_RUNNING)
-		return -ENODEV;
-	if (!dmabuf->write_channel) {
-		dmabuf->ready = 0;
-		dmabuf->write_channel = card->alloc_pcm_channel(card);
-		if(!dmabuf->write_channel)
-			return -EBUSY;
-	}
-	if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-		return ret;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	ret = 0;
-
-	pending = 0;
-
-        add_wait_queue(&dmabuf->wait, &waita);
-	while (count > 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&state->card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        schedule();
-                        if (signal_pending(current)) {
-                                if (!ret) ret = -EAGAIN;
-                                break;
-                        }
-                        continue;
-                }
-
-		cnt = i810_get_free_write_space(state);
-		swptr = dmabuf->swptr;
-		/* Bound the maximum size to how much we can copy to the
-		 * dma buffer before we hit the end.  If we have more to
-		 * copy then it will get done in a second pass of this
-		 * loop starting from the beginning of the buffer.
-		 */
-		if(cnt > (dmabuf->dmasize - swptr))
-			cnt = dmabuf->dmasize - swptr;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-#ifdef DEBUG2
-		printk(KERN_INFO "i810_audio: i810_write: %d bytes available space\n", cnt);
-#endif
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			unsigned long tmo;
-			// There is data waiting to be played
-			/*
-			 * Force the trigger setting since we would
-			 * deadlock with it set any other way
-			 */
-			dmabuf->trigger = PCM_ENABLE_OUTPUT;
-			i810_update_lvi(state,0);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
-				goto ret;
-			}
-			/* Not strictly correct but works */
-			tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4);
-			/* There are two situations when sleep_on_timeout returns, one is when
-			   the interrupt is serviced correctly and the process is waked up by
-			   ISR ON TIME. Another is when timeout is expired, which means that
-			   either interrupt is NOT serviced correctly (pending interrupt) or it
-			   is TOO LATE for the process to be scheduled to run (scheduler latency)
-			   which results in a (potential) buffer underrun. And worse, there is
-			   NOTHING we can do to prevent it. */
-			if (!schedule_timeout(tmo >= 2 ? tmo : 2)) {
-#ifdef DEBUG
-				printk(KERN_ERR "i810_audio: playback schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
-				/* a buffer underrun, we delay the recovery until next time the
-				   while loop begin and we REALLY have data to play */
-				//return ret;
-			}
-			if (signal_pending(current)) {
-				if (!ret) ret = -ERESTARTSYS;
-				goto ret;
-			}
-			continue;
-		}
-		if (copy_from_user(dmabuf->rawbuf+swptr,buffer,cnt)) {
-			if (!ret) ret = -EFAULT;
-			goto ret;
-		}
-
-		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
-
-		spin_lock_irqsave(&state->card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        continue;
-                }
-
-		dmabuf->swptr = swptr;
-		pending = dmabuf->count += cnt;
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-	}
-ret:
-	if (dmabuf->enable || pending >= dmabuf->userfragsize)
-		i810_update_lvi(state, 0);
-        set_current_state(TASK_RUNNING);
-        remove_wait_queue(&dmabuf->wait, &waita);
-
-	return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int i810_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	if(!dmabuf->ready)
-		return 0;
-	poll_wait(file, &dmabuf->wait, wait);
-	spin_lock_irqsave(&state->card->lock, flags);
-	if (dmabuf->enable & ADC_RUNNING ||
-	    dmabuf->trigger & PCM_ENABLE_INPUT) {
-		if (i810_get_available_read_data(state) >= 
-		    (signed)dmabuf->userfragsize)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	if (dmabuf->enable & DAC_RUNNING ||
-	    dmabuf->trigger & PCM_ENABLE_OUTPUT) {
-		if (i810_get_free_write_space(state) >=
-		    (signed)dmabuf->userfragsize)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	return mask;
-}
-
-static int i810_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int ret = -EINVAL;
-	unsigned long size;
-
-	lock_kernel();
-	if (vma->vm_flags & VM_WRITE) {
-		if (!dmabuf->write_channel &&
-		    (dmabuf->write_channel =
-		     state->card->alloc_pcm_channel(state->card)) == NULL) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-	if (vma->vm_flags & VM_READ) {
-		if (!dmabuf->read_channel &&
-		    (dmabuf->read_channel = 
-		     state->card->alloc_rec_pcm_channel(state->card)) == NULL) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-	if ((ret = prog_dmabuf(state, 0)) != 0)
-		goto out;
-
-	ret = -EINVAL;
-	if (vma->vm_pgoff != 0)
-		goto out;
-	size = vma->vm_end - vma->vm_start;
-	if (size > (PAGE_SIZE << dmabuf->buforder))
-		goto out;
-	ret = -EAGAIN;
-	if (remap_pfn_range(vma, vma->vm_start,
-			     virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-			     size, vma->vm_page_prot))
-		goto out;
-	dmabuf->mapped = 1;
-	dmabuf->trigger = 0;
-	ret = 0;
-#ifdef DEBUG_MMAP
-	printk("i810_audio: mmap'ed %ld bytes of data space\n", size);
-#endif
-out:
-	unlock_kernel();
-	return ret;
-}
-
-static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_channel *c = NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	unsigned int i_glob_cnt;
-	int val = 0, ret;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-#ifdef DEBUG
-	printk("i810_audio: i810_ioctl, arg=0x%x, cmd=", arg ? *p : 0);
-#endif
-
-	switch (cmd) 
-	{
-	case OSS_GETVERSION:
-#ifdef DEBUG
-		printk("OSS_GETVERSION\n");
-#endif
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_RESET\n");
-#endif
-		spin_lock_irqsave(&state->card->lock, flags);
-		if (dmabuf->enable == DAC_RUNNING) {
-			c = dmabuf->write_channel;
-			__stop_dac(state);
-		}
-		if (dmabuf->enable == ADC_RUNNING) {
-			c = dmabuf->read_channel;
-			__stop_adc(state);
-		}
-		if (c != NULL) {
-			I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
-			while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 )
-				cpu_relax();
-			I810_IOWRITEL((u32)state->card->chandma +
-			    c->num*sizeof(struct i810_channel),
-			    state->card, c->port+OFF_BDBAR);
-			CIV_TO_LVI(state->card, c->port, 0);
-		}
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-		synchronize_irq(state->card->pci_dev->irq);
-		dmabuf->ready = 0;
-		dmabuf->swptr = dmabuf->hwptr = 0;
-		dmabuf->count = dmabuf->total_bytes = 0;
-		return 0;
-
-	case SNDCTL_DSP_SYNC:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SYNC\n");
-#endif
-		if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK)
-			return 0;
-		if((val = drain_dac(state, 1)))
-			return val;
-		dmabuf->total_bytes = 0;
-		return 0;
-
-	case SNDCTL_DSP_SPEED: /* set smaple rate */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SPEED\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val >= 0) {
-			if (file->f_mode & FMODE_WRITE) {
-				if ( (state->card->ac97_status & SPDIF_ON) ) {  /* S/PDIF Enabled */
-					/* AD1886 only supports 48000, need to check that */
-					if ( i810_valid_spdif_rate ( codec, val ) ) {
-						/* Set DAC rate */
-                                        	i810_set_spdif_output ( state, -1, 0 );
-						stop_dac(state);
-						dmabuf->ready = 0;
-						spin_lock_irqsave(&state->card->lock, flags);
-						i810_set_dac_rate(state, val);
-						spin_unlock_irqrestore(&state->card->lock, flags);
-						/* Set S/PDIF transmitter rate. */
-						i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, val );
-	                                        if ( ! (state->card->ac97_status & SPDIF_ON) ) {
-							val = dmabuf->rate;
-						}
-					} else { /* Not a valid rate for S/PDIF, ignore it */
-						val = dmabuf->rate;
-					}
-				} else {
-					stop_dac(state);
-					dmabuf->ready = 0;
-					spin_lock_irqsave(&state->card->lock, flags);
-					i810_set_dac_rate(state, val);
-					spin_unlock_irqrestore(&state->card->lock, flags);
-				}
-			}
-			if (file->f_mode & FMODE_READ) {
-				stop_adc(state);
-				dmabuf->ready = 0;
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_set_adc_rate(state, val);
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-		}
-		return put_user(dmabuf->rate, p);
-
-	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_STEREO\n");
-#endif
-		if (dmabuf->enable & DAC_RUNNING) {
-			stop_dac(state);
-		}
-		if (dmabuf->enable & ADC_RUNNING) {
-			stop_adc(state);
-		}
-		return put_user(1, p);
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			if (!dmabuf->ready && (val = prog_dmabuf(state, 0)))
-				return val;
-		}
-		if (file->f_mode & FMODE_READ) {
-			if (!dmabuf->ready && (val = prog_dmabuf(state, 1)))
-				return val;
-		}
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize);
-#endif
-		return put_user(dmabuf->userfragsize, p);
-
-	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETFMTS\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_SETFMT: /* Select sample format */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETFMT\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_CHANNELS:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_CHANNELS\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (val > 0) {
-			if (dmabuf->enable & DAC_RUNNING) {
-				stop_dac(state);
-			}
-			if (dmabuf->enable & ADC_RUNNING) {
-				stop_adc(state);
-			}
-		} else {
-			return put_user(state->card->channels, p);
-		}
-
-		/* ICH and ICH0 only support 2 channels */
-		if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5
-		     || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5) 
-			return put_user(2, p);
-	
-		/* Multi-channel support was added with ICH2. Bits in */
-		/* Global Status and Global Control register are now  */
-		/* used to indicate this.                             */
-
-                i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT);
-
-		/* Current # of channels enabled */
-		if ( i_glob_cnt & 0x0100000 )
-			ret = 4;
-		else if ( i_glob_cnt & 0x0200000 )
-			ret = 6;
-		else
-			ret = 2;
-
-		switch ( val ) {
-			case 2: /* 2 channels is always supported */
-				I810_IOWRITEL(i_glob_cnt & 0xffcfffff,
-				     state->card, GLOB_CNT);
-				/* Do we need to change mixer settings????  */
-				break;
-			case 4: /* Supported on some chipsets, better check first */
-				if ( state->card->channels >= 4 ) {
-					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000,
-					      state->card, GLOB_CNT);
-					/* Do we need to change mixer settings??? */
-				} else {
-					val = ret;
-				}
-				break;
-			case 6: /* Supported on some chipsets, better check first */
-				if ( state->card->channels >= 6 ) {
-					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000,
-					      state->card, GLOB_CNT);
-					/* Do we need to change mixer settings??? */
-				} else {
-					val = ret;
-				}
-				break;
-			default: /* nothing else is ever supported by the chipset */
-				val = ret;
-				break;
-		}
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */
-		/* we update the swptr to the end of the last sg segment then return */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_POST\n");
-#endif
-		if(!dmabuf->ready || (dmabuf->enable != DAC_RUNNING))
-			return 0;
-		if((dmabuf->swptr % dmabuf->fragsize) != 0) {
-			val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize);
-			dmabuf->swptr += val;
-			dmabuf->count += val;
-		}
-		return 0;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		if (dmabuf->subdivision)
-			return -EINVAL;
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val != 1 && val != 2 && val != 4)
-			return -EINVAL;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SUBDIVIDE %d\n", val);
-#endif
-		dmabuf->subdivision = val;
-		dmabuf->ready = 0;
-		return 0;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, p))
-			return -EFAULT;
-
-		dmabuf->ossfragsize = 1<<(val & 0xffff);
-		dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-		if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags)
-			return -EINVAL;
-		/*
-		 * Bound the frag size into our allowed range of 256 - 4096
-		 */
-		if (dmabuf->ossfragsize < 256)
-			dmabuf->ossfragsize = 256;
-		else if (dmabuf->ossfragsize > 4096)
-			dmabuf->ossfragsize = 4096;
-		/*
-		 * The numfrags could be something reasonable, or it could
-		 * be 0xffff meaning "Give me as much as possible".  So,
-		 * we check the numfrags * fragsize doesn't exceed our
-		 * 64k buffer limit, nor is it less than our 8k minimum.
-		 * If it fails either one of these checks, then adjust the
-		 * number of fragments, not the size of them.  It's OK if
-		 * our number of fragments doesn't equal 32 or anything
-		 * like our hardware based number now since we are using
-		 * a different frag count for the hardware.  Before we get
-		 * into this though, bound the maxfrags to avoid overflow
-		 * issues.  A reasonable bound would be 64k / 256 since our
-		 * maximum buffer size is 64k and our minimum frag size is
-		 * 256.  On the other end, our minimum buffer size is 8k and
-		 * our maximum frag size is 4k, so the lower bound should
-		 * be 2.
-		 */
-
-		if(dmabuf->ossmaxfrags > 256)
-			dmabuf->ossmaxfrags = 256;
-		else if (dmabuf->ossmaxfrags < 2)
-			dmabuf->ossmaxfrags = 2;
-
-		val = dmabuf->ossfragsize * dmabuf->ossmaxfrags;
-		while (val < 8192) {
-		    val <<= 1;
-		    dmabuf->ossmaxfrags <<= 1;
-		}
-		while (val > 65536) {
-		    val >>= 1;
-		    dmabuf->ossmaxfrags >>= 1;
-		}
-		dmabuf->ready = 0;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val,
-			dmabuf->ossfragsize, dmabuf->ossmaxfrags);
-#endif
-
-		return 0;
-
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		abinfo.fragsize = dmabuf->userfragsize;
-		abinfo.fragstotal = dmabuf->userfrags;
-		if (dmabuf->mapped)
- 			abinfo.bytes = dmabuf->dmasize;
-  		else
- 			abinfo.bytes = i810_get_free_write_space(state);
-		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes,
-			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);
-#endif
-		return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		val = i810_get_free_write_space(state);
-		cinfo.bytes = dmabuf->total_bytes;
-		cinfo.ptr = dmabuf->hwptr;
-		cinfo.blocks = val/dmabuf->userfragsize;
-		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
-			dmabuf->count += val;
-			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
-			__i810_update_lvi(state, 0);
-		}
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes,
-			cinfo.blocks, cinfo.ptr, dmabuf->count);
-#endif
-		return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		abinfo.bytes = i810_get_available_read_data(state);
-		abinfo.fragsize = dmabuf->userfragsize;
-		abinfo.fragstotal = dmabuf->userfrags;
-		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes,
-			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);
-#endif
-		return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		val = i810_get_available_read_data(state);
-		cinfo.bytes = dmabuf->total_bytes;
-		cinfo.blocks = val/dmabuf->userfragsize;
-		cinfo.ptr = dmabuf->hwptr;
-		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) {
-			dmabuf->count -= val;
-			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
-			__i810_update_lvi(state, 1);
-		}
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes,
-			cinfo.blocks, cinfo.ptr, dmabuf->count);
-#endif
-		return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_NONBLOCK:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_NONBLOCK\n");
-#endif
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETCAPS\n");
-#endif
-	    return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND,
-			    p);
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger);
-#endif
-		return put_user(dmabuf->trigger, p);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, p))
-			return -EFAULT;
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
-#endif
-		/* silently ignore invalid PCM_ENABLE_xxx bits,
-		 * like the other drivers do
-		 */
-		if (!(file->f_mode & FMODE_READ ))
-			val &= ~PCM_ENABLE_INPUT;
-		if (!(file->f_mode & FMODE_WRITE ))
-			val &= ~PCM_ENABLE_OUTPUT;
-		if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
-			stop_adc(state);
-		}
-		if((file->f_mode & FMODE_WRITE) && !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) {
-			stop_dac(state);
-		}
-		dmabuf->trigger = val;
-		if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
-			if (!dmabuf->write_channel) {
-				dmabuf->ready = 0;
-				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
-				if (!dmabuf->write_channel)
-					return -EBUSY;
-			}
-			if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-				return ret;
-			if (dmabuf->mapped) {
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_update_ptr(state);
-				dmabuf->count = 0;
-				dmabuf->swptr = dmabuf->hwptr;
-				dmabuf->count = i810_get_free_write_space(state);
-				dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize;
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-			i810_update_lvi(state, 0);
-			start_dac(state);
-		}
-		if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
-			if (!dmabuf->read_channel) {
-				dmabuf->ready = 0;
-				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);
-				if (!dmabuf->read_channel)
-					return -EBUSY;
-			}
-			if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-				return ret;
-			if (dmabuf->mapped) {
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_update_ptr(state);
-				dmabuf->swptr = dmabuf->hwptr;
-				dmabuf->count = 0;
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-			i810_update_lvi(state, 1);
-			start_adc(state);
-		}
-		return 0;
-
-	case SNDCTL_DSP_SETDUPLEX:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETDUPLEX\n");
-#endif
-		return -EINVAL;
-
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		val = dmabuf->count;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count);
-#endif
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_RATE:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate);
-#endif
-		return put_user(dmabuf->rate, p);
-
-	case SOUND_PCM_READ_CHANNELS:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_CHANNELS\n");
-#endif
-		return put_user(2, p);
-
-	case SOUND_PCM_READ_BITS:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_BITS\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETSPDIF\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		/* Check to make sure the codec supports S/PDIF transmitter */
-
-		if((state->card->ac97_features & 4)) {
-			/* mask out the transmitter speed bits so the user can't set them */
-			val &= ~0x3000;
-
-			/* Add the current transmitter speed bits to the passed value */
-			ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL);
-			val |= (ret & 0x3000);
-
-			i810_ac97_set(codec, AC97_SPDIF_CONTROL, val);
-			if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) {
-				printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val);
-				return -EFAULT;
-			}
-		}
-#ifdef DEBUG
-		else 
-			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");
-#endif
-		return put_user(val, p);
-
-	case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETSPDIF\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		/* Check to make sure the codec supports S/PDIF transmitter */
-
-		if(!(state->card->ac97_features & 4)) {
-#ifdef DEBUG
-			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");
-#endif
-			val = 0;
-		} else {
-			val = i810_ac97_get(codec, AC97_SPDIF_CONTROL);
-		}
-		//return put_user((val & 0xcfff), p);
-		return put_user(val, p);
-   			
-	case SNDCTL_DSP_GETCHANNELMASK:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETCHANNELMASK\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		
-		/* Based on AC'97 DAC support, not ICH hardware */
-		val = DSP_BIND_FRONT;
-		if ( state->card->ac97_features & 0x0004 )
-			val |= DSP_BIND_SPDIF;
-
-		if ( state->card->ac97_features & 0x0080 )
-			val |= DSP_BIND_SURR;
-		if ( state->card->ac97_features & 0x0140 )
-			val |= DSP_BIND_CENTER_LFE;
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_BIND_CHANNEL:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_BIND_CHANNEL\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		if ( val == DSP_BIND_QUERY ) {
-			val = DSP_BIND_FRONT; /* Always report this as being enabled */
-			if ( state->card->ac97_status & SPDIF_ON ) 
-				val |= DSP_BIND_SPDIF;
-			else {
-				if ( state->card->ac97_status & SURR_ON )
-					val |= DSP_BIND_SURR;
-				if ( state->card->ac97_status & CENTER_LFE_ON )
-					val |= DSP_BIND_CENTER_LFE;
-			}
-		} else {  /* Not a query, set it */
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-			if ( dmabuf->enable == DAC_RUNNING ) {
-				stop_dac(state);
-			}
-			if ( val & DSP_BIND_SPDIF ) {  /* Turn on SPDIF */
-				/*  Ok, this should probably define what slots
-				 *  to use. For now, we'll only set it to the
-				 *  defaults:
-				 * 
-				 *   non multichannel codec maps to slots 3&4
-				 *   2 channel codec maps to slots 7&8
-				 *   4 channel codec maps to slots 6&9
-				 *   6 channel codec maps to slots 10&11
-				 *
-				 *  there should be some way for the app to
-				 *  select the slot assignment.
-				 */
-	
-				i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, dmabuf->rate );
-				if ( !(state->card->ac97_status & SPDIF_ON) )
-					val &= ~DSP_BIND_SPDIF;
-			} else {
-				int mask;
-				int channels;
-
-				/* Turn off S/PDIF if it was on */
-				if ( state->card->ac97_status & SPDIF_ON ) 
-					i810_set_spdif_output ( state, -1, 0 );
-				
-				mask = val & (DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE);
-				switch (mask) {
-					case DSP_BIND_FRONT:
-						channels = 2;
-						break;
-					case DSP_BIND_FRONT|DSP_BIND_SURR:
-						channels = 4;
-						break;
-					case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE:
-						channels = 6;
-						break;
-					default:
-						val = DSP_BIND_FRONT;
-						channels = 2;
-						break;
-				}
-				i810_set_dac_channels ( state, channels );
-
-				/* check that they really got turned on */
-				if (!(state->card->ac97_status & SURR_ON))
-					val &= ~DSP_BIND_SURR;
-				if (!(state->card->ac97_status & CENTER_LFE_ON))
-					val &= ~DSP_BIND_CENTER_LFE;
-			}
-		}
-		return put_user(val, p);
-		
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-#ifdef DEBUG
-		printk("SNDCTL_* -EINVAL\n");
-#endif
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-static int i810_open(struct inode *inode, struct file *file)
-{
-	int i = 0;
-	struct i810_card *card = devs;
-	struct i810_state *state = NULL;
-	struct dmabuf *dmabuf = NULL;
-
-	/* find an avaiable virtual channel (instance of /dev/dsp) */
-	while (card != NULL) {
-		/*
-		 * If we are initializing and then fail, card could go
-		 * away unuexpectedly while we are in the for() loop.
-		 * So, check for card on each iteration before we check
-		 * for card->initializing to avoid a possible oops.
-		 * This usually only matters for times when the driver is
-		 * autoloaded by kmod.
-		 */
-		for (i = 0; i < 50 && card && card->initializing; i++) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/20);
-		}
-		for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) {
-			if (card->states[i] == NULL) {
-				state = card->states[i] = (struct i810_state *)
-					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
-				if (state == NULL)
-					return -ENOMEM;
-				dmabuf = &state->dmabuf;
-				goto found_virt;
-			}
-		}
-		card = card->next;
-	}
-	/* no more virtual channel avaiable */
-	if (!state)
-		return -ENODEV;
-
-found_virt:
-	/* initialize the virtual channel */
-	state->virt = i;
-	state->card = card;
-	state->magic = I810_STATE_MAGIC;
-	init_waitqueue_head(&dmabuf->wait);
-	mutex_init(&state->open_mutex);
-	file->private_data = state;
-	dmabuf->trigger = 0;
-
-	/* allocate hardware channels */
-	if(file->f_mode & FMODE_READ) {
-		if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) {
-			kfree (card->states[i]);
-			card->states[i] = NULL;
-			return -EBUSY;
-		}
-		dmabuf->trigger |= PCM_ENABLE_INPUT;
-		i810_set_adc_rate(state, 8000);
-	}
-	if(file->f_mode & FMODE_WRITE) {
-		if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) {
-			/* make sure we free the record channel allocated above */
-			if(file->f_mode & FMODE_READ)
-				card->free_pcm_channel(card,dmabuf->read_channel->num);
-			kfree (card->states[i]);
-			card->states[i] = NULL;
-			return -EBUSY;
-		}
-		/* Initialize to 8kHz?  What if we don't support 8kHz? */
-		/*  Let's change this to check for S/PDIF stuff */
-	
-		dmabuf->trigger |= PCM_ENABLE_OUTPUT;
-		if ( spdif_locked ) {
-			i810_set_dac_rate(state, spdif_locked);
-			i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked);
-		} else {
-			i810_set_dac_rate(state, 8000);
-			/* Put the ACLink in 2 channel mode by default */
-			i = I810_IOREADL(card, GLOB_CNT);
-			I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT);
-		}
-	}
-		
-	/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-	   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-	   /dev/dspW will accept 16-bits sample, but we don't support those so we
-	   set it immediately to stereo and 16bit, which is all we do support */
-	dmabuf->fmt |= I810_FMT_16BIT | I810_FMT_STEREO;
-	dmabuf->ossfragsize = 0;
-	dmabuf->ossmaxfrags  = 0;
-	dmabuf->subdivision  = 0;
-
-	state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-
-	return nonseekable_open(inode, file);
-}
-
-static int i810_release(struct inode *inode, struct file *file)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card = state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-
-	lock_kernel();
-
-	/* stop DMA state machine and free DMA buffers/channels */
-	if(dmabuf->trigger & PCM_ENABLE_OUTPUT) {
-		drain_dac(state, 0);
-	}
-	if(dmabuf->trigger & PCM_ENABLE_INPUT) {
-		stop_adc(state);
-	}
-	spin_lock_irqsave(&card->lock, flags);
-	dealloc_dmabuf(state);
-	if (file->f_mode & FMODE_WRITE) {
-		state->card->free_pcm_channel(state->card, dmabuf->write_channel->num);
-	}
-	if (file->f_mode & FMODE_READ) {
-		state->card->free_pcm_channel(state->card, dmabuf->read_channel->num);
-	}
-
-	state->card->states[state->virt] = NULL;
-	kfree(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-	unlock_kernel();
-
-	return 0;
-}
-
-static /*const*/ struct file_operations i810_audio_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= i810_read,
-	.write		= i810_write,
-	.poll		= i810_poll,
-	.ioctl		= i810_ioctl,
-	.mmap		= i810_mmap,
-	.open		= i810_open,
-	.release	= i810_release,
-};
-
-/* Write AC97 codec registers */
-
-static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
-		udelay(1);
-	
-#ifdef DEBUG_MMIO
-	{
-		u16 ans = readw(card->ac97base_mmio + reg_set);
-		printk(KERN_DEBUG "i810_audio: ac97_get_mmio(%d) -> 0x%04X\n", ((int) reg_set) & 0xffff, (u32) ans);
-		return ans;
-	}
-#else
-	return readw(card->ac97base_mmio + reg_set);
-#endif
-}
-
-static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (I810_IOREADB(card, CAS) & 1)) 
-		udelay(1);
-	
-	return inw(card->ac97base + reg_set);
-}
-
-static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
-		udelay(1);
-	
-	writew(data, card->ac97base_mmio + reg_set);
-
-#ifdef DEBUG_MMIO
-	printk(KERN_DEBUG "i810_audio: ac97_set_mmio(0x%04X, %d)\n", (u32) data, ((int) reg_set) & 0xffff);
-#endif
-}
-
-static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (I810_IOREADB(card, CAS) & 1)) 
-		udelay(1);
-	
-        outw(data, card->ac97base + reg_set);
-}
-
-static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	u16 ret;
-	
-	spin_lock(&card->ac97_lock);
-	if (card->use_mmio) {
-		ret = i810_ac97_get_mmio(dev, reg);
-	}
-	else {
-		ret = i810_ac97_get_io(dev, reg);
-	}
-	spin_unlock(&card->ac97_lock);
-	
-	return ret;
-}
-
-static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	
-	spin_lock(&card->ac97_lock);
-	if (card->use_mmio) {
-		i810_ac97_set_mmio(dev, reg, data);
-	}
-	else {
-		i810_ac97_set_io(dev, reg, data);
-	}
-	spin_unlock(&card->ac97_lock);
-}
-
-
-/* OSS /dev/mixer file operation methods */
-
-static int i810_open_mixdev(struct inode *inode, struct file *file)
-{
-	int i;
-	int minor = iminor(inode);
-	struct i810_card *card = devs;
-
-	for (card = devs; card != NULL; card = card->next) {
-		/*
-		 * If we are initializing and then fail, card could go
-		 * away unuexpectedly while we are in the for() loop.
-		 * So, check for card on each iteration before we check
-		 * for card->initializing to avoid a possible oops.
-		 * This usually only matters for times when the driver is
-		 * autoloaded by kmod.
-		 */
-		for (i = 0; i < 50 && card && card->initializing; i++) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/20);
-		}
-		for (i = 0; i < NR_AC97 && card && !card->initializing; i++) 
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor) {
-				file->private_data = card->ac97_codec[i];
-				return nonseekable_open(inode, file);
-			}
-	}
-	return -ENODEV;
-}
-
-static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
-
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations i810_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= i810_ioctl_mixdev,
-	.open		= i810_open_mixdev,
-};
-
-/* AC97 codec initialisation.  These small functions exist so we don't
-   duplicate code between module init and apm resume */
-
-static inline int i810_ac97_exists(struct i810_card *card, int ac97_number)
-{
-	u32 reg = I810_IOREADL(card, GLOB_STA);
-	switch (ac97_number) {
-	case 0:
-		return reg & (1<<8);
-	case 1: 
-		return reg & (1<<9);
-	case 2:
-		return reg & (1<<28);
-	}
-	return 0;
-}
-
-static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec)
-{
-	i810_ac97_set(codec, AC97_EXTENDED_STATUS, 9);
-	i810_ac97_set(codec,AC97_EXTENDED_STATUS,
-		      i810_ac97_get(codec, AC97_EXTENDED_STATUS)|0xE800);
-	
-	return (i810_ac97_get(codec, AC97_EXTENDED_STATUS)&1);
-}
-
-
-static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec *codec)
-{
-	/* Returns 0 on failure */
-	int i;
-
-	if (ac97_probe_codec(codec) == 0) return 0;
-	
-	/* power it all up */
-	i810_ac97_set(codec, AC97_POWER_CONTROL,
-		      i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
-
-	/* wait for analog ready */
-	for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/20);
-	} 
-	return i;
-}
-
-static int is_new_ich(u16 pci_id)
-{
-	switch (pci_id) {
-	case PCI_DEVICE_ID_INTEL_82801DB_5:
-	case PCI_DEVICE_ID_INTEL_82801EB_5:
-	case PCI_DEVICE_ID_INTEL_ESB_5:
-	case PCI_DEVICE_ID_INTEL_ICH6_18:
-		return 1;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static inline int ich_use_mmio(struct i810_card *card)
-{
-	return is_new_ich(card->pci_id) && card->use_mmio;
-}
-
-/**
- *	i810_ac97_power_up_bus	-	bring up AC97 link
- *	@card : ICH audio device to power up
- *
- *	Bring up the ACLink AC97 codec bus
- */
- 
-static int i810_ac97_power_up_bus(struct i810_card *card)
-{	
-	u32 reg = I810_IOREADL(card, GLOB_CNT);
-	int i;
-	int primary_codec_id = 0;
-
-	if((reg&2)==0)	/* Cold required */
-		reg|=2;
-	else
-		reg|=4;	/* Warm */
-		
-	reg&=~8;	/* ACLink on */
-	
-	/* At this point we deassert AC_RESET # */
-	I810_IOWRITEL(reg , card, GLOB_CNT);
-
-	/* We must now allow time for the Codec initialisation.
-	   600mS is the specified time */
-	   	
-	for(i=0;i<10;i++)
-	{
-		if((I810_IOREADL(card, GLOB_CNT)&4)==0)
-			break;
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/20);
-	}
-	if(i==10)
-	{
-		printk(KERN_ERR "i810_audio: AC'97 reset failed.\n");
-		return 0;
-	}
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/2);
-
-	/*
-	 *	See if the primary codec comes ready. This must happen
-	 *	before we start doing DMA stuff
-	 */	
-	/* see i810_ac97_init for the next 10 lines (jsaw) */
-	if (card->use_mmio)
-		readw(card->ac97base_mmio);
-	else
-		inw(card->ac97base);
-	if (ich_use_mmio(card)) {
-		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
-		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
-		       primary_codec_id);
-	}
-
-	if(! i810_ac97_exists(card, primary_codec_id))
-	{
-		printk(KERN_INFO "i810_audio: Codec not ready.. wait.. ");
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ);	/* actually 600mS by the spec */
-
-		if(i810_ac97_exists(card, primary_codec_id))
-			printk("OK\n");
-		else 
-			printk("no response.\n");
-	}
-	if (card->use_mmio)
-		readw(card->ac97base_mmio);
-	else
-		inw(card->ac97base);
-	return 1;
-}
-
-static int __devinit i810_ac97_init(struct i810_card *card)
-{
-	int num_ac97 = 0;
-	int ac97_id;
-	int total_channels = 0;
-	int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;
-	struct ac97_codec *codec;
-	u16 eid;
-	u32 reg;
-
-	if(!i810_ac97_power_up_bus(card)) return 0;
-
-	/* Number of channels supported */
-	/* What about the codec?  Just because the ICH supports */
-	/* multiple channels doesn't mean the codec does.       */
-	/* we'll have to modify this in the codec section below */
-	/* to reflect what the codec has.                       */
-	/* ICH and ICH0 only support 2 channels so don't bother */
-	/* to check....                                         */
-
-	card->channels = 2;
-	reg = I810_IOREADL(card, GLOB_STA);
-	if ( reg & 0x0200000 )
-		card->channels = 6;
-	else if ( reg & 0x0100000 )
-		card->channels = 4;
-	printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels);
-	printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n");
-	reg = I810_IOREADL(card, GLOB_CNT);
-	I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT);
-		
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) 
-		card->ac97_codec[num_ac97] = NULL;
-
-	/*@FIXME I don't know, if I'm playing to safe here... (jsaw) */
-	if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2;
-
-	for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
-		/* codec reset */
-		printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
-		if (card->use_mmio)
-			readw(card->ac97base_mmio + 0x80*num_ac97);
-		else
-			inw(card->ac97base + 0x80*num_ac97);
-
-		/* If we have the SDATA_IN Map Register, as on ICH4, we
-		   do not loop thru all possible codec IDs but thru all 
-		   possible IO channels. Bit 0:1 of SDM then holds the 
-		   last codec ID spoken to. 
-		*/
-		if (ich_use_mmio(card)) {
-			ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
-			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
-			       num_ac97, ac97_id);
-		}
-		else {
-			ac97_id = num_ac97;
-		}
-
-		/* The ICH programmer's reference says you should   */
-		/* check the ready status before probing. So we chk */
-		/*   What do we do if it's not ready?  Wait and try */
-		/*   again, or abort?                               */
-		if (!i810_ac97_exists(card, ac97_id)) {
-			if(num_ac97 == 0)
-				printk(KERN_ERR "i810_audio: Primary codec not ready.\n");
-		}
-		
-		if ((codec = ac97_alloc_codec()) == NULL)
-			return -ENOMEM;
-
-		/* initialize some basic codec information, other fields will be filled
-		   in ac97_probe_codec */
-		codec->private_data = card;
-		codec->id = ac97_id;
-		card->ac97_id_map[ac97_id] = num_ac97 * 0x80;
-
-		if (card->use_mmio) {	
-			codec->codec_read = i810_ac97_get_mmio;
-			codec->codec_write = i810_ac97_set_mmio;
-		}
-		else {
-			codec->codec_read = i810_ac97_get_io;
-			codec->codec_write = i810_ac97_set_io;
-		}
-	
-		if(!i810_ac97_probe_and_powerup(card,codec)) {
-			printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id);
-			ac97_release_codec(codec);
-			break;	/* it didn't work */
-		}
-		/* Store state information about S/PDIF transmitter */
-		card->ac97_status = 0;
-		
-		/* Don't attempt to get eid until powerup is complete */
-		eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
-
-		if(eid==0xFFFF)
-		{
-			printk(KERN_WARNING "i810_audio: no codec attached ?\n");
-			ac97_release_codec(codec);
-			break;
-		}
-		
-		/* Check for an AC97 1.0 soft modem (ID1) */
-		
-		if(codec->modem)
-		{
-			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id);
-			ac97_release_codec(codec);
-			continue;
-		}
-		
-		card->ac97_features = eid;
-
-		/* Now check the codec for useful features to make up for
-		   the dumbness of the 810 hardware engine */
-
-		if(!(eid&0x0001))
-			printk(KERN_WARNING "i810_audio: only 48Khz playback available.\n");
-		else
-		{
-			if(!i810_ac97_enable_variable_rate(codec)) {
-				printk(KERN_WARNING "i810_audio: Codec refused to allow VRA, using 48Khz only.\n");
-				card->ac97_features&=~1;
-			}			
-		}
-   		
-		/* Turn on the amplifier */
-
-		codec->codec_write(codec, AC97_POWER_CONTROL, 
-			 codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000);
-				
-		/* Determine how many channels the codec(s) support   */
-		/*   - The primary codec always supports 2            */
-		/*   - If the codec supports AMAP, surround DACs will */
-		/*     automaticlly get assigned to slots.            */
-		/*     * Check for surround DACs and increment if     */
-		/*       found.                                       */
-		/*   - Else check if the codec is revision 2.2        */
-		/*     * If surround DACs exist, assign them to slots */
-		/*       and increment channel count.                 */
-
-		/* All of this only applies to ICH2 and above. ICH    */
-		/* and ICH0 only support 2 channels.  ICH2 will only  */
-		/* support multiple codecs in a "split audio" config. */
-		/* as described above.                                */
-
-		/* TODO: Remove all the debugging messages!           */
-
-		if((eid & 0xc000) == 0) /* primary codec */
-			total_channels += 2; 
-
-		if(eid & 0x200) { /* GOOD, AMAP support */
-			if (eid & 0x0080) /* L/R Surround channels */
-				total_channels += 2;
-			if (eid & 0x0140) /* LFE and Center channels */
-				total_channels += 2;
-			printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels);
-		} else if (eid & 0x0400) {  /* this only works on 2.2 compliant codecs */
-			eid &= 0xffcf;
-			if((eid & 0xc000) != 0)	{
-				switch ( total_channels ) {
-					case 2:
-						/* Set dsa1, dsa0 to 01 */
-						eid |= 0x0010;
-						break;
-					case 4:
-						/* Set dsa1, dsa0 to 10 */
-						eid |= 0x0020;
-						break;
-					case 6:
-						/* Set dsa1, dsa0 to 11 */
-						eid |= 0x0030;
-						break;
-				}
-				total_channels += 2;
-			}
-			i810_ac97_set(codec, AC97_EXTENDED_ID, eid);
-			eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
-			printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid);
-			if (eid & 0x0080) /* L/R Surround channels */
-				total_channels += 2;
-			if (eid & 0x0140) /* LFE and Center channels */
-				total_channels += 2;
-			printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels);
-		} else {
-			printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels);
-		}
-
-		if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) {
-			printk(KERN_ERR "i810_audio: couldn't register mixer!\n");
-			ac97_release_codec(codec);
-			break;
-		}
-
-		card->ac97_codec[num_ac97] = codec;
-	}
-
-	/* tune up the primary codec */
-	ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk);
-
-	/* pick the minimum of channels supported by ICHx or codec(s) */
-	card->channels = (card->channels > total_channels)?total_channels:card->channels;
-
-	return num_ac97;
-}
-
-static void __devinit i810_configure_clocking (void)
-{
-	struct i810_card *card;
-	struct i810_state *state;
-	struct dmabuf *dmabuf;
-	unsigned int i, offset, new_offset;
-	unsigned long flags;
-
-	card = devs;
-	/* We could try to set the clocking for multiple cards, but can you even have
-	 * more than one i810 in a machine?  Besides, clocking is global, so unless
-	 * someone actually thinks more than one i810 in a machine is possible and
-	 * decides to rewrite that little bit, setting the rate for more than one card
-	 * is a waste of time.
-	 */
-	if(card != NULL) {
-		state = card->states[0] = (struct i810_state *)
-					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
-		if (state == NULL)
-			return;
-		dmabuf = &state->dmabuf;
-
-		dmabuf->write_channel = card->alloc_pcm_channel(card);
-		state->virt = 0;
-		state->card = card;
-		state->magic = I810_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT;
-		dmabuf->trigger = PCM_ENABLE_OUTPUT;
-		i810_set_spdif_output(state, -1, 0);
-		i810_set_dac_channels(state, 2);
-		i810_set_dac_rate(state, 48000);
-		if(prog_dmabuf(state, 0) != 0) {
-			goto config_out_nodmabuf;
-		}
-		if(dmabuf->dmasize < 16384) {
-			goto config_out;
-		}
-		dmabuf->count = dmabuf->dmasize;
-		CIV_TO_LVI(card, dmabuf->write_channel->port, -1);
-		local_irq_save(flags);
-		start_dac(state);
-		offset = i810_get_dma_addr(state, 0);
-		mdelay(50);
-		new_offset = i810_get_dma_addr(state, 0);
-		stop_dac(state);
-		local_irq_restore(flags);
-		i = new_offset - offset;
-#ifdef DEBUG_INTERRUPTS
-		printk("i810_audio: %d bytes in 50 milliseconds\n", i);
-#endif
-		if(i == 0)
-			goto config_out;
-		i = i / 4 * 20;
-		if (i > 48500 || i < 47500) {
-			clocking = clocking * clocking / i;
-			printk("i810_audio: setting clocking to %d\n", clocking);
-		}
-config_out:
-		dealloc_dmabuf(state);
-config_out_nodmabuf:
-		state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num);
-		kfree(state);
-		card->states[0] = NULL;
-	}
-}
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
-   until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-   
-static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
-	struct i810_card *card;
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-
-	if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) {
-		printk(KERN_ERR "i810_audio: architecture does not support"
-		       " 32bit PCI busmaster DMA\n");
-		return -ENODEV;
-	}
-	
-	if ((card = kzalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "i810_audio: out of memory\n");
-		return -ENOMEM;
-	}
-
-	card->initializing = 1;
-	card->pci_dev = pci_dev;
-	card->pci_id = pci_id->device;
-	card->ac97base = pci_resource_start (pci_dev, 0);
-	card->iobase = pci_resource_start (pci_dev, 1);
-
-	if (!(card->ac97base) || !(card->iobase)) {
-		card->ac97base = 0;
-		card->iobase = 0;
-	}
-
-	/* if chipset could have mmio capability, check it */ 
-	if (card_cap[pci_id->driver_data].flags & CAP_MMIO) {
-		card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2);
-		card->iobase_mmio_phys = pci_resource_start (pci_dev, 3);
-
-		if ((card->ac97base_mmio_phys) && (card->iobase_mmio_phys)) {
-			card->use_mmio = 1;
-		}
-		else {
-			card->ac97base_mmio_phys = 0;
-			card->iobase_mmio_phys = 0;
-		}
-	}
-
-	if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) {
-		printk(KERN_ERR "i810_audio: No I/O resources available.\n");
-		goto out_mem;
-	}
-
-	card->irq = pci_dev->irq;
-	card->next = devs;
-	card->magic = I810_CARD_MAGIC;
-#ifdef CONFIG_PM
-	card->pm_suspended=0;
-#endif
-	spin_lock_init(&card->lock);
-	spin_lock_init(&card->ac97_lock);
-	devs = card;
-
-	pci_set_master(pci_dev);
-
-	printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, "
-	       "MEM 0x%04lx and 0x%04lx, IRQ %d\n",
-	       card_names[pci_id->driver_data], 
-	       card->iobase, card->ac97base, 
-	       card->ac97base_mmio_phys, card->iobase_mmio_phys,
-	       card->irq);
-
-	card->alloc_pcm_channel = i810_alloc_pcm_channel;
-	card->alloc_rec_pcm_channel = i810_alloc_rec_pcm_channel;
-	card->alloc_rec_mic_channel = i810_alloc_rec_mic_channel;
-	card->free_pcm_channel = i810_free_pcm_channel;
-
-	if ((card->channel = pci_alloc_consistent(pci_dev,
-	    sizeof(struct i810_channel)*NR_HW_CH, &card->chandma)) == NULL) {
-		printk(KERN_ERR "i810: cannot allocate channel DMA memory\n");
-		goto out_mem;
-	}
-
-	{ /* We may dispose of this altogether some time soon, so... */
-		struct i810_channel *cp = card->channel;
-
-		cp[0].offset = 0;
-		cp[0].port = 0x00;
-		cp[0].num = 0;
-		cp[1].offset = 0;
-		cp[1].port = 0x10;
-		cp[1].num = 1;
-		cp[2].offset = 0;
-		cp[2].port = 0x20;
-		cp[2].num = 2;
-	}
-
-	/* claim our iospace and irq */
-	if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
-		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
-		goto out_region1;
-	}
-	if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
-		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
-		goto out_region2;
-	}
-
-	if (card->use_mmio) {
-		if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) {
-			if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */
-				if (request_mem_region(card->iobase_mmio_phys, 256, "ich_audio MBBAR")) {
-					if ((card->iobase_mmio = ioremap(card->iobase_mmio_phys, 256))) {
-						printk(KERN_INFO "i810: %s mmio at 0x%04lx and 0x%04lx\n",
-						       card_names[pci_id->driver_data], 
-						       (unsigned long) card->ac97base_mmio, 
-						       (unsigned long) card->iobase_mmio); 
-					}
-					else {
-						iounmap(card->ac97base_mmio);
-						release_mem_region(card->ac97base_mmio_phys, 512);
-						release_mem_region(card->iobase_mmio_phys, 512);
-						card->use_mmio = 0;
-					}
-				}
-				else {
-					iounmap(card->ac97base_mmio);
-					release_mem_region(card->ac97base_mmio_phys, 512);
-					card->use_mmio = 0;
-				}
-			}
-		}
-		else {
-			card->use_mmio = 0;
-		}
-	}
-
-	/* initialize AC97 codec and register /dev/mixer */
-	if (i810_ac97_init(card) <= 0)
-		goto out_iospace;
-	pci_set_drvdata(pci_dev, card);
-
-	if(clocking == 0) {
-		clocking = 48000;
-		i810_configure_clocking();
-	}
-
-	/* register /dev/dsp */
-	if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) {
-		int i;
-		printk(KERN_ERR "i810_audio: couldn't register DSP device!\n");
-		for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-		}
-		goto out_iospace;
-	}
-
-	if (request_irq(card->irq, &i810_interrupt, IRQF_SHARED,
-			card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq);
-		goto out_iospace;
-	}
-
-
- 	card->initializing = 0;
-	return 0;
-
-out_iospace:
-	if (card->use_mmio) {
-		iounmap(card->ac97base_mmio);
-		iounmap(card->iobase_mmio);
-		release_mem_region(card->ac97base_mmio_phys, 512);
-		release_mem_region(card->iobase_mmio_phys, 256);
-	}
-	release_region(card->ac97base, 256);
-out_region2:
-	release_region(card->iobase, 64);
-out_region1:
-	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
-	    card->channel, card->chandma);
-out_mem:
-	kfree(card);
-	return -ENODEV;
-}
-
-static void __devexit i810_remove(struct pci_dev *pci_dev)
-{
-	int i;
-	struct i810_card *card = pci_get_drvdata(pci_dev);
-	/* free hardware resources */
-	free_irq(card->irq, devs);
-	release_region(card->iobase, 64);
-	release_region(card->ac97base, 256);
-	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
-			    card->channel, card->chandma);
-	if (card->use_mmio) {
-		iounmap(card->ac97base_mmio);
-		iounmap(card->iobase_mmio);
-		release_mem_region(card->ac97base_mmio_phys, 512);
-		release_mem_region(card->iobase_mmio_phys, 256);
-	}
-
-	/* unregister audio devices */
-	for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-			card->ac97_codec[i] = NULL;
-		}
-	unregister_sound_dsp(card->dev_audio);
-	kfree(card);
-}
-
-#ifdef CONFIG_PM
-static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
-{
-        struct i810_card *card = pci_get_drvdata(dev);
-        struct i810_state *state;
-	unsigned long flags;
-	struct dmabuf *dmabuf;
-	int i,num_ac97;
-#ifdef DEBUG
-	printk("i810_audio: i810_pm_suspend called\n");
-#endif
-	if(!card) return 0;
-	spin_lock_irqsave(&card->lock, flags);
-	card->pm_suspended=1;
-	for(i=0;i<NR_HW_CH;i++) {
-		state = card->states[i];
-		if(!state) continue;
-		/* this happens only if there are open files */
-		dmabuf = &state->dmabuf;
-		if(dmabuf->enable & DAC_RUNNING ||
-		   (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) {
-			state->pm_saved_dac_rate=dmabuf->rate;
-			stop_dac(state);
-		} else {
-			state->pm_saved_dac_rate=0;
-		}
-		if(dmabuf->enable & ADC_RUNNING) {
-			state->pm_saved_adc_rate=dmabuf->rate;	
-			stop_adc(state);
-		} else {
-			state->pm_saved_adc_rate=0;
-		}
-		dmabuf->ready = 0;
-		dmabuf->swptr = dmabuf->hwptr = 0;
-		dmabuf->count = dmabuf->total_bytes = 0;
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/* save mixer settings */
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		struct ac97_codec *codec = card->ac97_codec[num_ac97];
-		if(!codec) continue;
-		for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) {
-			if((supported_mixer(codec,i)) &&
-			   (codec->read_mixer)) {
-				card->pm_saved_mixer_settings[i][num_ac97]=
-					codec->read_mixer(codec,i);
-			}
-		}
-	}
-	pci_save_state(dev); /* XXX do we need this? */
-	pci_disable_device(dev); /* disable busmastering */
-	pci_set_power_state(dev,3); /* Zzz. */
-
-	return 0;
-}
-
-
-static int i810_pm_resume(struct pci_dev *dev)
-{
-	int num_ac97,i=0;
-	struct i810_card *card=pci_get_drvdata(dev);
-	pci_enable_device(dev);
-	pci_restore_state (dev);
-
-	/* observation of a toshiba portege 3440ct suggests that the 
-	   hardware has to be more or less completely reinitialized from
-	   scratch after an apm suspend.  Works For Me.   -dan */
-
-	i810_ac97_power_up_bus(card);
-
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		struct ac97_codec *codec = card->ac97_codec[num_ac97];
-		/* check they haven't stolen the hardware while we were
-		   away */
-		if(!codec || !i810_ac97_exists(card,num_ac97)) {
-			if(num_ac97) continue;
-			else BUG();
-		}
-		if(!i810_ac97_probe_and_powerup(card,codec)) BUG();
-		
-		if((card->ac97_features&0x0001)) {
-			/* at probe time we found we could do variable
-			   rates, but APM suspend has made it forget
-			   its magical powers */
-			if(!i810_ac97_enable_variable_rate(codec)) BUG();
-		}
-		/* we lost our mixer settings, so restore them */
-		for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) {
-			if(supported_mixer(codec,i)){
-				int val=card->
-					pm_saved_mixer_settings[i][num_ac97];
-				codec->mixer_state[i]=val;
-				codec->write_mixer(codec,i,
-						   (val  & 0xff) ,
-						   ((val >> 8)  & 0xff) );
-			}
-		}
-	}
-
-	/* we need to restore the sample rate from whatever it was */
-	for(i=0;i<NR_HW_CH;i++) {
-		struct i810_state * state=card->states[i];
-		if(state) {
-			if(state->pm_saved_adc_rate)
-				i810_set_adc_rate(state,state->pm_saved_adc_rate);
-			if(state->pm_saved_dac_rate)
-				i810_set_dac_rate(state,state->pm_saved_dac_rate);
-		}
-	}
-
-	
-        card->pm_suspended = 0;
-
-	/* any processes that were reading/writing during the suspend
-	   probably ended up here */
-	for(i=0;i<NR_HW_CH;i++) {
-		struct i810_state *state = card->states[i];
-		if(state) wake_up(&state->dmabuf.wait);
-        }
-
-	return 0;
-}	
-#endif /* CONFIG_PM */
-
-MODULE_AUTHOR("The Linux kernel team");
-MODULE_DESCRIPTION("Intel 810 audio support");
-MODULE_LICENSE("GPL");
-module_param(ftsodell, int, 0444);
-module_param(clocking, uint, 0444);
-module_param(strict_clocking, int, 0444);
-module_param(spdif_locked, int, 0444);
-
-#define I810_MODULE_NAME "i810_audio"
-
-static struct pci_driver i810_pci_driver = {
-	.name		= I810_MODULE_NAME,
-	.id_table	= i810_pci_tbl,
-	.probe		= i810_probe,
-	.remove		= __devexit_p(i810_remove),
-#ifdef CONFIG_PM
-	.suspend	= i810_pm_suspend,
-	.resume		= i810_pm_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init i810_init_module (void)
-{
-	int retval;
-
-	printk(KERN_INFO "Intel 810 + AC97 Audio, version "
-	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-	retval = pci_register_driver(&i810_pci_driver);
-	if (retval)
-		return retval;
-
-	if(ftsodell != 0) {
-		printk("i810_audio: ftsodell is now a deprecated option.\n");
-	}
-	if(spdif_locked > 0 ) {
-		if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) {
-			printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked);
-		} else {
-			printk("i810_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n");
-			spdif_locked = 0;
-		}
-	}
-	
-	return 0;
-}
-
-static void __exit i810_cleanup_module (void)
-{
-	pci_unregister_driver(&i810_pci_driver);
-}
-
-module_init(i810_init_module);
-module_exit(i810_cleanup_module);
-
-/*
-Local Variables:
-c-basic-offset: 8
-End:
-*/
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index ece428b..16ed069 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -232,14 +232,12 @@
 	return 1;
 }
 
-static int set_io_base(pss_confdata * devc, int dev, int base)
+static void set_io_base(pss_confdata * devc, int dev, int base)
 {
 	unsigned short  tmp = inw(REG(dev)) & 0x003f;
 	unsigned short  bits = (base & 0x0ffc) << 4;
 
 	outw(bits | tmp, REG(dev));
-
-	return 1;
 }
 
 static int set_dma(pss_confdata * devc, int dev, int dma)
@@ -673,20 +671,12 @@
 
 	/* Configure CDROM port */
 
-	if(pss_cdrom_port == -1)	/* If cdrom port enablation wasn't requested */
-	{
+	if (pss_cdrom_port == -1) {	/* If cdrom port enablation wasn't requested */
 		printk(KERN_INFO "PSS: CDROM port not enabled.\n");
-	}
-	else if(check_region(pss_cdrom_port, 2))
-	{
+	} else if (check_region(pss_cdrom_port, 2)) {
 		printk(KERN_ERR "PSS: CDROM I/O port conflict.\n");
-	}
-	else if(!set_io_base(devc, CONF_CDROM, pss_cdrom_port))
-	{
-		printk(KERN_ERR "PSS: CDROM I/O port could not be set.\n");
-	}
-	else					/* CDROM port successfully configured */
-	{
+	} else {
+		set_io_base(devc, CONF_CDROM, pss_cdrom_port);
 		printk(KERN_INFO "PSS: CDROM I/O port set to 0x%x.\n", pss_cdrom_port);
 	}
 }
@@ -758,10 +748,7 @@
 		printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 		return 0;
 	}
-	if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) {
-		printk(KERN_ERR "PSS: MIDI base could not be set.\n");
-		goto fail;
-	}
+	set_io_base(devc, CONF_MIDI, hw_config->io_base);
 	if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
 		printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
 		goto fail;
@@ -1057,10 +1044,7 @@
 		release_region(hw_config->io_base, 4);
 		return 0;
 	}
-	if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) {
-		printk("PSS: WSS base not settable.\n");
-		goto fail;
-	}
+	set_io_base(devc, CONF_WSS, hw_config->io_base);
 	if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
 		printk("PSS: WSS IRQ allocation error.\n");
 		goto fail;
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index 07cbacf..77d0e5e 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -1228,7 +1228,8 @@
 		}
 		attach_mpu401(hw_config, owner);
 		if (last_sb->irq == -hw_config->irq)
-			last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
+			last_sb->midi_irq_cookie =
+				(void *)(long) hw_config->slots[1];
 		return 1;
 	}
 #endif
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 96adc479..6959ee1 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -2935,7 +2935,7 @@
 	do {
 		if ((inw(TRID_REG(card, address)) & busy) == 0)
 			break;
-	} while (count--);
+	} while (--count);
 
 	data |= (mask | (reg & AC97_REG_ADDR));
 
@@ -2996,7 +2996,7 @@
 		data = inl(TRID_REG(card, address));
 		if ((data & busy) == 0)
 			break;
-	} while (count--);
+	} while (--count);
 	spin_unlock_irqrestore(&card->lock, flags);
 
 	if (count == 0) {
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
deleted file mode 100644
index f95aa09..0000000
--- a/sound/oss/via82cxxx_audio.c
+++ /dev/null
@@ -1,3616 +0,0 @@
-/*
- * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik
- *
- * Updated to support the VIA 8233/8235 audio subsystem
- * Alan Cox <alan@redhat.com> (C) Copyright 2002, 2003 Red Hat Inc
- *
- * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
- * See the "COPYING" file distributed with this software for more info.
- * NO WARRANTY
- *
- * For a list of known bugs (errata) and documentation,
- * see via-audio.pdf in Documentation/DocBook.
- * If this documentation does not exist, run "make pdfdocs".
- */
-
-
-#define VIA_VERSION	"1.9.1-ac4-2.5"
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/poison.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/sound.h>
-#include <linux/poll.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/mutex.h>
-
-#include "sound_config.h"
-#include "dev_table.h"
-#include "mpu401.h"
-
-
-#undef VIA_DEBUG	/* define to enable debugging output and checks */
-#ifdef VIA_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#undef VIA_NDEBUG	/* define to disable lightweight runtime checks */
-#ifdef VIA_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(!(expr)) {					\
-        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
-        #expr,__FILE__,__FUNCTION__,__LINE__);		\
-        }
-#endif
-
-#define VIA_SUPPORT_MMAP 1 /* buggy, for now... */
-
-#define MAX_CARDS	1
-
-#define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
-#define VIA_MODULE_NAME "via82cxxx"
-#define PFX		VIA_MODULE_NAME ": "
-
-#define VIA_COUNTER_LIMIT	100000
-
-/* size of DMA buffers */
-#define VIA_MAX_BUFFER_DMA_PAGES	32
-
-/* buffering default values in ms */
-#define VIA_DEFAULT_FRAG_TIME		20
-#define VIA_DEFAULT_BUFFER_TIME		500
-
-/* the hardware has a 256 fragment limit */
-#define VIA_MIN_FRAG_NUMBER		2
-#define VIA_MAX_FRAG_NUMBER		128
-
-#define VIA_MAX_FRAG_SIZE		PAGE_SIZE
-#define VIA_MIN_FRAG_SIZE		(VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE / VIA_MAX_FRAG_NUMBER)
-
-
-/* 82C686 function 5 (audio codec) PCI configuration registers */
-#define VIA_ACLINK_STATUS	0x40
-#define VIA_ACLINK_CTRL		0x41
-#define VIA_FUNC_ENABLE		0x42
-#define VIA_PNP_CONTROL		0x43
-#define VIA_FM_NMI_CTRL		0x48
-
-/*
- * controller base 0 (scatter-gather) registers
- *
- * NOTE: Via datasheet lists first channel as "read"
- * channel and second channel as "write" channel.
- * I changed the naming of the constants to be more
- * clear than I felt the datasheet to be.
- */
-
-#define VIA_BASE0_PCM_OUT_CHAN	0x00 /* output PCM to user */
-#define VIA_BASE0_PCM_OUT_CHAN_STATUS 0x00
-#define VIA_BASE0_PCM_OUT_CHAN_CTRL	0x01
-#define VIA_BASE0_PCM_OUT_CHAN_TYPE	0x02
-
-#define VIA_BASE0_PCM_IN_CHAN		0x10 /* input PCM from user */
-#define VIA_BASE0_PCM_IN_CHAN_STATUS	0x10
-#define VIA_BASE0_PCM_IN_CHAN_CTRL	0x11
-#define VIA_BASE0_PCM_IN_CHAN_TYPE	0x12
-
-/* offsets from base */
-#define VIA_PCM_STATUS			0x00
-#define VIA_PCM_CONTROL			0x01
-#define VIA_PCM_TYPE			0x02
-#define VIA_PCM_LEFTVOL			0x02
-#define VIA_PCM_RIGHTVOL		0x03
-#define VIA_PCM_TABLE_ADDR		0x04
-#define VIA_PCM_STOPRATE		0x08	/* 8233+ */
-#define VIA_PCM_BLOCK_COUNT		0x0C
-
-/* XXX unused DMA channel for FM PCM data */
-#define VIA_BASE0_FM_OUT_CHAN		0x20
-#define VIA_BASE0_FM_OUT_CHAN_STATUS	0x20
-#define VIA_BASE0_FM_OUT_CHAN_CTRL	0x21
-#define VIA_BASE0_FM_OUT_CHAN_TYPE	0x22
-
-/* Six channel audio output on 8233 */
-#define VIA_BASE0_MULTI_OUT_CHAN		0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_STATUS		0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_CTRL		0x41
-#define VIA_BASE0_MULTI_OUT_CHAN_TYPE		0x42
-
-#define VIA_BASE0_AC97_CTRL		0x80
-#define VIA_BASE0_SGD_STATUS_SHADOW	0x84
-#define VIA_BASE0_GPI_INT_ENABLE	0x8C
-#define VIA_INTR_OUT			((1<<0) |  (1<<4) |  (1<<8))
-#define VIA_INTR_IN			((1<<1) |  (1<<5) |  (1<<9))
-#define VIA_INTR_FM			((1<<2) |  (1<<6) | (1<<10))
-#define VIA_INTR_MASK		(VIA_INTR_OUT | VIA_INTR_IN | VIA_INTR_FM)
-
-/* Newer VIA we need to monitor the low 3 bits of each channel. This
-   mask covers the channels we don't yet use as well 
- */
- 
-#define VIA_NEW_INTR_MASK		0x77077777UL
-
-/* VIA_BASE0_AUDIO_xxx_CHAN_TYPE bits */
-#define VIA_IRQ_ON_FLAG			(1<<0)	/* int on each flagged scatter block */
-#define VIA_IRQ_ON_EOL			(1<<1)	/* int at end of scatter list */
-#define VIA_INT_SEL_PCI_LAST_LINE_READ	(0)	/* int at PCI read of last line */
-#define VIA_INT_SEL_LAST_SAMPLE_SENT	(1<<2)	/* int at last sample sent */
-#define VIA_INT_SEL_ONE_LINE_LEFT	(1<<3)	/* int at less than one line to send */
-#define VIA_PCM_FMT_STEREO		(1<<4)	/* PCM stereo format (bit clear == mono) */
-#define VIA_PCM_FMT_16BIT		(1<<5)	/* PCM 16-bit format (bit clear == 8-bit) */
-#define VIA_PCM_REC_FIFO		(1<<6)	/* PCM Recording FIFO */
-#define VIA_RESTART_SGD_ON_EOL		(1<<7)	/* restart scatter-gather at EOL */
-#define VIA_PCM_FMT_MASK		(VIA_PCM_FMT_STEREO|VIA_PCM_FMT_16BIT)
-#define VIA_CHAN_TYPE_MASK		(VIA_RESTART_SGD_ON_EOL | \
-					 VIA_IRQ_ON_FLAG | \
-					 VIA_IRQ_ON_EOL)
-#define VIA_CHAN_TYPE_INT_SELECT	(VIA_INT_SEL_LAST_SAMPLE_SENT)
-
-/* PCI configuration register bits and masks */
-#define VIA_CR40_AC97_READY	0x01
-#define VIA_CR40_AC97_LOW_POWER	0x02
-#define VIA_CR40_SECONDARY_READY 0x04
-
-#define VIA_CR41_AC97_ENABLE	0x80 /* enable AC97 codec */
-#define VIA_CR41_AC97_RESET	0x40 /* clear bit to reset AC97 */
-#define VIA_CR41_AC97_WAKEUP	0x20 /* wake up from power-down mode */
-#define VIA_CR41_AC97_SDO	0x10 /* force Serial Data Out (SDO) high */
-#define VIA_CR41_VRA		0x08 /* enable variable sample rate */
-#define VIA_CR41_PCM_ENABLE	0x04 /* AC Link SGD Read Channel PCM Data Output */
-#define VIA_CR41_FM_PCM_ENABLE	0x02 /* AC Link FM Channel PCM Data Out */
-#define VIA_CR41_SB_PCM_ENABLE	0x01 /* AC Link SB PCM Data Output */
-#define VIA_CR41_BOOT_MASK	(VIA_CR41_AC97_ENABLE | \
-				 VIA_CR41_AC97_WAKEUP | \
-				 VIA_CR41_AC97_SDO)
-#define VIA_CR41_RUN_MASK	(VIA_CR41_AC97_ENABLE | \
-				 VIA_CR41_AC97_RESET | \
-				 VIA_CR41_VRA | \
-				 VIA_CR41_PCM_ENABLE)
-
-#define VIA_CR42_SB_ENABLE	0x01
-#define VIA_CR42_MIDI_ENABLE	0x02
-#define VIA_CR42_FM_ENABLE	0x04
-#define VIA_CR42_GAME_ENABLE	0x08
-#define VIA_CR42_MIDI_IRQMASK   0x40
-#define VIA_CR42_MIDI_PNP	0x80
-
-#define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
-#define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
-
-#define VIA_CR48_FM_TRAP_TO_NMI		(1 << 2)
-
-/* controller base 0 register bitmasks */
-#define VIA_INT_DISABLE_MASK		(~(0x01|0x02))
-#define VIA_SGD_STOPPED			(1 << 2)
-#define VIA_SGD_PAUSED			(1 << 6)
-#define VIA_SGD_ACTIVE			(1 << 7)
-#define VIA_SGD_TERMINATE		(1 << 6)
-#define VIA_SGD_FLAG			(1 << 0)
-#define VIA_SGD_EOL			(1 << 1)
-#define VIA_SGD_START			(1 << 7)
-
-#define VIA_CR80_FIRST_CODEC		0
-#define VIA_CR80_SECOND_CODEC		(1 << 30)
-#define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
-#define VIA_CR80_VALID			(1 << 25)
-#define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
-#define VIA_CR80_BUSY			(1 << 24)
-#define VIA_CR83_BUSY			(1)
-#define VIA_CR83_FIRST_CODEC_VALID	(1 << 1)
-#define VIA_CR80_READ			(1 << 23)
-#define VIA_CR80_WRITE_MODE		0
-#define VIA_CR80_REG_IDX(idx)		((((idx) & 0xFF) >> 1) << 16)
-
-/* capabilities we announce */
-#ifdef VIA_SUPPORT_MMAP
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | DSP_CAP_MMAP | \
-		     DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#else
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | \
-		     DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#endif
-
-/* scatter-gather DMA table entry, exactly as passed to hardware */
-struct via_sgd_table {
-	u32 addr;
-	u32 count;	/* includes additional VIA_xxx bits also */
-};
-
-#define VIA_EOL (1 << 31)
-#define VIA_FLAG (1 << 30)
-#define VIA_STOP (1 << 29)
-
-
-enum via_channel_states {
-	sgd_stopped = 0,
-	sgd_in_progress = 1,
-};
-
-
-struct via_buffer_pgtbl {
-	dma_addr_t handle;
-	void *cpuaddr;
-};
-
-
-struct via_channel {
-	atomic_t n_frags;
-	atomic_t hw_ptr;
-	wait_queue_head_t wait;
-
-	unsigned int sw_ptr;
-	unsigned int slop_len;
-	unsigned int n_irqs;
-	int bytes;
-
-	unsigned is_active : 1;
-	unsigned is_record : 1;
-	unsigned is_mapped : 1;
-	unsigned is_enabled : 1;
-	unsigned is_multi: 1;	/* 8233 6 channel */
-	u8 pcm_fmt;		/* VIA_PCM_FMT_xxx */
-	u8 channels;		/* Channel count */
-
-	unsigned rate;		/* sample rate */
-	unsigned int frag_size;
-	unsigned int frag_number;
-	
-	unsigned char intmask;
-
-	volatile struct via_sgd_table *sgtable;
-	dma_addr_t sgt_handle;
-
-	unsigned int page_number;
-	struct via_buffer_pgtbl pgtbl[VIA_MAX_BUFFER_DMA_PAGES];
-
-	long iobase;
-
-	const char *name;
-};
-
-
-/* data stored for each chip */
-struct via_info {
-	struct pci_dev *pdev;
-	long baseaddr;
-
-	struct ac97_codec *ac97;
-	spinlock_t ac97_lock;
-	spinlock_t lock;
-	int card_num;		/* unique card number, from 0 */
-
-	int dev_dsp;		/* /dev/dsp index from register_sound_dsp() */
-
-	unsigned rev_h : 1;
-	unsigned legacy: 1;	/* Has legacy ports */
-	unsigned intmask: 1;	/* Needs int bits */
-	unsigned sixchannel: 1;	/* 8233/35 with 6 channel support */
-	unsigned volume: 1;
-
-	unsigned locked_rate : 1;
-	
-	int mixer_vol;		/* 8233/35 volume  - not yet implemented */
-
-	struct mutex syscall_mutex;
-	struct mutex open_mutex;
-
-	/* The 8233/8235 have 4 DX audio channels, two record and
-	   one six channel out. We bind ch_in to DX 1, ch_out to multichannel
-	   and ch_fm to DX 2. DX 3 and REC0/REC1 are unused at the
-	   moment */
-	   
-	struct via_channel ch_in;
-	struct via_channel ch_out;
-	struct via_channel ch_fm;
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-        void *midi_devc;
-        struct address_info midi_info;
-#endif
-};
-
-
-/* number of cards, used for assigning unique numbers to cards */
-static unsigned via_num_cards;
-
-
-
-/****************************************************************
- *
- * prototypes
- *
- *
- */
-
-static int via_init_one (struct pci_dev *dev, const struct pci_device_id *id);
-static void __devexit via_remove_one (struct pci_dev *pdev);
-
-static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
-static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
-static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait);
-static int via_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int via_dsp_open (struct inode *inode, struct file *file);
-static int via_dsp_release(struct inode *inode, struct file *file);
-static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma);
-
-static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg);
-static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value);
-static u8 via_ac97_wait_idle (struct via_info *card);
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan);
-static void via_chan_clear (struct via_info *card, struct via_channel *chan);
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset);
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan);
-
-
-/****************************************************************
- *
- * Various data the driver needs
- *
- *
- */
-
-
-static struct pci_device_id via_pci_tbl[] = {
-	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci,via_pci_tbl);
-
-
-static struct pci_driver via_driver = {
-	.name		= VIA_MODULE_NAME,
-	.id_table	= via_pci_tbl,
-	.probe		= via_init_one,
-	.remove		= __devexit_p(via_remove_one),
-};
-
-
-/****************************************************************
- *
- * Low-level base 0 register read/write helpers
- *
- *
- */
-
-/**
- *	via_chan_stop - Terminate DMA on specified PCM channel
- *	@iobase: PCI base address for SGD channel registers
- *
- *	Terminate scatter-gather DMA operation for given
- *	channel (derived from @iobase), if DMA is active.
- *
- *	Note that @iobase is not the PCI base address,
- *	but the PCI base address plus an offset to
- *	one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_stop (long iobase)
-{
-	if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
-		outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
-}
-
-
-/**
- *	via_chan_status_clear - Clear status flags on specified DMA channel
- *	@iobase: PCI base address for SGD channel registers
- *
- *	Clear any pending status flags for the given
- *	DMA channel (derived from @iobase), if any
- *	flags are asserted.
- *
- *	Note that @iobase is not the PCI base address,
- *	but the PCI base address plus an offset to
- *	one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_status_clear (long iobase)
-{
-	u8 tmp = inb (iobase + VIA_PCM_STATUS);
-
-	if (tmp != 0)
-		outb (tmp, iobase + VIA_PCM_STATUS);
-}
-
-
-/**
- *	sg_begin - Begin recording or playback on a PCM channel
- *	@chan: Channel for which DMA operation shall begin
- *
- *	Start scatter-gather DMA for the given channel.
- *
- */
-
-static inline void sg_begin (struct via_channel *chan)
-{
-	DPRINTK("Start with intmask %d\n", chan->intmask);
-	DPRINTK("About to start from %d to %d\n", 
-		inl(chan->iobase + VIA_PCM_BLOCK_COUNT),
-		inb(chan->iobase + VIA_PCM_STOPRATE + 3));
-	outb (VIA_SGD_START|chan->intmask, chan->iobase + VIA_PCM_CONTROL);
-	DPRINTK("Status is now %02X\n", inb(chan->iobase + VIA_PCM_STATUS));
-	DPRINTK("Control is now %02X\n", inb(chan->iobase + VIA_PCM_CONTROL));
-}
-
-
-static int sg_active (long iobase)
-{
-	u8 tmp = inb (iobase + VIA_PCM_STATUS);
-	if ((tmp & VIA_SGD_STOPPED) || (tmp & VIA_SGD_PAUSED)) {
-		printk(KERN_WARNING "via82cxxx warning: SG stopped or paused\n");
-		return 0;
-	}
-	if (tmp & VIA_SGD_ACTIVE)
-		return 1;
-	return 0;
-}
-
-static int via_sg_offset(struct via_channel *chan)
-{
-	return inl (chan->iobase + VIA_PCM_BLOCK_COUNT) & 0x00FFFFFF;
-}
-
-/****************************************************************
- *
- * Miscellaneous debris
- *
- *
- */
-
-
-/**
- *	via_syscall_down - down the card-specific syscell semaphore
- *	@card: Private info for specified board
- *	@nonblock: boolean, non-zero if O_NONBLOCK is set
- *
- *	Encapsulates standard method of acquiring the syscall sem.
- *
- *	Returns negative errno on error, or zero for success.
- */
-
-static inline int via_syscall_down (struct via_info *card, int nonblock)
-{
-	/* Thomas Sailer:
-	 * EAGAIN is supposed to be used if IO is pending,
-	 * not if there is contention on some internal
-	 * synchronization primitive which should be
-	 * held only for a short time anyway
-	 */
-	nonblock = 0;
-
-	if (nonblock) {
-		if (!mutex_trylock(&card->syscall_mutex))
-			return -EAGAIN;
-	} else {
-		if (mutex_lock_interruptible(&card->syscall_mutex))
-			return -ERESTARTSYS;
-	}
-
-	return 0;
-}
-
-
-/**
- *	via_stop_everything - Stop all audio operations
- *	@card: Private info for specified board
- *
- *	Stops all DMA operations and interrupts, and clear
- *	any pending status bits resulting from those operations.
- */
-
-static void via_stop_everything (struct via_info *card)
-{
-	u8 tmp, new_tmp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	/*
-	 * terminate any existing operations on audio read/write channels
-	 */
-	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_stop (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-	if(card->sixchannel)
-		via_chan_stop (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
-	/*
-	 * clear any existing stops / flags (sanity check mainly)
-	 */
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-	if(card->sixchannel)
-		via_chan_status_clear (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
-	/*
-	 * clear any enabled interrupt bits
-	 */
-	tmp = inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-
-	tmp = inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-
-	tmp = inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-
-	if(card->sixchannel)
-	{
-		tmp = inb (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
-		new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-		if (tmp != new_tmp)
-			outb (0, card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
-	}
-
-	udelay(10);
-
-	/*
-	 * clear any existing flags
-	 */
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_set_rate - Set PCM rate for given channel
- *	@ac97: Pointer to generic codec info struct
- *	@chan: Private info for specified channel
- *	@rate: Desired PCM sample rate, in Khz
- *
- *	Sets the PCM sample rate for a channel.
- *
- *	Values for @rate are clamped to a range of 4000 Khz through 48000 Khz,
- *	due to hardware constraints.
- */
-
-static int via_set_rate (struct ac97_codec *ac97,
-			 struct via_channel *chan, unsigned rate)
-{
-	struct via_info *card = ac97->private_data;
-	int rate_reg;
-	u32 dacp;
-	u32 mast_vol, phone_vol, mono_vol, pcm_vol;
-	u32 mute_vol = 0x8000;	/* The mute volume? -- Seems to work! */
-
-	DPRINTK ("ENTER, rate = %d\n", rate);
-
-	if (chan->rate == rate)
-		goto out;
-	if (card->locked_rate) {
-		chan->rate = 48000;
-		goto out;
-	}
-
-	if (rate > 48000)		rate = 48000;
-	if (rate < 4000) 		rate = 4000;
-
-	rate_reg = chan->is_record ? AC97_PCM_LR_ADC_RATE :
-			    AC97_PCM_FRONT_DAC_RATE;
-
-	/* Save current state */
-	dacp=via_ac97_read_reg(ac97, AC97_POWER_CONTROL);
-	mast_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_STEREO);
-	mono_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_MONO);
-	phone_vol = via_ac97_read_reg(ac97, AC97_HEADPHONE_VOL);
-	pcm_vol = via_ac97_read_reg(ac97, AC97_PCMOUT_VOL);
-	/* Mute - largely reduces popping */
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mute_vol);
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mute_vol);
-	via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, mute_vol);
-       	via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, mute_vol);
-	/* Power down the DAC */
-	via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp|0x0200);
-
-        /* Set new rate */
-	via_ac97_write_reg (ac97, rate_reg, rate);
-
-	/* Power DAC back up */
-	via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp);
-	udelay (200); /* reduces popping */
-
-	/* Restore volumes */
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mast_vol);
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mono_vol);
-	via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, phone_vol);
-	via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, pcm_vol);
-
-	/* the hardware might return a value different than what we
-	 * passed to it, so read the rate value back from hardware
-	 * to see what we came up with
-	 */
-	chan->rate = via_ac97_read_reg (ac97, rate_reg);
-
-	if (chan->rate == 0) {
-		card->locked_rate = 1;
-		chan->rate = 48000;
-		printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
-	}
-
-out:
-	DPRINTK ("EXIT, returning rate %d Hz\n", chan->rate);
-	return chan->rate;
-}
-
-
-/****************************************************************
- *
- * Channel-specific operations
- *
- *
- */
-
-
-/**
- *	via_chan_init_defaults - Initialize a struct via_channel
- *	@card: Private audio chip info
- *	@chan: Channel to be initialized
- *
- *	Zero @chan, and then set all static defaults for the structure.
- */
-
-static void via_chan_init_defaults (struct via_info *card, struct via_channel *chan)
-{
-	memset (chan, 0, sizeof (*chan));
-
-	if(card->intmask)
-		chan->intmask = 0x23;	/* Turn on the IRQ bits */
-		
-	if (chan == &card->ch_out) {
-		chan->name = "PCM-OUT";
-		if(card->sixchannel)
-		{
-			chan->iobase = card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN;
-			chan->is_multi = 1;
-			DPRINTK("Using multichannel for pcm out\n");
-		}
-		else
-			chan->iobase = card->baseaddr + VIA_BASE0_PCM_OUT_CHAN;
-	} else if (chan == &card->ch_in) {
-		chan->name = "PCM-IN";
-		chan->iobase = card->baseaddr + VIA_BASE0_PCM_IN_CHAN;
-		chan->is_record = 1;
-	} else if (chan == &card->ch_fm) {
-		chan->name = "PCM-OUT-FM";
-		chan->iobase = card->baseaddr + VIA_BASE0_FM_OUT_CHAN;
-	} else {
-		BUG();
-	}
-
-	init_waitqueue_head (&chan->wait);
-
-	chan->pcm_fmt = VIA_PCM_FMT_MASK;
-	chan->is_enabled = 1;
-
-	chan->frag_number = 0;
-        chan->frag_size = 0;
-	atomic_set(&chan->n_frags, 0);
-	atomic_set (&chan->hw_ptr, 0);
-}
-
-/**
- *      via_chan_init - Initialize PCM channel
- *      @card: Private audio chip info
- *      @chan: Channel to be initialized
- *
- *      Performs some of the preparations necessary to begin
- *      using a PCM channel.
- *
- *      Currently the preparations consist of
- *      setting the PCM channel to a known state.
- */
-
-
-static void via_chan_init (struct via_info *card, struct via_channel *chan)
-{
-
-        DPRINTK ("ENTER\n");
-
-	/* bzero channel structure, and init members to defaults */
-        via_chan_init_defaults (card, chan);
-
-        /* stop any existing channel output */
-        via_chan_clear (card, chan);
-        via_chan_status_clear (chan->iobase);
-        via_chan_pcm_fmt (chan, 1);
-
-	DPRINTK ("EXIT\n");
-}
-
-/**
- *	via_chan_buffer_init - Initialize PCM channel buffer
- *	@card: Private audio chip info
- *	@chan: Channel to be initialized
- *
- *	Performs some of the preparations necessary to begin
- *	using a PCM channel.
- *
- *	Currently the preparations include allocating the
- *	scatter-gather DMA table and buffers,
- *	and passing the
- *	address of the DMA table to the hardware.
- *
- *	Note that special care is taken when passing the
- *	DMA table address to hardware, because it was found
- *	during driver development that the hardware did not
- *	always "take" the address.
- */
-
-static int via_chan_buffer_init (struct via_info *card, struct via_channel *chan)
-{
-	int page, offset;
-	int i;
-
-	DPRINTK ("ENTER\n");
-
-
-	chan->intmask = 0;
-	if(card->intmask)
-		chan->intmask = 0x23;	/* Turn on the IRQ bits */
-		
-	if (chan->sgtable != NULL) {
-		DPRINTK ("EXIT\n");
-		return 0;
-	}
-
-	/* alloc DMA-able memory for scatter-gather table */
-	chan->sgtable = pci_alloc_consistent (card->pdev,
-		(sizeof (struct via_sgd_table) * chan->frag_number),
-		&chan->sgt_handle);
-	if (!chan->sgtable) {
-		printk (KERN_ERR PFX "DMA table alloc fail, aborting\n");
-		DPRINTK ("EXIT\n");
-		return -ENOMEM;
-	}
-
-	memset ((void*)chan->sgtable, 0,
-		(sizeof (struct via_sgd_table) * chan->frag_number));
-
-	/* alloc DMA-able memory for scatter-gather buffers */
-
-	chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
-			    (((chan->frag_number * chan->frag_size) % PAGE_SIZE) ? 1 : 0);
-
-	for (i = 0; i < chan->page_number; i++) {
-		chan->pgtbl[i].cpuaddr = pci_alloc_consistent (card->pdev, PAGE_SIZE,
-					      &chan->pgtbl[i].handle);
-
-		if (!chan->pgtbl[i].cpuaddr) {
-			chan->page_number = i;
-			goto err_out_nomem;
-		}
-
-#ifndef VIA_NDEBUG
-                memset (chan->pgtbl[i].cpuaddr, 0xBC, chan->frag_size);
-#endif
-
-#if 1
-                DPRINTK ("dmabuf_pg #%d (h=%lx, v2p=%lx, a=%p)\n",
-			i, (long)chan->pgtbl[i].handle,
-			virt_to_phys(chan->pgtbl[i].cpuaddr),
-			chan->pgtbl[i].cpuaddr);
-#endif
-	}
-
-	for (i = 0; i < chan->frag_number; i++) {
-
-		page = i / (PAGE_SIZE / chan->frag_size);
-		offset = (i % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
-
-		chan->sgtable[i].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
-		chan->sgtable[i].addr = cpu_to_le32 (chan->pgtbl[page].handle + offset);
-
-#if 1
-		DPRINTK ("dmabuf #%d (32(h)=%lx)\n",
-			 i,
-			 (long)chan->sgtable[i].addr);
-#endif
-	}
-
-	/* overwrite the last buffer information */
-	chan->sgtable[chan->frag_number - 1].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
-
-	/* set location of DMA-able scatter-gather info table */
-	DPRINTK ("outl (0x%X, 0x%04lX)\n",
-		chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
-
-	via_ac97_wait_idle (card);
-	outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
-	udelay (20);
-	via_ac97_wait_idle (card);
-	/* load no rate adaption, stereo 16bit, set up ring slots */
-	if(card->sixchannel)
-	{
-		if(!chan->is_multi)
-		{
-			outl (0xFFFFF | (0x3 << 20) | (chan->frag_number << 24), chan->iobase + VIA_PCM_STOPRATE);
-			udelay (20);
-			via_ac97_wait_idle (card);
-		}
-	}
-
-	DPRINTK ("inl (0x%lX) = %x\n",
-		chan->iobase + VIA_PCM_TABLE_ADDR,
-		inl(chan->iobase + VIA_PCM_TABLE_ADDR));
-
-	DPRINTK ("EXIT\n");
-	return 0;
-
-err_out_nomem:
-	printk (KERN_ERR PFX "DMA buffer alloc fail, aborting\n");
-	via_chan_buffer_free (card, chan);
-	DPRINTK ("EXIT\n");
-	return -ENOMEM;
-}
-
-
-/**
- *	via_chan_free - Release a PCM channel
- *	@card: Private audio chip info
- *	@chan: Channel to be released
- *
- *	Performs all the functions necessary to clean up
- *	an initialized channel.
- *
- *	Currently these functions include disabled any
- *	active DMA operations, setting the PCM channel
- *	back to a known state, and releasing any allocated
- *	sound buffers.
- */
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-
-	spin_lock_irq (&card->lock);
-
-	/* stop any existing channel output */
-	via_chan_status_clear (chan->iobase);
-	via_chan_stop (chan->iobase);
-	via_chan_status_clear (chan->iobase);
-
-	spin_unlock_irq (&card->lock);
-
-	synchronize_irq(card->pdev->irq);
-
-	DPRINTK ("EXIT\n");
-}
-
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan)
-{
-	int i;
-
-        DPRINTK ("ENTER\n");
-
-	/* zero location of DMA-able scatter-gather info table */
-	via_ac97_wait_idle(card);
-	outl (0, chan->iobase + VIA_PCM_TABLE_ADDR);
-
-	for (i = 0; i < chan->page_number; i++)
-		if (chan->pgtbl[i].cpuaddr) {
-			pci_free_consistent (card->pdev, PAGE_SIZE,
-					     chan->pgtbl[i].cpuaddr,
-					     chan->pgtbl[i].handle);
-			chan->pgtbl[i].cpuaddr = NULL;
-			chan->pgtbl[i].handle = 0;
-		}
-
-	chan->page_number = 0;
-
-	if (chan->sgtable) {
-		pci_free_consistent (card->pdev,
-			(sizeof (struct via_sgd_table) * chan->frag_number),
-			(void*)chan->sgtable, chan->sgt_handle);
-		chan->sgtable = NULL;
-	}
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_chan_pcm_fmt - Update PCM channel settings
- *	@chan: Channel to be updated
- *	@reset: Boolean.  If non-zero, channel will be reset
- *		to 8-bit mono mode.
- *
- *	Stores the settings of the current PCM format,
- *	8-bit or 16-bit, and mono/stereo, into the
- *	hardware settings for the specified channel.
- *	If @reset is non-zero, the channel is reset
- *	to 8-bit mono mode.  Otherwise, the channel
- *	is set to the values stored in the channel
- *	information struct @chan.
- */
-
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset)
-{
-	DPRINTK ("ENTER, pcm_fmt=0x%02X, reset=%s\n",
-		 chan->pcm_fmt, reset ? "yes" : "no");
-
-	assert (chan != NULL);
-
-	if (reset)
-	{
-		/* reset to 8-bit mono mode */
-		chan->pcm_fmt = 0;
-		chan->channels = 1;
-	}
-
-	/* enable interrupts on FLAG and EOL */
-	chan->pcm_fmt |= VIA_CHAN_TYPE_MASK;
-
-	/* if we are recording, enable recording fifo bit */
-	if (chan->is_record)
-		chan->pcm_fmt |= VIA_PCM_REC_FIFO;
-	/* set interrupt select bits where applicable (PCM in & out channels) */
-	if (!chan->is_record)
-		chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
-	
-	DPRINTK("SET FMT - %02x %02x\n", chan->intmask , chan->is_multi);
-	
-	if(chan->intmask)
-	{
-		u32 m;
-
-		/*
-		 *	Channel 0x4 is up to 6 x 16bit and has to be
-		 *	programmed differently 
-		 */
-		 		
-		if(chan->is_multi)
-		{
-			u8 c = 0;
-			
-			/*
-			 *	Load the type bit for num channels
-			 *	and 8/16bit
-			 */
-			 
-			if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
-				c = 1 << 7;
-			if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
-				c |= (2<<4);
-			else
-				c |= (1<<4);
-				
-			outb(c, chan->iobase + VIA_PCM_TYPE);
-			
-			/*
-			 *	Set the channel steering
-			 *	Mono
-			 *		Channel 0 to slot 3
-			 *		Channel 0 to slot 4
-			 *	Stereo
-			 *		Channel 0 to slot 3
-			 *		Channel 1 to slot 4
-			 */
-			 
-			switch(chan->channels)
-			{
-				case 1:
-					outl(0xFF000000 | (1<<0) | (1<<4) , chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 2:
-					outl(0xFF000000 | (1<<0) | (2<<4) , chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 4:
-					outl(0xFF000000 | (1<<0) | (2<<4) | (3<<8) | (4<<12), chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 6:
-					outl(0xFF000000 | (1<<0) | (2<<4) | (5<<8) | (6<<12) | (3<<16) | (4<<20), chan->iobase + VIA_PCM_STOPRATE);
-					break;
-			}				
-		}
-		else
-		{
-			/*
-			 *	New style, turn off channel volume
-			 *	control, set bits in the right register
-			 */	
-			outb(0x0, chan->iobase + VIA_PCM_LEFTVOL);
-			outb(0x0, chan->iobase + VIA_PCM_RIGHTVOL);
-
-			m = inl(chan->iobase + VIA_PCM_STOPRATE);
-			m &= ~(3<<20);
-			if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
-				m |= (1 << 20);
-			if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
-				m |= (1 << 21);
-			outl(m, chan->iobase + VIA_PCM_STOPRATE);
-		}		
-	}
-	else
-		outb (chan->pcm_fmt, chan->iobase + VIA_PCM_TYPE);
-
-
-	DPRINTK ("EXIT, pcm_fmt = 0x%02X, reg = 0x%02X\n",
-		 chan->pcm_fmt,
-		 inb (chan->iobase + VIA_PCM_TYPE));
-}
-
-
-/**
- *	via_chan_clear - Stop DMA channel operation, and reset pointers
- *	@card: the chip to accessed
- *	@chan: Channel to be cleared
- *
- *	Call via_chan_stop to halt DMA operations, and then resets
- *	all software pointers which track DMA operation.
- */
-
-static void via_chan_clear (struct via_info *card, struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-	via_chan_stop (chan->iobase);
-	via_chan_buffer_free(card, chan);
-	chan->is_active = 0;
-	chan->is_mapped = 0;
-	chan->is_enabled = 1;
-	chan->slop_len = 0;
-	chan->sw_ptr = 0;
-	chan->n_irqs = 0;
-	atomic_set (&chan->hw_ptr, 0);
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_chan_set_speed - Set PCM sample rate for given channel
- *	@card: Private info for specified board
- *	@chan: Channel whose sample rate will be adjusted
- *	@val: New sample rate, in Khz
- *
- *	Helper function for the %SNDCTL_DSP_SPEED ioctl.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when the %SNDCTL_DSP_SPEED is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_set_rate to set the audio hardware
- *	to the new rate.
- */
-
-static int via_chan_set_speed (struct via_info *card,
-			       struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, requested rate = %d\n", val);
-
-	via_chan_clear (card, chan);
-
-	val = via_set_rate (card->ac97, chan, val);
-
-	DPRINTK ("EXIT, returning %d\n", val);
-	return val;
-}
-
-
-/**
- *	via_chan_set_fmt - Set PCM sample size for given channel
- *	@card: Private info for specified board
- *	@chan: Channel whose sample size will be adjusted
- *	@val: New sample size, use the %AFMT_xxx constants
- *
- *	Helper function for the %SNDCTL_DSP_SETFMT ioctl.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when the %SNDCTL_DSP_SETFMT is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
- *	to the new sample size, either 8-bit or 16-bit.
- */
-
-static int via_chan_set_fmt (struct via_info *card,
-			     struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, val=%s\n",
-		 val == AFMT_U8 ? "AFMT_U8" :
-	 	 val == AFMT_S16_LE ? "AFMT_S16_LE" :
-		 "unknown");
-
-	via_chan_clear (card, chan);
-
-	assert (val != AFMT_QUERY); /* this case is handled elsewhere */
-
-	switch (val) {
-	case AFMT_S16_LE:
-		if ((chan->pcm_fmt & VIA_PCM_FMT_16BIT) == 0) {
-			chan->pcm_fmt |= VIA_PCM_FMT_16BIT;
-			via_chan_pcm_fmt (chan, 0);
-		}
-		break;
-
-	case AFMT_U8:
-		if (chan->pcm_fmt & VIA_PCM_FMT_16BIT) {
-			chan->pcm_fmt &= ~VIA_PCM_FMT_16BIT;
-			via_chan_pcm_fmt (chan, 0);
-		}
-		break;
-
-	default:
-		DPRINTK ("unknown AFMT: 0x%X\n", val);
-		val = AFMT_S16_LE;
-	}
-
-	DPRINTK ("EXIT\n");
-	return val;
-}
-
-
-/**
- *	via_chan_set_stereo - Enable or disable stereo for a DMA channel
- *	@card: Private info for specified board
- *	@chan: Channel whose stereo setting will be adjusted
- *	@val: New sample size, use the %AFMT_xxx constants
- *
- *	Helper function for the %SNDCTL_DSP_CHANNELS and %SNDCTL_DSP_STEREO ioctls.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when %SNDCTL_DSP_CHANNELS or SNDCTL_DSP_STEREO is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
- *	to enable or disable stereo.
- */
-
-static int via_chan_set_stereo (struct via_info *card,
-			        struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, channels = %d\n", val);
-
-	via_chan_clear (card, chan);
-
-	switch (val) {
-
-	/* mono */
-	case 1:
-		chan->pcm_fmt &= ~VIA_PCM_FMT_STEREO;
-		chan->channels = 1;
-		via_chan_pcm_fmt (chan, 0);
-		break;
-
-	/* stereo */
-	case 2:
-		chan->pcm_fmt |= VIA_PCM_FMT_STEREO;
-		chan->channels = 2;
-		via_chan_pcm_fmt (chan, 0);
-		break;
-
-	case 4:
-	case 6:
-		if(chan->is_multi)
-		{
-			chan->pcm_fmt |= VIA_PCM_FMT_STEREO;
-			chan->channels = val;
-			break;
-		}
-	/* unknown */
-	default:
-		val = -EINVAL;
-		break;
-	}
-
-	DPRINTK ("EXIT, returning %d\n", val);
-	return val;
-}
-
-static int via_chan_set_buffering (struct via_info *card,
-                                struct via_channel *chan, int val)
-{
-	int shift;
-
-        DPRINTK ("ENTER\n");
-
-	/* in both cases the buffer cannot be changed */
-	if (chan->is_active || chan->is_mapped) {
-		DPRINTK ("EXIT\n");
-		return -EINVAL;
-	}
-
-	/* called outside SETFRAGMENT */
-	/* set defaults or do nothing */
-	if (val < 0) {
-
-		if (chan->frag_size && chan->frag_number)
-			goto out;
-
-		DPRINTK ("\n");
-
-		chan->frag_size = (VIA_DEFAULT_FRAG_TIME * chan->rate * chan->channels
-				   * ((chan->pcm_fmt & VIA_PCM_FMT_16BIT) ? 2 : 1)) / 1000 - 1;
-
-		shift = 0;
-		while (chan->frag_size) {
-			chan->frag_size >>= 1;
-			shift++;
-		}
-		chan->frag_size = 1 << shift;
-
-		chan->frag_number = (VIA_DEFAULT_BUFFER_TIME / VIA_DEFAULT_FRAG_TIME);
-
-		DPRINTK ("setting default values %d %d\n", chan->frag_size, chan->frag_number);
-	} else {
-		chan->frag_size = 1 << (val & 0xFFFF);
-		chan->frag_number = (val >> 16) & 0xFFFF;
-
-		DPRINTK ("using user values %d %d\n", chan->frag_size, chan->frag_number);
-	}
-
-	/* quake3 wants frag_number to be a power of two */
-	shift = 0;
-	while (chan->frag_number) {
-		chan->frag_number >>= 1;
-		shift++;
-	}
-	chan->frag_number = 1 << shift;
-
-	if (chan->frag_size > VIA_MAX_FRAG_SIZE)
-		chan->frag_size = VIA_MAX_FRAG_SIZE;
-	else if (chan->frag_size < VIA_MIN_FRAG_SIZE)
-		chan->frag_size = VIA_MIN_FRAG_SIZE;
-
-	if (chan->frag_number < VIA_MIN_FRAG_NUMBER)
-                chan->frag_number = VIA_MIN_FRAG_NUMBER;
-        if (chan->frag_number > VIA_MAX_FRAG_NUMBER)
-        	chan->frag_number = VIA_MAX_FRAG_NUMBER;
-
-	if ((chan->frag_number * chan->frag_size) / PAGE_SIZE > VIA_MAX_BUFFER_DMA_PAGES)
-		chan->frag_number = (VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE) / chan->frag_size;
-
-out:
-	if (chan->is_record)
-		atomic_set (&chan->n_frags, 0);
-	else
-		atomic_set (&chan->n_frags, chan->frag_number);
-
-	DPRINTK ("EXIT\n");
-
-	return 0;
-}
-
-#ifdef VIA_CHAN_DUMP_BUFS
-/**
- *	via_chan_dump_bufs - Display DMA table contents
- *	@chan: Channel whose DMA table will be displayed
- *
- *	Debugging function which displays the contents of the
- *	scatter-gather DMA table for the given channel @chan.
- */
-
-static void via_chan_dump_bufs (struct via_channel *chan)
-{
-	int i;
-
-	for (i = 0; i < chan->frag_number; i++) {
-		DPRINTK ("#%02d: addr=%x, count=%u, flag=%d, eol=%d\n",
-			 i, chan->sgtable[i].addr,
-			 chan->sgtable[i].count & 0x00FFFFFF,
-			 chan->sgtable[i].count & VIA_FLAG ? 1 : 0,
-			 chan->sgtable[i].count & VIA_EOL ? 1 : 0);
-	}
-	DPRINTK ("buf_in_use = %d, nextbuf = %d\n",
-		 atomic_read (&chan->buf_in_use),
-		 atomic_read (&chan->sw_ptr));
-}
-#endif /* VIA_CHAN_DUMP_BUFS */
-
-
-/**
- *	via_chan_flush_frag - Flush partially-full playback buffer to hardware
- *	@chan: Channel whose DMA table will be flushed
- *
- *	Flushes partially-full playback buffer to hardware.
- */
-
-static void via_chan_flush_frag (struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (chan->slop_len > 0);
-
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	chan->slop_len = 0;
-
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-
-/**
- *	via_chan_maybe_start - Initiate audio hardware DMA operation
- *	@chan: Channel whose DMA is to be started
- *
- *	Initiate DMA operation, if the DMA engine for the given
- *	channel @chan is not already active.
- */
-
-static inline void via_chan_maybe_start (struct via_channel *chan)
-{
-	assert (chan->is_active == sg_active(chan->iobase));
-
-	DPRINTK ("MAYBE START %s\n", chan->name);
-	if (!chan->is_active && chan->is_enabled) {
-		chan->is_active = 1;
-		sg_begin (chan);
-		DPRINTK ("starting channel %s\n", chan->name);
-	}
-}
-
-
-/****************************************************************
- *
- * Interface to ac97-codec module
- *
- *
- */
-
-/**
- *	via_ac97_wait_idle - Wait until AC97 codec is not busy
- *	@card: Private info for specified board
- *
- *	Sleep until the AC97 codec is no longer busy.
- *	Returns the final value read from the SGD
- *	register being polled.
- */
-
-static u8 via_ac97_wait_idle (struct via_info *card)
-{
-	u8 tmp8;
-	int counter = VIA_COUNTER_LIMIT;
-
-	DPRINTK ("ENTER/EXIT\n");
-
-	assert (card != NULL);
-	assert (card->pdev != NULL);
-
-	do {
-		udelay (15);
-
-		tmp8 = inb (card->baseaddr + 0x83);
-	} while ((tmp8 & VIA_CR83_BUSY) && (counter-- > 0));
-
-	if (tmp8 & VIA_CR83_BUSY)
-		printk (KERN_WARNING PFX "timeout waiting on AC97 codec\n");
-	return tmp8;
-}
-
-
-/**
- *	via_ac97_read_reg - Read AC97 standard register
- *	@codec: Pointer to generic AC97 codec info
- *	@reg: Index of AC97 register to be read
- *
- *	Read the value of a single AC97 codec register,
- *	as defined by the Intel AC97 specification.
- *
- *	Defines the standard AC97 read-register operation
- *	required by the kernel's ac97_codec interface.
- *
- *	Returns the 16-bit value stored in the specified
- *	register.
- */
-
-static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg)
-{
-	unsigned long data;
-	struct via_info *card;
-	int counter;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	assert (codec->private_data != NULL);
-
-	card = codec->private_data;
-	
-	spin_lock(&card->ac97_lock);
-
-	/* Every time we write to register 80 we cause a transaction.
-	   The only safe way to clear the valid bit is to write it at
-	   the same time as the command */
-	data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID;
-
-	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
-	udelay (20);
-
-	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
-		udelay (1);
-		if ((((data = inl(card->baseaddr + VIA_BASE0_AC97_CTRL)) &
-		      (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))
-			goto out;
-	}
-
-	printk (KERN_WARNING PFX "timeout while reading AC97 codec (0x%lX)\n", data);
-	goto err_out;
-
-out:
-	/* Once the valid bit has become set, we must wait a complete AC97
-	   frame before the data has settled. */
-	udelay(25);
-	data = (unsigned long) inl (card->baseaddr + VIA_BASE0_AC97_CTRL);
-
-	outb (0x02, card->baseaddr + 0x83);
-
-	if (((data & 0x007F0000) >> 16) == reg) {
-		DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n",
-			 data, data & 0x0000FFFF);
-		spin_unlock(&card->ac97_lock);
-		return data & 0x0000FFFF;
-	}
-
-	printk (KERN_WARNING "via82cxxx_audio: not our index: reg=0x%x, newreg=0x%lx\n",
-		reg, ((data & 0x007F0000) >> 16));
-
-err_out:
-	spin_unlock(&card->ac97_lock);
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/**
- *	via_ac97_write_reg - Write AC97 standard register
- *	@codec: Pointer to generic AC97 codec info
- *	@reg: Index of AC97 register to be written
- *	@value: Value to be written to AC97 register
- *
- *	Write the value of a single AC97 codec register,
- *	as defined by the Intel AC97 specification.
- *
- *	Defines the standard AC97 write-register operation
- *	required by the kernel's ac97_codec interface.
- */
-
-static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value)
-{
-	u32 data;
-	struct via_info *card;
-	int counter;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	assert (codec->private_data != NULL);
-
-	card = codec->private_data;
-
-	spin_lock(&card->ac97_lock);
-	
-	data = (reg << 16) + value;
-	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
-	udelay (10);
-
-	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
-		if ((inb (card->baseaddr + 0x83) & VIA_CR83_BUSY) == 0)
-			goto out;
-
-		udelay (15);
-	}
-
-	printk (KERN_WARNING PFX "timeout after AC97 codec write (0x%X, 0x%X)\n", reg, value);
-
-out:
-	spin_unlock(&card->ac97_lock);
-	DPRINTK ("EXIT\n");
-}
-
-
-static int via_mixer_open (struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct via_info *card;
-	struct pci_dev *pdev = NULL;
-	struct pci_driver *drvr;
-
-	DPRINTK ("ENTER\n");
-
-	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		drvr = pci_dev_driver (pdev);
-		if (drvr == &via_driver) {
-			assert (pci_get_drvdata (pdev) != NULL);
-
-			card = pci_get_drvdata (pdev);
-			if (card->ac97->dev_mixer == minor)
-				goto match;
-		}
-	}
-
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-match:
-	pci_dev_put(pdev);
-	file->private_data = card->ac97;
-
-	DPRINTK ("EXIT, returning 0\n");
-	return nonseekable_open(inode, file);
-}
-
-static int via_mixer_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-			    unsigned long arg)
-{
-	struct ac97_codec *codec = file->private_data;
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	card = codec->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-	
-#if 0
-	/*
-	 *	Intercept volume control on 8233 and 8235
-	 */
-	if(card->volume)
-	{
-		switch(cmd)
-		{
-			case SOUND_MIXER_READ_VOLUME:
-				return card->mixer_vol;
-			case SOUND_MIXER_WRITE_VOLUME:
-			{
-				int v;
-				if(get_user(v, (int *)arg))
-				{
-					rc = -EFAULT;
-					goto out;
-				}
-				card->mixer_vol = v;
-			}
-		}
-	}		
-#endif
-	rc = codec->mixer_ioctl(codec, cmd, arg);
-
-	mutex_unlock(&card->syscall_mutex);
-
-out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static const struct file_operations via_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.open		= via_mixer_open,
-	.llseek		= no_llseek,
-	.ioctl		= via_mixer_ioctl,
-};
-
-
-static int __devinit via_ac97_reset (struct via_info *card)
-{
-	struct pci_dev *pdev = card->pdev;
-	u8 tmp8;
-	u16 tmp16;
-
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
-
-#ifndef NDEBUG
-	{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		spin_lock_irq (&card->lock);
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-		spin_unlock_irq (&card->lock);
-
-	}
-#endif
-
-        /*
-         * Reset AC97 controller: enable, disable, enable,
-         * pausing after each command for good luck.  Only
-	 * do this if the codec is not ready, because it causes
-	 * loud pops and such due to such a hard codec reset.
-         */
-	pci_read_config_byte (pdev, VIA_ACLINK_STATUS, &tmp8);
-	if ((tmp8 & VIA_CR40_AC97_READY) == 0) {
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-                		       VIA_CR41_AC97_RESET |
-				       VIA_CR41_AC97_WAKEUP);
-        	udelay (100);
-
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
-        	udelay (100);
-
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-				       VIA_CR41_PCM_ENABLE |
-                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
-        	udelay (100);
-	}
-
-	/* Make sure VRA is enabled, in case we didn't do a
-	 * complete codec reset, above
-	 */
-	pci_read_config_byte (pdev, VIA_ACLINK_CTRL, &tmp8);
-	if (((tmp8 & VIA_CR41_VRA) == 0) ||
-	    ((tmp8 & VIA_CR41_AC97_ENABLE) == 0) ||
-	    ((tmp8 & VIA_CR41_PCM_ENABLE) == 0) ||
-	    ((tmp8 & VIA_CR41_AC97_RESET) == 0)) {
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-				       VIA_CR41_PCM_ENABLE |
-                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
-        	udelay (100);
-	}
-
-	if(card->legacy)
-	{
-#if 0 /* this breaks on K7M */
-		/* disable legacy stuff */
-		pci_write_config_byte (pdev, 0x42, 0x00);
-		udelay(10);
-#endif
-
-		/* route FM trap to IRQ, disable FM trap */
-		pci_write_config_byte (pdev, 0x48, 0x05);
-		udelay(10);
-	}
-	
-	/* disable all codec GPI interrupts */
-	outl (0, pci_resource_start (pdev, 0) + 0x8C);
-
-	/* WARNING: this line is magic.  Remove this
-	 * and things break. */
-	/* enable variable rate */
- 	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 	if ((tmp16 & 1) == 0)
- 		via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void via_ac97_codec_wait (struct ac97_codec *codec)
-{
-	assert (codec->private_data != NULL);
-	via_ac97_wait_idle (codec->private_data);
-}
-
-
-static int __devinit via_ac97_init (struct via_info *card)
-{
-	int rc;
-	u16 tmp16;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	card->ac97 = ac97_alloc_codec();
-	if(card->ac97 == NULL)
-		return -ENOMEM;
-		
-	card->ac97->private_data = card;
-	card->ac97->codec_read = via_ac97_read_reg;
-	card->ac97->codec_write = via_ac97_write_reg;
-	card->ac97->codec_wait = via_ac97_codec_wait;
-
-	card->ac97->dev_mixer = register_sound_mixer (&via_mixer_fops, -1);
-	if (card->ac97->dev_mixer < 0) {
-		printk (KERN_ERR PFX "unable to register AC97 mixer, aborting\n");
-		DPRINTK ("EXIT, returning -EIO\n");
-		ac97_release_codec(card->ac97);
-		return -EIO;
-	}
-
-	rc = via_ac97_reset (card);
-	if (rc) {
-		printk (KERN_ERR PFX "unable to reset AC97 codec, aborting\n");
-		goto err_out;
-	}
-	
-	mdelay(10);
-	
-	if (ac97_probe_codec (card->ac97) == 0) {
-		printk (KERN_ERR PFX "unable to probe AC97 codec, aborting\n");
-		rc = -EIO;
-		goto err_out;
-	}
-
-	/* enable variable rate */
-	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
-	via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
-
- 	/*
- 	 * If we cannot enable VRA, we have a locked-rate codec.
- 	 * We try again to enable VRA before assuming so, however.
- 	 */
- 	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 	if ((tmp16 & 1) == 0) {
- 		via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
- 		tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 		if ((tmp16 & 1) == 0) {
- 			card->locked_rate = 1;
- 			printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
- 		}
- 	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out:
-	unregister_sound_mixer (card->ac97->dev_mixer);
-	DPRINTK ("EXIT, returning %d\n", rc);
-	ac97_release_codec(card->ac97);
-	return rc;
-}
-
-
-static void via_ac97_cleanup (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->ac97->dev_mixer >= 0);
-
-	unregister_sound_mixer (card->ac97->dev_mixer);
-	ac97_release_codec(card->ac97);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-
-/****************************************************************
- *
- * Interrupt-related code
- *
- */
-
-/**
- *	via_intr_channel - handle an interrupt for a single channel
- *      @card: unused
- *	@chan: handle interrupt for this channel
- *
- *	This is the "meat" of the interrupt handler,
- *	containing the actions taken each time an interrupt
- *	occurs.  All communication and coordination with
- *	userspace takes place here.
- *
- *	Locking: inside card->lock
- */
-
-static void via_intr_channel (struct via_info *card, struct via_channel *chan)
-{
-	u8 status;
-	int n;
-	
-	/* check pertinent bits of status register for action bits */
-	status = inb (chan->iobase) & (VIA_SGD_FLAG | VIA_SGD_EOL | VIA_SGD_STOPPED);
-	if (!status)
-		return;
-
-	/* acknowledge any flagged bits ASAP */
-	outb (status, chan->iobase);
-
-	if (!chan->sgtable) /* XXX: temporary solution */
-		return;
-
-	/* grab current h/w ptr value */
-	n = atomic_read (&chan->hw_ptr);
-
-	/* sanity check: make sure our h/w ptr doesn't have a weird value */
-	assert (n >= 0);
-	assert (n < chan->frag_number);
-
-	
-	/* reset SGD data structure in memory to reflect a full buffer,
-	 * and advance the h/w ptr, wrapping around to zero if needed
-	 */
-	if (n == (chan->frag_number - 1)) {
-		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_EOL);
-		atomic_set (&chan->hw_ptr, 0);
-	} else {
-		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_FLAG);
-		atomic_inc (&chan->hw_ptr);
-	}
-
-	/* accounting crap for SNDCTL_DSP_GETxPTR */
-	chan->n_irqs++;
-	chan->bytes += chan->frag_size;
-	/* FIXME - signed overflow is undefined */
-	if (chan->bytes < 0) /* handle overflow of 31-bit value */
-		chan->bytes = chan->frag_size;
-	/* all following checks only occur when not in mmap(2) mode */
-	if (!chan->is_mapped)
-	{
-		/* If we are recording, then n_frags represents the number
-		 * of fragments waiting to be handled by userspace.
-		 * If we are playback, then n_frags represents the number
-		 * of fragments remaining to be filled by userspace.
-		 * We increment here.  If we reach max number of fragments,
-		 * this indicates an underrun/overrun.  For this case under OSS,
-		 * we stop the record/playback process.
-		 */
-		if (atomic_read (&chan->n_frags) < chan->frag_number)
-			atomic_inc (&chan->n_frags);
-		assert (atomic_read (&chan->n_frags) <= chan->frag_number);
-		if (atomic_read (&chan->n_frags) == chan->frag_number) {
-			chan->is_active = 0;
-			via_chan_stop (chan->iobase);
-		}
-	}
-	/* wake up anyone listening to see when interrupts occur */
-	wake_up_all (&chan->wait);
-
-	DPRINTK ("%s intr, status=0x%02X, hwptr=0x%lX, chan->hw_ptr=%d\n",
-		 chan->name, status, (long) inl (chan->iobase + 0x04),
-		 atomic_read (&chan->hw_ptr));
-
-	DPRINTK ("%s intr, channel n_frags == %d, missed %d\n", chan->name,
-		 atomic_read (&chan->n_frags), missed);
-}
-
-
-static irqreturn_t  via_interrupt(int irq, void *dev_id)
-{
-	struct via_info *card = dev_id;
-	u32 status32;
-
-	/* to minimize interrupt sharing costs, we use the SGD status
-	 * shadow register to check the status of all inputs and
-	 * outputs with a single 32-bit bus read.  If no interrupt
-	 * conditions are flagged, we exit immediately
-	 */
-	status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
-	if (!(status32 & VIA_INTR_MASK))
-        {
-#ifdef CONFIG_MIDI_VIA82CXXX
-	    	 if (card->midi_devc)
-                    	uart401intr(irq, card->midi_devc);
-#endif
-		return IRQ_HANDLED;
-    	}
-	DPRINTK ("intr, status32 == 0x%08X\n", status32);
-
-	/* synchronize interrupt handling under SMP.  this spinlock
-	 * goes away completely on UP
-	 */
-	spin_lock (&card->lock);
-
-	if (status32 & VIA_INTR_OUT)
-		via_intr_channel (card, &card->ch_out);
-	if (status32 & VIA_INTR_IN)
-		via_intr_channel (card, &card->ch_in);
-	if (status32 & VIA_INTR_FM)
-		via_intr_channel (card, &card->ch_fm);
-
-	spin_unlock (&card->lock);
-	
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t via_new_interrupt(int irq, void *dev_id)
-{
-	struct via_info *card = dev_id;
-	u32 status32;
-
-	/* to minimize interrupt sharing costs, we use the SGD status
-	 * shadow register to check the status of all inputs and
-	 * outputs with a single 32-bit bus read.  If no interrupt
-	 * conditions are flagged, we exit immediately
-	 */
-	status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
-	if (!(status32 & VIA_NEW_INTR_MASK))
-		return IRQ_NONE;
-	/*
-	 * goes away completely on UP
-	 */
-	spin_lock (&card->lock);
-
-	via_intr_channel (card, &card->ch_out);
-	via_intr_channel (card, &card->ch_in);
-	via_intr_channel (card, &card->ch_fm);
-
-	spin_unlock (&card->lock);
-	return IRQ_HANDLED;
-}
-
-
-/**
- *	via_interrupt_init - Initialize interrupt handling
- *	@card: Private info for specified board
- *
- *	Obtain and reserve IRQ for using in handling audio events.
- *	Also, disable any IRQ-generating resources, to make sure
- *	we don't get interrupts before we want them.
- */
-
-static int via_interrupt_init (struct via_info *card)
-{
-	u8 tmp8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->pdev != NULL);
-
-	/* check for sane IRQ number. can this ever happen? */
-	if (card->pdev->irq < 2) {
-		printk (KERN_ERR PFX "insane IRQ %d, aborting\n",
-			card->pdev->irq);
-		DPRINTK ("EXIT, returning -EIO\n");
-		return -EIO;
-	}
-
-	/* VIA requires this is done */
-	pci_write_config_byte(card->pdev, PCI_INTERRUPT_LINE, card->pdev->irq);
-	
-	if(card->legacy)
-	{
-		/* make sure FM irq is not routed to us */
-		pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
-		if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
-			tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
-			pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
-		}
-		if (request_irq (card->pdev->irq, via_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) {
-			printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
-				card->pdev->irq);
-			DPRINTK ("EXIT, returning -EBUSY\n");
-			return -EBUSY;
-		}
-	}
-	else 
-	{
-		if (request_irq (card->pdev->irq, via_new_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) {
-			printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
-				card->pdev->irq);
-			DPRINTK ("EXIT, returning -EBUSY\n");
-			return -EBUSY;
-		}
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/****************************************************************
- *
- * OSS DSP device
- *
- */
-
-static const struct file_operations via_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.open		= via_dsp_open,
-	.release	= via_dsp_release,
-	.read		= via_dsp_read,
-	.write		= via_dsp_write,
-	.poll		= via_dsp_poll,
-	.llseek		= no_llseek,
-	.ioctl		= via_dsp_ioctl,
-	.mmap		= via_dsp_mmap,
-};
-
-
-static int __devinit via_dsp_init (struct via_info *card)
-{
-	u8 tmp8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	if(card->legacy)
-	{
-		/* turn off legacy features, if not already */
-		pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8);
-		if (tmp8 & (VIA_CR42_SB_ENABLE |  VIA_CR42_FM_ENABLE)) {
-			tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE);
-			pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8);
-		}
-	}
-
-	via_stop_everything (card);
-
-	card->dev_dsp = register_sound_dsp (&via_dsp_fops, -1);
-	if (card->dev_dsp < 0) {
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
-	}
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void via_dsp_cleanup (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->dev_dsp >= 0);
-
-	via_stop_everything (card);
-
-	unregister_sound_dsp (card->dev_dsp);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-static struct page * via_mm_nopage (struct vm_area_struct * vma,
-				    unsigned long address, int *type)
-{
-	struct via_info *card = vma->vm_private_data;
-	struct via_channel *chan = &card->ch_out;
-	unsigned long max_bufs;
-	struct page *dmapage;
-	unsigned long pgoff;
-	int rd, wr;
-
-	DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n",
-		 vma->vm_start,
-		 address - vma->vm_start,
-		 (address - vma->vm_start) >> PAGE_SHIFT,
-		 address);
-
-        if (address > vma->vm_end) {
-		DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS; /* Disallow mremap */
-	}
-        if (!card) {
-		DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS;	/* Nothing allocated */
-	}
-
-	pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
-	rd = card->ch_in.is_mapped;
-	wr = card->ch_out.is_mapped;
-
-	max_bufs = chan->frag_number;
-	if (rd && wr)
-		max_bufs *= 2;
-	if (pgoff >= max_bufs)
-		return NOPAGE_SIGBUS;
-
-	/* if full-duplex (read+write) and we have two sets of bufs,
-	 * then the playback buffers come first, sez soundcard.c */
-	if (pgoff >= chan->page_number) {
-		pgoff -= chan->page_number;
-		chan = &card->ch_in;
-	} else if (!wr)
-		chan = &card->ch_in;
-
-	assert ((((unsigned long)chan->pgtbl[pgoff].cpuaddr) % PAGE_SIZE) == 0);
-
-	dmapage = virt_to_page (chan->pgtbl[pgoff].cpuaddr);
-	DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n",
-		 dmapage, (unsigned long) chan->pgtbl[pgoff].cpuaddr);
-	get_page (dmapage);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return dmapage;
-}
-
-
-#ifndef VM_RESERVED
-static int via_mm_swapout (struct page *page, struct file *filp)
-{
-	return 0;
-}
-#endif /* VM_RESERVED */
-
-
-static struct vm_operations_struct via_mm_ops = {
-	.nopage		= via_mm_nopage,
-
-#ifndef VM_RESERVED
-	.swapout	= via_mm_swapout,
-#endif
-};
-
-
-static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc = -EINVAL, rd=0, wr=0;
-	unsigned long max_size, size, start, offset;
-
-	assert (file != NULL);
-	assert (vma != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	DPRINTK ("ENTER, start %lXh, size %ld, pgoff %ld\n",
-		 vma->vm_start,
-		 vma->vm_end - vma->vm_start,
-		 vma->vm_pgoff);
-
-	max_size = 0;
-	if (vma->vm_flags & VM_READ) {
-		rd = 1;
-		via_chan_set_buffering(card, &card->ch_in, -1);
-		via_chan_buffer_init (card, &card->ch_in);
-		max_size += card->ch_in.page_number << PAGE_SHIFT;
-	}
-	if (vma->vm_flags & VM_WRITE) {
-		wr = 1;
-		via_chan_set_buffering(card, &card->ch_out, -1);
-		via_chan_buffer_init (card, &card->ch_out);
-		max_size += card->ch_out.page_number << PAGE_SHIFT;
-	}
-
-	start = vma->vm_start;
-	offset = (vma->vm_pgoff << PAGE_SHIFT);
-	size = vma->vm_end - vma->vm_start;
-
-	/* some basic size/offset sanity checks */
-	if (size > max_size)
-		goto out;
-	if (offset > max_size - size)
-		goto out;
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	vma->vm_ops = &via_mm_ops;
-	vma->vm_private_data = card;
-
-#ifdef VM_RESERVED
-	vma->vm_flags |= VM_RESERVED;
-#endif
-
-	if (rd)
-		card->ch_in.is_mapped = 1;
-	if (wr)
-		card->ch_out.is_mapped = 1;
-
-	mutex_unlock(&card->syscall_mutex);
-	rc = 0;
-
-out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static ssize_t via_dsp_do_read (struct via_info *card,
-				char __user *userbuf, size_t count,
-				int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	const char __user *orig_userbuf = userbuf;
-	struct via_channel *chan = &card->ch_in;
-	size_t size;
-	int n, tmp;
-	ssize_t ret = 0;
-
-	/* if SGD has not yet been started, start it */
-	via_chan_maybe_start (chan);
-
-handle_one_block:
-	/* just to be a nice neighbor */
-	/* Thomas Sailer:
-	 * But also to ourselves, release semaphore if we do so */
-	if (need_resched()) {
-		mutex_unlock(&card->syscall_mutex);
-		schedule ();
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			goto out;
-	}
-
-	/* grab current channel software pointer.  In the case of
-	 * recording, this is pointing to the next buffer that
-	 * will receive data from the audio hardware.
-	 */
-	n = chan->sw_ptr;
-
-	/* n_frags represents the number of fragments waiting
-	 * to be copied to userland.  sleep until at least
-	 * one buffer has been read from the audio hardware.
-	 */
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		tmp = atomic_read (&chan->n_frags);
-		assert (tmp >= 0);
-		assert (tmp <= chan->frag_number);
-		if (tmp)
-			break;
-		if (nonblock || !chan->is_active) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("Sleeping on block %d\n", n);
-		schedule();
-
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			break;
-
-		if (signal_pending (current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-	if (ret)
-		goto out;
-
-	/* Now that we have a buffer we can read from, send
-	 * as much as sample data possible to userspace.
-	 */
-	while ((count > 0) && (chan->slop_len < chan->frag_size)) {
-		size_t slop_left = chan->frag_size - chan->slop_len;
-		void *base = chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr;
-		unsigned ofs = (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
-
-		size = (count < slop_left) ? count : slop_left;
-		if (copy_to_user (userbuf,
-				  base + ofs + chan->slop_len,
-				  size)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		count -= size;
-		chan->slop_len += size;
-		userbuf += size;
-	}
-
-	/* If we didn't copy the buffer completely to userspace,
-	 * stop now.
-	 */
-	if (chan->slop_len < chan->frag_size)
-		goto out;
-
-	/*
-	 * If we get to this point, we copied one buffer completely
-	 * to userspace, give the buffer back to the hardware.
-	 */
-
-	/* advance channel software pointer to point to
-	 * the next buffer from which we will copy
-	 */
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	/* mark one less buffer waiting to be processed */
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	/* we are at a block boundary, there is no fragment data */
-	chan->slop_len = 0;
-
-	DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
-		n, chan->sw_ptr, atomic_read (&chan->n_frags));
-
-	DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-		 inb (card->baseaddr + 0x00),
-		 inb (card->baseaddr + 0x01),
-		 inb (card->baseaddr + 0x02),
-		 inl (card->baseaddr + 0x04),
-		 inl (card->baseaddr + 0x0C),
-		 inl (card->baseaddr + 0x80),
-		 inl (card->baseaddr + 0x84));
-
-	if (count > 0)
-		goto handle_one_block;
-
-out:
-	return (userbuf != orig_userbuf) ? (userbuf - orig_userbuf) : ret;
-}
-
-
-static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER, file=%p, buffer=%p, count=%u, ppos=%lu\n",
-		 file, buffer, count, ppos ? ((unsigned long)*ppos) : 0);
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	if (card->ch_in.is_mapped) {
-		rc = -ENXIO;
-		goto out_up;
-	}
-
-	via_chan_set_buffering(card, &card->ch_in, -1);
-        rc = via_chan_buffer_init (card, &card->ch_in);
-
-	if (rc)
-		goto out_up;
-
-	rc = via_dsp_do_read (card, buffer, count, nonblock);
-
-out_up:
-	mutex_unlock(&card->syscall_mutex);
-out:
-	DPRINTK ("EXIT, returning %ld\n",(long) rc);
-	return rc;
-}
-
-
-static ssize_t via_dsp_do_write (struct via_info *card,
-				 const char __user *userbuf, size_t count,
-				 int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	const char __user *orig_userbuf = userbuf;
-	struct via_channel *chan = &card->ch_out;
-	volatile struct via_sgd_table *sgtable = chan->sgtable;
-	size_t size;
-	int n, tmp;
-	ssize_t ret = 0;
-
-handle_one_block:
-	/* just to be a nice neighbor */
-	/* Thomas Sailer:
-	 * But also to ourselves, release semaphore if we do so */
-	if (need_resched()) {
-		mutex_unlock(&card->syscall_mutex);
-		schedule ();
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			goto out;
-	}
-
-	/* grab current channel fragment pointer.  In the case of
-	 * playback, this is pointing to the next fragment that
-	 * should receive data from userland.
-	 */
-	n = chan->sw_ptr;
-
-	/* n_frags represents the number of fragments remaining
-	 * to be filled by userspace.  Sleep until
-	 * at least one fragment is available for our use.
-	 */
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		tmp = atomic_read (&chan->n_frags);
-		assert (tmp >= 0);
-		assert (tmp <= chan->frag_number);
-		if (tmp)
-			break;
-		if (nonblock || !chan->is_active) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("Sleeping on page %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
-		schedule();
-
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			break;
-
-		if (signal_pending (current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-	if (ret)
-		goto out;
-
-	/* Now that we have at least one fragment we can write to, fill the buffer
-	 * as much as possible with data from userspace.
-	 */
-	while ((count > 0) && (chan->slop_len < chan->frag_size)) {
-		size_t slop_left = chan->frag_size - chan->slop_len;
-
-		size = (count < slop_left) ? count : slop_left;
-		if (copy_from_user (chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size + chan->slop_len,
-				    userbuf, size)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		count -= size;
-		chan->slop_len += size;
-		userbuf += size;
-	}
-
-	/* If we didn't fill up the buffer with data, stop now.
-         * Put a 'stop' marker in the DMA table too, to tell the
-         * audio hardware to stop if it gets here.
-         */
-	if (chan->slop_len < chan->frag_size) {
-		sgtable[n].count = cpu_to_le32 (chan->slop_len | VIA_EOL | VIA_STOP);
-		goto out;
-	}
-
-	/*
-         * If we get to this point, we have filled a buffer with
-         * audio data, flush the buffer to audio hardware.
-         */
-
-	/* Record the true size for the audio hardware to notice */
-        if (n == (chan->frag_number - 1))
-                sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
-        else
-                sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
-
-	/* advance channel software pointer to point to
-	 * the next buffer we will fill with data
-	 */
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	/* mark one less buffer as being available for userspace consumption */
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	/* we are at a block boundary, there is no fragment data */
-	chan->slop_len = 0;
-
-	/* if SGD has not yet been started, start it */
-	via_chan_maybe_start (chan);
-
-	DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
-		n, chan->sw_ptr, atomic_read (&chan->n_frags));
-
-	DPRINTK ("regs==S=%02X C=%02X TP=%02X BP=%08X RT=%08X SG=%08X CC=%08X SS=%08X\n",
-		 inb (card->baseaddr + 0x00),
-		 inb (card->baseaddr + 0x01),
-		 inb (card->baseaddr + 0x02),
-		 inl (card->baseaddr + 0x04),
-		 inl (card->baseaddr + 0x08),
-		 inl (card->baseaddr + 0x0C),
-		 inl (card->baseaddr + 0x80),
-		 inl (card->baseaddr + 0x84));
-
-	if (count > 0)
-		goto handle_one_block;
-
-out:
-	if (userbuf - orig_userbuf)
-		return userbuf - orig_userbuf;
-	else
-		return ret;
-}
-
-
-static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct via_info *card;
-	ssize_t rc;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-
-	DPRINTK ("ENTER, file=%p, buffer=%p, count=%u, ppos=%lu\n",
-		 file, buffer, count, ppos ? ((unsigned long)*ppos) : 0);
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	if (card->ch_out.is_mapped) {
-		rc = -ENXIO;
-		goto out_up;
-	}
-
-	via_chan_set_buffering(card, &card->ch_out, -1);
-	rc = via_chan_buffer_init (card, &card->ch_out);
-
-	if (rc)
-		goto out_up;
-
-	rc = via_dsp_do_write (card, buffer, count, nonblock);
-
-out_up:
-	mutex_unlock(&card->syscall_mutex);
-out:
-	DPRINTK ("EXIT, returning %ld\n",(long) rc);
-	return rc;
-}
-
-
-static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct via_info *card;
-	struct via_channel *chan;
-	unsigned int mask = 0;
-
-	DPRINTK ("ENTER\n");
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	if (file->f_mode & FMODE_READ) {
-		chan = &card->ch_in;
-		if (sg_active (chan->iobase))
-	                poll_wait(file, &chan->wait, wait);
-		if (atomic_read (&chan->n_frags) > 0)
-			mask |= POLLIN | POLLRDNORM;
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		chan = &card->ch_out;
-		if (sg_active (chan->iobase))
-	                poll_wait(file, &chan->wait, wait);
-		if (atomic_read (&chan->n_frags) > 0)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-
-	DPRINTK ("EXIT, returning %u\n", mask);
-	return mask;
-}
-
-
-/**
- *	via_dsp_drain_playback - sleep until all playback samples are flushed
- *	@card: Private info for specified board
- *	@chan: Channel to drain
- *	@nonblock: boolean, non-zero if O_NONBLOCK is set
- *
- *	Sleeps until all playback has been flushed to the audio
- *	hardware.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_drain_playback (struct via_info *card,
-				   struct via_channel *chan, int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
-
-	DPRINTK ("ENTER, nonblock = %d\n", nonblock);
-
-	if (chan->slop_len > 0)
-		via_chan_flush_frag (chan);
-
-	if (atomic_read (&chan->n_frags) == chan->frag_number)
-		goto out;
-
-	via_chan_maybe_start (chan);
-
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		DPRINTK ("FRAGS %d FRAGNUM %d\n", atomic_read(&chan->n_frags), chan->frag_number);
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (atomic_read (&chan->n_frags) >= chan->frag_number)
-			break;
-
-		if (nonblock) {
-			DPRINTK ("EXIT, returning -EAGAIN\n");
-			ret = -EAGAIN;
-			break;
-		}
-
-#ifdef VIA_DEBUG
-		{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-		}
-
-		if (!chan->is_active)
-			printk (KERN_ERR "sleeping but not active\n");
-#endif
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_frags));
-		schedule();
-
-		if ((ret = via_syscall_down (card, nonblock)))
-			break;
-
-		if (signal_pending (current)) {
-			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-
-#ifdef VIA_DEBUG
-	{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-
-		DPRINTK ("final nbufs=%d\n", atomic_read (&chan->n_frags));
-	}
-#endif
-
-out:
-	DPRINTK ("EXIT, returning %d\n", ret);
-	return ret;
-}
-
-
-/**
- *	via_dsp_ioctl_space - get information about channel buffering
- *	@card: Private info for specified board
- *	@chan: pointer to channel-specific info
- *	@arg: user buffer for returned information
- *
- *	Handles SNDCTL_DSP_GETISPACE and SNDCTL_DSP_GETOSPACE.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_ioctl_space (struct via_info *card,
-				struct via_channel *chan,
-				void __user *arg)
-{
-	audio_buf_info info;
-
-	via_chan_set_buffering(card, chan, -1);
-
-	info.fragstotal = chan->frag_number;
-	info.fragsize = chan->frag_size;
-
-	/* number of full fragments we can read/write without blocking */
-	info.fragments = atomic_read (&chan->n_frags);
-
-	if ((chan->slop_len % chan->frag_size > 0) && (info.fragments > 0))
-		info.fragments--;
-
-	/* number of bytes that can be read or written immediately
-	 * without blocking.
-	 */
-	info.bytes = (info.fragments * chan->frag_size);
-	if (chan->slop_len % chan->frag_size > 0)
-		info.bytes += chan->frag_size - (chan->slop_len % chan->frag_size);
-
-	DPRINTK ("EXIT, returning fragstotal=%d, fragsize=%d, fragments=%d, bytes=%d\n",
-		info.fragstotal,
-		info.fragsize,
-		info.fragments,
-		info.bytes);
-
-	return copy_to_user (arg, &info, sizeof (info))?-EFAULT:0;
-}
-
-
-/**
- *	via_dsp_ioctl_ptr - get information about hardware buffer ptr
- *	@card: Private info for specified board
- *	@chan: pointer to channel-specific info
- *	@arg: user buffer for returned information
- *
- *	Handles SNDCTL_DSP_GETIPTR and SNDCTL_DSP_GETOPTR.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_ioctl_ptr (struct via_info *card,
-				struct via_channel *chan,
-				void __user *arg)
-{
-	count_info info;
-
-	spin_lock_irq (&card->lock);
-
-	info.bytes = chan->bytes;
-	info.blocks = chan->n_irqs;
-	chan->n_irqs = 0;
-
-	spin_unlock_irq (&card->lock);
-
-	if (chan->is_active) {
-		unsigned long extra;
-		info.ptr = atomic_read (&chan->hw_ptr) * chan->frag_size;
-		extra = chan->frag_size - via_sg_offset(chan);
-		info.ptr += extra;
-		info.bytes += extra;
-	} else {
-		info.ptr = 0;
-	}
-
-	DPRINTK ("EXIT, returning bytes=%d, blocks=%d, ptr=%d\n",
-		info.bytes,
-		info.blocks,
-		info.ptr);
-
-	return copy_to_user (arg, &info, sizeof (info))?-EFAULT:0;
-}
-
-
-static int via_dsp_ioctl_trigger (struct via_channel *chan, int val)
-{
-	int enable, do_something;
-
-	if (chan->is_record)
-		enable = (val & PCM_ENABLE_INPUT);
-	else
-		enable = (val & PCM_ENABLE_OUTPUT);
-
-	if (!chan->is_enabled && enable) {
-		do_something = 1;
-	} else if (chan->is_enabled && !enable) {
-		do_something = -1;
-	} else {
-		do_something = 0;
-	}
-
-	DPRINTK ("enable=%d, do_something=%d\n",
-		 enable, do_something);
-
-	if (chan->is_active && do_something)
-		return -EINVAL;
-
-	if (do_something == 1) {
-		chan->is_enabled = 1;
-		via_chan_maybe_start (chan);
-		DPRINTK ("Triggering input\n");
-	}
-
-	else if (do_something == -1) {
-		chan->is_enabled = 0;
-		DPRINTK ("Setup input trigger\n");
-	}
-
-	return 0;
-}
-
-
-static int via_dsp_ioctl (struct inode *inode, struct file *file,
-			  unsigned int cmd, unsigned long arg)
-{
-	int rc, rd=0, wr=0, val=0;
-	struct via_info *card;
-	struct via_channel *chan;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int __user *ip = (int __user *)arg;
-	void __user *p = (void __user *)arg;
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	if (file->f_mode & FMODE_WRITE)
-		wr = 1;
-	if (file->f_mode & FMODE_READ)
-		rd = 1;
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc)
-		return rc;
-	rc = -EINVAL;
-
-	switch (cmd) {
-
-	/* OSS API version.  XXX unverified */
-	case OSS_GETVERSION:
-		DPRINTK ("ioctl OSS_GETVERSION, EXIT, returning SOUND_VERSION\n");
-		rc = put_user (SOUND_VERSION, ip);
-		break;
-
-	/* list of supported PCM data formats */
-	case SNDCTL_DSP_GETFMTS:
-		DPRINTK ("DSP_GETFMTS, EXIT, returning AFMT U8|S16_LE\n");
-                rc = put_user (AFMT_U8 | AFMT_S16_LE, ip);
-		break;
-
-	/* query or set current channel's PCM data format */
-	case SNDCTL_DSP_SETFMT:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETFMT, val==%d\n", val);
-		if (val != AFMT_QUERY) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_fmt (card, &card->ch_in, val);
-
-			if (rc >= 0 && wr)
-				rc = via_chan_set_fmt (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_16BIT)) ||
-			    (wr && (card->ch_out.pcm_fmt & VIA_PCM_FMT_16BIT)))
-				val = AFMT_S16_LE;
-			else
-				val = AFMT_U8;
-		}
-		DPRINTK ("SETFMT EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* query or set number of channels (1=mono, 2=stereo, 4/6 for multichannel) */
-        case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_CHANNELS, val==%d\n", val);
-		if (val != 0) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_stereo (card, &card->ch_in, val);
-
-			if (rc >= 0 && wr)
-				rc = via_chan_set_stereo (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if (rd)
-				val = card->ch_in.channels;
-			else
-				val = card->ch_out.channels;
-		}
-		DPRINTK ("CHANNELS EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* enable (val is not zero) or disable (val == 0) stereo */
-        case SNDCTL_DSP_STEREO:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_STEREO, val==%d\n", val);
-		rc = 0;
-
-		if (rd)
-			rc = via_chan_set_stereo (card, &card->ch_in, val ? 2 : 1);
-		if (rc >= 0 && wr)
-			rc = via_chan_set_stereo (card, &card->ch_out, val ? 2 : 1);
-
-		if (rc < 0)
-			break;
-
-		val = rc - 1;
-
-		DPRINTK ("STEREO EXIT, returning %d\n", val);
-		rc = put_user(val, ip);
-		break;
-
-	/* query or set sampling rate */
-        case SNDCTL_DSP_SPEED:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SPEED, val==%d\n", val);
-		if (val < 0) {
-			rc = -EINVAL;
-			break;
-		}
-		if (val > 0) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_speed (card, &card->ch_in, val);
-			if (rc >= 0 && wr)
-				rc = via_chan_set_speed (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if (rd)
-				val = card->ch_in.rate;
-			else if (wr)
-				val = card->ch_out.rate;
-			else
-				val = 0;
-		}
-		DPRINTK ("SPEED EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* wait until all buffers have been played, and then stop device */
-	case SNDCTL_DSP_SYNC:
-		DPRINTK ("DSP_SYNC\n");
-		rc = 0;
-		if (wr) {
-			DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n");
-			rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
-		}
-		break;
-
-	/* stop recording/playback immediately */
-        case SNDCTL_DSP_RESET:
-		DPRINTK ("DSP_RESET\n");
-		if (rd) {
-			via_chan_clear (card, &card->ch_in);
-			card->ch_in.frag_number = 0;
-			card->ch_in.frag_size = 0;
-			atomic_set(&card->ch_in.n_frags, 0);
-		}
-
-		if (wr) {
-			via_chan_clear (card, &card->ch_out);
-			card->ch_out.frag_number = 0;
-			card->ch_out.frag_size = 0;
-			atomic_set(&card->ch_out.n_frags, 0);
-		}
-
-		rc = 0;
-		break;
-
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		rc = 0;
-		break;
-
-	/* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
-	case SNDCTL_DSP_GETCAPS:
-		DPRINTK ("DSP_GETCAPS\n");
-		rc = put_user(VIA_DSP_CAP, ip);
-		break;
-
-	/* obtain buffer fragment size */
-	case SNDCTL_DSP_GETBLKSIZE:
-		DPRINTK ("DSP_GETBLKSIZE\n");
-
-		if (rd) {
-			via_chan_set_buffering(card, &card->ch_in, -1);
-			rc = put_user(card->ch_in.frag_size, ip);
-		} else if (wr) {
-			via_chan_set_buffering(card, &card->ch_out, -1);
-			rc = put_user(card->ch_out.frag_size, ip);
-		}
-		break;
-
-	/* obtain information about input buffering */
-	case SNDCTL_DSP_GETISPACE:
-		DPRINTK ("DSP_GETISPACE\n");
-		if (rd)
-			rc = via_dsp_ioctl_space (card, &card->ch_in, p);
-		break;
-
-	/* obtain information about output buffering */
-	case SNDCTL_DSP_GETOSPACE:
-		DPRINTK ("DSP_GETOSPACE\n");
-		if (wr)
-			rc = via_dsp_ioctl_space (card, &card->ch_out, p);
-		break;
-
-	/* obtain information about input hardware pointer */
-	case SNDCTL_DSP_GETIPTR:
-		DPRINTK ("DSP_GETIPTR\n");
-		if (rd)
-			rc = via_dsp_ioctl_ptr (card, &card->ch_in, p);
-		break;
-
-	/* obtain information about output hardware pointer */
-	case SNDCTL_DSP_GETOPTR:
-		DPRINTK ("DSP_GETOPTR\n");
-		if (wr)
-			rc = via_dsp_ioctl_ptr (card, &card->ch_out, p);
-		break;
-
-	/* return number of bytes remaining to be played by DMA engine */
-	case SNDCTL_DSP_GETODELAY:
-		{
-		DPRINTK ("DSP_GETODELAY\n");
-
-		chan = &card->ch_out;
-
-		if (!wr)
-			break;
-
-		if (chan->is_active) {
-
-			val = chan->frag_number - atomic_read (&chan->n_frags);
-
-			assert(val >= 0);
-				
-			if (val > 0) {
-				val *= chan->frag_size;
-				val -= chan->frag_size - via_sg_offset(chan);
-			}
-			val += chan->slop_len % chan->frag_size;
-		} else
-			val = 0;
-
-		assert (val <= (chan->frag_size * chan->frag_number));
-
-		DPRINTK ("GETODELAY EXIT, val = %d bytes\n", val);
-                rc = put_user (val, ip);
-		break;
-		}
-
-	/* handle the quick-start of a channel,
-	 * or the notification that a quick-start will
-	 * occur in the future
-	 */
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETTRIGGER, rd=%d, wr=%d, act=%d/%d, en=%d/%d\n",
-			rd, wr, card->ch_in.is_active, card->ch_out.is_active,
-			card->ch_in.is_enabled, card->ch_out.is_enabled);
-
-		rc = 0;
-
-		if (rd)
-			rc = via_dsp_ioctl_trigger (&card->ch_in, val);
-
-		if (!rc && wr)
-			rc = via_dsp_ioctl_trigger (&card->ch_out, val);
-
-		break;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		if ((file->f_mode & FMODE_READ) && card->ch_in.is_enabled)
-			val |= PCM_ENABLE_INPUT;
-		if ((file->f_mode & FMODE_WRITE) && card->ch_out.is_enabled)
-			val |= PCM_ENABLE_OUTPUT;
-		rc = put_user(val, ip);
-		break;
-
-	/* Enable full duplex.  Since we do this as soon as we are opened
-	 * with O_RDWR, this is mainly a no-op that always returns success.
-	 */
-	case SNDCTL_DSP_SETDUPLEX:
-		DPRINTK ("DSP_SETDUPLEX\n");
-		if (!rd || !wr)
-			break;
-		rc = 0;
-		break;
-
-	/* set fragment size.  implemented as a successful no-op for now */
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETFRAGMENT, val==%d\n", val);
-
-		if (rd)
-			rc = via_chan_set_buffering(card, &card->ch_in, val);
-
-		if (wr)
-			rc = via_chan_set_buffering(card, &card->ch_out, val);
-
-		DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
-			 val & 0xFFFF,
-			 val & 0xFFFF,
-			 (val >> 16) & 0xFFFF,
-			 (val >> 16) & 0xFFFF);
-
-		rc = 0;
-		break;
-
-	/* inform device of an upcoming pause in input (or output). */
-	case SNDCTL_DSP_POST:
-		DPRINTK ("DSP_POST\n");
-		if (wr) {
-			if (card->ch_out.slop_len > 0)
-				via_chan_flush_frag (&card->ch_out);
-			via_chan_maybe_start (&card->ch_out);
-		}
-
-		rc = 0;
-		break;
-
-	/* not implemented */
-	default:
-		DPRINTK ("unhandled ioctl, cmd==%u, arg==%p\n",
-			 cmd, p);
-		break;
-	}
-
-	mutex_unlock(&card->syscall_mutex);
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static int via_dsp_open (struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct via_info *card;
-	struct pci_dev *pdev = NULL;
-	struct via_channel *chan;
-	struct pci_driver *drvr;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-
-	DPRINTK ("ENTER, minor=%d, file->f_mode=0x%x\n", minor, file->f_mode);
-
-	if (!(file->f_mode & (FMODE_READ | FMODE_WRITE))) {
-		DPRINTK ("EXIT, returning -EINVAL\n");
-		return -EINVAL;
-	}
-
-	card = NULL;
-	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		drvr = pci_dev_driver (pdev);
-		if (drvr == &via_driver) {
-			assert (pci_get_drvdata (pdev) != NULL);
-
-			card = pci_get_drvdata (pdev);
-			DPRINTK ("dev_dsp = %d, minor = %d, assn = %d\n",
-				 card->dev_dsp, minor,
-				 (card->dev_dsp ^ minor) & ~0xf);
-
-			if (((card->dev_dsp ^ minor) & ~0xf) == 0)
-				goto match;
-		}
-	}
-
-	DPRINTK ("no matching %s found\n", card ? "minor" : "driver");
-	return -ENODEV;
-
-match:
-	pci_dev_put(pdev);
-	if (nonblock) {
-		if (!mutex_trylock(&card->open_mutex)) {
-			DPRINTK ("EXIT, returning -EAGAIN\n");
-			return -EAGAIN;
-		}
-	} else {
-		if (mutex_lock_interruptible(&card->open_mutex)) {
-			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
-			return -ERESTARTSYS;
-		}
-	}
-
-	file->private_data = card;
-	DPRINTK ("file->f_mode == 0x%x\n", file->f_mode);
-
-	/* handle input from analog source */
-	if (file->f_mode & FMODE_READ) {
-		chan = &card->ch_in;
-
-		via_chan_init (card, chan);
-
-		/* why is this forced to 16-bit stereo in all drivers? */
-		chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
-		chan->channels = 2;
-
-		// TO DO - use FIFO: via_capture_fifo(card, 1);
-		via_chan_pcm_fmt (chan, 0);
-		via_set_rate (card->ac97, chan, 44100);
-	}
-
-	/* handle output to analog source */
-	if (file->f_mode & FMODE_WRITE) {
-		chan = &card->ch_out;
-
-		via_chan_init (card, chan);
-
-		if (file->f_mode & FMODE_READ) {
-			/* if in duplex mode make the recording and playback channels
-			   have the same settings */
-			chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
-			chan->channels = 2;
-			via_chan_pcm_fmt (chan, 0);
-                        via_set_rate (card->ac97, chan, 44100);
-		} else {
-			 if ((minor & 0xf) == SND_DEV_DSP16) {
-				chan->pcm_fmt = VIA_PCM_FMT_16BIT;
-				via_chan_pcm_fmt (chan, 0);
-				via_set_rate (card->ac97, chan, 44100);
-			} else {
-				via_chan_pcm_fmt (chan, 1);
-				via_set_rate (card->ac97, chan, 8000);
-			}
-		}
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return nonseekable_open(inode, file);
-}
-
-
-static int via_dsp_release(struct inode *inode, struct file *file)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) {
-		DPRINTK ("EXIT (syscall_down error), rc=%d\n", rc);
-		return rc;
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
-		if (rc && rc != -ERESTARTSYS)	/* Nobody needs to know about ^C */
-			printk (KERN_DEBUG "via_audio: ignoring drain playback error %d\n", rc);
-
-		via_chan_free (card, &card->ch_out);
-		via_chan_buffer_free(card, &card->ch_out);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		via_chan_free (card, &card->ch_in);
-		via_chan_buffer_free (card, &card->ch_in);
-	}
-
-	mutex_unlock(&card->syscall_mutex);
-	mutex_unlock(&card->open_mutex);
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/****************************************************************
- *
- * Chip setup and kernel registration
- *
- *
- */
-
-static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
-{
-#ifdef CONFIG_MIDI_VIA82CXXX
-	u8 r42;
-#endif
-	int rc;
-	struct via_info *card;
-	static int printed_version;
-
-	DPRINTK ("ENTER\n");
-
-	if (printed_version++ == 0)
-		printk (KERN_INFO "Via 686a/8233/8235 audio driver " VIA_VERSION "\n");
-
-	rc = pci_enable_device (pdev);
-	if (rc)
-		goto err_out;
-
-	rc = pci_request_regions (pdev, "via82cxxx_audio");
-	if (rc)
-		goto err_out_disable;
-
-	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc)
-		goto err_out_res;
-	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc)
-		goto err_out_res;
-
-	card = kmalloc (sizeof (*card), GFP_KERNEL);
-	if (!card) {
-		printk (KERN_ERR PFX "out of memory, aborting\n");
-		rc = -ENOMEM;
-		goto err_out_res;
-	}
-
-	pci_set_drvdata (pdev, card);
-
-	memset (card, 0, sizeof (*card));
-	card->pdev = pdev;
-	card->baseaddr = pci_resource_start (pdev, 0);
-	card->card_num = via_num_cards++;
-	spin_lock_init (&card->lock);
-	spin_lock_init (&card->ac97_lock);
-	mutex_init(&card->syscall_mutex);
-	mutex_init(&card->open_mutex);
-
-	/* we must init these now, in case the intr handler needs them */
-	via_chan_init_defaults (card, &card->ch_out);
-	via_chan_init_defaults (card, &card->ch_in);
-	via_chan_init_defaults (card, &card->ch_fm);
-
-	/* if BAR 2 is present, chip is Rev H or later,
-	 * which means it has a few extra features */
-	if (pci_resource_start (pdev, 2) > 0)
-		card->rev_h = 1;
-		
-	/* Overkill for now, but more flexible done right */
-	
-	card->intmask = id->driver_data;
-	card->legacy = !card->intmask;
-	card->sixchannel = id->driver_data;
-	
-	if(card->sixchannel)
-		printk(KERN_INFO PFX "Six channel audio available\n");
-	if (pdev->irq < 1) {
-		printk (KERN_ERR PFX "invalid PCI IRQ %d, aborting\n", pdev->irq);
-		rc = -ENODEV;
-		goto err_out_kfree;
-	}
-
-	if (!(pci_resource_flags (pdev, 0) & IORESOURCE_IO)) {
-		printk (KERN_ERR PFX "unable to locate I/O resources, aborting\n");
-		rc = -ENODEV;
-		goto err_out_kfree;
-	}
-
-	pci_set_master(pdev);
-	
-	/*
-	 * init AC97 mixer and codec
-	 */
-	rc = via_ac97_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "AC97 init failed, aborting\n");
-		goto err_out_kfree;
-	}
-
-	/*
-	 * init DSP device
-	 */
-	rc = via_dsp_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "DSP device init failed, aborting\n");
-		goto err_out_have_mixer;
-	}
-
-	/*
-	 * init and turn on interrupts, as the last thing we do
-	 */
-	rc = via_interrupt_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "interrupt init failed, aborting\n");
-		goto err_out_have_dsp;
-	}
-
-	printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n",
-		card->card_num + 1, card->baseaddr, pdev->irq);
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-	/* Disable by default */
-	card->midi_info.io_base = 0;
-
-	if(card->legacy)
-	{
-		pci_read_config_byte (pdev, 0x42, &r42);
-		/* Disable MIDI interrupt */
-		pci_write_config_byte (pdev, 0x42, r42 | VIA_CR42_MIDI_IRQMASK);
-		if (r42 & VIA_CR42_MIDI_ENABLE)
-		{
-			if (r42 & VIA_CR42_MIDI_PNP) /* Address selected by iobase 2 - not tested */
-				card->midi_info.io_base = pci_resource_start (pdev, 2);
-			else /* Address selected by byte 0x43 */
-			{
-				u8 r43;
-				pci_read_config_byte (pdev, 0x43, &r43);
-				card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2);
-			}
-
-			card->midi_info.irq = -pdev->irq;
-			if (probe_uart401(& card->midi_info, THIS_MODULE))
-			{
-				card->midi_devc=midi_devs[card->midi_info.slots[4]]->devc;
-				pci_write_config_byte(pdev, 0x42, r42 & ~VIA_CR42_MIDI_IRQMASK);
-				printk("Enabled Via MIDI\n");
-			}
-		}
-	}
-#endif
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_have_dsp:
-	via_dsp_cleanup (card);
-
-err_out_have_mixer:
-	via_ac97_cleanup (card);
-
-err_out_kfree:
-#ifndef VIA_NDEBUG
-	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
-#endif
-	kfree (card);
-
-err_out_res:
-	pci_release_regions (pdev);
-
-err_out_disable:
-	pci_disable_device (pdev);
-
-err_out:
-	pci_set_drvdata (pdev, NULL);
-	DPRINTK ("EXIT - returning %d\n", rc);
-	return rc;
-}
-
-
-static void __devexit via_remove_one (struct pci_dev *pdev)
-{
-	struct via_info *card;
-
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
-	card = pci_get_drvdata (pdev);
-	assert (card != NULL);
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-	if (card->midi_info.io_base)
-		unload_uart401(&card->midi_info);
-#endif
-
-	free_irq (card->pdev->irq, card);
-	via_dsp_cleanup (card);
-	via_ac97_cleanup (card);
-
-#ifndef VIA_NDEBUG
-	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
-#endif
-	kfree (card);
-
-	pci_set_drvdata (pdev, NULL);
-
-	pci_release_regions (pdev);
-	pci_disable_device (pdev);
-	pci_set_power_state (pdev, 3); /* ...zzzzzz */
-
-	DPRINTK ("EXIT\n");
-	return;
-}
-
-
-/****************************************************************
- *
- * Driver initialization and cleanup
- *
- *
- */
-
-static int __init init_via82cxxx_audio(void)
-{
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	rc = pci_register_driver (&via_driver);
-	if (rc) {
-		DPRINTK ("EXIT, returning %d\n", rc);
-		return rc;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void __exit cleanup_via82cxxx_audio(void)
-{
-	DPRINTK ("ENTER\n");
-
-	pci_unregister_driver (&via_driver);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-module_init(init_via82cxxx_audio);
-module_exit(cleanup_via82cxxx_audio);
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("DSP audio and mixer driver for Via 82Cxxx audio devices");
-MODULE_LICENSE("GPL");
-