diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-01 11:58:34 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-08-01 11:58:34 -0700 |
commit | 3a1f5780a14fa700a0b186391a65c6d1aed8e8d9 (patch) | |
tree | 541bc07ff796dd26a1683ecc6a97827c65c6f6bd | |
parent | 8cb4c7c14e758ea1e1a2209d45a7444a13752f62 (diff) | |
download | stable-queue-3a1f5780a14fa700a0b186391a65c6d1aed8e8d9.tar.gz |
2.6.39 patches
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 = ®, .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 = ®, .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; + |