summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-08-01 11:58:34 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-08-01 11:58:34 -0700
commit3a1f5780a14fa700a0b186391a65c6d1aed8e8d9 (patch)
tree541bc07ff796dd26a1683ecc6a97827c65c6f6bd
parent8cb4c7c14e758ea1e1a2209d45a7444a13752f62 (diff)
downloadstable-queue-3a1f5780a14fa700a0b186391a65c6d1aed8e8d9.tar.gz
2.6.39 patches
-rw-r--r--queue-2.6.39/cifs-clean-up-wsize-negotiation-and-allow-for-larger-wsize.patch126
-rw-r--r--queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch89
-rw-r--r--queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch71
-rw-r--r--queue-2.6.39/davinci-dm365-evm-fix-video-input-mux-bits.patch43
-rw-r--r--queue-2.6.39/ext4-fix-oops-in-ext4_quota_off.patch39
-rw-r--r--queue-2.6.39/libata-fix-unexpectedly-frozen-port-after-ata_eh_reset.patch70
-rw-r--r--queue-2.6.39/mm-compaction-abort-compaction-if-too-many-pages-are-isolated-and-caller-is-asynchronous-v2.patch114
-rw-r--r--queue-2.6.39/mm-compaction-ensure-that-the-compaction-free-scanner-does-not-move-to-the-next-zone.patch70
-rw-r--r--queue-2.6.39/mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.patch85
-rw-r--r--queue-2.6.39/mm-vmscan-do-not-use-page_count-without-a-page-pin.patch54
-rw-r--r--queue-2.6.39/mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch129
-rw-r--r--queue-2.6.39/revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch1185
-rw-r--r--queue-2.6.39/series16
-rw-r--r--queue-2.6.39/vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch50
-rw-r--r--queue-2.6.39/vmscan-fix-a-livelock-in-kswapd.patch49
-rw-r--r--queue-2.6.39/x86-make-dell-latitude-e5420-use-reboot-pci.patch43
-rw-r--r--queue-2.6.39/xfs-restart-busy-extent-search-after-node-removal.patch65
17 files changed, 2298 insertions, 0 deletions
diff --git a/queue-2.6.39/cifs-clean-up-wsize-negotiation-and-allow-for-larger-wsize.patch b/queue-2.6.39/cifs-clean-up-wsize-negotiation-and-allow-for-larger-wsize.patch
new file mode 100644
index 0000000000..f246e945ae
--- /dev/null
+++ b/queue-2.6.39/cifs-clean-up-wsize-negotiation-and-allow-for-larger-wsize.patch
@@ -0,0 +1,126 @@
+From f7910cbd9fa319ee4501074f1f3b5ce23c4b1518 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Thu, 19 May 2011 16:22:58 -0400
+Subject: cifs: clean up wsize negotiation and allow for larger wsize
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit f7910cbd9fa319ee4501074f1f3b5ce23c4b1518 upstream.
+
+Now that we can handle larger wsizes in writepages, fix up the
+negotiation of the wsize to allow for that. find_get_pages only seems to
+give out a max of 256 pages at a time, so that gives us a reasonable
+default of 1M for the wsize.
+
+If the server however does not support large writes via POSIX
+extensions, then we cap the wsize to (128k - PAGE_CACHE_SIZE). That
+gives us a size that goes up to the max frame size specified in RFC1001.
+
+Finally, if CAP_LARGE_WRITE_AND_X isn't set, then further cap it to the
+largest size allowed by the protocol (USHRT_MAX).
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Reviewed-and-Tested-by: Pavel Shilovsky <piastry@etersoft.ru>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/cifs/connect.c | 69 ++++++++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 49 insertions(+), 20 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -2571,23 +2571,6 @@ static void setup_cifs_sb(struct smb_vol
+ else /* default */
+ cifs_sb->rsize = CIFSMaxBufSize;
+
+- if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+- cERROR(1, "wsize %d too large, using 4096 instead",
+- pvolume_info->wsize);
+- cifs_sb->wsize = 4096;
+- } else if (pvolume_info->wsize)
+- cifs_sb->wsize = pvolume_info->wsize;
+- else
+- cifs_sb->wsize = min_t(const int,
+- PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+- 127*1024);
+- /* old default of CIFSMaxBufSize was too small now
+- that SMB Write2 can send multiple pages in kvec.
+- RFC1001 does not describe what happens when frame
+- bigger than 128K is sent so use that as max in
+- conjunction with 52K kvec constraint on arch with 4K
+- page size */
+-
+ if (cifs_sb->rsize < 2048) {
+ cifs_sb->rsize = 2048;
+ /* Windows ME may prefer this */
+@@ -2665,6 +2648,53 @@ static void setup_cifs_sb(struct smb_vol
+ "mount option supported");
+ }
+
++/*
++ * When the server supports very large writes via POSIX extensions, we can
++ * allow up to 2^24 - PAGE_CACHE_SIZE.
++ *
++ * Note that this might make for "interesting" allocation problems during
++ * writeback however (as we have to allocate an array of pointers for the
++ * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
++ */
++#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE)
++
++/*
++ * When the server doesn't allow large posix writes, default to a wsize of
++ * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size
++ * described in RFC1001. This allows space for the header without going over
++ * that by default.
++ */
++#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE)
++
++/*
++ * The default wsize is 1M. find_get_pages seems to return a maximum of 256
++ * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
++ * a single wsize request with a single call.
++ */
++#define CIFS_DEFAULT_WSIZE (1024 * 1024)
++
++static unsigned int
++cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
++{
++ __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
++ struct TCP_Server_Info *server = tcon->ses->server;
++ unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
++ CIFS_DEFAULT_WSIZE;
++
++ /* can server support 24-bit write sizes? (via UNIX extensions) */
++ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
++ wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE);
++
++ /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */
++ if (!(server->capabilities & CAP_LARGE_WRITE_X))
++ wsize = min_t(unsigned int, wsize, USHRT_MAX);
++
++ /* hard limit of CIFS_MAX_WSIZE */
++ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
++
++ return wsize;
++}
++
+ static int
+ is_path_accessible(int xid, struct cifsTconInfo *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path)
+@@ -2866,13 +2896,12 @@ try_mount_again:
+ cifs_sb->rsize = 1024 * 127;
+ cFYI(DBG2, "no very large read support, rsize now 127K");
+ }
+- if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
+- cifs_sb->wsize = min(cifs_sb->wsize,
+- (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
+ cifs_sb->rsize = min(cifs_sb->rsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+
++ cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
++
+ remote_path_check:
+ /* check if a whole path (including prepath) is not remote */
+ if (!rc && tcon) {
diff --git a/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch b/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
new file mode 100644
index 0000000000..8f0d31868f
--- /dev/null
+++ b/queue-2.6.39/cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
@@ -0,0 +1,89 @@
+From 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Wed, 22 Jun 2011 17:33:57 -0400
+Subject: cifs: fix wsize negotiation to respect max buffer size and
+ active signing (try #4)
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 1190f6a067bf27b2ee7e06ec0776a17fe0f6c4d8 upstream.
+
+Hopefully last version. Base signing check on CAP_UNIX instead of
+tcon->unix_ext, also clean up the comments a bit more.
+
+According to Hongwei Sun's blog posting here:
+
+ http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
+
+CAP_LARGE_WRITEX is ignored when signing is active. Also, the maximum
+size for a write without CAP_LARGE_WRITEX should be the maxBuf that
+the server sent in the NEGOTIATE request.
+
+Fix the wsize negotiation to take this into account. While we're at it,
+alter the other wsize definitions to use sizeof(WRITE_REQ) to allow for
+slightly larger amounts of data to potentially be written per request.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/cifs/connect.c | 33 ++++++++++++++++++++-------------
+ 1 file changed, 20 insertions(+), 13 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -2650,21 +2650,21 @@ static void setup_cifs_sb(struct smb_vol
+
+ /*
+ * When the server supports very large writes via POSIX extensions, we can
+- * allow up to 2^24 - PAGE_CACHE_SIZE.
++ * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
++ * the RFC1001 length.
+ *
+ * Note that this might make for "interesting" allocation problems during
+- * writeback however (as we have to allocate an array of pointers for the
+- * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
++ * writeback however as we have to allocate an array of pointers for the
++ * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
+ */
+-#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE)
++#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
+
+ /*
+- * When the server doesn't allow large posix writes, default to a wsize of
+- * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size
+- * described in RFC1001. This allows space for the header without going over
+- * that by default.
++ * When the server doesn't allow large posix writes, only allow a wsize of
++ * 128k minus the size of the WRITE_AND_X header. That allows for a write up
++ * to the maximum size described by RFC1002.
+ */
+-#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE)
++#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
+
+ /*
+ * The default wsize is 1M. find_get_pages seems to return a maximum of 256
+@@ -2683,11 +2683,18 @@ cifs_negotiate_wsize(struct cifsTconInfo
+
+ /* can server support 24-bit write sizes? (via UNIX extensions) */
+ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+- wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE);
++ wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
+
+- /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */
+- if (!(server->capabilities & CAP_LARGE_WRITE_X))
+- wsize = min_t(unsigned int, wsize, USHRT_MAX);
++ /*
++ * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
++ * Limit it to max buffer offered by the server, minus the size of the
++ * WRITEX header, not including the 4 byte RFC1001 length.
++ */
++ if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
++ (!(server->capabilities & CAP_UNIX) &&
++ (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
++ wsize = min_t(unsigned int, wsize,
++ server->maxBuf - sizeof(WRITE_REQ) + 4);
+
+ /* hard limit of CIFS_MAX_WSIZE */
+ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
diff --git a/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch b/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch
new file mode 100644
index 0000000000..7c9705bb9d
--- /dev/null
+++ b/queue-2.6.39/cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch
@@ -0,0 +1,71 @@
+From jlayton@redhat.com Mon Aug 1 11:49:28 2011
+From: Jeff Layton <jlayton@redhat.com>
+Date: Wed, 13 Jul 2011 06:40:37 -0400
+Subject: cifs: lower default and max wsize to what 2.6.39 can handle
+To: stable@kernel.org
+Cc: linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org, helge.hafting@hist.no
+Message-ID: <1310553637-26792-1-git-send-email-jlayton@redhat.com>
+
+From: Jeff Layton <jlayton@redhat.com>
+
+This patch is intended for 2.6.39-stable kernels only and is needed to
+fix a regression introduced in 2.6.39. Prior to 2.6.39, when signing was
+enabled on a socket the client only sent single-page writes. This
+changed with commit ca83ce3, which made signed and unsigned connections
+use the same codepaths for write calls.
+
+This caused a regression when working with windows servers. Windows
+machines will reject writes larger than the MaxBufferSize when signing
+is active, but do not clear the CAP_LARGE_WRITE_X flag in the protocol
+negotiation. The upshot is that when signing is active, windows servers
+often reject large writes from the client in 2.6.39.
+
+Because 3.0 adds support for larger wsize values, simply cherry picking
+the upstream patches that fix the wsize negotiation isn't sufficient to
+fix this issue. We also need to alter the maximum and default values to
+something suitable for 2.6.39.
+
+Cc: <stable@kernel.org> # .39.x: f7910cb: cifs: clean up wsize negotiation and allow for larger wsize
+Cc: <stable@kernel.org> # .39.x: 1190f6a: cifs: fix wsize negotiation to respect max buffer size and active signing (try #4)
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ fs/cifs/connect.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -2648,16 +2648,8 @@ static void setup_cifs_sb(struct smb_vol
+ "mount option supported");
+ }
+
+-/*
+- * When the server supports very large writes via POSIX extensions, we can
+- * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
+- * the RFC1001 length.
+- *
+- * Note that this might make for "interesting" allocation problems during
+- * writeback however as we have to allocate an array of pointers for the
+- * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
+- */
+-#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
++/* Prior to 3.0, cifs couldn't handle writes larger than this */
++#define CIFS_MAX_WSIZE (PAGEVEC_SIZE * PAGE_CACHE_SIZE)
+
+ /*
+ * When the server doesn't allow large posix writes, only allow a wsize of
+@@ -2666,12 +2658,8 @@ static void setup_cifs_sb(struct smb_vol
+ */
+ #define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
+
+-/*
+- * The default wsize is 1M. find_get_pages seems to return a maximum of 256
+- * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill
+- * a single wsize request with a single call.
+- */
+-#define CIFS_DEFAULT_WSIZE (1024 * 1024)
++/* Make the default the same as the max */
++#define CIFS_DEFAULT_WSIZE CIFS_MAX_WSIZE
+
+ static unsigned int
+ cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
diff --git a/queue-2.6.39/davinci-dm365-evm-fix-video-input-mux-bits.patch b/queue-2.6.39/davinci-dm365-evm-fix-video-input-mux-bits.patch
new file mode 100644
index 0000000000..24336ebd9b
--- /dev/null
+++ b/queue-2.6.39/davinci-dm365-evm-fix-video-input-mux-bits.patch
@@ -0,0 +1,43 @@
+From 9daedd833a38edd90cf7baa1b1fcf61c3a0721e3 Mon Sep 17 00:00:00 2001
+From: Jon Povey <jon.povey@racelogic.co.uk>
+Date: Tue, 19 Jul 2011 12:30:11 +0900
+Subject: davinci: DM365 EVM: fix video input mux bits
+
+From: Jon Povey <jon.povey@racelogic.co.uk>
+
+commit 9daedd833a38edd90cf7baa1b1fcf61c3a0721e3 upstream.
+
+Video input mux settings for tvp7002 and imager inputs were swapped.
+Comment was correct.
+
+Tested on EVM with tvp7002 input.
+
+Signed-off-by: Jon Povey <jon.povey@racelogic.co.uk>
+Acked-by: Manjunath Hadli <manjunath.hadli@ti.com>
+Signed-off-by: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/arm/mach-davinci/board-dm365-evm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-davinci/board-dm365-evm.c
++++ b/arch/arm/mach-davinci/board-dm365-evm.c
+@@ -520,7 +520,7 @@ fail:
+ */
+ if (have_imager()) {
+ label = "HD imager";
+- mux |= 1;
++ mux |= 2;
+
+ /* externally mux MMC1/ENET/AIC33 to imager */
+ mux |= BIT(6) | BIT(5) | BIT(3);
+@@ -540,7 +540,7 @@ fail:
+ resets &= ~BIT(1);
+
+ if (have_tvp7002()) {
+- mux |= 2;
++ mux |= 1;
+ resets &= ~BIT(2);
+ label = "tvp7002 HD";
+ } else {
diff --git a/queue-2.6.39/ext4-fix-oops-in-ext4_quota_off.patch b/queue-2.6.39/ext4-fix-oops-in-ext4_quota_off.patch
new file mode 100644
index 0000000000..df7d4a89bc
--- /dev/null
+++ b/queue-2.6.39/ext4-fix-oops-in-ext4_quota_off.patch
@@ -0,0 +1,39 @@
+From 0b26859027ce0005ef89520af20351360e51ad76 Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Mon, 16 May 2011 09:59:13 -0400
+Subject: ext4: fix oops in ext4_quota_off()
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+commit 0b26859027ce0005ef89520af20351360e51ad76 upstream.
+
+If quota is not enabled when ext4_quota_off() is called, we must not
+dereference quota file inode since it is NULL. Check properly for
+this.
+
+This fixes a bug in commit 21f976975cbe (ext4: remove unnecessary
+[cm]time update of quota file), which was merged for 2.6.39-rc3.
+
+Reported-by: Amir Goldstein <amir73il@users.sf.net>
+Signed-off-by: Amir Goldstein <amir73il@users.sf.net>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Cc: Chris Dunlop <chris@onthe.net.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext4/super.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -4635,6 +4635,9 @@ static int ext4_quota_off(struct super_b
+ if (test_opt(sb, DELALLOC))
+ sync_filesystem(sb);
+
++ if (!inode)
++ goto out;
++
+ /* Update modification times of quota files when userspace can
+ * start looking at them */
+ handle = ext4_journal_start(inode, 1);
diff --git a/queue-2.6.39/libata-fix-unexpectedly-frozen-port-after-ata_eh_reset.patch b/queue-2.6.39/libata-fix-unexpectedly-frozen-port-after-ata_eh_reset.patch
new file mode 100644
index 0000000000..01d3819f72
--- /dev/null
+++ b/queue-2.6.39/libata-fix-unexpectedly-frozen-port-after-ata_eh_reset.patch
@@ -0,0 +1,70 @@
+From 8c56cacc724c7650b893d43068fa66044aa29a61 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Wed, 25 May 2011 13:19:39 +0200
+Subject: libata: fix unexpectedly frozen port after ata_eh_reset()
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 8c56cacc724c7650b893d43068fa66044aa29a61 upstream.
+
+To work around controllers which can't properly plug events while
+reset, ata_eh_reset() clears error states and ATA_PFLAG_EH_PENDING
+after reset but before RESET is marked done. As reset is the final
+recovery action and full verification of devices including onlineness
+and classfication match is done afterwards, this shouldn't lead to
+lost devices or missed hotplug events.
+
+Unfortunately, it forgot to thaw the port when clearing EH_PENDING, so
+if the condition happens after resetting an empty port, the port could
+be left frozen and EH will end without thawing it, making the port
+unresponsive to further hotplug events.
+
+Thaw if the port is frozen after clearing EH_PENDING. This problem is
+reported by Bruce Stenning in the following thread.
+
+ http://thread.gmane.org/gmane.linux.kernel/1123265
+
+stable: I think we should weather this patch a bit longer in -rcX
+ before sending it to -stable. Please wait at least a month
+ after this patch makes upstream. Thanks.
+
+-v2: Fixed spelling in the comment per Dave Howorth.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Bruce Stenning <b.stenning@indigovision.com>
+Cc: Dave Howorth <dhoworth@mrc-lmb.cam.ac.uk>
+Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-eh.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -2802,10 +2802,11 @@ int ata_eh_reset(struct ata_link *link,
+ }
+
+ /*
+- * Some controllers can't be frozen very well and may set
+- * spuruious error conditions during reset. Clear accumulated
+- * error information. As reset is the final recovery action,
+- * nothing is lost by doing this.
++ * Some controllers can't be frozen very well and may set spurious
++ * error conditions during reset. Clear accumulated error
++ * information and re-thaw the port if frozen. As reset is the
++ * final recovery action and we cross check link onlineness against
++ * device classification later, no hotplug event is lost by this.
+ */
+ spin_lock_irqsave(link->ap->lock, flags);
+ memset(&link->eh_info, 0, sizeof(link->eh_info));
+@@ -2814,6 +2815,9 @@ int ata_eh_reset(struct ata_link *link,
+ ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+ spin_unlock_irqrestore(link->ap->lock, flags);
+
++ if (ap->pflags & ATA_PFLAG_FROZEN)
++ ata_eh_thaw_port(ap);
++
+ /*
+ * Make sure onlineness and classification result correspond.
+ * Hotplug could have happened during reset and some
diff --git a/queue-2.6.39/mm-compaction-abort-compaction-if-too-many-pages-are-isolated-and-caller-is-asynchronous-v2.patch b/queue-2.6.39/mm-compaction-abort-compaction-if-too-many-pages-are-isolated-and-caller-is-asynchronous-v2.patch
new file mode 100644
index 0000000000..1f9abe66a8
--- /dev/null
+++ b/queue-2.6.39/mm-compaction-abort-compaction-if-too-many-pages-are-isolated-and-caller-is-asynchronous-v2.patch
@@ -0,0 +1,114 @@
+From mgorman@suse.de Mon Aug 1 11:42:31 2011
+From: Mel Gorman <mgorman@suse.de>
+Date: Tue, 19 Jul 2011 10:15:51 +0100
+Subject: [stable] [PATCH 3/3] mm: compaction: abort compaction if too many pages are isolated and caller is asynchronous V2
+To: stable@kernel.org
+Cc: Andrea Arcangeli <aarcange@redhat.com>, Andrew Morton <akpm@linux-foundation.org>, Thomas Sattler <tsattler@gmx.de>, Mel Gorman <mgorman@suse.de>
+Message-ID: <1311066951-25546-4-git-send-email-mgorman@suse.de>
+
+From: Mel Gorman <mgorman@suse.de>
+
+commit: f9e35b3b41f47c4e17d8132edbcab305a6aaa4b0 upstream
+
+Asynchronous compaction is used when promoting to huge pages. This is all
+very nice but if there are a number of processes in compacting memory, a
+large number of pages can be isolated. An "asynchronous" process can
+stall for long periods of time as a result with a user reporting that
+firefox can stall for 10s of seconds. This patch aborts asynchronous
+compaction if too many pages are isolated as it's better to fail a
+hugepage promotion than stall a process.
+
+[minchan.kim@gmail.com: return COMPACT_PARTIAL for abort]
+Reported-and-tested-by: Ury Stankevich <urykhy@gmail.com>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
+Reviewed-by: Michal Hocko <mhocko@suse.cz>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/compaction.c | 29 ++++++++++++++++++++++++-----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -251,11 +251,18 @@ static bool too_many_isolated(struct zon
+ return isolated > (inactive + active) / 2;
+ }
+
++/* possible outcome of isolate_migratepages */
++typedef enum {
++ ISOLATE_ABORT, /* Abort compaction now */
++ ISOLATE_NONE, /* No pages isolated, continue scanning */
++ ISOLATE_SUCCESS, /* Pages isolated, migrate */
++} isolate_migrate_t;
++
+ /*
+ * Isolate all pages that can be migrated from the block pointed to by
+ * the migrate scanner within compact_control.
+ */
+-static unsigned long isolate_migratepages(struct zone *zone,
++static isolate_migrate_t isolate_migratepages(struct zone *zone,
+ struct compact_control *cc)
+ {
+ unsigned long low_pfn, end_pfn;
+@@ -272,7 +279,7 @@ static unsigned long isolate_migratepage
+ /* Do not cross the free scanner or scan within a memory hole */
+ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
+ cc->migrate_pfn = end_pfn;
+- return 0;
++ return ISOLATE_NONE;
+ }
+
+ /*
+@@ -281,10 +288,14 @@ static unsigned long isolate_migratepage
+ * delay for some time until fewer pages are isolated
+ */
+ while (unlikely(too_many_isolated(zone))) {
++ /* async migration should just abort */
++ if (!cc->sync)
++ return ISOLATE_ABORT;
++
+ congestion_wait(BLK_RW_ASYNC, HZ/10);
+
+ if (fatal_signal_pending(current))
+- return 0;
++ return ISOLATE_ABORT;
+ }
+
+ /* Time to isolate some pages for migration */
+@@ -369,7 +380,7 @@ static unsigned long isolate_migratepage
+
+ trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
+
+- return cc->nr_migratepages;
++ return ISOLATE_SUCCESS;
+ }
+
+ /*
+@@ -533,8 +544,15 @@ static int compact_zone(struct zone *zon
+ unsigned long nr_migrate, nr_remaining;
+ int err;
+
+- if (!isolate_migratepages(zone, cc))
++ switch (isolate_migratepages(zone, cc)) {
++ case ISOLATE_ABORT:
++ ret = COMPACT_PARTIAL;
++ goto out;
++ case ISOLATE_NONE:
+ continue;
++ case ISOLATE_SUCCESS:
++ ;
++ }
+
+ nr_migrate = cc->nr_migratepages;
+ err = migrate_pages(&cc->migratepages, compaction_alloc,
+@@ -558,6 +576,7 @@ static int compact_zone(struct zone *zon
+
+ }
+
++out:
+ /* Release free pages and check accounting */
+ cc->nr_freepages -= release_freepages(&cc->freepages);
+ VM_BUG_ON(cc->nr_freepages != 0);
diff --git a/queue-2.6.39/mm-compaction-ensure-that-the-compaction-free-scanner-does-not-move-to-the-next-zone.patch b/queue-2.6.39/mm-compaction-ensure-that-the-compaction-free-scanner-does-not-move-to-the-next-zone.patch
new file mode 100644
index 0000000000..a4a70ba454
--- /dev/null
+++ b/queue-2.6.39/mm-compaction-ensure-that-the-compaction-free-scanner-does-not-move-to-the-next-zone.patch
@@ -0,0 +1,70 @@
+From mgorman@suse.de Mon Aug 1 11:41:52 2011
+From: Mel Gorman <mgorman@suse.de>
+Date: Tue, 19 Jul 2011 10:15:49 +0100
+Subject: mm: compaction: ensure that the compaction free scanner does not move to the next zone
+To: stable@kernel.org
+Cc: Andrea Arcangeli <aarcange@redhat.com>, Andrew Morton <akpm@linux-foundation.org>, Thomas Sattler <tsattler@gmx.de>, Mel Gorman <mgorman@suse.de>
+Message-ID: <1311066951-25546-2-git-send-email-mgorman@suse.de>
+
+From: Mel Gorman <mgorman@suse.de>
+
+commit: 7454f4ba40b419eb999a3c61a99da662bf1a2bb8 upstream
+
+Compaction works with two scanners, a migration and a free scanner. When
+the scanners crossover, migration within the zone is complete. The
+location of the scanner is recorded on each cycle to avoid excesive
+scanning.
+
+When a zone is small and mostly reserved, it's very easy for the migration
+scanner to be close to the end of the zone. Then the following situation
+can occurs
+
+ o migration scanner isolates some pages near the end of the zone
+ o free scanner starts at the end of the zone but finds that the
+ migration scanner is already there
+ o free scanner gets reinitialised for the next cycle as
+ cc->migrate_pfn + pageblock_nr_pages
+ moving the free scanner into the next zone
+ o migration scanner moves into the next zone
+
+When this happens, NR_ISOLATED accounting goes haywire because some of the
+accounting happens against the wrong zone. One zones counter remains
+positive while the other goes negative even though the overall global
+count is accurate. This was reported on X86-32 with !SMP because !SMP
+allows the negative counters to be visible. The fact that it is the bug
+should theoritically be possible there.
+
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
+Reviewed-by: Michal Hocko <mhocko@suse.cz>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ mm/compaction.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -144,9 +144,20 @@ static void isolate_freepages(struct zon
+ int nr_freepages = cc->nr_freepages;
+ struct list_head *freelist = &cc->freepages;
+
++ /*
++ * Initialise the free scanner. The starting point is where we last
++ * scanned from (or the end of the zone if starting). The low point
++ * is the end of the pageblock the migration scanner is using.
++ */
+ pfn = cc->free_pfn;
+ low_pfn = cc->migrate_pfn + pageblock_nr_pages;
+- high_pfn = low_pfn;
++
++ /*
++ * Take care that if the migration scanner is at the end of the zone
++ * that the free scanner does not accidentally move to the next zone
++ * in the next isolation cycle.
++ */
++ high_pfn = min(low_pfn, pfn);
+
+ /*
+ * Isolate free pages until enough are available to migrate the
diff --git a/queue-2.6.39/mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.patch b/queue-2.6.39/mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.patch
new file mode 100644
index 0000000000..2578abbcdc
--- /dev/null
+++ b/queue-2.6.39/mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.patch
@@ -0,0 +1,85 @@
+From mgorman@suse.de Mon Aug 1 11:50:25 2011
+From: Mel Gorman <mgorman@suse.de>
+Date: Mon, 11 Jul 2011 10:11:21 +0100
+Subject: mm: vmscan: do not apply pressure to slab if we are not applying pressure to zone
+To: stable@kernel.org
+Cc: mgorman@suse.de
+Message-ID: <1310375483-31999-3-git-send-email-mgorman@suse.de>
+
+From: Mel Gorman <mgorman@suse.de>
+
+commit d7868dae893c83c50c7824bc2bc75f93d114669f upstream
+
+During allocator-intensive workloads, kswapd will be woken frequently
+causing free memory to oscillate between the high and min watermark. This
+is expected behaviour.
+
+When kswapd applies pressure to zones during node balancing, it checks if
+the zone is above a high+balance_gap threshold. If it is, it does not
+apply pressure but it unconditionally shrinks slab on a global basis which
+is excessive. In the event kswapd is being kept awake due to a high small
+unreclaimable zone, it skips zone shrinking but still calls shrink_slab().
+
+Once pressure has been applied, the check for zone being unreclaimable is
+being made before the check is made if all_unreclaimable should be set.
+This miss of unreclaimable can cause has_under_min_watermark_zone to be
+set due to an unreclaimable zone preventing kswapd backing off on
+congestion_wait().
+
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Reported-by: Pádraig Brady <P@draigBrady.com>
+Tested-by: Pádraig Brady <P@draigBrady.com>
+Tested-by: Andrew Lutomirski <luto@mit.edu>
+Acked-by: Rik van Riel <riel@redhat.com>
+Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
+Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ mm/vmscan.c | 25 ++++++++++++++-----------
+ 1 file changed, 14 insertions(+), 11 deletions(-)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -2449,19 +2449,19 @@ loop_again:
+ KSWAPD_ZONE_BALANCE_GAP_RATIO);
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone) + balance_gap,
+- end_zone, 0))
++ end_zone, 0)) {
+ shrink_zone(priority, zone, &sc);
+- reclaim_state->reclaimed_slab = 0;
+- nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
+- lru_pages);
+- sc.nr_reclaimed += reclaim_state->reclaimed_slab;
+- total_scanned += sc.nr_scanned;
+
+- if (zone->all_unreclaimable)
+- continue;
+- if (nr_slab == 0 &&
+- !zone_reclaimable(zone))
+- zone->all_unreclaimable = 1;
++ reclaim_state->reclaimed_slab = 0;
++ nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
++ lru_pages);
++ sc.nr_reclaimed += reclaim_state->reclaimed_slab;
++ total_scanned += sc.nr_scanned;
++
++ if (nr_slab == 0 && !zone_reclaimable(zone))
++ zone->all_unreclaimable = 1;
++ }
++
+ /*
+ * If we've done a decent amount of scanning and
+ * the reclaim ratio is low, start doing writepage
+@@ -2471,6 +2471,9 @@ loop_again:
+ total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
+ sc.may_writepage = 1;
+
++ if (zone->all_unreclaimable)
++ continue;
++
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone), end_zone, 0)) {
+ all_zones_ok = 0;
diff --git a/queue-2.6.39/mm-vmscan-do-not-use-page_count-without-a-page-pin.patch b/queue-2.6.39/mm-vmscan-do-not-use-page_count-without-a-page-pin.patch
new file mode 100644
index 0000000000..1a85b9e783
--- /dev/null
+++ b/queue-2.6.39/mm-vmscan-do-not-use-page_count-without-a-page-pin.patch
@@ -0,0 +1,54 @@
+From mgorman@suse.de Mon Aug 1 11:42:14 2011
+From: Mel Gorman <mgorman@suse.de>
+Date: Tue, 19 Jul 2011 10:15:50 +0100
+Subject: mm: vmscan: do not use page_count without a page pin
+To: stable@kernel.org
+Cc: Andrea Arcangeli <aarcange@redhat.com>, Andrew Morton <akpm@linux-foundation.org>, Thomas Sattler <tsattler@gmx.de>, Mel Gorman <mgorman@suse.de>
+Message-ID: <1311066951-25546-3-git-send-email-mgorman@suse.de>
+
+
+From: Andrea Arcangeli <aarcange@redhat.com>
+
+commit: d179e84ba5da1d0024087d1759a2938817a00f3f upstream
+
+It is unsafe to run page_count during the physical pfn scan because
+compound_head could trip on a dangling pointer when reading
+page->first_page if the compound page is being freed by another CPU.
+
+[mgorman@suse.de: split out patch]
+Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Reviewed-by: Michal Hocko <mhocko@suse.cz>
+Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ mm/vmscan.c | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -1114,8 +1114,20 @@ static unsigned long isolate_lru_pages(u
+ nr_lumpy_dirty++;
+ scan++;
+ } else {
+- /* the page is freed already. */
+- if (!page_count(cursor_page))
++ /*
++ * Check if the page is freed already.
++ *
++ * We can't use page_count() as that
++ * requires compound_head and we don't
++ * have a pin on the page here. If a
++ * page is tail, we may or may not
++ * have isolated the head, so assume
++ * it's not free, it'd be tricky to
++ * track the head status without a
++ * page pin.
++ */
++ if (!PageTail(cursor_page) &&
++ !atomic_read(&cursor_page->_count))
+ continue;
+ break;
+ }
diff --git a/queue-2.6.39/mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch b/queue-2.6.39/mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch
new file mode 100644
index 0000000000..810b27f12f
--- /dev/null
+++ b/queue-2.6.39/mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch
@@ -0,0 +1,129 @@
+From mgorman@suse.de Mon Aug 1 11:50:49 2011
+From: Mel Gorman <mgorman@suse.de>
+Date: Mon, 11 Jul 2011 10:11:23 +0100
+Subject: mm: vmscan: only read new_classzone_idx from pgdat when reclaiming successfully
+To: stable@kernel.org
+Cc: mgorman@suse.de
+Message-ID: <1310375483-31999-5-git-send-email-mgorman@suse.de>
+
+From: Mel Gorman <mgorman@suse.de>
+
+commit 215ddd6664ced067afca7eebd2d1eb83f064ff5a upstream
+
+During allocator-intensive workloads, kswapd will be woken frequently
+causing free memory to oscillate between the high and min watermark. This
+is expected behaviour. Unfortunately, if the highest zone is small, a
+problem occurs.
+
+When balance_pgdat() returns, it may be at a lower classzone_idx than it
+started because the highest zone was unreclaimable. Before checking if it
+should go to sleep though, it checks pgdat->classzone_idx which when there
+is no other activity will be MAX_NR_ZONES-1. It interprets this as it has
+been woken up while reclaiming, skips scheduling and reclaims again. As
+there is no useful reclaim work to do, it enters into a loop of shrinking
+slab consuming loads of CPU until the highest zone becomes reclaimable for
+a long period of time.
+
+There are two problems here. 1) If the returned classzone or order is
+lower, it'll continue reclaiming without scheduling. 2) if the highest
+zone was marked unreclaimable but balance_pgdat() returns immediately at
+DEF_PRIORITY, the new lower classzone is not communicated back to kswapd()
+for sleeping.
+
+This patch does two things that are related. If the end_zone is
+unreclaimable, this information is communicated back. Second, if the
+classzone or order was reduced due to failing to reclaim, new information
+is not read from pgdat and instead an attempt is made to go to sleep. Due
+to this, it is also necessary that pgdat->classzone_idx be initialised
+each time to pgdat->nr_zones - 1 to avoid re-reads being interpreted as
+wakeups.
+
+Signed-off-by: Mel Gorman <mgorman@suse.de>
+Reported-by: Pádraig Brady <P@draigBrady.com>
+Tested-by: Pádraig Brady <P@draigBrady.com>
+Tested-by: Andrew Lutomirski <luto@mit.edu>
+Acked-by: Rik van Riel <riel@redhat.com>
+Cc: Minchan Kim <minchan.kim@gmail.com>
+Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ mm/vmscan.c | 34 +++++++++++++++++++++-------------
+ 1 file changed, 21 insertions(+), 13 deletions(-)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -2394,7 +2394,6 @@ loop_again:
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone), 0, 0)) {
+ end_zone = i;
+- *classzone_idx = i;
+ break;
+ }
+ }
+@@ -2471,8 +2470,11 @@ loop_again:
+ total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
+ sc.may_writepage = 1;
+
+- if (zone->all_unreclaimable)
++ if (zone->all_unreclaimable) {
++ if (end_zone && end_zone == i)
++ end_zone--;
+ continue;
++ }
+
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone), end_zone, 0)) {
+@@ -2652,8 +2654,8 @@ static void kswapd_try_to_sleep(pg_data_
+ */
+ static int kswapd(void *p)
+ {
+- unsigned long order;
+- int classzone_idx;
++ unsigned long order, new_order;
++ int classzone_idx, new_classzone_idx;
+ pg_data_t *pgdat = (pg_data_t*)p;
+ struct task_struct *tsk = current;
+
+@@ -2683,17 +2685,23 @@ static int kswapd(void *p)
+ tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+ set_freezable();
+
+- order = 0;
+- classzone_idx = MAX_NR_ZONES - 1;
++ order = new_order = 0;
++ classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
+ for ( ; ; ) {
+- unsigned long new_order;
+- int new_classzone_idx;
+ int ret;
+
+- new_order = pgdat->kswapd_max_order;
+- new_classzone_idx = pgdat->classzone_idx;
+- pgdat->kswapd_max_order = 0;
+- pgdat->classzone_idx = MAX_NR_ZONES - 1;
++ /*
++ * If the last balance_pgdat was unsuccessful it's unlikely a
++ * new request of a similar or harder type will succeed soon
++ * so consider going to sleep on the basis we reclaimed at
++ */
++ if (classzone_idx >= new_classzone_idx && order == new_order) {
++ new_order = pgdat->kswapd_max_order;
++ new_classzone_idx = pgdat->classzone_idx;
++ pgdat->kswapd_max_order = 0;
++ pgdat->classzone_idx = pgdat->nr_zones - 1;
++ }
++
+ if (order < new_order || classzone_idx > new_classzone_idx) {
+ /*
+ * Don't sleep if someone wants a larger 'order'
+@@ -2706,7 +2714,7 @@ static int kswapd(void *p)
+ order = pgdat->kswapd_max_order;
+ classzone_idx = pgdat->classzone_idx;
+ pgdat->kswapd_max_order = 0;
+- pgdat->classzone_idx = MAX_NR_ZONES - 1;
++ pgdat->classzone_idx = pgdat->nr_zones - 1;
+ }
+
+ ret = try_to_freeze();
diff --git a/queue-2.6.39/revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch b/queue-2.6.39/revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch
new file mode 100644
index 0000000000..6e858abaf5
--- /dev/null
+++ b/queue-2.6.39/revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch
@@ -0,0 +1,1185 @@
+From e4f708b85622e2bbc25e6ae1e05bf0eed4d3e29e Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@suse.de>
+Date: Mon, 1 Aug 2011 11:53:11 -0700
+Subject: Revert "DiBxxxx: get rid of DMA buffer on stack"
+
+This reverts commit 673de951a6cbaa7a9c4518e03e78b88809828497 which was
+commit 5a0deeed5741117ee8625d6305d0034e219f102c upstream.
+
+Based on comments from users, this broke things.
+
+Acked-by: Olivier Grenie <Olivier.Grenie@dibcom.com>
+Cc: Florian Mickler <florian@mickler.org>
+Cc: Patrick Boettcher <patrick.boettcher@dibcom.fr>
+Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/media/dvb/frontends/dib0070.c | 40 +-----
+ drivers/media/dvb/frontends/dib0090.c | 71 ++---------
+ drivers/media/dvb/frontends/dib7000m.c | 47 ++-----
+ drivers/media/dvb/frontends/dib7000p.c | 72 +++--------
+ drivers/media/dvb/frontends/dib8000.c | 126 +++++--------------
+ drivers/media/dvb/frontends/dib9000.c | 172 +++++++++------------------
+ drivers/media/dvb/frontends/dibx000_common.c | 113 +++++++----------
+ drivers/media/dvb/frontends/dibx000_common.h | 5
+ 8 files changed, 202 insertions(+), 444 deletions(-)
+
+--- a/drivers/media/dvb/frontends/dib0070.c
++++ b/drivers/media/dvb/frontends/dib0070.c
+@@ -73,47 +73,27 @@ struct dib0070_state {
+
+ u8 wbd_gain_current;
+ u16 wbd_offset_3_3[2];
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[3];
+- u8 i2c_read_buffer[2];
+ };
+
+ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
+ {
+- state->i2c_write_buffer[0] = reg;
+-
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->cfg->i2c_address;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 1;
+- state->msg[1].addr = state->cfg->i2c_address;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = state->i2c_read_buffer;
+- state->msg[1].len = 2;
+-
+- if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
++ u8 b[2];
++ struct i2c_msg msg[2] = {
++ { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
++ { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
++ };
++ if (i2c_transfer(state->i2c, msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0070 I2C read failed\n");
+ return 0;
+ }
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (b[0] << 8) | b[1];
+ }
+
+ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = reg;
+- state->i2c_write_buffer[1] = val >> 8;
+- state->i2c_write_buffer[2] = val & 0xff;
+-
+- memset(state->msg, 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->cfg->i2c_address;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 3;
+-
+- if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
++ u8 b[3] = { reg, val >> 8, val & 0xff };
++ struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0070 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+--- a/drivers/media/dvb/frontends/dib0090.c
++++ b/drivers/media/dvb/frontends/dib0090.c
+@@ -191,11 +191,6 @@ struct dib0090_state {
+ u8 wbd_calibration_gain;
+ const struct dib0090_wbd_slope *current_wbd_table;
+ u16 wbdmux;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[3];
+- u8 i2c_read_buffer[2];
+ };
+
+ struct dib0090_fw_state {
+@@ -203,48 +198,27 @@ struct dib0090_fw_state {
+ struct dvb_frontend *fe;
+ struct dib0090_identity identity;
+ const struct dib0090_config *config;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg;
+- u8 i2c_write_buffer[2];
+- u8 i2c_read_buffer[2];
+ };
+
+ static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+ {
+- state->i2c_write_buffer[0] = reg;
+-
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->config->i2c_address;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 1;
+- state->msg[1].addr = state->config->i2c_address;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = state->i2c_read_buffer;
+- state->msg[1].len = 2;
+-
+- if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
++ u8 b[2];
++ struct i2c_msg msg[2] = {
++ {.addr = state->config->i2c_address, .flags = 0, .buf = &reg, .len = 1},
++ {.addr = state->config->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2},
++ };
++ if (i2c_transfer(state->i2c, msg, 2) != 2) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+ return 0;
+ }
+-
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (b[0] << 8) | b[1];
+ }
+
+ static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = reg & 0xff;
+- state->i2c_write_buffer[1] = val >> 8;
+- state->i2c_write_buffer[2] = val & 0xff;
+-
+- memset(state->msg, 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->config->i2c_address;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 3;
+-
+- if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
++ u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
++ struct i2c_msg msg = {.addr = state->config->i2c_address, .flags = 0, .buf = b, .len = 3 };
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+@@ -253,31 +227,20 @@ static int dib0090_write_reg(struct dib0
+
+ static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+ {
+- state->i2c_write_buffer[0] = reg;
+-
+- memset(&state->msg, 0, sizeof(struct i2c_msg));
+- state->msg.addr = reg;
+- state->msg.flags = I2C_M_RD;
+- state->msg.buf = state->i2c_read_buffer;
+- state->msg.len = 2;
+- if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
++ u8 b[2];
++ struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C read failed\n");
+ return 0;
+ }
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (b[0] << 8) | b[1];
+ }
+
+ static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = val >> 8;
+- state->i2c_write_buffer[1] = val & 0xff;
+-
+- memset(&state->msg, 0, sizeof(struct i2c_msg));
+- state->msg.addr = reg;
+- state->msg.flags = 0;
+- state->msg.buf = state->i2c_write_buffer;
+- state->msg.len = 2;
+- if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
++ u8 b[2] = { val >> 8, val & 0xff };
++ struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
++ if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+ printk(KERN_WARNING "DiB0090 I2C write failed\n");
+ return -EREMOTEIO;
+ }
+--- a/drivers/media/dvb/frontends/dib7000m.c
++++ b/drivers/media/dvb/frontends/dib7000m.c
+@@ -50,11 +50,6 @@ struct dib7000m_state {
+ u16 revision;
+
+ u8 agc_state;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[4];
+- u8 i2c_read_buffer[2];
+ };
+
+ enum dib7000m_power_mode {
+@@ -69,39 +64,29 @@ enum dib7000m_power_mode {
+
+ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+ {
+- state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
+- state->i2c_write_buffer[1] = reg & 0xff;
+-
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 2;
+- state->msg[1].addr = state->i2c_addr >> 1;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = state->i2c_read_buffer;
+- state->msg[1].len = 2;
++ u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
++ u8 rb[2];
++ struct i2c_msg msg[2] = {
++ { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 },
++ { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
++ };
+
+- if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
++ if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d",reg);
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (rb[0] << 8) | rb[1];
+ }
+
+ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- state->i2c_write_buffer[1] = reg & 0xff;
+- state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+- state->i2c_write_buffer[3] = val & 0xff;
+-
+- memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 4;
+-
+- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ u8 b[4] = {
++ (reg >> 8) & 0xff, reg & 0xff,
++ (val >> 8) & 0xff, val & 0xff,
++ };
++ struct i2c_msg msg = {
++ .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
++ };
++ return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+ static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+ {
+--- a/drivers/media/dvb/frontends/dib7000p.c
++++ b/drivers/media/dvb/frontends/dib7000p.c
+@@ -63,11 +63,6 @@ struct dib7000p_state {
+
+ u16 tuner_enable;
+ struct i2c_adapter dib7090_tuner_adap;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[4];
+- u8 i2c_read_buffer[2];
+ };
+
+ enum dib7000p_power_mode {
+@@ -81,39 +76,29 @@ static int dib7090_set_diversity_in(stru
+
+ static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+ {
+- state->i2c_write_buffer[0] = reg >> 8;
+- state->i2c_write_buffer[1] = reg & 0xff;
+-
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 2;
+- state->msg[1].addr = state->i2c_addr >> 1;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = state->i2c_read_buffer;
+- state->msg[1].len = 2;
++ u8 wb[2] = { reg >> 8, reg & 0xff };
++ u8 rb[2];
++ struct i2c_msg msg[2] = {
++ {.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
++ {.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
++ };
+
+- if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
++ if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (rb[0] << 8) | rb[1];
+ }
+
+ static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- state->i2c_write_buffer[1] = reg & 0xff;
+- state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+- state->i2c_write_buffer[3] = val & 0xff;
+-
+- memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 4;
+-
+- return i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ u8 b[4] = {
++ (reg >> 8) & 0xff, reg & 0xff,
++ (val >> 8) & 0xff, val & 0xff,
++ };
++ struct i2c_msg msg = {
++ .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
++ };
++ return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
+@@ -1565,24 +1550,11 @@ static void dib7000p_release(struct dvb_
+
+ int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+ {
+- u8 *tx, *rx;
++ u8 tx[2], rx[2];
+ struct i2c_msg msg[2] = {
+- {.addr = 18 >> 1, .flags = 0, .len = 2},
+- {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
++ {.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
++ {.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
+ };
+- int ret = 0;
+-
+- tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+- if (!tx)
+- return -ENOMEM;
+- rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+- if (!rx) {
+- goto rx_memory_error;
+- ret = -ENOMEM;
+- }
+-
+- msg[0].buf = tx;
+- msg[1].buf = rx;
+
+ tx[0] = 0x03;
+ tx[1] = 0x00;
+@@ -1602,11 +1574,7 @@ int dib7000pc_detection(struct i2c_adapt
+ }
+
+ dprintk("-D- DiB7000PC not detected");
+-
+- kfree(rx);
+-rx_memory_error:
+- kfree(tx);
+- return ret;
++ return 0;
+ }
+ EXPORT_SYMBOL(dib7000pc_detection);
+
+--- a/drivers/media/dvb/frontends/dib8000.c
++++ b/drivers/media/dvb/frontends/dib8000.c
+@@ -35,8 +35,6 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+ struct i2c_device {
+ struct i2c_adapter *adap;
+ u8 addr;
+- u8 *i2c_write_buffer;
+- u8 *i2c_read_buffer;
+ };
+
+ struct dib8000_state {
+@@ -72,11 +70,6 @@ struct dib8000_state {
+ u32 status;
+
+ struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[4];
+- u8 i2c_read_buffer[2];
+ };
+
+ enum dib8000_power_mode {
+@@ -86,41 +79,22 @@ enum dib8000_power_mode {
+
+ static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
++ u8 wb[2] = { reg >> 8, reg & 0xff };
++ u8 rb[2];
+ struct i2c_msg msg[2] = {
+- {.addr = i2c->addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 2},
+- {.addr = i2c->addr >> 1, .flags = I2C_M_RD,
+- .buf = i2c->i2c_read_buffer, .len = 2},
++ {.addr = i2c->addr >> 1,.flags = 0,.buf = wb,.len = 2},
++ {.addr = i2c->addr >> 1,.flags = I2C_M_RD,.buf = rb,.len = 2},
+ };
+
+- msg[0].buf[0] = reg >> 8;
+- msg[0].buf[1] = reg & 0xff;
+-
+ if (i2c_transfer(i2c->adap, msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (msg[1].buf[0] << 8) | msg[1].buf[1];
++ return (rb[0] << 8) | rb[1];
+ }
+
+ static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+ {
+- state->i2c_write_buffer[0] = reg >> 8;
+- state->i2c_write_buffer[1] = reg & 0xff;
+-
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c.addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 2;
+- state->msg[1].addr = state->i2c.addr >> 1;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = state->i2c_read_buffer;
+- state->msg[1].len = 2;
+-
+- if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
+- dprintk("i2c read error on %d", reg);
+-
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return dib8000_i2c_read16(&state->i2c, reg);
+ }
+
+ static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+@@ -135,34 +109,19 @@ static u32 dib8000_read32(struct dib8000
+
+ static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
+- struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 4};
+- int ret = 0;
+-
+- msg.buf[0] = (reg >> 8) & 0xff;
+- msg.buf[1] = reg & 0xff;
+- msg.buf[2] = (val >> 8) & 0xff;
+- msg.buf[3] = val & 0xff;
+-
+- ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+-
+- return ret;
++ u8 b[4] = {
++ (reg >> 8) & 0xff, reg & 0xff,
++ (val >> 8) & 0xff, val & 0xff,
++ };
++ struct i2c_msg msg = {
++ .addr = i2c->addr >> 1,.flags = 0,.buf = b,.len = 4
++ };
++ return i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+ {
+- state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- state->i2c_write_buffer[1] = reg & 0xff;
+- state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+- state->i2c_write_buffer[3] = val & 0xff;
+-
+- memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c.addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 4;
+-
+- return i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ return dib8000_i2c_write16(&state->i2c, reg, val);
+ }
+
+ static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
+@@ -1021,31 +980,30 @@ static void dib8000_update_timf(struct d
+ dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
+ }
+
+-static const u16 adc_target_16dB[11] = {
+- (1 << 13) - 825 - 117,
+- (1 << 13) - 837 - 117,
+- (1 << 13) - 811 - 117,
+- (1 << 13) - 766 - 117,
+- (1 << 13) - 737 - 117,
+- (1 << 13) - 693 - 117,
+- (1 << 13) - 648 - 117,
+- (1 << 13) - 619 - 117,
+- (1 << 13) - 575 - 117,
+- (1 << 13) - 531 - 117,
+- (1 << 13) - 501 - 117
+-};
+-static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
+-
+ static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
+ {
+ u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
+ u8 guard, crate, constellation, timeI;
++ u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
+ u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff; // All 13 segments enabled
+ const s16 *ncoeff = NULL, *ana_fe;
+ u16 tmcc_pow = 0;
+ u16 coff_pow = 0x2800;
+ u16 init_prbs = 0xfff;
+ u16 ana_gain = 0;
++ u16 adc_target_16dB[11] = {
++ (1 << 13) - 825 - 117,
++ (1 << 13) - 837 - 117,
++ (1 << 13) - 811 - 117,
++ (1 << 13) - 766 - 117,
++ (1 << 13) - 737 - 117,
++ (1 << 13) - 693 - 117,
++ (1 << 13) - 648 - 117,
++ (1 << 13) - 619 - 117,
++ (1 << 13) - 575 - 117,
++ (1 << 13) - 531 - 117,
++ (1 << 13) - 501 - 117
++ };
+
+ if (state->ber_monitored_layer != LAYER_ALL)
+ dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
+@@ -2421,22 +2379,10 @@ EXPORT_SYMBOL(dib8000_get_slave_frontend
+
+ int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+ {
+- int k = 0, ret = 0;
++ int k = 0;
+ u8 new_addr = 0;
+ struct i2c_device client = {.adap = host };
+
+- client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+- if (!client.i2c_write_buffer) {
+- dprintk("%s: not enough memory", __func__);
+- return -ENOMEM;
+- }
+- client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+- if (!client.i2c_read_buffer) {
+- dprintk("%s: not enough memory", __func__);
+- ret = -ENOMEM;
+- goto error_memory;
+- }
+-
+ for (k = no_of_demods - 1; k >= 0; k--) {
+ /* designated i2c address */
+ new_addr = first_addr + (k << 1);
+@@ -2448,8 +2394,7 @@ int dib8000_i2c_enumeration(struct i2c_a
+ client.addr = default_addr;
+ if (dib8000_identify(&client) == 0) {
+ dprintk("#%d: not identified", k);
+- ret = -EINVAL;
+- goto error;
++ return -EINVAL;
+ }
+ }
+
+@@ -2475,12 +2420,7 @@ int dib8000_i2c_enumeration(struct i2c_a
+ dib8000_i2c_write16(&client, 1286, 0);
+ }
+
+-error:
+- kfree(client.i2c_read_buffer);
+-error_memory:
+- kfree(client.i2c_write_buffer);
+-
+- return ret;
++ return 0;
+ }
+
+ EXPORT_SYMBOL(dib8000_i2c_enumeration);
+@@ -2579,8 +2519,6 @@ struct dvb_frontend *dib8000_attach(stru
+ memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
+ state->i2c.adap = i2c_adap;
+ state->i2c.addr = i2c_addr;
+- state->i2c.i2c_write_buffer = state->i2c_write_buffer;
+- state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+ state->gpio_val = cfg->gpio_val;
+ state->gpio_dir = cfg->gpio_dir;
+
+--- a/drivers/media/dvb/frontends/dib9000.c
++++ b/drivers/media/dvb/frontends/dib9000.c
+@@ -27,8 +27,6 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+ struct i2c_device {
+ struct i2c_adapter *i2c_adap;
+ u8 i2c_addr;
+- u8 *i2c_read_buffer;
+- u8 *i2c_write_buffer;
+ };
+
+ /* lock */
+@@ -94,16 +92,11 @@ struct dib9000_state {
+
+ struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+ u16 component_bus_speed;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[2];
+- u8 i2c_write_buffer[255];
+- u8 i2c_read_buffer[255];
+ };
+
+-static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+- 0, 0, 0, 0, 0, 0, 0, 0
++ 0, 0, 0
+ };
+
+ enum dib9000_power_mode {
+@@ -224,33 +217,25 @@ static u16 dib9000_read16_attr(struct di
+ u32 chunk_size = 126;
+ u32 l;
+ int ret;
++ u8 wb[2] = { reg >> 8, reg & 0xff };
++ struct i2c_msg msg[2] = {
++ {.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
++ {.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
++ };
+
+ if (state->platform.risc.fw_is_running && (reg < 1024))
+ return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
+
+- memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c.i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = 2;
+- state->msg[1].addr = state->i2c.i2c_addr >> 1;
+- state->msg[1].flags = I2C_M_RD;
+- state->msg[1].buf = b;
+- state->msg[1].len = len;
+-
+- state->i2c_write_buffer[0] = reg >> 8;
+- state->i2c_write_buffer[1] = reg & 0xff;
+-
+ if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+- state->i2c_write_buffer[0] |= (1 << 5);
++ wb[0] |= (1 << 5);
+ if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+- state->i2c_write_buffer[0] |= (1 << 4);
++ wb[0] |= (1 << 4);
+
+ do {
+ l = len < chunk_size ? len : chunk_size;
+- state->msg[1].len = l;
+- state->msg[1].buf = b;
+- ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
++ msg[1].len = l;
++ msg[1].buf = b;
++ ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
+ if (ret != 0) {
+ dprintk("i2c read error on %d", reg);
+ return -EREMOTEIO;
+@@ -268,47 +253,50 @@ static u16 dib9000_read16_attr(struct di
+
+ static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
+ {
++ u8 b[2];
++ u8 wb[2] = { reg >> 8, reg & 0xff };
+ struct i2c_msg msg[2] = {
+- {.addr = i2c->i2c_addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 2},
+- {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
+- .buf = i2c->i2c_read_buffer, .len = 2},
++ {.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
++ {.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
+ };
+
+- i2c->i2c_write_buffer[0] = reg >> 8;
+- i2c->i2c_write_buffer[1] = reg & 0xff;
+-
+ if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
+ dprintk("read register %x error", reg);
+ return 0;
+ }
+
+- return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
++ return (b[0] << 8) | b[1];
+ }
+
+ static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
+ {
+- if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
++ u8 b[2];
++ if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
+ return 0;
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (b[0] << 8 | b[1]);
+ }
+
+ static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
+ {
+- if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
+- attribute) != 0)
++ u8 b[2];
++ if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
+ return 0;
+- return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
++ return (b[0] << 8 | b[1]);
+ }
+
+ #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+ static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
+ {
++ u8 b[255];
+ u32 chunk_size = 126;
+ u32 l;
+ int ret;
+
++ struct i2c_msg msg = {
++ .addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
++ };
++
+ if (state->platform.risc.fw_is_running && (reg < 1024)) {
+ if (dib9000_risc_apb_access_write
+ (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
+@@ -316,26 +304,20 @@ static u16 dib9000_write16_attr(struct d
+ return 0;
+ }
+
+- memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+- state->msg[0].addr = state->i2c.i2c_addr >> 1;
+- state->msg[0].flags = 0;
+- state->msg[0].buf = state->i2c_write_buffer;
+- state->msg[0].len = len + 2;
+-
+- state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- state->i2c_write_buffer[1] = (reg) & 0xff;
++ b[0] = (reg >> 8) & 0xff;
++ b[1] = (reg) & 0xff;
+
+ if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+- state->i2c_write_buffer[0] |= (1 << 5);
++ b[0] |= (1 << 5);
+ if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+- state->i2c_write_buffer[0] |= (1 << 4);
++ b[0] |= (1 << 4);
+
+ do {
+ l = len < chunk_size ? len : chunk_size;
+- state->msg[0].len = l + 2;
+- memcpy(&state->i2c_write_buffer[2], buf, l);
++ msg.len = l + 2;
++ memcpy(&b[2], buf, l);
+
+- ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
++ ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+
+ buf += l;
+ len -= l;
+@@ -349,16 +331,11 @@ static u16 dib9000_write16_attr(struct d
+
+ static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+ {
++ u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
+ struct i2c_msg msg = {
+- .addr = i2c->i2c_addr >> 1, .flags = 0,
+- .buf = i2c->i2c_write_buffer, .len = 4
++ .addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+ };
+
+- i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- i2c->i2c_write_buffer[1] = reg & 0xff;
+- i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
+- i2c->i2c_write_buffer[3] = val & 0xff;
+-
+ return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+@@ -1038,8 +1015,8 @@ static int dib9000_fw_memmbx_sync(struct
+ return 0;
+ dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
+ do {
+- dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
+- } while (state->i2c_read_buffer[0] && index_loop--);
++ dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
++ } while (i && index_loop--);
+
+ if (index_loop > 0)
+ return 0;
+@@ -1162,7 +1139,7 @@ static int dib9000_fw_get_channel(struct
+
+ s8 intlv_native;
+ };
+- struct dibDVBTChannel *ch;
++ struct dibDVBTChannel ch;
+ int ret = 0;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+@@ -1171,12 +1148,9 @@ static int dib9000_fw_get_channel(struct
+ ret = -EIO;
+ }
+
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
+- state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
+- ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
+-
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
+
+- switch (ch->spectrum_inversion & 0x7) {
++ switch (ch.spectrum_inversion & 0x7) {
+ case 1:
+ state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
+ break;
+@@ -1188,7 +1162,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
+ break;
+ }
+- switch (ch->nfft) {
++ switch (ch.nfft) {
+ case 0:
+ state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+ break;
+@@ -1203,7 +1177,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
+ break;
+ }
+- switch (ch->guard) {
++ switch (ch.guard) {
+ case 0:
+ state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
+ break;
+@@ -1221,7 +1195,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
+ break;
+ }
+- switch (ch->constellation) {
++ switch (ch.constellation) {
+ case 2:
+ state->fe[0]->dtv_property_cache.modulation = QAM_64;
+ break;
+@@ -1236,7 +1210,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
+ break;
+ }
+- switch (ch->hrch) {
++ switch (ch.hrch) {
+ case 0:
+ state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
+ break;
+@@ -1248,7 +1222,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
+ break;
+ }
+- switch (ch->code_rate_hp) {
++ switch (ch.code_rate_hp) {
+ case 1:
+ state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
+ break;
+@@ -1269,7 +1243,7 @@ static int dib9000_fw_get_channel(struct
+ state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
+ break;
+ }
+- switch (ch->code_rate_lp) {
++ switch (ch.code_rate_lp) {
+ case 1:
+ state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
+ break;
+@@ -1465,10 +1439,9 @@ static int dib9000_fw_tune(struct dvb_fr
+ break;
+ case CT_DEMOD_STEP_1:
+ if (search)
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
+ else
+- dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
+- i = (s8)state->i2c_read_buffer[0];
++ dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
+ switch (i) { /* something happened */
+ case 0:
+ break;
+@@ -2065,17 +2038,14 @@ static int dib9000_read_status(struct dv
+ static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 *c;
++ u16 c[16];
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+- state->i2c_read_buffer, 16 * 2);
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+- c = (u16 *)state->i2c_read_buffer;
+-
+ *ber = c[10] << 16 | c[11];
+ return 0;
+ }
+@@ -2084,7 +2054,7 @@ static int dib9000_read_signal_strength(
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+ u8 index_frontend;
+- u16 *c = (u16 *)state->i2c_read_buffer;
++ u16 c[16];
+ u16 val;
+
+ *strength = 0;
+@@ -2099,7 +2069,7 @@ static int dib9000_read_signal_strength(
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ val = 65535 - c[4];
+@@ -2113,14 +2083,14 @@ static int dib9000_read_signal_strength(
+ static u32 dib9000_get_snr(struct dvb_frontend *fe)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 *c = (u16 *)state->i2c_read_buffer;
++ u16 c[16];
+ u32 n, s, exp;
+ u16 val;
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ val = c[7];
+@@ -2167,12 +2137,12 @@ static int dib9000_read_snr(struct dvb_f
+ static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+ {
+ struct dib9000_state *state = fe->demodulator_priv;
+- u16 *c = (u16 *)state->i2c_read_buffer;
++ u16 c[16];
+
+ DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+ if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+ return -EIO;
+- dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
++ dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+ DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+ *unc = c[12];
+@@ -2181,22 +2151,10 @@ static int dib9000_read_unc_blocks(struc
+
+ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+ {
+- int k = 0, ret = 0;
++ int k = 0;
+ u8 new_addr = 0;
+ struct i2c_device client = {.i2c_adap = i2c };
+
+- client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+- if (!client.i2c_write_buffer) {
+- dprintk("%s: not enough memory", __func__);
+- return -ENOMEM;
+- }
+- client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+- if (!client.i2c_read_buffer) {
+- dprintk("%s: not enough memory", __func__);
+- ret = -ENOMEM;
+- goto error_memory;
+- }
+-
+ client.i2c_addr = default_addr + 16;
+ dib9000_i2c_write16(&client, 1796, 0x0);
+
+@@ -2220,8 +2178,7 @@ int dib9000_i2c_enumeration(struct i2c_a
+ client.i2c_addr = default_addr;
+ if (dib9000_identify(&client) == 0) {
+ dprintk("DiB9000 #%d: not identified", k);
+- ret = -EIO;
+- goto error;
++ return -EIO;
+ }
+ }
+
+@@ -2239,12 +2196,7 @@ int dib9000_i2c_enumeration(struct i2c_a
+ dib9000_i2c_write16(&client, 1795, 0);
+ }
+
+-error:
+- kfree(client.i2c_read_buffer);
+-error_memory:
+- kfree(client.i2c_write_buffer);
+-
+- return ret;
++ return 0;
+ }
+ EXPORT_SYMBOL(dib9000_i2c_enumeration);
+
+@@ -2309,8 +2261,6 @@ struct dvb_frontend *dib9000_attach(stru
+ memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
+ st->i2c.i2c_adap = i2c_adap;
+ st->i2c.i2c_addr = i2c_addr;
+- st->i2c.i2c_write_buffer = st->i2c_write_buffer;
+- st->i2c.i2c_read_buffer = st->i2c_read_buffer;
+
+ st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
+ st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
+--- a/drivers/media/dvb/frontends/dibx000_common.c
++++ b/drivers/media/dvb/frontends/dibx000_common.c
+@@ -10,39 +10,30 @@ MODULE_PARM_DESC(debug, "turn on debuggi
+
+ static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+ {
+- mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+- mst->i2c_write_buffer[1] = reg & 0xff;
+- mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
+- mst->i2c_write_buffer[3] = val & 0xff;
+-
+- memset(mst->msg, 0, sizeof(struct i2c_msg));
+- mst->msg[0].addr = mst->i2c_addr;
+- mst->msg[0].flags = 0;
+- mst->msg[0].buf = mst->i2c_write_buffer;
+- mst->msg[0].len = 4;
++ u8 b[4] = {
++ (reg >> 8) & 0xff, reg & 0xff,
++ (val >> 8) & 0xff, val & 0xff,
++ };
++ struct i2c_msg msg = {
++ .addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
++ };
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
++ return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+ }
+
+ static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+ {
+- mst->i2c_write_buffer[0] = reg >> 8;
+- mst->i2c_write_buffer[1] = reg & 0xff;
++ u8 wb[2] = { reg >> 8, reg & 0xff };
++ u8 rb[2];
++ struct i2c_msg msg[2] = {
++ {.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
++ {.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
++ };
+
+- memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
+- mst->msg[0].addr = mst->i2c_addr;
+- mst->msg[0].flags = 0;
+- mst->msg[0].buf = mst->i2c_write_buffer;
+- mst->msg[0].len = 2;
+- mst->msg[1].addr = mst->i2c_addr;
+- mst->msg[1].flags = I2C_M_RD;
+- mst->msg[1].buf = mst->i2c_read_buffer;
+- mst->msg[1].len = 2;
+-
+- if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
++ if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
+ dprintk("i2c read error on %d", reg);
+
+- return (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
++ return (rb[0] << 8) | rb[1];
+ }
+
+ static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+@@ -257,32 +248,26 @@ static int dibx000_i2c_gated_gpio67_xfer
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++ struct i2c_msg m[2 + num];
++ u8 tx_open[4], tx_close[4];
+
+- if (num > 32) {
+- dprintk("%s: too much I2C message to be transmitted (%i).\
+- Maximum is 32", __func__, num);
+- return -ENOMEM;
+- }
+-
+- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++ memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
+
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+
+- /* open the gate */
+- dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+- mst->msg[0].addr = mst->i2c_addr;
+- mst->msg[0].buf = &mst->i2c_write_buffer[0];
+- mst->msg[0].len = 4;
+-
+- memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
+-
+- /* close the gate */
+- dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+- mst->msg[num + 1].addr = mst->i2c_addr;
+- mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+- mst->msg[num + 1].len = 4;
++ dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
++ m[0].addr = mst->i2c_addr;
++ m[0].buf = tx_open;
++ m[0].len = 4;
++
++ memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
++
++ dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
++ m[num + 1].addr = mst->i2c_addr;
++ m[num + 1].buf = tx_close;
++ m[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++ return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+@@ -294,32 +279,26 @@ static int dibx000_i2c_gated_tuner_xfer(
+ struct i2c_msg msg[], int num)
+ {
+ struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
++ struct i2c_msg m[2 + num];
++ u8 tx_open[4], tx_close[4];
+
+- if (num > 32) {
+- dprintk("%s: too much I2C message to be transmitted (%i).\
+- Maximum is 32", __func__, num);
+- return -ENOMEM;
+- }
+-
+- memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
++ memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
+
+ dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
+- /* open the gate */
+- dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+- mst->msg[0].addr = mst->i2c_addr;
+- mst->msg[0].buf = &mst->i2c_write_buffer[0];
+- mst->msg[0].len = 4;
+-
+- memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
+-
+- /* close the gate */
+- dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+- mst->msg[num + 1].addr = mst->i2c_addr;
+- mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+- mst->msg[num + 1].len = 4;
++ dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
++ m[0].addr = mst->i2c_addr;
++ m[0].buf = tx_open;
++ m[0].len = 4;
++
++ memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
++
++ dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
++ m[num + 1].addr = mst->i2c_addr;
++ m[num + 1].buf = tx_close;
++ m[num + 1].len = 4;
+
+- return i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? num : -EIO;
++ return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
+ }
+
+ static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+--- a/drivers/media/dvb/frontends/dibx000_common.h
++++ b/drivers/media/dvb/frontends/dibx000_common.h
+@@ -28,11 +28,6 @@ struct dibx000_i2c_master {
+ u8 i2c_addr;
+
+ u16 base_reg;
+-
+- /* for the I2C transfer */
+- struct i2c_msg msg[34];
+- u8 i2c_write_buffer[8];
+- u8 i2c_read_buffer[2];
+ };
+
+ extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
diff --git a/queue-2.6.39/series b/queue-2.6.39/series
index c715eef6d8..9ebdd115fe 100644
--- a/queue-2.6.39/series
+++ b/queue-2.6.39/series
@@ -50,3 +50,19 @@ hwmon-asus_atk0110-fix-memory-leak.patch
hwmon-max1111-fix-race-condition-causing-null-pointer-exception.patch
mmc-added-quirks-for-ricoh-1180-e823-lower-base-clock.patch
mmc-sdhci-esdhc-imx-sdhci_card_present-does-not-get.patch
+x86-make-dell-latitude-e5420-use-reboot-pci.patch
+davinci-dm365-evm-fix-video-input-mux-bits.patch
+vmscan-fix-a-livelock-in-kswapd.patch
+libata-fix-unexpectedly-frozen-port-after-ata_eh_reset.patch
+ext4-fix-oops-in-ext4_quota_off.patch
+mm-compaction-ensure-that-the-compaction-free-scanner-does-not-move-to-the-next-zone.patch
+mm-vmscan-do-not-use-page_count-without-a-page-pin.patch
+mm-compaction-abort-compaction-if-too-many-pages-are-isolated-and-caller-is-asynchronous-v2.patch
+xfs-restart-busy-extent-search-after-node-removal.patch
+cifs-clean-up-wsize-negotiation-and-allow-for-larger-wsize.patch
+cifs-fix-wsize-negotiation-to-respect-max-buffer-size-and.patch
+cifs-lower-default-and-max-wsize-to-what-2.6.39-can-handle.patch
+mm-vmscan-do-not-apply-pressure-to-slab-if-we-are-not-applying-pressure-to-zone.patch
+mm-vmscan-only-read-new_classzone_idx-from-pgdat-when-reclaiming-successfully.patch
+revert-dibxxxx-get-rid-of-dma-buffer-on-stack.patch
+vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch
diff --git a/queue-2.6.39/vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch b/queue-2.6.39/vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch
new file mode 100644
index 0000000000..59f46ec2e0
--- /dev/null
+++ b/queue-2.6.39/vfs-fix-race-in-rcu-lookup-of-pruned-dentry.patch
@@ -0,0 +1,50 @@
+From hughd@google.com Mon Aug 1 11:55:24 2011
+From: Hugh Dickins <hughd@google.com>
+Date: Tue, 26 Jul 2011 13:04:16 -0700 (PDT)
+Subject: vfs: fix race in rcu lookup of pruned dentry
+To: Stable Kernel <stable@kernel.org>
+Cc: Mike Waychison <mikew@google.com>, Linus Torvalds <torvalds@linux-foundation.org>, Al Viro <viro@zeniv.linux.org.uk>, Ian Kent <raven@themaw.net>
+Message-ID: <alpine.LSU.2.00.1107261239110.24976@sister.anvils>
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+Backport of commit 59430262401bec02d415179c43dbe5b8819c09ce
+done by Hugh Dickins <hughd@google.com>
+
+
+Don't update *inode in __follow_mount_rcu() until we'd verified that
+there is mountpoint there. Kudos to Hugh Dickins for catching that
+one in the first place and eventually figuring out the solution (and
+catching a braino in the earlier version of patch).
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Hugh Dickins <hughd@google.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+
+---
+ fs/namei.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1013,7 +1013,6 @@ static bool __follow_mount_rcu(struct na
+ * Don't forget we might have a non-mountpoint managed dentry
+ * that wants to block transit.
+ */
+- *inode = path->dentry->d_inode;
+ if (!reverse_transit &&
+ unlikely(managed_dentry_might_block(path->dentry)))
+ return false;
+@@ -1027,6 +1026,12 @@ static bool __follow_mount_rcu(struct na
+ path->mnt = mounted;
+ path->dentry = mounted->mnt_root;
+ nd->seq = read_seqcount_begin(&path->dentry->d_seq);
++ /*
++ * Update the inode too. We don't need to re-check the
++ * dentry sequence number here after this d_inode read,
++ * because a mount-point is always pinned.
++ */
++ *inode = path->dentry->d_inode;
+ }
+
+ if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
diff --git a/queue-2.6.39/vmscan-fix-a-livelock-in-kswapd.patch b/queue-2.6.39/vmscan-fix-a-livelock-in-kswapd.patch
new file mode 100644
index 0000000000..b1572e8e52
--- /dev/null
+++ b/queue-2.6.39/vmscan-fix-a-livelock-in-kswapd.patch
@@ -0,0 +1,49 @@
+From 4746efded84d7c5a9c8d64d4c6e814ff0cf9fb42 Mon Sep 17 00:00:00 2001
+From: Shaohua Li <shaohua.li@intel.com>
+Date: Tue, 19 Jul 2011 08:49:26 -0700
+Subject: vmscan: fix a livelock in kswapd
+
+From: Shaohua Li <shaohua.li@intel.com>
+
+commit 4746efded84d7c5a9c8d64d4c6e814ff0cf9fb42 upstream.
+
+I'm running a workload which triggers a lot of swap in a machine with 4
+nodes. After I kill the workload, I found a kswapd livelock. Sometimes
+kswapd3 or kswapd2 are keeping running and I can't access filesystem,
+but most memory is free.
+
+This looks like a regression since commit 08951e545918c159 ("mm: vmscan:
+correct check for kswapd sleeping in sleeping_prematurely").
+
+Node 2 and 3 have only ZONE_NORMAL, but balance_pgdat() will return 0
+for classzone_idx. The reason is end_zone in balance_pgdat() is 0 by
+default, if all zones have watermark ok, end_zone will keep 0.
+
+Later sleeping_prematurely() always returns true. Because this is an
+order 3 wakeup, and if classzone_idx is 0, both balanced_pages and
+present_pages in pgdat_balanced() are 0. We add a special case here.
+If a zone has no page, we think it's balanced. This fixes the livelock.
+
+Signed-off-by: Shaohua Li <shaohua.li@intel.com>
+Acked-by: Mel Gorman <mgorman@suse.de>
+Cc: Minchan Kim <minchan.kim@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ mm/vmscan.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -2245,7 +2245,8 @@ static bool pgdat_balanced(pg_data_t *pg
+ for (i = 0; i <= classzone_idx; i++)
+ present_pages += pgdat->node_zones[i].present_pages;
+
+- return balanced_pages > (present_pages >> 2);
++ /* A special case here: if zone has no page, we think it's balanced */
++ return balanced_pages >= (present_pages >> 2);
+ }
+
+ /* is kswapd sleeping prematurely? */
diff --git a/queue-2.6.39/x86-make-dell-latitude-e5420-use-reboot-pci.patch b/queue-2.6.39/x86-make-dell-latitude-e5420-use-reboot-pci.patch
new file mode 100644
index 0000000000..6fc911cc2f
--- /dev/null
+++ b/queue-2.6.39/x86-make-dell-latitude-e5420-use-reboot-pci.patch
@@ -0,0 +1,43 @@
+From b7798d28ec15d20fd34b70fa57eb13f0cf6d1ecd Mon Sep 17 00:00:00 2001
+From: Daniel J Blueman <daniel.blueman@gmail.com>
+Date: Fri, 13 May 2011 09:04:59 +0800
+Subject: x86: Make Dell Latitude E5420 use reboot=pci
+
+From: Daniel J Blueman <daniel.blueman@gmail.com>
+
+commit b7798d28ec15d20fd34b70fa57eb13f0cf6d1ecd upstream.
+
+Rebooting on the Dell E5420 often hangs with the keyboard or ACPI
+methods, but is reliable via the PCI method.
+
+[ hpa: this was deferred because we believed for a long time that the
+ recent reshuffling of the boot priorities in commit
+ 660e34cebf0a11d54f2d5dd8838607452355f321 fixed this platform.
+ Unfortunately that turned out to be incorrect. ]
+
+Signed-off-by: Daniel J Blueman <daniel.blueman@gmail.com>
+Link: http://lkml.kernel.org/r/1305248699-2347-1-git-send-email-daniel.blueman@gmail.com
+Signed-off-by: H. Peter Anvin <hpa@zytor.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/kernel/reboot.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -411,6 +411,14 @@ static struct dmi_system_id __initdata p
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
+ },
+ },
++ { /* Handle problems with rebooting on the Latitude E5420. */
++ .callback = set_pci_reboot,
++ .ident = "Dell Latitude E5420",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
++ },
++ },
+ { }
+ };
+
diff --git a/queue-2.6.39/xfs-restart-busy-extent-search-after-node-removal.patch b/queue-2.6.39/xfs-restart-busy-extent-search-after-node-removal.patch
new file mode 100644
index 0000000000..8e5a61e65a
--- /dev/null
+++ b/queue-2.6.39/xfs-restart-busy-extent-search-after-node-removal.patch
@@ -0,0 +1,65 @@
+From sandeen@sandeen.net Mon Aug 1 11:47:45 2011
+From: Eric Sandeen <sandeen@sandeen.net>
+Date: Wed, 13 Jul 2011 10:48:46 -0500
+Subject: xfs [stable only]: restart busy extent search after node removal
+To: stable@kernel.org, xfs-oss <xfs@oss.sgi.com>
+Message-ID: <4E1DBE5E.3060308@sandeen.net>
+
+From: Eric Sandeen <sandeen@sandeen.net>
+
+A user on #xfs reported that a log replay was oopsing in
+__rb_rotate_left() with a null pointer deref, and provided
+an xfs_metadump image for reproduction and testing.
+
+I traced this down to the fact that in xfs_alloc_busy_insert(),
+we erased a node with rb_erase() when the new node overlapped,
+but left the erased node specified as the parent node for the
+new insertion.
+
+So when we try to insert a new node with an erased node as
+its parent, obviously things go very wrong.
+
+Upstream,
+97d3ac75e5e0ebf7ca38ae74cebd201c09b97ab2 xfs: exact busy extent tracking
+actually fixed this, but as part of a much larger change. Here's
+the relevant code from that commit:
+
+ * We also need to restart the busy extent search from the
+ * tree root, because erasing the node can rearrange the
+ * tree topology.
+ */
+ rb_erase(&busyp->rb_node, &pag->pagb_tree);
+ busyp->length = 0;
+ return false;
+
+We can do essentially the same thing to older codebases by restarting
+the tree search after the erase.
+
+This should apply to .35.y through .39.y, and was tested on .39
+with the oopsing replay reproducer.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Reviewed-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Alex Elder <aelder@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+
+---
+ fs/xfs/xfs_alloc.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/xfs/xfs_alloc.c
++++ b/fs/xfs/xfs_alloc.c
+@@ -2610,6 +2610,12 @@ restart:
+ new->bno + new->length) -
+ min(busyp->bno, new->bno);
+ new->bno = min(busyp->bno, new->bno);
++ /*
++ * Start the search over from the tree root, because
++ * erasing the node can rearrange the tree topology.
++ */
++ spin_unlock(&pag->pagb_lock);
++ goto restart;
+ } else
+ busyp = NULL;
+