summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--releases/2.6.16.22/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch98
-rw-r--r--releases/2.6.16.22/i2o-bugfixes-to-get-i2o-working-again.patch249
-rw-r--r--releases/2.6.16.22/jfs-fix-multiple-errors-in-metapage_releasepage.patch75
-rw-r--r--releases/2.6.16.22/missed-error-checking-for-intent-s-filp-in-open_namei.patch53
-rw-r--r--releases/2.6.16.22/ntfs-critical-bug-fix.patch50
-rw-r--r--releases/2.6.16.22/powernow-k8-crash-workaround.patch47
-rw-r--r--releases/2.6.16.22/scsi_lib.c-properly-count-the-number-of-pages-in-scsi_req_map_sg.patch33
-rw-r--r--releases/2.6.16.22/serial-parport_serial-should-depend-on-serial_8250_pci.patch28
-rw-r--r--releases/2.6.16.22/series13
-rw-r--r--releases/2.6.16.22/sparc64-fix-d-cache-corruption-in-mremap.patch95
-rw-r--r--releases/2.6.16.22/sparc64-fix-missing-fold-at-end-of-checksums.patch56
-rw-r--r--releases/2.6.16.22/sparc64-respect-gfp_t-argument-to-dma_alloc_coherent.patch226
-rw-r--r--releases/2.6.16.22/tmpfs-time-granularity-fix-for-time-going-backwards.patch45
-rw-r--r--releases/2.6.16.22/usb-whiteheat-fix-firmware-spurious-errors.patch36
14 files changed, 1104 insertions, 0 deletions
diff --git a/releases/2.6.16.22/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch b/releases/2.6.16.22/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch
new file mode 100644
index 0000000000..8605484b6c
--- /dev/null
+++ b/releases/2.6.16.22/fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch
@@ -0,0 +1,98 @@
+From stable-bounces@linux.kernel.org Tue Jun 6 08:23:00 2006
+Date: Tue, 6 Jun 2006 11:19:35 -0400
+From: Joe Korty <joe.korty@ccur.com>
+To: stable@kernel.org
+Cc:
+Subject: fs/namei.c: Call to file_permission() under a spinlock in do_lookup_path()
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+We're presently running lock_kernel() under fs_lock via nfs's ->permission
+handler. That's a ranking bug and sometimes a sleep-in-spinlock bug. This
+problem was introduced in the openat() patchset.
+
+We should not need to hold the current->fs->lock for a codepath that doesn't
+use current->fs.
+
+[vsu@altlinux.ru: fix error path]
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+Cc: Al Viro <viro@ftp.linux.org.uk>
+Signed-off-by: Sergey Vlasov <vsu@altlinux.ru>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ fs/namei.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+--- linux-2.6.16.21.orig/fs/namei.c
++++ linux-2.6.16.21/fs/namei.c
+@@ -1077,8 +1077,8 @@ static int fastcall do_path_lookup(int d
+ nd->flags = flags;
+ nd->depth = 0;
+
+- read_lock(&current->fs->lock);
+ if (*name=='/') {
++ read_lock(&current->fs->lock);
+ if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+ nd->mnt = mntget(current->fs->altrootmnt);
+ nd->dentry = dget(current->fs->altroot);
+@@ -1089,33 +1089,35 @@ static int fastcall do_path_lookup(int d
+ }
+ nd->mnt = mntget(current->fs->rootmnt);
+ nd->dentry = dget(current->fs->root);
++ read_unlock(&current->fs->lock);
+ } else if (dfd == AT_FDCWD) {
++ read_lock(&current->fs->lock);
+ nd->mnt = mntget(current->fs->pwdmnt);
+ nd->dentry = dget(current->fs->pwd);
++ read_unlock(&current->fs->lock);
+ } else {
+ struct dentry *dentry;
+
+ file = fget_light(dfd, &fput_needed);
+ retval = -EBADF;
+ if (!file)
+- goto unlock_fail;
++ goto out_fail;
+
+ dentry = file->f_dentry;
+
+ retval = -ENOTDIR;
+ if (!S_ISDIR(dentry->d_inode->i_mode))
+- goto fput_unlock_fail;
++ goto fput_fail;
+
+ retval = file_permission(file, MAY_EXEC);
+ if (retval)
+- goto fput_unlock_fail;
++ goto fput_fail;
+
+ nd->mnt = mntget(file->f_vfsmnt);
+ nd->dentry = dget(dentry);
+
+ fput_light(file, fput_needed);
+ }
+- read_unlock(&current->fs->lock);
+ current->total_link_count = 0;
+ retval = link_path_walk(name, nd);
+ out:
+@@ -1124,13 +1126,12 @@ out:
+ nd->dentry->d_inode))
+ audit_inode(name, nd->dentry->d_inode, flags);
+ }
++out_fail:
+ return retval;
+
+-fput_unlock_fail:
++fput_fail:
+ fput_light(file, fput_needed);
+-unlock_fail:
+- read_unlock(&current->fs->lock);
+- return retval;
++ goto out_fail;
+ }
+
+ int fastcall path_lookup(const char *name, unsigned int flags,
diff --git a/releases/2.6.16.22/i2o-bugfixes-to-get-i2o-working-again.patch b/releases/2.6.16.22/i2o-bugfixes-to-get-i2o-working-again.patch
new file mode 100644
index 0000000000..0c5654616d
--- /dev/null
+++ b/releases/2.6.16.22/i2o-bugfixes-to-get-i2o-working-again.patch
@@ -0,0 +1,249 @@
+From stable-bounces@linux.kernel.org Sat Jun 10 09:57:42 2006
+Date: Sat, 10 Jun 2006 09:54:14 -0700
+From: akpm@osdl.org
+To: torvalds@osdl.org
+Cc: Markus.Lidel@shadowconnect.com, stable@kernel.org
+Subject: I2O: Bugfixes to get I2O working again
+
+From: Markus Lidel <Markus.Lidel@shadowconnect.com>
+
+- Fixed locking of struct i2o_exec_wait in Executive-OSM
+
+- Removed LCT Notify in i2o_exec_probe() which caused freeing memory and
+ accessing freed memory during first enumeration of I2O devices
+
+- Added missing locking in i2o_exec_lct_notify()
+
+- removed put_device() of I2O controller in i2o_iop_remove() which caused
+ the controller structure get freed to early
+
+- Fixed size of mempool in i2o_iop_alloc()
+
+- Fixed access to freed memory in i2o_msg_get()
+
+See http://bugzilla.kernel.org/show_bug.cgi?id=6561
+
+Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ drivers/message/i2o/exec-osm.c | 72 +++++++++++++++++++++--------------------
+ drivers/message/i2o/iop.c | 4 --
+ include/linux/i2o.h | 5 ++
+ 3 files changed, 42 insertions(+), 39 deletions(-)
+
+--- linux-2.6.16.21.orig/drivers/message/i2o/exec-osm.c
++++ linux-2.6.16.21/drivers/message/i2o/exec-osm.c
+@@ -55,6 +55,7 @@ struct i2o_exec_wait {
+ u32 m; /* message id */
+ struct i2o_message *msg; /* pointer to the reply message */
+ struct list_head list; /* node in global wait list */
++ spinlock_t lock; /* lock before modifying */
+ };
+
+ /* Exec OSM class handling definition */
+@@ -80,6 +81,7 @@ static struct i2o_exec_wait *i2o_exec_wa
+ return NULL;
+
+ INIT_LIST_HEAD(&wait->list);
++ spin_lock_init(&wait->lock);
+
+ return wait;
+ };
+@@ -118,6 +120,7 @@ int i2o_msg_post_wait_mem(struct i2o_con
+ DECLARE_WAIT_QUEUE_HEAD(wq);
+ struct i2o_exec_wait *wait;
+ static u32 tcntxt = 0x80000000;
++ long flags;
+ int rc = 0;
+
+ wait = i2o_exec_wait_alloc();
+@@ -139,33 +142,28 @@ int i2o_msg_post_wait_mem(struct i2o_con
+ wait->tcntxt = tcntxt++;
+ msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
+
++ wait->wq = &wq;
++ /*
++ * we add elements to the head, because if a entry in the list will
++ * never be removed, we have to iterate over it every time
++ */
++ list_add(&wait->list, &i2o_exec_wait_list);
++
+ /*
+ * Post the message to the controller. At some point later it will
+ * return. If we time out before it returns then complete will be zero.
+ */
+ i2o_msg_post(c, msg);
+
+- if (!wait->complete) {
+- wait->wq = &wq;
+- /*
+- * we add elements add the head, because if a entry in the list
+- * will never be removed, we have to iterate over it every time
+- */
+- list_add(&wait->list, &i2o_exec_wait_list);
+-
+- wait_event_interruptible_timeout(wq, wait->complete,
+- timeout * HZ);
++ wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
+
+- wait->wq = NULL;
+- }
++ spin_lock_irqsave(&wait->lock, flags);
+
+- barrier();
++ wait->wq = NULL;
+
+- if (wait->complete) {
++ if (wait->complete)
+ rc = le32_to_cpu(wait->msg->body[0]) >> 24;
+- i2o_flush_reply(c, wait->m);
+- i2o_exec_wait_free(wait);
+- } else {
++ else {
+ /*
+ * We cannot remove it now. This is important. When it does
+ * terminate (which it must do if the controller has not
+@@ -179,6 +177,13 @@ int i2o_msg_post_wait_mem(struct i2o_con
+ rc = -ETIMEDOUT;
+ }
+
++ spin_unlock_irqrestore(&wait->lock, flags);
++
++ if (rc != -ETIMEDOUT) {
++ i2o_flush_reply(c, wait->m);
++ i2o_exec_wait_free(wait);
++ }
++
+ return rc;
+ };
+
+@@ -206,7 +211,6 @@ static int i2o_msg_post_wait_complete(st
+ {
+ struct i2o_exec_wait *wait, *tmp;
+ unsigned long flags;
+- static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ int rc = 1;
+
+ /*
+@@ -216,23 +220,24 @@ static int i2o_msg_post_wait_complete(st
+ * already expired. Not much we can do about that except log it for
+ * debug purposes, increase timeout, and recompile.
+ */
+- spin_lock_irqsave(&lock, flags);
+ list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
+ if (wait->tcntxt == context) {
+- list_del(&wait->list);
++ spin_lock_irqsave(&wait->lock, flags);
+
+- spin_unlock_irqrestore(&lock, flags);
++ list_del(&wait->list);
+
+ wait->m = m;
+ wait->msg = msg;
+ wait->complete = 1;
+
+- barrier();
+-
+- if (wait->wq) {
+- wake_up_interruptible(wait->wq);
++ if (wait->wq)
+ rc = 0;
+- } else {
++ else
++ rc = -1;
++
++ spin_unlock_irqrestore(&wait->lock, flags);
++
++ if (rc) {
+ struct device *dev;
+
+ dev = &c->pdev->dev;
+@@ -241,15 +246,13 @@ static int i2o_msg_post_wait_complete(st
+ c->name);
+ i2o_dma_free(dev, &wait->dma);
+ i2o_exec_wait_free(wait);
+- rc = -1;
+- }
++ } else
++ wake_up_interruptible(wait->wq);
+
+ return rc;
+ }
+ }
+
+- spin_unlock_irqrestore(&lock, flags);
+-
+ osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
+ context);
+
+@@ -315,14 +318,9 @@ static DEVICE_ATTR(product_id, S_IRUGO,
+ static int i2o_exec_probe(struct device *dev)
+ {
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
+- struct i2o_controller *c = i2o_dev->iop;
+
+ i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
+
+- c->exec = i2o_dev;
+-
+- i2o_exec_lct_notify(c, c->lct->change_ind + 1);
+-
+ device_create_file(dev, &dev_attr_vendor_id);
+ device_create_file(dev, &dev_attr_product_id);
+
+@@ -510,6 +508,8 @@ static int i2o_exec_lct_notify(struct i2
+ struct device *dev;
+ struct i2o_message *msg;
+
++ down(&c->lct_lock);
++
+ dev = &c->pdev->dev;
+
+ if (i2o_dma_realloc
+@@ -532,6 +532,8 @@ static int i2o_exec_lct_notify(struct i2
+
+ i2o_msg_post(c, msg);
+
++ up(&c->lct_lock);
++
+ return 0;
+ };
+
+--- linux-2.6.16.21.orig/drivers/message/i2o/iop.c
++++ linux-2.6.16.21/drivers/message/i2o/iop.c
+@@ -804,8 +804,6 @@ void i2o_iop_remove(struct i2o_controlle
+
+ /* Ask the IOP to switch to RESET state */
+ i2o_iop_reset(c);
+-
+- put_device(&c->device);
+ }
+
+ /**
+@@ -1059,7 +1057,7 @@ struct i2o_controller *i2o_iop_alloc(voi
+
+ snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
+ if (i2o_pool_alloc
+- (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4,
++ (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
+ I2O_MSG_INPOOL_MIN)) {
+ kfree(c);
+ return ERR_PTR(-ENOMEM);
+--- linux-2.6.16.21.orig/include/linux/i2o.h
++++ linux-2.6.16.21/include/linux/i2o.h
+@@ -1116,8 +1116,11 @@ static inline struct i2o_message *i2o_ms
+
+ mmsg->mfa = readl(c->in_port);
+ if (unlikely(mmsg->mfa >= c->in_queue.len)) {
++ u32 mfa = mmsg->mfa;
++
+ mempool_free(mmsg, c->in_msg.mempool);
+- if(mmsg->mfa == I2O_QUEUE_EMPTY)
++
++ if (mfa == I2O_QUEUE_EMPTY)
+ return ERR_PTR(-EBUSY);
+ return ERR_PTR(-EFAULT);
+ }
diff --git a/releases/2.6.16.22/jfs-fix-multiple-errors-in-metapage_releasepage.patch b/releases/2.6.16.22/jfs-fix-multiple-errors-in-metapage_releasepage.patch
new file mode 100644
index 0000000000..9730ff167c
--- /dev/null
+++ b/releases/2.6.16.22/jfs-fix-multiple-errors-in-metapage_releasepage.patch
@@ -0,0 +1,75 @@
+From stable-bounces@linux.kernel.org Tue Jun 6 20:00:50 2006
+Date: Tue, 6 Jun 2006 22:54:44 -0400
+From: Chuck Ebbert <76306.1226@compuserve.com>
+To: linux-stable <stable@kernel.org>
+Cc: Dave Kleikamp <shaggy@austin.ibm.com>
+Subject: JFS: Fix multiple errors in metapage_releasepage
+
+From: Dave Kleikamp <shaggy@austin.ibm.com>
+
+It looks like metapage_releasepage was making in invalid assumption that
+the releasepage method would not be called on a dirty page. Instead of
+issuing a warning and releasing the metapage, it should return 0, indicating
+that the private data for the page cannot be released.
+
+I also realized that metapage_releasepage had the return code all wrong. If
+it is successful in releasing the private data, it should return 1, otherwise
+it needs to return 0.
+
+Lastly, there is no need to call wait_on_page_writeback, since
+try_to_release_page will not call us with a page in writback state.
+
+Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ fs/jfs/jfs_metapage.c | 20 +++++---------------
+ 1 file changed, 5 insertions(+), 15 deletions(-)
+
+--- linux-2.6.16.21.orig/fs/jfs/jfs_metapage.c
++++ linux-2.6.16.21/fs/jfs/jfs_metapage.c
+@@ -543,7 +543,7 @@ add_failed:
+ static int metapage_releasepage(struct page *page, gfp_t gfp_mask)
+ {
+ struct metapage *mp;
+- int busy = 0;
++ int ret = 1;
+ unsigned int offset;
+
+ for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) {
+@@ -553,30 +553,20 @@ static int metapage_releasepage(struct p
+ continue;
+
+ jfs_info("metapage_releasepage: mp = 0x%p", mp);
+- if (mp->count || mp->nohomeok) {
++ if (mp->count || mp->nohomeok ||
++ test_bit(META_dirty, &mp->flag)) {
+ jfs_info("count = %ld, nohomeok = %d", mp->count,
+ mp->nohomeok);
+- busy = 1;
++ ret = 0;
+ continue;
+ }
+- wait_on_page_writeback(page);
+- //WARN_ON(test_bit(META_dirty, &mp->flag));
+- if (test_bit(META_dirty, &mp->flag)) {
+- dump_mem("dirty mp in metapage_releasepage", mp,
+- sizeof(struct metapage));
+- dump_mem("page", page, sizeof(struct page));
+- dump_stack();
+- }
+ if (mp->lsn)
+ remove_from_logsync(mp);
+ remove_metapage(page, mp);
+ INCREMENT(mpStat.pagefree);
+ free_metapage(mp);
+ }
+- if (busy)
+- return -1;
+-
+- return 0;
++ return ret;
+ }
+
+ static int metapage_invalidatepage(struct page *page, unsigned long offset)
diff --git a/releases/2.6.16.22/missed-error-checking-for-intent-s-filp-in-open_namei.patch b/releases/2.6.16.22/missed-error-checking-for-intent-s-filp-in-open_namei.patch
new file mode 100644
index 0000000000..304b0def52
--- /dev/null
+++ b/releases/2.6.16.22/missed-error-checking-for-intent-s-filp-in-open_namei.patch
@@ -0,0 +1,53 @@
+From nobody Mon Sep 17 00:00:00 2001
+From: Oleg Drokin <green@linuxhacker.ru>
+Date: Sat, 25 Mar 2006 03:06:54 -0800
+Subject: [PATCH] Missed error checking for intent's filp in open_namei().
+
+It seems there is error check missing in open_namei for errors returned
+through intent.open.file (from lookup_instantiate_filp).
+
+If there is plain open performed, then such a check done inside
+__path_lookup_intent_open called from path_lookup_open(), but when the open
+is performed with O_CREAT flag set, then __path_lookup_intent_open is only
+called with LOOKUP_PARENT set where no file opening can occur yet.
+
+Later on lookup_hash is called where exact opening might take place and
+intent.open.file may be filled. If it is filled with error value of some
+sort, then we get kernel attempting to dereference this error value as
+address (and corresponding oops) in nameidata_to_filp() called from
+filp_open().
+
+While this is relatively simple to workaround in ->lookup() method by just
+checking lookup_instantiate_filp() return value and returning error as
+needed, this is not so easy in ->d_revalidate(), where we can only return
+"yes, dentry is valid" or "no, dentry is invalid, perform full lookup
+again", and just returning 0 on error would cause extra lookup (with
+potential extra costly RPCs).
+
+So in short, I believe that there should be no difference in error handling
+for opening a file and creating a file in open_namei() and propose this
+simple patch as a solution.
+
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- linux-2.6.16.21.orig/fs/namei.c
++++ linux-2.6.16.21/fs/namei.c
+@@ -1628,6 +1628,12 @@ do_last:
+ goto exit;
+ }
+
++ if (IS_ERR(nd->intent.open.file)) {
++ mutex_unlock(&dir->d_inode->i_mutex);
++ error = PTR_ERR(nd->intent.open.file);
++ goto exit_dput;
++ }
++
+ /* Negative dentry, just create the file */
+ if (!path.dentry->d_inode) {
+ if (!IS_POSIXACL(dir->d_inode))
diff --git a/releases/2.6.16.22/ntfs-critical-bug-fix.patch b/releases/2.6.16.22/ntfs-critical-bug-fix.patch
new file mode 100644
index 0000000000..3ee3d63aa1
--- /dev/null
+++ b/releases/2.6.16.22/ntfs-critical-bug-fix.patch
@@ -0,0 +1,50 @@
+From stable-bounces@linux.kernel.org Tue Jun 20 00:30:20 2006
+Date: Tue, 20 Jun 2006 00:29:41 -0700
+From: akpm@osdl.org
+To: aia21@cam.ac.uk, aia21@cantab.net, stable@kernel.org
+Cc:
+Subject: NTFS: Critical bug fix (affects MIPS and possibly others)
+
+From: Anton Altaparmakov <aia21@cam.ac.uk>
+
+It fixes a crash in NTFS on architectures where flush_dcache_page()
+is a real function. I never noticed this as all my testing is done on
+i386 where flush_dcache_page() is NULL.
+
+http://bugzilla.kernel.org/show_bug.cgi?id=6700
+
+Many thanks to Pauline Ng for the detailed bug report and analysis!
+
+Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ fs/ntfs/file.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- linux-2.6.16.21.orig/fs/ntfs/file.c
++++ linux-2.6.16.21/fs/ntfs/file.c
+@@ -1489,14 +1489,15 @@ static inline void ntfs_flush_dcache_pag
+ unsigned nr_pages)
+ {
+ BUG_ON(!nr_pages);
++ /*
++ * Warning: Do not do the decrement at the same time as the call to
++ * flush_dcache_page() because it is a NULL macro on i386 and hence the
++ * decrement never happens so the loop never terminates.
++ */
+ do {
+- /*
+- * Warning: Do not do the decrement at the same time as the
+- * call because flush_dcache_page() is a NULL macro on i386
+- * and hence the decrement never happens.
+- */
++ --nr_pages;
+ flush_dcache_page(pages[nr_pages]);
+- } while (--nr_pages > 0);
++ } while (nr_pages > 0);
+ }
+
+ /**
diff --git a/releases/2.6.16.22/powernow-k8-crash-workaround.patch b/releases/2.6.16.22/powernow-k8-crash-workaround.patch
new file mode 100644
index 0000000000..27c3b3b570
--- /dev/null
+++ b/releases/2.6.16.22/powernow-k8-crash-workaround.patch
@@ -0,0 +1,47 @@
+From stable-bounces@linux.kernel.org Sat Jun 10 23:33:22 2006
+Date: Sat, 10 Jun 2006 18:59:23 GMT
+From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+To: git-commits-head@vger.kernel.org
+Cc:
+Subject: powernow-k8 crash workaround
+
+From: Andrew Morton <akpm@osdl.org>
+
+Work around the oops reported in
+http://bugzilla.kernel.org/show_bug.cgi?id=6478.
+
+Thanks to Ralf Hildebrandt <ralf.hildebrandt@charite.de> for testing and
+reporting.
+
+Acked-by: Dave Jones <davej@codemonkey.org.uk>
+Cc: "Brown, Len" <len.brown@intel.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ drivers/acpi/processor_perflib.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- linux-2.6.16.21.orig/drivers/acpi/processor_perflib.c
++++ linux-2.6.16.21/drivers/acpi/processor_perflib.c
+@@ -577,6 +577,8 @@ acpi_processor_register_performance(stru
+ return_VALUE(-EBUSY);
+ }
+
++ WARN_ON(!performance);
++
+ pr->performance = performance;
+
+ if (acpi_processor_get_performance_info(pr)) {
+@@ -609,7 +611,8 @@ acpi_processor_unregister_performance(st
+ return_VOID;
+ }
+
+- kfree(pr->performance->states);
++ if (pr->performance)
++ kfree(pr->performance->states);
+ pr->performance = NULL;
+
+ acpi_cpufreq_remove_file(pr);
diff --git a/releases/2.6.16.22/scsi_lib.c-properly-count-the-number-of-pages-in-scsi_req_map_sg.patch b/releases/2.6.16.22/scsi_lib.c-properly-count-the-number-of-pages-in-scsi_req_map_sg.patch
new file mode 100644
index 0000000000..f773cd1afc
--- /dev/null
+++ b/releases/2.6.16.22/scsi_lib.c-properly-count-the-number-of-pages-in-scsi_req_map_sg.patch
@@ -0,0 +1,33 @@
+From stable-bounces@linux.kernel.org Wed Jun 7 21:15:48 2006
+Date: Thu, 8 Jun 2006 00:03:28 -0400
+From: Chuck Ebbert <76306.1226@compuserve.com>
+To: linux-stable <stable@kernel.org>
+Cc: James Bottomley <James.Bottomley@steeleye.com>, Brian Holty <lgeek@frontiernet.net>
+Subject: scsi_lib.c: properly count the number of pages in scsi_req_map_sg()
+
+From: James Bottomley <jejb@mulgrave.il.steeleye.com>
+
+The calculation of nr_pages in scsi_req_map_sg() doesn't account for
+the fact that the first page could have an offset that pushes the end
+of the buffer onto a new page.
+
+Signed-off-by: Bryan Holty <lgeek@frontiernet.net>
+Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ drivers/scsi/scsi_lib.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.16.21.orig/drivers/scsi/scsi_lib.c
++++ linux-2.6.16.21/drivers/scsi/scsi_lib.c
+@@ -368,7 +368,7 @@ static int scsi_req_map_sg(struct reques
+ int nsegs, unsigned bufflen, gfp_t gfp)
+ {
+ struct request_queue *q = rq->q;
+- int nr_pages = (bufflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
++ int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ unsigned int data_len = 0, len, bytes, off;
+ struct page *page;
+ struct bio *bio = NULL;
diff --git a/releases/2.6.16.22/serial-parport_serial-should-depend-on-serial_8250_pci.patch b/releases/2.6.16.22/serial-parport_serial-should-depend-on-serial_8250_pci.patch
new file mode 100644
index 0000000000..6e0e86a566
--- /dev/null
+++ b/releases/2.6.16.22/serial-parport_serial-should-depend-on-serial_8250_pci.patch
@@ -0,0 +1,28 @@
+Date: Sun, 18 Jun 2006 13:05:43 +0100
+From: Russell King <rmk+lkml@arm.linux.org.uk>
+To: Andrey Borzenkov <arvidjaar@mail.ru>
+Subject: SERIAL: PARPORT_SERIAL should depend on SERIAL_8250_PCI
+
+Since parport_serial uses symbols from 8250_pci, there should
+be a dependency between the configuration symbols for these
+two modules. Problem reported by Andrey Borzenkov
+
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ drivers/parport/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- linux-2.6.16.21.orig/drivers/parport/Kconfig
++++ linux-2.6.16.21/drivers/parport/Kconfig
+@@ -48,7 +48,7 @@ config PARPORT_PC
+
+ config PARPORT_SERIAL
+ tristate "Multi-IO cards (parallel and serial)"
+- depends on SERIAL_8250 && PARPORT_PC && PCI
++ depends on SERIAL_8250_PCI && PARPORT_PC && PCI
+ help
+ This adds support for multi-IO PCI cards that have parallel and
+ serial ports. You should say Y or M here. If you say M, the module
diff --git a/releases/2.6.16.22/series b/releases/2.6.16.22/series
new file mode 100644
index 0000000000..8c8a3b1e25
--- /dev/null
+++ b/releases/2.6.16.22/series
@@ -0,0 +1,13 @@
+usb-whiteheat-fix-firmware-spurious-errors.patch
+sparc64-fix-d-cache-corruption-in-mremap.patch
+sparc64-respect-gfp_t-argument-to-dma_alloc_coherent.patch
+sparc64-fix-missing-fold-at-end-of-checksums.patch
+missed-error-checking-for-intent-s-filp-in-open_namei.patch
+tmpfs-time-granularity-fix-for-time-going-backwards.patch
+serial-parport_serial-should-depend-on-serial_8250_pci.patch
+fs-namei.c-call-to-file_permission-under-a-spinlock-in-do_lookup_path.patch
+jfs-fix-multiple-errors-in-metapage_releasepage.patch
+scsi_lib.c-properly-count-the-number-of-pages-in-scsi_req_map_sg.patch
+i2o-bugfixes-to-get-i2o-working-again.patch
+powernow-k8-crash-workaround.patch
+ntfs-critical-bug-fix.patch
diff --git a/releases/2.6.16.22/sparc64-fix-d-cache-corruption-in-mremap.patch b/releases/2.6.16.22/sparc64-fix-d-cache-corruption-in-mremap.patch
new file mode 100644
index 0000000000..d18338640b
--- /dev/null
+++ b/releases/2.6.16.22/sparc64-fix-d-cache-corruption-in-mremap.patch
@@ -0,0 +1,95 @@
+From stable-bounces@linux.kernel.org Fri Jun 2 18:34:53 2006
+Date: Fri, 02 Jun 2006 18:30:58 -0700 (PDT)
+From: David Miller <davem@davemloft.net>
+To: stable@kernel.org
+Cc:
+Subject: SPARC64: Fix D-cache corruption in mremap
+
+If we move a mapping from one virtual address to another,
+and this changes the virtual color of the mapping to those
+pages, we can see corrupt data due to D-cache aliasing.
+
+Check for and deal with this by overriding the move_pte()
+macro. Set things up so that other platforms can cleanly
+override the move_pte() macro too.
+
+This long standing bug corrupts user memory, and in particular
+has been notorious for corrupting Debian package database
+files on sparc64 boxes.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ include/asm-generic/pgtable.h | 11 +----------
+ include/asm-mips/pgtable.h | 10 +++++++++-
+ include/asm-sparc64/pgtable.h | 17 +++++++++++++++++
+ 3 files changed, 27 insertions(+), 11 deletions(-)
+
+--- linux-2.6.16.21.orig/include/asm-generic/pgtable.h
++++ linux-2.6.16.21/include/asm-generic/pgtable.h
+@@ -159,17 +159,8 @@ static inline void ptep_set_wrprotect(st
+ #define lazy_mmu_prot_update(pte) do { } while (0)
+ #endif
+
+-#ifndef __HAVE_ARCH_MULTIPLE_ZERO_PAGE
++#ifndef __HAVE_ARCH_MOVE_PTE
+ #define move_pte(pte, prot, old_addr, new_addr) (pte)
+-#else
+-#define move_pte(pte, prot, old_addr, new_addr) \
+-({ \
+- pte_t newpte = (pte); \
+- if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
+- pte_page(pte) == ZERO_PAGE(old_addr)) \
+- newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
+- newpte; \
+-})
+ #endif
+
+ /*
+--- linux-2.6.16.21.orig/include/asm-mips/pgtable.h
++++ linux-2.6.16.21/include/asm-mips/pgtable.h
+@@ -70,7 +70,15 @@ extern unsigned long zero_page_mask;
+ #define ZERO_PAGE(vaddr) \
+ (virt_to_page(empty_zero_page + (((unsigned long)(vaddr)) & zero_page_mask)))
+
+-#define __HAVE_ARCH_MULTIPLE_ZERO_PAGE
++#define __HAVE_ARCH_MOVE_PTE
++#define move_pte(pte, prot, old_addr, new_addr) \
++({ \
++ pte_t newpte = (pte); \
++ if (pte_present(pte) && pfn_valid(pte_pfn(pte)) && \
++ pte_page(pte) == ZERO_PAGE(old_addr)) \
++ newpte = mk_pte(ZERO_PAGE(new_addr), (prot)); \
++ newpte; \
++})
+
+ extern void paging_init(void);
+
+--- linux-2.6.16.21.orig/include/asm-sparc64/pgtable.h
++++ linux-2.6.16.21/include/asm-sparc64/pgtable.h
+@@ -335,6 +335,23 @@ static inline void set_pte_at(struct mm_
+ #define pte_clear(mm,addr,ptep) \
+ set_pte_at((mm), (addr), (ptep), __pte(0UL))
+
++#ifdef DCACHE_ALIASING_POSSIBLE
++#define __HAVE_ARCH_MOVE_PTE
++#define move_pte(pte, prot, old_addr, new_addr) \
++({ \
++ pte_t newpte = (pte); \
++ if (pte_present(pte)) { \
++ unsigned long this_pfn = pte_pfn(pte); \
++ \
++ if (pfn_valid(this_pfn) && \
++ (((old_addr) ^ (new_addr)) & (1 << 13))) \
++ flush_dcache_page_all(current->mm, \
++ pfn_to_page(this_pfn)); \
++ } \
++ newpte; \
++})
++#endif
++
+ extern pgd_t swapper_pg_dir[2048];
+ extern pmd_t swapper_low_pmd_dir[2048];
+
diff --git a/releases/2.6.16.22/sparc64-fix-missing-fold-at-end-of-checksums.patch b/releases/2.6.16.22/sparc64-fix-missing-fold-at-end-of-checksums.patch
new file mode 100644
index 0000000000..a202573dde
--- /dev/null
+++ b/releases/2.6.16.22/sparc64-fix-missing-fold-at-end-of-checksums.patch
@@ -0,0 +1,56 @@
+From stable-bounces@linux.kernel.org Mon Jun 5 11:30:48 2006
+Date: Mon, 05 Jun 2006 11:27:10 -0700 (PDT)
+From: David Miller <davem@davemloft.net>
+To: stable@kernel.org
+Cc:
+Subject: SPARC64: Fix missing fold at end of checksums.
+
+Both csum_partial() and the csum_partial_copy*() family of routines
+forget to do a final fold on the computed checksum value on sparc64.
+So do the standard Sparc "add + set condition codes, add carry"
+sequence, then make sure the high 32-bits of the return value are
+clear.
+
+Based upon some excellent detective work and debugging done by
+Richard Braun and Samuel Thibault.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ arch/sparc64/lib/checksum.S | 5 +++--
+ arch/sparc64/lib/csum_copy.S | 5 +++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+--- linux-2.6.16.21.orig/arch/sparc64/lib/checksum.S
++++ linux-2.6.16.21/arch/sparc64/lib/checksum.S
+@@ -165,8 +165,9 @@ csum_partial_end_cruft:
+ sll %g1, 8, %g1
+ or %o5, %g1, %o4
+
+-1: add %o2, %o4, %o2
++1: addcc %o2, %o4, %o2
++ addc %g0, %o2, %o2
+
+ csum_partial_finish:
+ retl
+- mov %o2, %o0
++ srl %o2, 0, %o0
+--- linux-2.6.16.21.orig/arch/sparc64/lib/csum_copy.S
++++ linux-2.6.16.21/arch/sparc64/lib/csum_copy.S
+@@ -221,11 +221,12 @@ FUNC_NAME: /* %o0=src, %o1=dst, %o2=len
+ sll %g1, 8, %g1
+ or %o5, %g1, %o4
+
+-1: add %o3, %o4, %o3
++1: addcc %o3, %o4, %o3
++ addc %g0, %o3, %o3
+
+ 70:
+ retl
+- mov %o3, %o0
++ srl %o3, 0, %o0
+
+ 95: mov 0, GLOBAL_SPARE
+ brlez,pn %o2, 4f
diff --git a/releases/2.6.16.22/sparc64-respect-gfp_t-argument-to-dma_alloc_coherent.patch b/releases/2.6.16.22/sparc64-respect-gfp_t-argument-to-dma_alloc_coherent.patch
new file mode 100644
index 0000000000..8713bafd72
--- /dev/null
+++ b/releases/2.6.16.22/sparc64-respect-gfp_t-argument-to-dma_alloc_coherent.patch
@@ -0,0 +1,226 @@
+From stable-bounces@linux.kernel.org Sun Jun 4 20:44:37 2006
+Date: Sun, 04 Jun 2006 20:41:00 -0700 (PDT)
+From: David Miller <davem@davemloft.net>
+To: stable@kernel.org
+Cc:
+Subject: SPARC64: Respect gfp_t argument to dma_alloc_coherent().
+
+Using asm-generic/dma-mapping.h does not work because pushing
+the call down to pci_alloc_coherent() causes the gfp_t argument
+of dma_alloc_coherent() to be ignored.
+
+Fix this by implementing things directly, and adding a gfp_t
+argument we can use in the internal call down to the PCI DMA
+implementation of pci_alloc_coherent().
+
+This fixes massive memory corruption when using the sound driver
+layer, which passes things like __GFP_COMP down into these
+routines and (correctly) expects that to work.
+
+This is a disk eater when sound is used, so it's pretty critical.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+ arch/sparc64/kernel/pci_iommu.c | 4 -
+ arch/sparc64/kernel/sparc64_ksyms.c | 2
+ include/asm-sparc64/dma-mapping.h | 141 +++++++++++++++++++++++++++++++++++-
+ include/asm-sparc64/pci.h | 4 -
+ 4 files changed, 146 insertions(+), 5 deletions(-)
+
+--- linux-2.6.16.21.orig/arch/sparc64/kernel/pci_iommu.c
++++ linux-2.6.16.21/arch/sparc64/kernel/pci_iommu.c
+@@ -219,7 +219,7 @@ static inline void iommu_free_ctx(struct
+ * DMA for PCI device PDEV. Return non-NULL cpu-side address if
+ * successful and set *DMA_ADDRP to the PCI side dma address.
+ */
+-void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
++void *__pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
+ {
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+@@ -233,7 +233,7 @@ void *pci_alloc_consistent(struct pci_de
+ if (order >= 10)
+ return NULL;
+
+- first_page = __get_free_pages(GFP_ATOMIC, order);
++ first_page = __get_free_pages(gfp, order);
+ if (first_page == 0UL)
+ return NULL;
+ memset((char *)first_page, 0, PAGE_SIZE << order);
+--- linux-2.6.16.21.orig/arch/sparc64/kernel/sparc64_ksyms.c
++++ linux-2.6.16.21/arch/sparc64/kernel/sparc64_ksyms.c
+@@ -221,7 +221,7 @@ EXPORT_SYMBOL(insl);
+ EXPORT_SYMBOL(ebus_chain);
+ EXPORT_SYMBOL(isa_chain);
+ EXPORT_SYMBOL(pci_memspace_mask);
+-EXPORT_SYMBOL(pci_alloc_consistent);
++EXPORT_SYMBOL(__pci_alloc_consistent);
+ EXPORT_SYMBOL(pci_free_consistent);
+ EXPORT_SYMBOL(pci_map_single);
+ EXPORT_SYMBOL(pci_unmap_single);
+--- linux-2.6.16.21.orig/include/asm-sparc64/dma-mapping.h
++++ linux-2.6.16.21/include/asm-sparc64/dma-mapping.h
+@@ -4,7 +4,146 @@
+ #include <linux/config.h>
+
+ #ifdef CONFIG_PCI
+-#include <asm-generic/dma-mapping.h>
++
++/* we implement the API below in terms of the existing PCI one,
++ * so include it */
++#include <linux/pci.h>
++/* need struct page definitions */
++#include <linux/mm.h>
++
++static inline int
++dma_supported(struct device *dev, u64 mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_dma_supported(to_pci_dev(dev), mask);
++}
++
++static inline int
++dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
++}
++
++static inline void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
++ gfp_t flag)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return __pci_alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
++}
++
++static inline void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t dma_handle)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
++}
++
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
++}
++
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
++}
++
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
++}
++
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
++}
++
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
++}
++
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
++ size, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
++ enum dma_data_direction direction)
++{
++ BUG_ON(dev->bus != &pci_bus_type);
++
++ pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
++}
++
++static inline int
++dma_mapping_error(dma_addr_t dma_addr)
++{
++ return pci_dma_mapping_error(dma_addr);
++}
++
+ #else
+
+ struct device;
+--- linux-2.6.16.21.orig/include/asm-sparc64/pci.h
++++ linux-2.6.16.21/include/asm-sparc64/pci.h
+@@ -44,7 +44,9 @@ struct pci_dev;
+ /* Allocate and map kernel buffer using consistent mode DMA for a device.
+ * hwdev should be valid struct pci_dev pointer for PCI devices.
+ */
+-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
++extern void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp);
++#define pci_alloc_consistent(DEV,SZ,HANDLE) \
++ __pci_alloc_consistent(DEV,SZ,HANDLE,GFP_ATOMIC)
+
+ /* Free and unmap a consistent DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistent,
diff --git a/releases/2.6.16.22/tmpfs-time-granularity-fix-for-time-going-backwards.patch b/releases/2.6.16.22/tmpfs-time-granularity-fix-for-time-going-backwards.patch
new file mode 100644
index 0000000000..7a627f6be4
--- /dev/null
+++ b/releases/2.6.16.22/tmpfs-time-granularity-fix-for-time-going-backwards.patch
@@ -0,0 +1,45 @@
+From hugh_dickins@symantec.com Tue Jun 13 10:08:40 2006
+Date: Tue, 13 Jun 2006 18:06:11 +0100 (BST)
+From: Hugh Dickins <hugh@veritas.com>
+To: Chris Wright <chrisw@sous-sol.org>
+cc: "Robin H. Johnson" <robbat2@gentoo.org>, Andi Kleen <ak@suse.de>, stable@kernel.org
+Subject: tmpfs: time granularity fix for [acm]time going backwards
+
+From: Robin H. Johnson <robbat2@gentoo.org>
+
+I noticed a strange behavior in a tmpfs file system the other day, while
+building packages - occasionally, and seemingly at random, make decided to
+rebuild a target. However, only on tmpfs.
+
+A file would be created, and if checked, it had a sub-second timestamp.
+However, after an utimes related call where sub-seconds should be set, they
+were zeroed instead. In the case that a file was created, and utimes(...,NULL)
+was used on it in the same second, the timestamp on the file moved backwards.
+
+After some digging, I found that this was being caused by tmpfs not having a
+time granularity set, thus inheriting the default 1 second granularity.
+
+Hugh adds: yes, we missed tmpfs when the s_time_gran mods went into 2.6.11.
+Unfortunately, the granularity of CURRENT_TIME, often used in filesystems,
+does not match the default granularity set by alloc_super. A few more such
+discrepancies have been found, but this is the most important to fix now.
+
+Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
+Acked-by: Andi Kleen <ak@suse.de>
+Signed-off-by: Hugh Dickins <hugh@veritas.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ mm/shmem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- linux-2.6.16.21.orig/mm/shmem.c
++++ linux-2.6.16.21/mm/shmem.c
+@@ -2100,6 +2100,7 @@ static int shmem_fill_super(struct super
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+ sb->s_magic = TMPFS_MAGIC;
+ sb->s_op = &shmem_ops;
++ sb->s_time_gran = 1;
+
+ inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
+ if (!inode)
diff --git a/releases/2.6.16.22/usb-whiteheat-fix-firmware-spurious-errors.patch b/releases/2.6.16.22/usb-whiteheat-fix-firmware-spurious-errors.patch
new file mode 100644
index 0000000000..189e049d69
--- /dev/null
+++ b/releases/2.6.16.22/usb-whiteheat-fix-firmware-spurious-errors.patch
@@ -0,0 +1,36 @@
+From stuartm@connecttech.com Wed May 31 10:40:58 2006
+From: "Stuart MacDonald" <stuartm@connecttech.com>
+To: <greg@kroah.com>
+Subject: USB: Whiteheat: fix firmware spurious errors
+Date: Wed, 31 May 2006 13:28:40 -0400
+Message-ID: <02d901c684d7$a87b8460$294b82ce@stuartm>
+
+Attached patch fixes spurious errors during firmware load.
+
+Signed-off-by: Stuart MacDonald <stuartm@connecttech.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ drivers/usb/serial/whiteheat.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- linux-2.6.16.21.orig/drivers/usb/serial/whiteheat.c
++++ linux-2.6.16.21/drivers/usb/serial/whiteheat.c
+@@ -388,7 +388,7 @@ static int whiteheat_attach (struct usb_
+ if (ret) {
+ err("%s: Couldn't send command [%d]", serial->type->description, ret);
+ goto no_firmware;
+- } else if (alen != sizeof(command)) {
++ } else if (alen != 2) {
+ err("%s: Send command incomplete [%d]", serial->type->description, alen);
+ goto no_firmware;
+ }
+@@ -400,7 +400,7 @@ static int whiteheat_attach (struct usb_
+ if (ret) {
+ err("%s: Couldn't get results [%d]", serial->type->description, ret);
+ goto no_firmware;
+- } else if (alen != sizeof(result)) {
++ } else if (alen != sizeof(*hw_info) + 1) {
+ err("%s: Get results incomplete [%d]", serial->type->description, alen);
+ goto no_firmware;
+ } else if (result[0] != command[0]) {