diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-05-08 10:57:25 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-05-08 10:57:25 -0400 |
commit | fb0f146bd226339638e1441f0bd91a393bf7aff4 (patch) | |
tree | fbc14051a5bfc5fa945811467225bfc26f18584f | |
parent | 8a09d04dd382b39f9a964eb4e52fc4df42cd1e66 (diff) | |
download | longterm-queue-2.6.34-fb0f146bd226339638e1441f0bd91a393bf7aff4.tar.gz |
import of selections paralleling 2.6.32.43
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
31 files changed, 2099 insertions, 0 deletions
diff --git a/queue/6pack-mkiss-fix-lock-inconsistency.patch b/queue/6pack-mkiss-fix-lock-inconsistency.patch new file mode 100644 index 0000000..bd0f0d7 --- /dev/null +++ b/queue/6pack-mkiss-fix-lock-inconsistency.patch @@ -0,0 +1,71 @@ +From 1b7c6193df85e80e941a8249de864c33737da706 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann <arnd@arndb.de> +Date: Fri, 1 Jul 2011 17:30:00 -0700 +Subject: [PATCH] 6pack,mkiss: fix lock inconsistency + +commit 6e4e2f811bade330126d4029c88c831784a7efd9 upstream. + +Lockdep found a locking inconsistency in the mkiss_close function: + +> kernel: [ INFO: inconsistent lock state ] +> kernel: 2.6.39.1 #3 +> kernel: --------------------------------- +> kernel: inconsistent {IN-SOFTIRQ-R} -> {SOFTIRQ-ON-W} usage. +> kernel: ax25ipd/2813 [HC0[0]:SC0[0]:HE1:SE1] takes: +> kernel: (disc_data_lock){+++?.-}, at: [<ffffffffa018552b>] mkiss_close+0x1b/0x90 [mkiss] +> kernel: {IN-SOFTIRQ-R} state was registered at: + +The message hints that disc_data_lock is aquired with softirqs disabled, +but does not itself disable softirqs, which can in rare circumstances +lead to a deadlock. +The same problem is present in the 6pack driver, this patch fixes both +by using write_lock_bh instead of write_lock. + +Reported-by: Bernard F6BVP <f6bvp@free.fr> +Tested-by: Bernard F6BVP <f6bvp@free.fr> +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Ralf Baechle<ralf@linux-mips.org> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/net/hamradio/6pack.c | 4 ++-- + drivers/net/hamradio/mkiss.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c +index 4b52c76..26843e2 100644 +--- a/drivers/net/hamradio/6pack.c ++++ b/drivers/net/hamradio/6pack.c +@@ -692,10 +692,10 @@ static void sixpack_close(struct tty_struct *tty) + { + struct sixpack *sp; + +- write_lock(&disc_data_lock); ++ write_lock_bh(&disc_data_lock); + sp = tty->disc_data; + tty->disc_data = NULL; +- write_unlock(&disc_data_lock); ++ write_unlock_bh(&disc_data_lock); + if (!sp) + return; + +diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c +index 66e88bd..bb94407 100644 +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -813,10 +813,10 @@ static void mkiss_close(struct tty_struct *tty) + { + struct mkiss *ax; + +- write_lock(&disc_data_lock); ++ write_lock_bh(&disc_data_lock); + ax = tty->disc_data; + tty->disc_data = NULL; +- write_unlock(&disc_data_lock); ++ write_unlock_bh(&disc_data_lock); + + if (!ax) + return; +-- +1.7.9.6 + diff --git a/queue/PM-Free-memory-bitmaps-if-opening-dev-snapshot-fails.patch b/queue/PM-Free-memory-bitmaps-if-opening-dev-snapshot-fails.patch new file mode 100644 index 0000000..80c6b35 --- /dev/null +++ b/queue/PM-Free-memory-bitmaps-if-opening-dev-snapshot-fails.patch @@ -0,0 +1,41 @@ +From ace3b611f740b06cae5069fada2a55027228541d Mon Sep 17 00:00:00 2001 +From: Michal Kubecek <mkubecek@suse.cz> +Date: Sat, 18 Jun 2011 20:34:01 +0200 +Subject: [PATCH] PM: Free memory bitmaps if opening /dev/snapshot fails + +commit 8440f4b19494467883f8541b7aa28c7bbf6ac92b upstream. + +When opening /dev/snapshot device, snapshot_open() creates memory +bitmaps which are freed in snapshot_release(). But if any of the +callbacks called by pm_notifier_call_chain() returns NOTIFY_BAD, open() +fails, snapshot_release() is never called and bitmaps are not freed. +Next attempt to open /dev/snapshot then triggers BUG_ON() check in +create_basic_memory_bitmaps(). This happens e.g. when vmwatchdog module +is active on s390x. + +Signed-off-by: Michal Kubecek <mkubecek@suse.cz> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + kernel/power/user.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/kernel/power/user.c b/kernel/power/user.c +index 16a7d95..37b32d5 100644 +--- a/kernel/power/user.c ++++ b/kernel/power/user.c +@@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp) + if (error) + pm_notifier_call_chain(PM_POST_RESTORE); + } +- if (error) ++ if (error) { ++ free_basic_memory_bitmaps(); + atomic_inc(&snapshot_device_available); ++ } + data->frozen = 0; + data->ready = 0; + data->platform_support = 0; +-- +1.7.9.6 + diff --git a/queue/PM-Hibernate-Avoid-hitting-OOM-during-preallocation-.patch b/queue/PM-Hibernate-Avoid-hitting-OOM-during-preallocation-.patch new file mode 100644 index 0000000..935ba2c --- /dev/null +++ b/queue/PM-Hibernate-Avoid-hitting-OOM-during-preallocation-.patch @@ -0,0 +1,175 @@ +From 227a790147422a72bd2a06d4b374ec38dd5a4a4f Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" <rjw@sisk.pl> +Date: Sat, 11 Sep 2010 20:58:27 +0200 +Subject: [PATCH] PM / Hibernate: Avoid hitting OOM during preallocation of + memory + +commit 6715045ddc7472a22be5e49d4047d2d89b391f45 upstream. + +There is a problem in hibernate_preallocate_memory() that it calls +preallocate_image_memory() with an argument that may be greater than +the total number of available non-highmem memory pages. If that's +the case, the OOM condition is guaranteed to trigger, which in turn +can cause significant slowdown to occur during hibernation. + +To avoid that, make preallocate_image_memory() adjust its argument +before calling preallocate_image_pages(), so that the total number of +saveable non-highem pages left is not less than the minimum size of +a hibernation image. Change hibernate_preallocate_memory() to try to +allocate from highmem if the number of pages allocated by +preallocate_image_memory() is too low. + +Modify free_unnecessary_pages() to take all possible memory +allocation patterns into account. + +Reported-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +Tested-by: M. Vefa Bicakci <bicave@superonline.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + kernel/power/snapshot.c | 85 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 65 insertions(+), 20 deletions(-) + +diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c +index 0652dcc..a204467 100644 +--- a/kernel/power/snapshot.c ++++ b/kernel/power/snapshot.c +@@ -1121,9 +1121,19 @@ static unsigned long preallocate_image_pages(unsigned long nr_pages, gfp_t mask) + return nr_alloc; + } + +-static unsigned long preallocate_image_memory(unsigned long nr_pages) ++static unsigned long preallocate_image_memory(unsigned long nr_pages, ++ unsigned long avail_normal) + { +- return preallocate_image_pages(nr_pages, GFP_IMAGE); ++ unsigned long alloc; ++ ++ if (avail_normal <= alloc_normal) ++ return 0; ++ ++ alloc = avail_normal - alloc_normal; ++ if (nr_pages < alloc) ++ alloc = nr_pages; ++ ++ return preallocate_image_pages(alloc, GFP_IMAGE); + } + + #ifdef CONFIG_HIGHMEM +@@ -1169,15 +1179,22 @@ static inline unsigned long preallocate_highmem_fraction(unsigned long nr_pages, + */ + static void free_unnecessary_pages(void) + { +- unsigned long save_highmem, to_free_normal, to_free_highmem; ++ unsigned long save, to_free_normal, to_free_highmem; + +- to_free_normal = alloc_normal - count_data_pages(); +- save_highmem = count_highmem_pages(); +- if (alloc_highmem > save_highmem) { +- to_free_highmem = alloc_highmem - save_highmem; ++ save = count_data_pages(); ++ if (alloc_normal >= save) { ++ to_free_normal = alloc_normal - save; ++ save = 0; ++ } else { ++ to_free_normal = 0; ++ save -= alloc_normal; ++ } ++ save += count_highmem_pages(); ++ if (alloc_highmem >= save) { ++ to_free_highmem = alloc_highmem - save; + } else { + to_free_highmem = 0; +- to_free_normal -= save_highmem - alloc_highmem; ++ to_free_normal -= save - alloc_highmem; + } + + memory_bm_position_reset(©_bm); +@@ -1258,7 +1275,7 @@ int hibernate_preallocate_memory(void) + { + struct zone *zone; + unsigned long saveable, size, max_size, count, highmem, pages = 0; +- unsigned long alloc, save_highmem, pages_highmem; ++ unsigned long alloc, save_highmem, pages_highmem, avail_normal; + struct timeval start, stop; + int error; + +@@ -1295,6 +1312,7 @@ int hibernate_preallocate_memory(void) + else + count += zone_page_state(zone, NR_FREE_PAGES); + } ++ avail_normal = count; + count += highmem; + count -= totalreserve_pages; + +@@ -1309,12 +1327,21 @@ int hibernate_preallocate_memory(void) + */ + if (size >= saveable) { + pages = preallocate_image_highmem(save_highmem); +- pages += preallocate_image_memory(saveable - pages); ++ pages += preallocate_image_memory(saveable - pages, avail_normal); + goto out; + } + + /* Estimate the minimum size of the image. */ + pages = minimum_image_size(saveable); ++ /* ++ * To avoid excessive pressure on the normal zone, leave room in it to ++ * accommodate an image of the minimum size (unless it's already too ++ * small, in which case don't preallocate pages from it at all). ++ */ ++ if (avail_normal > pages) ++ avail_normal -= pages; ++ else ++ avail_normal = 0; + if (size < pages) + size = min_t(unsigned long, pages, max_size); + +@@ -1335,16 +1362,34 @@ int hibernate_preallocate_memory(void) + */ + pages_highmem = preallocate_image_highmem(highmem / 2); + alloc = (count - max_size) - pages_highmem; +- pages = preallocate_image_memory(alloc); +- if (pages < alloc) +- goto err_out; +- size = max_size - size; +- alloc = size; +- size = preallocate_highmem_fraction(size, highmem, count); +- pages_highmem += size; +- alloc -= size; +- pages += preallocate_image_memory(alloc); +- pages += pages_highmem; ++ pages = preallocate_image_memory(alloc, avail_normal); ++ if (pages < alloc) { ++ /* We have exhausted non-highmem pages, try highmem. */ ++ alloc -= pages; ++ pages += pages_highmem; ++ pages_highmem = preallocate_image_highmem(alloc); ++ if (pages_highmem < alloc) ++ goto err_out; ++ pages += pages_highmem; ++ /* ++ * size is the desired number of saveable pages to leave in ++ * memory, so try to preallocate (all memory - size) pages. ++ */ ++ alloc = (count - pages) - size; ++ pages += preallocate_image_highmem(alloc); ++ } else { ++ /* ++ * There are approximately max_size saveable pages at this point ++ * and we want to reduce this number down to size. ++ */ ++ alloc = max_size - size; ++ size = preallocate_highmem_fraction(alloc, highmem, count); ++ pages_highmem += size; ++ alloc -= size; ++ size = preallocate_image_memory(alloc, avail_normal); ++ pages_highmem += preallocate_image_highmem(alloc - size); ++ pages += pages_highmem + size; ++ } + + /* + * We only need as many page frames for the image as there are saveable +-- +1.7.9.6 + diff --git a/queue/PM-Hibernate-Fix-free_unnecessary_pages.patch b/queue/PM-Hibernate-Fix-free_unnecessary_pages.patch new file mode 100644 index 0000000..fe46894 --- /dev/null +++ b/queue/PM-Hibernate-Fix-free_unnecessary_pages.patch @@ -0,0 +1,48 @@ +From 4ac80160f86ad8bef6e3a06ae7ed8d0fca06a6d6 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" <rjw@sisk.pl> +Date: Wed, 6 Jul 2011 20:15:23 +0200 +Subject: [PATCH] PM / Hibernate: Fix free_unnecessary_pages() + +commit 4d4cf23cdde2f8f9324f5684a7f349e182039529 upstream. + +There is a bug in free_unnecessary_pages() that causes it to +attempt to free too many pages in some cases, which triggers the +BUG_ON() in memory_bm_clear_bit() for copy_bm. Namely, if +count_data_pages() is initially greater than alloc_normal, we get +to_free_normal equal to 0 and "save" greater from 0. In that case, +if the sum of "save" and count_highmem_pages() is greater than +alloc_highmem, we subtract a positive number from to_free_normal. +Hence, since to_free_normal was 0 before the subtraction and is +an unsigned int, the result is converted to a huge positive number +that is used as the number of pages to free. + +Fix this bug by checking if to_free_normal is actually greater +than or equal to the number we're going to subtract from it. + +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +Reported-and-tested-by: Matthew Garrett <mjg@redhat.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + kernel/power/snapshot.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c +index a204467..5e16efe 100644 +--- a/kernel/power/snapshot.c ++++ b/kernel/power/snapshot.c +@@ -1194,7 +1194,11 @@ static void free_unnecessary_pages(void) + to_free_highmem = alloc_highmem - save; + } else { + to_free_highmem = 0; +- to_free_normal -= save - alloc_highmem; ++ save -= alloc_highmem; ++ if (to_free_normal > save) ++ to_free_normal -= save; ++ else ++ to_free_normal = 0; + } + + memory_bm_position_reset(©_bm); +-- +1.7.9.6 + diff --git a/queue/SUNRPC-Ensure-the-RPC-client-only-quits-on-fatal-sig.patch b/queue/SUNRPC-Ensure-the-RPC-client-only-quits-on-fatal-sig.patch new file mode 100644 index 0000000..70c9edf --- /dev/null +++ b/queue/SUNRPC-Ensure-the-RPC-client-only-quits-on-fatal-sig.patch @@ -0,0 +1,53 @@ +From 054f9d9b168aae937be347d00b0795138e1fb1bf Mon Sep 17 00:00:00 2001 +From: Trond Myklebust <Trond.Myklebust@netapp.com> +Date: Fri, 17 Jun 2011 10:14:59 -0400 +Subject: [PATCH] SUNRPC: Ensure the RPC client only quits on fatal signals + +commit 5afa9133cfe67f1bfead6049a9640c9262a7101c upstream. + +Fix a couple of instances where we were exiting the RPC client on +arbitrary signals. We should only do so on fatal signals. + +Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + net/sunrpc/auth_gss/auth_gss.c | 4 ++-- + net/sunrpc/clnt.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c +index c369ea6..891b59e 100644 +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -554,13 +554,13 @@ retry: + } + inode = &gss_msg->inode->vfs_inode; + for (;;) { +- prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE); ++ prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); + spin_lock(&inode->i_lock); + if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { + break; + } + spin_unlock(&inode->i_lock); +- if (signalled()) { ++ if (fatal_signal_pending(current)) { + err = -ERESTARTSYS; + goto out_intr; + } +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index 19c9983..0ad7828 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -939,7 +939,7 @@ call_allocate(struct rpc_task *task) + + dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid); + +- if (RPC_IS_ASYNC(task) || !signalled()) { ++ if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) { + task->tk_action = call_allocate; + rpc_delay(task, HZ>>4); + return; +-- +1.7.9.6 + diff --git a/queue/TTY-ldisc-do-not-close-until-there-are-readers.patch b/queue/TTY-ldisc-do-not-close-until-there-are-readers.patch new file mode 100644 index 0000000..ce9d211 --- /dev/null +++ b/queue/TTY-ldisc-do-not-close-until-there-are-readers.patch @@ -0,0 +1,104 @@ +From c0f48a5a05b0d54abd69e51fc086bc1eba207367 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby <jslaby@suse.cz> +Date: Sun, 5 Jun 2011 14:16:16 +0200 +Subject: [PATCH] TTY: ldisc, do not close until there are readers + +commit 92f6fa09bd453ffe3351fa1f1377a1b7cfa911e6 upstream. + +We restored tty_ldisc_wait_idle in 100eeae2c5c (TTY: restore +tty_ldisc_wait_idle). We used it in the ldisc changing path to fix the +case where there are tasks in n_tty_read waiting for data and somebody +tries to change ldisc. + +Similar to the case above, there may be also tasks waiting in +n_tty_read while hangup is performed. As 65b770468e98 (tty-ldisc: turn +ldisc user count into a proper refcount) removed the wait-until-idle +from all paths, hangup path won't wait for them to disappear either +now. So add it back even to the hangup path. + +There is a difference, we need uninterruptible sleep as there is +obviously HUP signal pending. So tty_ldisc_wait_idle now sleeps +without possibility to be interrupted. This is what original +tty_ldisc_wait_idle did. After the wait idle reintroduction +(100eeae2c5c), we have had interruptible sleeps for the ldisc changing +path. But as there is a 5s timeout anyway, we don't allow it to be +interrupted from now on. It's not worth the added complexity of +deciding what kind of sleep we want. + +Before 65b770468e98 tty_ldisc_release was called also from +tty_ldisc_release. It is called from tty_release, so I don't think we +need to restore that one. + +This is nicely reproducible after constifying the timing when +drivers/tty/n_tty.c is patched as follows ("TTY: ntty, add one more +sanity check" patch is needed to actually see it explode): +%% -1548,6 +1549,7 @@ static int n_tty_open(struct tty_struct *tty) + + /* These are ugly. Currently a malloc failure here can panic */ + if (!tty->read_buf) { ++ msleep(100); + tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); + if (!tty->read_buf) + return -ENOMEM; +%% -1785,6 +1788,7 @@ do_it_again: + break; + } + timeout = schedule_timeout(timeout); ++ msleep(20); + continue; + } + __set_current_state(TASK_RUNNING); +===== With a process: ===== + while (1) { + int fd = open(argv[1], O_RDWR); + read(fd, buf, sizeof(buf)); + close(fd); + } +===== and its child: ===== + setsid(); + while (1) { + int fd = open(tty, O_RDWR|O_NOCTTY); + ioctl(fd, TIOCSCTTY, 1); + vhangup(); + close(fd); + usleep(100 * (10 + random() % 1000)); + } +===== EOF ===== + +References: https://bugzilla.novell.com/show_bug.cgi?id=693374 +References: https://bugzilla.novell.com/show_bug.cgi?id=694509 +Signed-off-by: Jiri Slaby <jslaby@suse.cz> +Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +[PG: account for char --> tty file rename post 2.6.34] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/char/tty_ldisc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c +index 236628f..48de74a 100644 +--- a/drivers/char/tty_ldisc.c ++++ b/drivers/char/tty_ldisc.c +@@ -543,7 +543,7 @@ static int tty_ldisc_halt(struct tty_struct *tty) + static int tty_ldisc_wait_idle(struct tty_struct *tty) + { + int ret; +- ret = wait_event_interruptible_timeout(tty_ldisc_idle, ++ ret = wait_event_timeout(tty_ldisc_idle, + atomic_read(&tty->ldisc->users) == 1, 5 * HZ); + if (ret < 0) + return ret; +@@ -750,6 +750,8 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) + if (IS_ERR(ld)) + return -1; + ++ WARN_ON_ONCE(tty_ldisc_wait_idle(tty)); ++ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + tty->ldisc = NULL; +-- +1.7.9.6 + diff --git a/queue/USB-don-t-let-errors-prevent-system-sleep.patch b/queue/USB-don-t-let-errors-prevent-system-sleep.patch new file mode 100644 index 0000000..940c420 --- /dev/null +++ b/queue/USB-don-t-let-errors-prevent-system-sleep.patch @@ -0,0 +1,59 @@ +From 3d3b1c8f3d94fa30912e8cfc61530d52431b178b Mon Sep 17 00:00:00 2001 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Wed, 15 Jun 2011 16:27:43 -0400 +Subject: [PATCH] USB: don't let errors prevent system sleep + +commit 0af212ba8f123c2eba151af7726c34a50b127962 upstream. + +This patch (as1464) implements the recommended policy that most errors +during suspend or hibernation should not prevent the system from going +to sleep. In particular, failure to suspend a USB driver or a USB +device should not prevent the sleep from succeeding: + +Failure to suspend a device won't matter, because the device will +automatically go into suspend mode when the USB bus stops carrying +packets. (This might be less true for USB-3.0 devices, but let's not +worry about them now.) + +Failure of a driver to suspend might lead to trouble later on when the +system wakes up, but it isn't sufficient reason to prevent the system +from going to sleep. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/usb/core/driver.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index 212b5e82..f045f19 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1183,13 +1183,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) + for (i = n - 1; i >= 0; --i) { + intf = udev->actconfig->interface[i]; + status = usb_suspend_interface(udev, intf, msg); ++ ++ /* Ignore errors during system sleep transitions */ ++ if (!(msg.event & PM_EVENT_AUTO)) ++ status = 0; + if (status != 0) + break; + } + } +- if (status == 0) ++ if (status == 0) { + status = usb_suspend_device(udev, msg); + ++ /* Again, ignore errors during system sleep transitions */ ++ if (!(msg.event & PM_EVENT_AUTO)) ++ status = 0; ++ } ++ + /* If the suspend failed, resume interfaces that did get suspended */ + if (status != 0) { + msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME); +-- +1.7.9.6 + diff --git a/queue/USB-don-t-let-the-hub-driver-prevent-system-sleep.patch b/queue/USB-don-t-let-the-hub-driver-prevent-system-sleep.patch new file mode 100644 index 0000000..8209844 --- /dev/null +++ b/queue/USB-don-t-let-the-hub-driver-prevent-system-sleep.patch @@ -0,0 +1,68 @@ +From 3b71a1476d990d39b66e592231754579d47a5dc2 Mon Sep 17 00:00:00 2001 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Wed, 15 Jun 2011 16:29:16 -0400 +Subject: [PATCH] USB: don't let the hub driver prevent system sleep + +commit cbb330045e5df8f665ac60227ff898421fc8fb92 upstream. + +This patch (as1465) continues implementation of the policy that errors +during suspend or hibernation should not prevent the system from going +to sleep. + +In this case, failure to turn on the Suspend feature for a hub port +shouldn't be reported as an error. There are situations where this +does actually occur (such as when the device plugged into that port +was disconnected in the recent past), and it turns out to be harmless. +There's no reason for it to prevent a system sleep. + +Also, don't allow the hub driver to fail a system suspend if the +downstream ports aren't all suspended. This is also harmless (and +should never happen, given the change mentioned above); printing a +warning message in the kernel log is all we really need to do. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/usb/core/hub.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 642fc7e..40815d0 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2222,6 +2222,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); ++ ++ /* System sleep transitions should never fail */ ++ if (!(msg.event & PM_EVENT_AUTO)) ++ status = 0; + } else { + /* device has up to 10 msec to fully suspend */ + dev_dbg(&udev->dev, "usb %ssuspend\n", +@@ -2459,16 +2463,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) + struct usb_device *hdev = hub->hdev; + unsigned port1; + +- /* fail if children aren't already suspended */ ++ /* Warn if children aren't already suspended */ + for (port1 = 1; port1 <= hdev->maxchild; port1++) { + struct usb_device *udev; + + udev = hdev->children [port1-1]; + if (udev && udev->can_submit) { +- if (!(msg.event & PM_EVENT_AUTO)) +- dev_dbg(&intf->dev, "port %d nyet suspended\n", +- port1); +- return -EBUSY; ++ dev_warn(&intf->dev, "port %d nyet suspended\n", port1); ++ if (msg.event & PM_EVENT_AUTO) ++ return -EBUSY; + } + } + +-- +1.7.9.6 + diff --git a/queue/af_packet-prevent-information-leak.patch b/queue/af_packet-prevent-information-leak.patch new file mode 100644 index 0000000..124a77f --- /dev/null +++ b/queue/af_packet-prevent-information-leak.patch @@ -0,0 +1,64 @@ +From 14e6c9bd7e48dd99e54600d2c0351cd50c5b02b6 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet <eric.dumazet@gmail.com> +Date: Mon, 6 Jun 2011 22:42:06 -0700 +Subject: [PATCH] af_packet: prevent information leak + +commit 13fcb7bd322164c67926ffe272846d4860196dc6 upstream. + +In 2.6.27, commit 393e52e33c6c2 (packet: deliver VLAN TCI to userspace) +added a small information leak. + +Add padding field and make sure its zeroed before copy to user. + +Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> +CC: Patrick McHardy <kaber@trash.net> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + include/linux/if_packet.h | 2 ++ + net/packet/af_packet.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h +index aa57a5f..9b8dc3a 100644 +--- a/include/linux/if_packet.h ++++ b/include/linux/if_packet.h +@@ -60,6 +60,7 @@ struct tpacket_auxdata { + __u16 tp_mac; + __u16 tp_net; + __u16 tp_vlan_tci; ++ __u16 tp_padding; + }; + + /* Rx ring - header status */ +@@ -98,6 +99,7 @@ struct tpacket2_hdr { + __u32 tp_sec; + __u32 tp_nsec; + __u16 tp_vlan_tci; ++ __u16 tp_padding; + }; + + #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index b1bc2d2..4096a66 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -751,6 +751,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, + h.h2->tp_sec = ts.tv_sec; + h.h2->tp_nsec = ts.tv_nsec; + h.h2->tp_vlan_tci = vlan_tx_tag_get(skb); ++ h.h2->tp_padding = 0; + hdrlen = sizeof(*h.h2); + break; + default: +@@ -1617,6 +1618,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, + aux.tp_net = skb_network_offset(skb); + aux.tp_vlan_tci = vlan_tx_tag_get(skb); + ++ aux.tp_padding = 0; + put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux); + } + +-- +1.7.9.6 + diff --git a/queue/ath5k-fix-memory-leak-when-fewer-than-N_PD_CURVES-ar.patch b/queue/ath5k-fix-memory-leak-when-fewer-than-N_PD_CURVES-ar.patch new file mode 100644 index 0000000..ad3dada --- /dev/null +++ b/queue/ath5k-fix-memory-leak-when-fewer-than-N_PD_CURVES-ar.patch @@ -0,0 +1,46 @@ +From a5f5fbbd4ea75ae573b11c01d212bdbb95bfd526 Mon Sep 17 00:00:00 2001 +From: "Eugene A. Shatokhin" <dame_eugene@mail.ru> +Date: Tue, 28 Jun 2011 23:04:51 -0400 +Subject: [PATCH] ath5k: fix memory leak when fewer than N_PD_CURVES are in + use + +commit a0b8de350be458b33248e48b2174d9af8a4c4798 upstream. + +We would free the proper number of curves, but in the wrong +slots, due to a missing level of indirection through +the pdgain_idx table. + +It's simpler just to try to free all four slots, so do that. + +Signed-off-by: Bob Copeland <me@bobcopeland.com> +Signed-off-by: John W. Linville <linville@tuxdriver.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/net/wireless/ath/ath5k/eeprom.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c +index 67665cd..df1b8c4 100644 +--- a/drivers/net/wireless/ath/ath5k/eeprom.c ++++ b/drivers/net/wireless/ath/ath5k/eeprom.c +@@ -1590,14 +1590,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) + if (!chinfo[pier].pd_curves) + continue; + +- for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { ++ for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) { + struct ath5k_pdgain_info *pd = + &chinfo[pier].pd_curves[pdg]; + +- if (pd != NULL) { +- kfree(pd->pd_step); +- kfree(pd->pd_pwr); +- } ++ kfree(pd->pd_step); ++ kfree(pd->pd_pwr); + } + + kfree(chinfo[pier].pd_curves); +-- +1.7.9.6 + diff --git a/queue/bug.h-Add-WARN_RATELIMIT.patch b/queue/bug.h-Add-WARN_RATELIMIT.patch new file mode 100644 index 0000000..c77d9e2 --- /dev/null +++ b/queue/bug.h-Add-WARN_RATELIMIT.patch @@ -0,0 +1,50 @@ +From 8a3b78716fb0032ab97c63b81d104454815c785f Mon Sep 17 00:00:00 2001 +From: Joe Perches <joe@perches.com> +Date: Sat, 21 May 2011 07:48:39 +0000 +Subject: [PATCH] bug.h: Add WARN_RATELIMIT + +commit b3eec79b0776e5340a3db75b34953977c7e5086e upstream. + +Add a generic mechanism to ratelimit WARN(foo, fmt, ...) messages +using a hidden per call site static struct ratelimit_state. + +Also add an __WARN_RATELIMIT variant to be able to use a specific +struct ratelimit_state. + +Signed-off-by: Joe Perches <joe@perches.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + include/asm-generic/bug.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h +index 18c435d..bf58d4c 100644 +--- a/include/asm-generic/bug.h ++++ b/include/asm-generic/bug.h +@@ -135,6 +135,22 @@ extern void warn_slowpath_null(const char *file, const int line); + #define WARN_ON_RATELIMIT(condition, state) \ + WARN_ON((condition) && __ratelimit(state)) + ++#define __WARN_RATELIMIT(condition, state, format...) \ ++({ \ ++ int rtn = 0; \ ++ if (unlikely(__ratelimit(state))) \ ++ rtn = WARN(condition, format); \ ++ rtn; \ ++}) ++ ++#define WARN_RATELIMIT(condition, format...) \ ++({ \ ++ static DEFINE_RATELIMIT_STATE(_rs, \ ++ DEFAULT_RATELIMIT_INTERVAL, \ ++ DEFAULT_RATELIMIT_BURST); \ ++ __WARN_RATELIMIT(condition, &_rs, format); \ ++}) ++ + #ifdef CONFIG_SMP + # define WARN_ON_SMP(x) WARN_ON(x) + #else +-- +1.7.9.6 + diff --git a/queue/cfq-iosched-fix-a-rcu-warning.patch b/queue/cfq-iosched-fix-a-rcu-warning.patch new file mode 100644 index 0000000..26322c3 --- /dev/null +++ b/queue/cfq-iosched-fix-a-rcu-warning.patch @@ -0,0 +1,40 @@ +From db9f10dbcfdde67b3c0373e1f13f6ec6353db0ff Mon Sep 17 00:00:00 2001 +From: Shaohua Li <shaohua.li@intel.com> +Date: Mon, 27 Jun 2011 09:03:47 +0200 +Subject: [PATCH] cfq-iosched: fix a rcu warning + +commit 3181faa85bda3dc3f5e630a1846526c9caaa38e3 upstream. + +I got a rcu warnning at boot. the ioc->ioc_data is rcu_deferenced, but +doesn't hold rcu_read_lock. + +Signed-off-by: Shaohua Li <shaohua.li@intel.com> +Signed-off-by: Jens Axboe <jaxboe@fusionio.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + block/cfq-iosched.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 510552a..d39a07a 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -2559,11 +2559,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, + cic->dead_key = (unsigned long) cic->key; + cic->key = NULL; + ++ rcu_read_lock(); + if (rcu_dereference(ioc->ioc_data) == cic) { ++ rcu_read_unlock(); + spin_lock(&ioc->lock); + rcu_assign_pointer(ioc->ioc_data, NULL); + spin_unlock(&ioc->lock); +- } ++ } else ++ rcu_read_unlock(); + + if (cic->cfqq[BLK_RW_ASYNC]) { + cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); +-- +1.7.9.6 + diff --git a/queue/cfq-iosched-fix-locking-around-ioc-ioc_data-assignme.patch b/queue/cfq-iosched-fix-locking-around-ioc-ioc_data-assignme.patch new file mode 100644 index 0000000..523954b --- /dev/null +++ b/queue/cfq-iosched-fix-locking-around-ioc-ioc_data-assignme.patch @@ -0,0 +1,49 @@ +From ca2c5cec61bf02953bd842a9723250ff8bd1fe18 Mon Sep 17 00:00:00 2001 +From: Jens Axboe <jaxboe@fusionio.com> +Date: Sun, 5 Jun 2011 06:01:13 +0200 +Subject: [PATCH] cfq-iosched: fix locking around ioc->ioc_data assignment + +commit ab4bd22d3cce6977dc039664cc2d052e3147d662 upstream. + +Since we are modifying this RCU pointer, we need to hold +the lock protecting it around it. + +This fixes a potential reuse and double free of a cfq +io_context structure. The bug has been in CFQ for a long +time, it hit very few people but those it did hit seemed +to see it a lot. + +Tracked in RH bugzilla here: + +https://bugzilla.redhat.com/show_bug.cgi?id=577968 + +Credit goes to Paul Bolle for figuring out that the issue +was around the one-hit ioc->ioc_data cache. Thanks to his +hard work the issue is now fixed. + +Signed-off-by: Jens Axboe <jaxboe@fusionio.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + block/cfq-iosched.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c +index 4fab7c9..510552a 100644 +--- a/block/cfq-iosched.c ++++ b/block/cfq-iosched.c +@@ -2559,8 +2559,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd, + cic->dead_key = (unsigned long) cic->key; + cic->key = NULL; + +- if (ioc->ioc_data == cic) ++ if (rcu_dereference(ioc->ioc_data) == cic) { ++ spin_lock(&ioc->lock); + rcu_assign_pointer(ioc->ioc_data, NULL); ++ spin_unlock(&ioc->lock); ++ } + + if (cic->cfqq[BLK_RW_ASYNC]) { + cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); +-- +1.7.9.6 + diff --git a/queue/clocksource-Make-watchdog-robust-vs.-interruption.patch b/queue/clocksource-Make-watchdog-robust-vs.-interruption.patch new file mode 100644 index 0000000..8a5d811 --- /dev/null +++ b/queue/clocksource-Make-watchdog-robust-vs.-interruption.patch @@ -0,0 +1,104 @@ +From 80920901a04bc87a38541854947085d389770e7b Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Thu, 16 Jun 2011 16:22:08 +0200 +Subject: [PATCH] clocksource: Make watchdog robust vs. interruption + +commit b5199515c25cca622495eb9c6a8a1d275e775088 upstream. + +The clocksource watchdog code is interruptible and it has been +observed that this can trigger false positives which disable the TSC. + +The reason is that an interrupt storm or a long running interrupt +handler between the read of the watchdog source and the read of the +TSC brings the two far enough apart that the delta is larger than the +unstable treshold. Move both reads into a short interrupt disabled +region to avoid that. + +Reported-and-tested-by: Vernon Mauery <vernux@us.ibm.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + include/linux/clocksource.h | 1 + + kernel/time/clocksource.c | 24 +++++++++++++----------- + 2 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h +index 4bca8b6..f99e32b 100644 +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -192,6 +192,7 @@ struct clocksource { + #ifdef CONFIG_CLOCKSOURCE_WATCHDOG + /* Watchdog related data, used by the framework */ + struct list_head wd_list; ++ cycle_t cs_last; + cycle_t wd_last; + #endif + }; +diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c +index db24c5c..8569f91 100644 +--- a/kernel/time/clocksource.c ++++ b/kernel/time/clocksource.c +@@ -184,7 +184,6 @@ static struct clocksource *watchdog; + static struct timer_list watchdog_timer; + static DECLARE_WORK(watchdog_work, clocksource_watchdog_work); + static DEFINE_SPINLOCK(watchdog_lock); +-static cycle_t watchdog_last; + static int watchdog_running; + + static int clocksource_watchdog_kthread(void *data); +@@ -253,11 +252,6 @@ static void clocksource_watchdog(unsigned long data) + if (!watchdog_running) + goto out; + +- wdnow = watchdog->read(watchdog); +- wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask, +- watchdog->mult, watchdog->shift); +- watchdog_last = wdnow; +- + list_for_each_entry(cs, &watchdog_list, wd_list) { + + /* Clocksource already marked unstable? */ +@@ -267,19 +261,28 @@ static void clocksource_watchdog(unsigned long data) + continue; + } + ++ local_irq_disable(); + csnow = cs->read(cs); ++ wdnow = watchdog->read(watchdog); ++ local_irq_enable(); + + /* Clocksource initialized ? */ + if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) { + cs->flags |= CLOCK_SOURCE_WATCHDOG; +- cs->wd_last = csnow; ++ cs->wd_last = wdnow; ++ cs->cs_last = csnow; + continue; + } + +- /* Check the deviation from the watchdog clocksource. */ +- cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) & ++ wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask, ++ watchdog->mult, watchdog->shift); ++ ++ cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) & + cs->mask, cs->mult, cs->shift); +- cs->wd_last = csnow; ++ cs->cs_last = csnow; ++ cs->wd_last = wdnow; ++ ++ /* Check the deviation from the watchdog clocksource. */ + if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) { + clocksource_unstable(cs, cs_nsec - wd_nsec); + continue; +@@ -317,7 +320,6 @@ static inline void clocksource_start_watchdog(void) + return; + init_timer(&watchdog_timer); + watchdog_timer.function = clocksource_watchdog; +- watchdog_last = watchdog->read(watchdog); + watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL; + add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask)); + watchdog_running = 1; +-- +1.7.9.6 + diff --git a/queue/debugobjects-Fix-boot-crash-when-kmemleak-and-debugo.patch b/queue/debugobjects-Fix-boot-crash-when-kmemleak-and-debugo.patch new file mode 100644 index 0000000..3f6bac0 --- /dev/null +++ b/queue/debugobjects-Fix-boot-crash-when-kmemleak-and-debugo.patch @@ -0,0 +1,66 @@ +From baf705661782e05364c072910c7c41e41d020921 Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz <marcin.slusarz@gmail.com> +Date: Sat, 28 May 2011 13:23:42 +0200 +Subject: [PATCH] debugobjects: Fix boot crash when kmemleak and debugobjects + enabled + +commit 161b6ae0e067e421b20bb35caf66bdb405c929ac upstream. + +Order of initialization look like this: +... +debugobjects +kmemleak +...(lots of other subsystems)... +workqueues (through early initcall) +... + +debugobjects use schedule_work for batch freeing of its data and kmemleak +heavily use debugobjects, so when it comes to freeing and workqueues were +not initialized yet, kernel crashes: + +BUG: unable to handle kernel NULL pointer dereference at (null) +IP: [<ffffffff810854d1>] __queue_work+0x29/0x41a + [<ffffffff81085910>] queue_work_on+0x16/0x1d + [<ffffffff81085abc>] queue_work+0x29/0x55 + [<ffffffff81085afb>] schedule_work+0x13/0x15 + [<ffffffff81242de1>] free_object+0x90/0x95 + [<ffffffff81242f6d>] debug_check_no_obj_freed+0x187/0x1d3 + [<ffffffff814b6504>] ? _raw_spin_unlock_irqrestore+0x30/0x4d + [<ffffffff8110bd14>] ? free_object_rcu+0x68/0x6d + [<ffffffff8110890c>] kmem_cache_free+0x64/0x12c + [<ffffffff8110bd14>] free_object_rcu+0x68/0x6d + [<ffffffff810b58bc>] __rcu_process_callbacks+0x1b6/0x2d9 +... + +because system_wq is NULL. + +Fix it by checking if workqueues susbystem was initialized before using. + +Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com> +Cc: Catalin Marinas <catalin.marinas@arm.com> +Cc: Tejun Heo <tj@kernel.org> +Cc: Dipankar Sarma <dipankar@in.ibm.com> +Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> +Link: http://lkml.kernel.org/r/20110528112342.GA3068@joi.lan +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + lib/debugobjects.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/debugobjects.c b/lib/debugobjects.c +index b862b30..e60bd59 100644 +--- a/lib/debugobjects.c ++++ b/lib/debugobjects.c +@@ -197,7 +197,7 @@ static void free_object(struct debug_obj *obj) + * initialized: + */ + if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache) +- sched = !work_pending(&debug_obj_work); ++ sched = keventd_up() && !work_pending(&debug_obj_work); + hlist_add_head(&obj->node, &obj_pool); + obj_pool_free++; + obj_pool_used--; +-- +1.7.9.6 + diff --git a/queue/i2c-taos-evm-Fix-log-messages.patch b/queue/i2c-taos-evm-Fix-log-messages.patch new file mode 100644 index 0000000..4c5d572 --- /dev/null +++ b/queue/i2c-taos-evm-Fix-log-messages.patch @@ -0,0 +1,60 @@ +From 88c47b48065d15504bdea92d33e38f4b3399f640 Mon Sep 17 00:00:00 2001 +From: Jean Delvare <khali@linux-fr.org> +Date: Wed, 29 Jun 2011 11:36:10 +0200 +Subject: [PATCH] i2c-taos-evm: Fix log messages + +commit 9b640f2e154268cb516efcaf9c434f2e73c6783e upstream. + +* Print all error and information messages even when debugging is + disabled. +* Don't use adapter device to log messages before it is ready. + +Signed-off-by: Jean Delvare <khali@linux-fr.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/i2c/busses/i2c-taos-evm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c +index dd39c1e..26c352a 100644 +--- a/drivers/i2c/busses/i2c-taos-evm.c ++++ b/drivers/i2c/busses/i2c-taos-evm.c +@@ -234,7 +234,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) + + if (taos->state != TAOS_STATE_IDLE) { + err = -ENODEV; +- dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, " ++ dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, " + "pos=%d)\n", taos->state, taos->pos); + goto exit_close; + } +@@ -255,7 +255,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) + msecs_to_jiffies(250)); + if (taos->state != TAOS_STATE_IDLE) { + err = -ENODEV; +- dev_err(&adapter->dev, "Echo off failed " ++ dev_err(&serio->dev, "TAOS EVM echo off failed " + "(state=%d)\n", taos->state); + goto exit_close; + } +@@ -263,7 +263,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) + err = i2c_add_adapter(adapter); + if (err) + goto exit_close; +- dev_dbg(&serio->dev, "Connected to TAOS EVM\n"); ++ dev_info(&serio->dev, "Connected to TAOS EVM\n"); + + taos->client = taos_instantiate_device(adapter); + return 0; +@@ -288,7 +288,7 @@ static void taos_disconnect(struct serio *serio) + serio_set_drvdata(serio, NULL); + kfree(taos); + +- dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n"); ++ dev_info(&serio->dev, "Disconnected from TAOS EVM\n"); + } + + static struct serio_device_id taos_serio_ids[] = { +-- +1.7.9.6 + diff --git a/queue/ipv6-udp-Use-the-correct-variable-to-determine-non-b.patch b/queue/ipv6-udp-Use-the-correct-variable-to-determine-non-b.patch new file mode 100644 index 0000000..d882b5b --- /dev/null +++ b/queue/ipv6-udp-Use-the-correct-variable-to-determine-non-b.patch @@ -0,0 +1,67 @@ +From bd1789ad1bec25dd89a1d13781c0a6e5e40288f3 Mon Sep 17 00:00:00 2001 +From: Xufeng Zhang <xufeng.zhang@windriver.com> +Date: Tue, 21 Jun 2011 10:43:39 +0000 +Subject: [PATCH] ipv6/udp: Use the correct variable to determine non-blocking + condition + +commit 32c90254ed4a0c698caa0794ebb4de63fcc69631 upstream. + +udpv6_recvmsg() function is not using the correct variable to determine +whether or not the socket is in non-blocking operation, this will lead +to unexpected behavior when a UDP checksum error occurs. + +Consider a non-blocking udp receive scenario: when udpv6_recvmsg() is +called by sock_common_recvmsg(), MSG_DONTWAIT bit of flags variable in +udpv6_recvmsg() is cleared by "flags & ~MSG_DONTWAIT" in this call: + + err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT, + flags & ~MSG_DONTWAIT, &addr_len); + +i.e. with udpv6_recvmsg() getting these values: + + int noblock = flags & MSG_DONTWAIT + int flags = flags & ~MSG_DONTWAIT + +So, when udp checksum error occurs, the execution will go to +csum_copy_err, and then the problem happens: + + csum_copy_err: + ............... + if (flags & MSG_DONTWAIT) + return -EAGAIN; + goto try_again; + ............... + +But it will always go to try_again as MSG_DONTWAIT has been cleared +from flags at call time -- only noblock contains the original value +of MSG_DONTWAIT, so the test should be: + + if (noblock) + return -EAGAIN; + +This is also consistent with what the ipv4/udp code does. + +Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + net/ipv6/udp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 479f926..a0a6a08 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -441,7 +441,7 @@ csum_copy_err: + } + release_sock(sk); + +- if (flags & MSG_DONTWAIT) ++ if (noblock) + return -EAGAIN; + goto try_again; + } +-- +1.7.9.6 + diff --git a/queue/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch b/queue/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch new file mode 100644 index 0000000..6c46549 --- /dev/null +++ b/queue/ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch @@ -0,0 +1,87 @@ +From 12d0af8817be7d08486d3602ad279db70521189c Mon Sep 17 00:00:00 2001 +From: Hugh Dickins <hughd@google.com> +Date: Wed, 15 Jun 2011 15:08:58 -0700 +Subject: [PATCH] ksm: fix NULL pointer dereference in + scan_get_next_rmap_item() + +commit 2b472611a32a72f4a118c069c2d62a1a3f087afd upstream. + +Andrea Righi reported a case where an exiting task can race against +ksmd::scan_get_next_rmap_item (http://lkml.org/lkml/2011/6/1/742) easily +triggering a NULL pointer dereference in ksmd. + +ksm_scan.mm_slot == &ksm_mm_head with only one registered mm + +CPU 1 (__ksm_exit) CPU 2 (scan_get_next_rmap_item) + list_empty() is false +lock slot == &ksm_mm_head +list_del(slot->mm_list) +(list now empty) +unlock + lock + slot = list_entry(slot->mm_list.next) + (list is empty, so slot is still ksm_mm_head) + unlock + slot->mm == NULL ... Oops + +Close this race by revalidating that the new slot is not simply the list +head again. + +Andrea's test case: + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> + +#define BUFSIZE getpagesize() + +int main(int argc, char **argv) +{ + void *ptr; + + if (posix_memalign(&ptr, getpagesize(), BUFSIZE) < 0) { + perror("posix_memalign"); + exit(1); + } + if (madvise(ptr, BUFSIZE, MADV_MERGEABLE) < 0) { + perror("madvise"); + exit(1); + } + *(char *)NULL = 0; + + return 0; +} + +Reported-by: Andrea Righi <andrea@betterlinux.com> +Tested-by: Andrea Righi <andrea@betterlinux.com> +Cc: Andrea Arcangeli <aarcange@redhat.com> +Signed-off-by: Hugh Dickins <hughd@google.com> +Signed-off-by: Chris Wright <chrisw@sous-sol.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/ksm.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/mm/ksm.c b/mm/ksm.c +index 956880f..5e8e222 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -1270,6 +1270,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page) + slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list); + ksm_scan.mm_slot = slot; + spin_unlock(&ksm_mmlist_lock); ++ /* ++ * Although we tested list_empty() above, a racing __ksm_exit ++ * of the last mm on the list may have removed it since then. ++ */ ++ if (slot == &ksm_mm_head) ++ return NULL; + next_mm: + ksm_scan.address = 0; + ksm_scan.rmap_list = &slot->rmap_list; +-- +1.7.9.6 + diff --git a/queue/md-avoid-endless-recovery-loop-when-waiting-for-fail.patch b/queue/md-avoid-endless-recovery-loop-when-waiting-for-fail.patch new file mode 100644 index 0000000..8e613db --- /dev/null +++ b/queue/md-avoid-endless-recovery-loop-when-waiting-for-fail.patch @@ -0,0 +1,45 @@ +From 2cb2936f7fd7e15ac810a52a20690f96727482c8 Mon Sep 17 00:00:00 2001 +From: NeilBrown <neilb@suse.de> +Date: Tue, 28 Jun 2011 16:59:42 +1000 +Subject: [PATCH] md: avoid endless recovery loop when waiting for fail device + to complete. + +commit 4274215d24633df7302069e51426659d4759c5ed upstream. + +If a device fails in a way that causes pending request to take a while +to complete, md will not be able to immediately remove it from the +array in remove_and_add_spares. +It will then incorrectly look like a spare device and md will try to +recover it even though it is failed. +This leads to a recovery process starting and instantly aborting over +and over again. + +We should check if the device is faulty before considering it to be a +spare. This will avoid trying to start a recovery that cannot +proceed. + +This bug was introduced in 2.6.26 so that patch is suitable for any +kernel since then. + +Reported-by: Jim Paradis <james.paradis@stratus.com> +Signed-off-by: NeilBrown <neilb@suse.de> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/md/md.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 1287b03..d26df7f 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -6863,6 +6863,7 @@ static int remove_and_add_spares(mddev_t *mddev) + list_for_each_entry(rdev, &mddev->disks, same_set) { + if (rdev->raid_disk >= 0 && + !test_bit(In_sync, &rdev->flags) && ++ !test_bit(Faulty, &rdev->flags) && + !test_bit(Blocked, &rdev->flags)) + spares++; + if (rdev->raid_disk < 0 +-- +1.7.9.6 + diff --git a/queue/migrate-don-t-account-swapcache-as-shmem.patch b/queue/migrate-don-t-account-swapcache-as-shmem.patch new file mode 100644 index 0000000..09bdffc --- /dev/null +++ b/queue/migrate-don-t-account-swapcache-as-shmem.patch @@ -0,0 +1,38 @@ +From 2a2a098d4d647867633a17917b96f0feacdcdd8d Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli <aarcange@redhat.com> +Date: Thu, 16 Jun 2011 12:56:19 -0700 +Subject: [PATCH] migrate: don't account swapcache as shmem + +commit 99a15e21d96f6857dafab1e5167e5e8183215c9c upstream. + +swapcache will reach the below code path in migrate_page_move_mapping, +and swapcache is accounted as NR_FILE_PAGES but it's not accounted as +NR_SHMEM. + +Hugh pointed out we must use PageSwapCache instead of comparing +mapping to &swapper_space, to avoid build failure with CONFIG_SWAP=n. + +Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> +Acked-by: Hugh Dickins <hughd@google.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/migrate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index d3f3f7f..c8e7195 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -262,7 +262,7 @@ static int migrate_page_move_mapping(struct address_space *mapping, + */ + __dec_zone_page_state(page, NR_FILE_PAGES); + __inc_zone_page_state(newpage, NR_FILE_PAGES); +- if (PageSwapBacked(page)) { ++ if (!PageSwapCache(page) && PageSwapBacked(page)) { + __dec_zone_page_state(page, NR_SHMEM); + __inc_zone_page_state(newpage, NR_SHMEM); + } +-- +1.7.9.6 + diff --git a/queue/mm-fix-negative-commitlimit-when-gigantic-hugepages-.patch b/queue/mm-fix-negative-commitlimit-when-gigantic-hugepages-.patch new file mode 100644 index 0000000..0347901 --- /dev/null +++ b/queue/mm-fix-negative-commitlimit-when-gigantic-hugepages-.patch @@ -0,0 +1,76 @@ +From c9160be4ea528ca36d7cbdc86664919e691fd87d Mon Sep 17 00:00:00 2001 +From: Rafael Aquini <aquini@linux.com> +Date: Wed, 15 Jun 2011 15:08:39 -0700 +Subject: [PATCH] mm: fix negative commitlimit when gigantic hugepages are + allocated + +commit b0320c7b7d1ac1bd5c2d9dff3258524ab39bad32 upstream. + +When 1GB hugepages are allocated on a system, free(1) reports less +available memory than what really is installed in the box. Also, if the +total size of hugepages allocated on a system is over half of the total +memory size, CommitLimit becomes a negative number. + +The problem is that gigantic hugepages (order > MAX_ORDER) can only be +allocated at boot with bootmem, thus its frames are not accounted to +'totalram_pages'. However, they are accounted to hugetlb_total_pages() + +What happens to turn CommitLimit into a negative number is this +calculation, in fs/proc/meminfo.c: + + allowed = ((totalram_pages - hugetlb_total_pages()) + * sysctl_overcommit_ratio / 100) + total_swap_pages; + +A similar calculation occurs in __vm_enough_memory() in mm/mmap.c. + +Also, every vm statistic which depends on 'totalram_pages' will render +confusing values, as if system were 'missing' some part of its memory. + +Impact of this bug: + +When gigantic hugepages are allocated and sysctl_overcommit_memory == +OVERCOMMIT_NEVER. In a such situation, __vm_enough_memory() goes through +the mentioned 'allowed' calculation and might end up mistakenly returning +-ENOMEM, thus forcing the system to start reclaiming pages earlier than it +would be ususal, and this could cause detrimental impact to overall +system's performance, depending on the workload. + +Besides the aforementioned scenario, I can only think of this causing +annoyances with memory reports from /proc/meminfo and free(1). + +[akpm@linux-foundation.org: standardize comment layout] +Reported-by: Russ Anderson <rja@sgi.com> +Signed-off-by: Rafael Aquini <aquini@linux.com> +Acked-by: Russ Anderson <rja@sgi.com> +Cc: Andrea Arcangeli <aarcange@redhat.com> +Cc: Christoph Lameter <cl@linux.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> + +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + mm/hugetlb.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 2583bbe..ca9ce49 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -1105,6 +1105,14 @@ static void __init gather_bootmem_prealloc(void) + WARN_ON(page_count(page) != 1); + prep_compound_huge_page(page, h->order); + prep_new_huge_page(h, page, page_to_nid(page)); ++ /* ++ * If we had gigantic hugepages allocated at boot time, we need ++ * to restore the 'stolen' pages to totalram_pages in order to ++ * fix confusing memory reports from free(1) and another ++ * side-effects, like CommitLimit going negative. ++ */ ++ if (h->order > (MAX_ORDER - 1)) ++ totalram_pages += 1 << h->order; + } + } + +-- +1.7.9.6 + diff --git a/queue/mm-prevent-concurrent-unmap_mapping_range-on-the-sam.patch b/queue/mm-prevent-concurrent-unmap_mapping_range-on-the-sam.patch new file mode 100644 index 0000000..9cae097 --- /dev/null +++ b/queue/mm-prevent-concurrent-unmap_mapping_range-on-the-sam.patch @@ -0,0 +1,213 @@ +From fc028e033f94529921b8d84a72281c750fc7ecbd Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi <mszeredi@suse.cz> +Date: Wed, 23 Feb 2011 13:49:47 +0100 +Subject: [PATCH] mm: prevent concurrent unmap_mapping_range() on the same + inode + +commit 2aa15890f3c191326678f1bd68af61ec6b8753ec upstream. + +Michael Leun reported that running parallel opens on a fuse filesystem +can trigger a "kernel BUG at mm/truncate.c:475" + +Gurudas Pai reported the same bug on NFS. + +The reason is, unmap_mapping_range() is not prepared for more than +one concurrent invocation per inode. For example: + + thread1: going through a big range, stops in the middle of a vma and + stores the restart address in vm_truncate_count. + + thread2: comes in with a small (e.g. single page) unmap request on + the same vma, somewhere before restart_address, finds that the + vma was already unmapped up to the restart address and happily + returns without doing anything. + +Another scenario would be two big unmap requests, both having to +restart the unmapping and each one setting vm_truncate_count to its +own value. This could go on forever without any of them being able to +finish. + +Truncate and hole punching already serialize with i_mutex. Other +callers of unmap_mapping_range() do not, and it's difficult to get +i_mutex protection for all callers. In particular ->d_revalidate(), +which calls invalidate_inode_pages2_range() in fuse, may be called +with or without i_mutex. + +This patch adds a new mutex to 'struct address_space' to prevent +running multiple concurrent unmap_mapping_range() on the same mapping. + +[ We'll hopefully get rid of all this with the upcoming mm + preemptibility series by Peter Zijlstra, the "mm: Remove i_mmap_mutex + lockbreak" patch in particular. But that is for 2.6.39 ] + +Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> +Reported-by: Michael Leun <lkml20101129@newton.leun.net> +Reported-by: Gurudas Pai <gurudas.pai@oracle.com> +Tested-by: Gurudas Pai <gurudas.pai@oracle.com> +Acked-by: Hugh Dickins <hughd@google.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[Some chunks dropped, since no ebdfed4dc5 in 34; came in at 2.6.37] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + fs/gfs2/main.c | 9 +-------- + fs/inode.c | 22 +++++++++++++++------- + fs/nilfs2/btnode.c | 14 -------------- + fs/nilfs2/btnode.h | 1 - + fs/nilfs2/super.c | 2 +- + include/linux/fs.h | 2 ++ + mm/memory.c | 2 ++ + 7 files changed, 21 insertions(+), 31 deletions(-) + +diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c +index a88fadc..79ebf86 100644 +--- a/fs/gfs2/main.c ++++ b/fs/gfs2/main.c +@@ -58,14 +58,7 @@ static void gfs2_init_gl_aspace_once(void *foo) + struct address_space *mapping = (struct address_space *)(gl + 1); + + gfs2_init_glock_once(gl); +- memset(mapping, 0, sizeof(*mapping)); +- INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); +- spin_lock_init(&mapping->tree_lock); +- spin_lock_init(&mapping->i_mmap_lock); +- INIT_LIST_HEAD(&mapping->private_list); +- spin_lock_init(&mapping->private_lock); +- INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); +- INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); ++ address_space_init_once(mapping); + } + + /** +diff --git a/fs/inode.c b/fs/inode.c +index 407bf39..f84377a 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -245,6 +245,20 @@ void destroy_inode(struct inode *inode) + kmem_cache_free(inode_cachep, (inode)); + } + ++void address_space_init_once(struct address_space *mapping) ++{ ++ memset(mapping, 0, sizeof(*mapping)); ++ INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); ++ spin_lock_init(&mapping->tree_lock); ++ spin_lock_init(&mapping->i_mmap_lock); ++ INIT_LIST_HEAD(&mapping->private_list); ++ spin_lock_init(&mapping->private_lock); ++ INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); ++ INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); ++ mutex_init(&mapping->unmap_mutex); ++} ++EXPORT_SYMBOL(address_space_init_once); ++ + /* + * These are initializations that only need to be done + * once, because the fields are idempotent across use +@@ -256,13 +270,7 @@ void inode_init_once(struct inode *inode) + INIT_HLIST_NODE(&inode->i_hash); + INIT_LIST_HEAD(&inode->i_dentry); + INIT_LIST_HEAD(&inode->i_devices); +- INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); +- spin_lock_init(&inode->i_data.tree_lock); +- spin_lock_init(&inode->i_data.i_mmap_lock); +- INIT_LIST_HEAD(&inode->i_data.private_list); +- spin_lock_init(&inode->i_data.private_lock); +- INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap); +- INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); ++ address_space_init_once(&inode->i_data); + i_size_ordered_init(inode); + #ifdef CONFIG_INOTIFY + INIT_LIST_HEAD(&inode->inotify_watches); +diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c +index 447ce47..bebb9a9 100644 +--- a/fs/nilfs2/btnode.c ++++ b/fs/nilfs2/btnode.c +@@ -34,20 +34,6 @@ + #include "page.h" + #include "btnode.h" + +- +-void nilfs_btnode_cache_init_once(struct address_space *btnc) +-{ +- memset(btnc, 0, sizeof(*btnc)); +- INIT_RADIX_TREE(&btnc->page_tree, GFP_ATOMIC); +- spin_lock_init(&btnc->tree_lock); +- INIT_LIST_HEAD(&btnc->private_list); +- spin_lock_init(&btnc->private_lock); +- +- spin_lock_init(&btnc->i_mmap_lock); +- INIT_RAW_PRIO_TREE_ROOT(&btnc->i_mmap); +- INIT_LIST_HEAD(&btnc->i_mmap_nonlinear); +-} +- + static const struct address_space_operations def_btnode_aops = { + .sync_page = block_sync_page, + }; +diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h +index 07da83f..fa2f1e6 100644 +--- a/fs/nilfs2/btnode.h ++++ b/fs/nilfs2/btnode.h +@@ -37,7 +37,6 @@ struct nilfs_btnode_chkey_ctxt { + struct buffer_head *newbh; + }; + +-void nilfs_btnode_cache_init_once(struct address_space *); + void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *); + void nilfs_btnode_cache_clear(struct address_space *); + struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, +diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c +index fadefe1..bce4109 100644 +--- a/fs/nilfs2/super.c ++++ b/fs/nilfs2/super.c +@@ -163,7 +163,7 @@ static void init_once(void *obj) + #ifdef CONFIG_NILFS_XATTR + init_rwsem(&ii->xattr_sem); + #endif +- nilfs_btnode_cache_init_once(&ii->i_btnode_cache); ++ address_space_init_once(&ii->i_btnode_cache); + ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; + inode_init_once(&ii->vfs_inode); + } +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 8aa6bd9..2e97c2c 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -638,6 +638,7 @@ struct address_space { + spinlock_t private_lock; /* for use by the address_space */ + struct list_head private_list; /* ditto */ + struct address_space *assoc_mapping; /* ditto */ ++ struct mutex unmap_mutex; /* to protect unmapping */ + } __attribute__((aligned(sizeof(long)))); + /* + * On most architectures that alignment is already the case; but +@@ -2145,6 +2146,7 @@ extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); + + extern int inode_init_always(struct super_block *, struct inode *); + extern void inode_init_once(struct inode *); ++extern void address_space_init_once(struct address_space *mapping); + extern void inode_add_to_lists(struct super_block *, struct inode *); + extern void iput(struct inode *); + extern struct inode * igrab(struct inode *); +diff --git a/mm/memory.c b/mm/memory.c +index 3410236..43dc216 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -2564,6 +2564,7 @@ void unmap_mapping_range(struct address_space *mapping, + details.last_index = ULONG_MAX; + details.i_mmap_lock = &mapping->i_mmap_lock; + ++ mutex_lock(&mapping->unmap_mutex); + spin_lock(&mapping->i_mmap_lock); + + /* Protect against endless unmapping loops */ +@@ -2580,6 +2581,7 @@ void unmap_mapping_range(struct address_space *mapping, + if (unlikely(!list_empty(&mapping->i_mmap_nonlinear))) + unmap_mapping_range_list(&mapping->i_mmap_nonlinear, &details); + spin_unlock(&mapping->i_mmap_lock); ++ mutex_unlock(&mapping->unmap_mutex); + } + EXPORT_SYMBOL(unmap_mapping_range); + +-- +1.7.9.6 + diff --git a/queue/net-filter-Use-WARN_RATELIMIT.patch b/queue/net-filter-Use-WARN_RATELIMIT.patch new file mode 100644 index 0000000..1346d4c --- /dev/null +++ b/queue/net-filter-Use-WARN_RATELIMIT.patch @@ -0,0 +1,36 @@ +From 022f572269db33de6bfca7279110c6fc6adb8bac Mon Sep 17 00:00:00 2001 +From: Joe Perches <joe@perches.com> +Date: Sat, 21 May 2011 07:48:40 +0000 +Subject: [PATCH] net: filter: Use WARN_RATELIMIT + +commit 6c4a5cb219520c7bc937ee186ca53f03733bd09f upstream. + +A mis-configured filter can spam the logs with lots of stack traces. + +Rate-limit the warnings and add printout of the bogus filter information. + +Original-patch-by: Ben Greear <greearb@candelatech.com> +Signed-off-by: Joe Perches <joe@perches.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/core/filter.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 2bc5376..85d1340 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -292,7 +292,9 @@ load_b: + mem[f_k] = X; + continue; + default: +- WARN_ON(1); ++ WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n", ++ fentry->code, fentry->jt, ++ fentry->jf, fentry->k); + return 0; + } + +-- +1.7.9.6 + diff --git a/queue/net-ipv4-Check-for-mistakenly-passed-in-non-IPv4-add.patch b/queue/net-ipv4-Check-for-mistakenly-passed-in-non-IPv4-add.patch new file mode 100644 index 0000000..140ebc2 --- /dev/null +++ b/queue/net-ipv4-Check-for-mistakenly-passed-in-non-IPv4-add.patch @@ -0,0 +1,35 @@ +From 7afb3cce71c1ce45ac675073f7a29b4b61e05d71 Mon Sep 17 00:00:00 2001 +From: Marcus Meissner <meissner@suse.de> +Date: Wed, 1 Jun 2011 21:05:22 -0700 +Subject: [PATCH] net/ipv4: Check for mistakenly passed in non-IPv4 address + +commit d0733d2e29b652b2e7b1438ececa732e4eed98eb upstream. + +Check against mistakenly passing in IPv6 addresses (which would result +in an INADDR_ANY bind) or similar incompatible sockaddrs. + +Signed-off-by: Marcus Meissner <meissner@suse.de> +Cc: Reinhard Max <max@suse.de> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + net/ipv4/af_inet.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index f713574..8897b3c 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -462,6 +462,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) + if (addr_len < sizeof(struct sockaddr_in)) + goto out; + ++ if (addr->sin_family != AF_INET) ++ goto out; ++ + chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); + + /* Not specified by any standard per-se, however it breaks too +-- +1.7.9.6 + diff --git a/queue/series b/queue/series index 4f7139e..db7aae4 100644 --- a/queue/series +++ b/queue/series @@ -74,3 +74,33 @@ xen-events-do-not-unmask-event-channels-on-resume.patch genirq-Add-IRQF_FORCE_RESUME.patch xen-Use-IRQF_FORCE_RESUME.patch time-Compensate-for-rounding-on-odd-frequency-clocks.patch +ksm-fix-NULL-pointer-dereference-in-scan_get_next_rm.patch +migrate-don-t-account-swapcache-as-shmem.patch +xen-partially-revert-xen-set-max_pfn_mapped-to-the-l.patch +clocksource-Make-watchdog-robust-vs.-interruption.patch +TTY-ldisc-do-not-close-until-there-are-readers.patch +xhci-Reject-double-add-of-active-endpoints.patch +PM-Free-memory-bitmaps-if-opening-dev-snapshot-fails.patch +ath5k-fix-memory-leak-when-fewer-than-N_PD_CURVES-ar.patch +mm-fix-negative-commitlimit-when-gigantic-hugepages-.patch +uvcvideo-Remove-buffers-from-the-queues-when-freeing.patch +watchdog-mtx1-wdt-request-gpio-before-using-it.patch +debugobjects-Fix-boot-crash-when-kmemleak-and-debugo.patch +cfq-iosched-fix-locking-around-ioc-ioc_data-assignme.patch +cfq-iosched-fix-a-rcu-warning.patch +i2c-taos-evm-Fix-log-messages.patch +md-avoid-endless-recovery-loop-when-waiting-for-fail.patch +SUNRPC-Ensure-the-RPC-client-only-quits-on-fatal-sig.patch +6pack-mkiss-fix-lock-inconsistency.patch +USB-don-t-let-errors-prevent-system-sleep.patch +USB-don-t-let-the-hub-driver-prevent-system-sleep.patch +uml-fix-CONFIG_STATIC_LINK-y-build-failure-with-newe.patch +PM-Hibernate-Avoid-hitting-OOM-during-preallocation-.patch +PM-Hibernate-Fix-free_unnecessary_pages.patch +bug.h-Add-WARN_RATELIMIT.patch +net-filter-Use-WARN_RATELIMIT.patch +af_packet-prevent-information-leak.patch +net-ipv4-Check-for-mistakenly-passed-in-non-IPv4-add.patch +ipv6-udp-Use-the-correct-variable-to-determine-non-b.patch +udp-recvmsg-Clear-MSG_TRUNC-flag-when-starting-over-.patch +mm-prevent-concurrent-unmap_mapping_range-on-the-sam.patch diff --git a/queue/udp-recvmsg-Clear-MSG_TRUNC-flag-when-starting-over-.patch b/queue/udp-recvmsg-Clear-MSG_TRUNC-flag-when-starting-over-.patch new file mode 100644 index 0000000..50d6c83 --- /dev/null +++ b/queue/udp-recvmsg-Clear-MSG_TRUNC-flag-when-starting-over-.patch @@ -0,0 +1,59 @@ +From 371e284d09022f4f28596784bad9c5a4fc6dc6bb Mon Sep 17 00:00:00 2001 +From: Xufeng Zhang <xufeng.zhang@windriver.com> +Date: Tue, 21 Jun 2011 10:43:40 +0000 +Subject: [PATCH] udp/recvmsg: Clear MSG_TRUNC flag when starting over for a + new packet + +commit 9cfaa8def1c795a512bc04f2aec333b03724ca2e upstream. + +Consider this scenario: When the size of the first received udp packet +is bigger than the receive buffer, MSG_TRUNC bit is set in msg->msg_flags. +However, if checksum error happens and this is a blocking socket, it will +goto try_again loop to receive the next packet. But if the size of the +next udp packet is smaller than receive buffer, MSG_TRUNC flag should not +be set, but because MSG_TRUNC bit is not cleared in msg->msg_flags before +receive the next packet, MSG_TRUNC is still set, which is wrong. + +Fix this problem by clearing MSG_TRUNC flag when starting over for a +new packet. + +Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + net/ipv4/udp.c | 3 +++ + net/ipv6/udp.c | 3 +++ + 2 files changed, 6 insertions(+) + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index ff6a18e..7932dc6 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1203,6 +1203,9 @@ csum_copy_err: + + if (noblock) + return -EAGAIN; ++ ++ /* starting over for a new packet */ ++ msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index a0a6a08..a1d3d32 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -443,6 +443,9 @@ csum_copy_err: + + if (noblock) + return -EAGAIN; ++ ++ /* starting over for a new packet */ ++ msg->msg_flags &= ~MSG_TRUNC; + goto try_again; + } + +-- +1.7.9.6 + diff --git a/queue/uml-fix-CONFIG_STATIC_LINK-y-build-failure-with-newe.patch b/queue/uml-fix-CONFIG_STATIC_LINK-y-build-failure-with-newe.patch new file mode 100644 index 0000000..2453aec --- /dev/null +++ b/queue/uml-fix-CONFIG_STATIC_LINK-y-build-failure-with-newe.patch @@ -0,0 +1,80 @@ +From 8d9604cf6e5038fa99a2687233fefa8c9bbecfb3 Mon Sep 17 00:00:00 2001 +From: Roland McGrath <roland@redhat.com> +Date: Tue, 26 Oct 2010 14:22:19 -0700 +Subject: [PATCH] uml: fix CONFIG_STATIC_LINK=y build failure with newer glibc + +commit aa5fb4dbfd121296ca97c68cf90043a7ea97579d upstream. + +With glibc 2.11 or later that was built with --enable-multi-arch, the UML +link fails with undefined references to __rel_iplt_start and similar +symbols. In recent binutils, the default linker script defines these +symbols (see ld --verbose). Fix the UML linker scripts to match the new +defaults for these sections. + +Signed-off-by: Roland McGrath <roland@redhat.com> +Cc: Jeff Dike <jdike@addtoit.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + arch/um/kernel/dyn.lds.S | 14 ++++++++++++-- + arch/um/kernel/uml.lds.S | 17 +++++++++++++++++ + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S +index 7fcad58..3d6b43f 100644 +--- a/arch/um/kernel/dyn.lds.S ++++ b/arch/um/kernel/dyn.lds.S +@@ -50,8 +50,18 @@ SECTIONS + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } +- .rel.plt : { *(.rel.plt) } +- .rela.plt : { *(.rela.plt) } ++ .rel.plt : { ++ *(.rel.plt) ++ PROVIDE_HIDDEN(__rel_iplt_start = .); ++ *(.rel.iplt) ++ PROVIDE_HIDDEN(__rel_iplt_end = .); ++ } ++ .rela.plt : { ++ *(.rela.plt) ++ PROVIDE_HIDDEN(__rela_iplt_start = .); ++ *(.rela.iplt) ++ PROVIDE_HIDDEN(__rela_iplt_end = .); ++ } + .init : { + KEEP (*(.init)) + } =0x90909090 +diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S +index 664f942..79a077a 100644 +--- a/arch/um/kernel/uml.lds.S ++++ b/arch/um/kernel/uml.lds.S +@@ -43,6 +43,23 @@ SECTIONS + __syscall_stub_end = .; + } + ++ /* ++ * These are needed even in a static link, even if they wind up being empty. ++ * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols. ++ */ ++ .rel.plt : { ++ *(.rel.plt) ++ PROVIDE_HIDDEN(__rel_iplt_start = .); ++ *(.rel.iplt) ++ PROVIDE_HIDDEN(__rel_iplt_end = .); ++ } ++ .rela.plt : { ++ *(.rela.plt) ++ PROVIDE_HIDDEN(__rela_iplt_start = .); ++ *(.rela.iplt) ++ PROVIDE_HIDDEN(__rela_iplt_end = .); ++ } ++ + #include "asm/common.lds.S" + + init.data : { INIT_DATA } +-- +1.7.9.6 + diff --git a/queue/uvcvideo-Remove-buffers-from-the-queues-when-freeing.patch b/queue/uvcvideo-Remove-buffers-from-the-queues-when-freeing.patch new file mode 100644 index 0000000..f25dc70 --- /dev/null +++ b/queue/uvcvideo-Remove-buffers-from-the-queues-when-freeing.patch @@ -0,0 +1,45 @@ +From 5008d4e7ba3d0be7cf06af6d029def19e8c22b75 Mon Sep 17 00:00:00 2001 +From: Sjoerd Simons <sjoerd.simons@collabora.co.uk> +Date: Tue, 24 May 2011 12:22:03 -0300 +Subject: [PATCH] uvcvideo: Remove buffers from the queues when freeing + +commit 8ca2c80b170c47eeb55f0c2a0f2b8edf85f35d49 upstream. + +When freeing memory for the video buffers also remove them from the +irq & main queues. + +This fixes an oops when doing the following: + +open ("/dev/video", ..) +VIDIOC_REQBUFS +VIDIOC_QBUF +VIDIOC_REQBUFS +close () + +As the second VIDIOC_REQBUFS will cause the list entries of the buffers +to be cleared while they still hang around on the main and irc queues + +Signed-off-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> +Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/media/video/uvc/uvc_queue.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c +index 4a925a3..ad87703 100644 +--- a/drivers/media/video/uvc/uvc_queue.c ++++ b/drivers/media/video/uvc/uvc_queue.c +@@ -165,6 +165,8 @@ int uvc_free_buffers(struct uvc_video_queue *queue) + } + + if (queue->count) { ++ uvc_queue_cancel(queue, 0); ++ INIT_LIST_HEAD(&queue->mainqueue); + vfree(queue->mem); + queue->count = 0; + } +-- +1.7.9.6 + diff --git a/queue/watchdog-mtx1-wdt-request-gpio-before-using-it.patch b/queue/watchdog-mtx1-wdt-request-gpio-before-using-it.patch new file mode 100644 index 0000000..a59445d --- /dev/null +++ b/queue/watchdog-mtx1-wdt-request-gpio-before-using-it.patch @@ -0,0 +1,49 @@ +From 937bf462978f81f1b366e5eb2fc907ecd1c4c129 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli <florian@openwrt.org> +Date: Wed, 15 Jun 2011 19:15:23 +0200 +Subject: [PATCH] watchdog: mtx1-wdt: request gpio before using it + +commit 9b19d40aa3ebaf1078779da10555da2ab8512422 upstream. + +Otherwise, the gpiolib autorequest feature will produce a WARN_ON(): + +WARNING: at drivers/gpio/gpiolib.c:101 0x8020ec6c() +autorequest GPIO-215 +[...] + +Signed-off-by: Florian Fainelli <florian@openwrt.org> +Signed-off-by: Wim Van Sebroeck <wim@iguana.be> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/watchdog/mtx-1_wdt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c +index 08e8a6a..e797a2c 100644 +--- a/drivers/watchdog/mtx-1_wdt.c ++++ b/drivers/watchdog/mtx-1_wdt.c +@@ -211,6 +211,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev) + int ret; + + mtx1_wdt_device.gpio = pdev->resource[0].start; ++ ret = gpio_request_one(mtx1_wdt_device.gpio, ++ GPIOF_OUT_INIT_HIGH, "mtx1-wdt"); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request gpio"); ++ return ret; ++ } + + spin_lock_init(&mtx1_wdt_device.lock); + init_completion(&mtx1_wdt_device.stop); +@@ -236,6 +242,8 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev) + mtx1_wdt_device.queue = 0; + wait_for_completion(&mtx1_wdt_device.stop); + } ++ ++ gpio_free(mtx1_wdt_device.gpio); + misc_deregister(&mtx1_wdt_misc); + return 0; + } +-- +1.7.9.6 + diff --git a/queue/xen-partially-revert-xen-set-max_pfn_mapped-to-the-l.patch b/queue/xen-partially-revert-xen-set-max_pfn_mapped-to-the-l.patch new file mode 100644 index 0000000..3278a44 --- /dev/null +++ b/queue/xen-partially-revert-xen-set-max_pfn_mapped-to-the-l.patch @@ -0,0 +1,56 @@ +From 0a9d63108cfe92e86b33ccb950494bb39be508e2 Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini <stefano.stabellini@eu.citrix.com> +Date: Fri, 3 Jun 2011 09:51:34 +0000 +Subject: [PATCH] xen: partially revert "xen: set max_pfn_mapped to the last + pfn mapped" + +commit a91d92875ee94e4703fd017ccaadb48cfb344994 upstream. + +We only need to set max_pfn_mapped to the last pfn mapped on x86_64 to +make sure that cleanup_highmap doesn't remove important mappings at +_end. + +We don't need to do this on x86_32 because cleanup_highmap is not called +on x86_32. Besides lowering max_pfn_mapped on x86_32 has the unwanted +side effect of limiting the amount of memory available for the 1:1 +kernel pagetable allocation. + +This patch reverts the x86_32 part of the original patch. + +Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> +Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + arch/x86/xen/mmu.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c +index 4916176..96cdf78 100644 +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1641,6 +1641,11 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn) + for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) { + pte_t pte; + ++#ifdef CONFIG_X86_32 ++ if (pfn > max_pfn_mapped) ++ max_pfn_mapped = pfn; ++#endif ++ + if (!pte_none(pte_page[pteidx])) + continue; + +@@ -1753,7 +1758,9 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, + { + pmd_t *kernel_pmd; + +- max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list)); ++ max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) + ++ xen_start_info->nr_pt_frames * PAGE_SIZE + ++ 512*1024); + + kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd); + memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD); +-- +1.7.9.6 + diff --git a/queue/xhci-Reject-double-add-of-active-endpoints.patch b/queue/xhci-Reject-double-add-of-active-endpoints.patch new file mode 100644 index 0000000..9d3c77f --- /dev/null +++ b/queue/xhci-Reject-double-add-of-active-endpoints.patch @@ -0,0 +1,85 @@ +From 3f0edaa9144bf0993443cb6d7b67bb3db963c3aa Mon Sep 17 00:00:00 2001 +From: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Date: Sun, 5 Jun 2011 23:10:04 -0700 +Subject: [PATCH] xhci: Reject double add of active endpoints. + +commit fa75ac379e63c2864e9049b5e8615e40f65c1e70 upstream. + +While trying to switch a UAS device from the BOT configuration to the UAS +configuration via the bConfigurationValue file, Tanya ran into an issue in +the USB core. usb_disable_device() sets entries in udev->ep_out and +udev->ep_out to NULL, but doesn't call into the xHCI bandwidth management +functions to remove the BOT configuration endpoints from the xHCI host's +internal structures. + +The USB core would then attempt to add endpoints for the UAS +configuration, and some of the endpoints had the same address as endpoints +in the BOT configuration. The xHCI driver blindly added the endpoints +again, but the xHCI host controller rejected the Configure Endpoint +command because active endpoints were added without being dropped. + +Make the xHCI driver reject calls to xhci_add_endpoint() that attempt to +add active endpoints without first calling xhci_drop_endpoint(). + +This should be backported to kernels as old as 2.6.31. + +Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Reported-by: Tanya Brokhman <tlinder@codeaurora.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> +--- + drivers/usb/host/xhci.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 5a752d6..0a5901f 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -996,6 +996,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, + u32 added_ctxs; + unsigned int last_ctx; + u32 new_add_flags, new_drop_flags, new_slot_info; ++ struct xhci_virt_device *virt_dev; + int ret = 0; + + ret = xhci_check_args(hcd, udev, ep, 1, __func__); +@@ -1024,11 +1025,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, + return -EINVAL; + } + +- in_ctx = xhci->devs[udev->slot_id]->in_ctx; +- out_ctx = xhci->devs[udev->slot_id]->out_ctx; ++ virt_dev = xhci->devs[udev->slot_id]; ++ in_ctx = virt_dev->in_ctx; ++ out_ctx = virt_dev->out_ctx; + ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); + ep_index = xhci_get_endpoint_index(&ep->desc); + ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); ++ ++ /* If this endpoint is already in use, and the upper layers are trying ++ * to add it again without dropping it, reject the addition. ++ */ ++ if (virt_dev->eps[ep_index].ring && ++ !(le32_to_cpu(ctrl_ctx->drop_flags) & ++ xhci_get_endpoint_flag(&ep->desc))) { ++ xhci_warn(xhci, "Trying to add endpoint 0x%x " ++ "without dropping it.\n", ++ (unsigned int) ep->desc.bEndpointAddress); ++ return -EINVAL; ++ } ++ + /* If the HCD has already noted the endpoint is enabled, + * ignore this request. + */ +@@ -1043,8 +1058,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, + * process context, not interrupt context (or so documenation + * for usb_set_interface() and usb_set_configuration() claim). + */ +- if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], +- udev, ep, GFP_NOIO) < 0) { ++ if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) { + dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", + __func__, ep->desc.bEndpointAddress); + return -ENOMEM; +-- +1.7.9.6 + |