]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 29 Aug 2014 19:12:13 +0000 (12:12 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 29 Aug 2014 19:12:13 +0000 (12:12 -0700)
added patches:
crypto-ux500-make-interrupt-mode-plausible.patch
debugfs-fix-corrupted-loop-in-debugfs_remove_recursive.patch
drivers-i2c-busses-use-correct-type-for-dma_map-unmap.patch
ext4-fix-ext4_discard_allocated_blocks-if-we-can-t-allocate-the-pa-struct.patch
ext4-fix-punch-hole-on-files-with-indirect-mapping.patch
i2c-rk3x-fix-interrupt-handling-issue.patch
kvm-s390-mm-fix-page-table-locking-vs.-split-pmd-lock.patch
kvm-x86-always-exit-on-eois-for-interrupts-listed-in-the-ioapic-redir-table.patch
kvm-x86-inter-privilege-level-ret-emulation-is-not-implemeneted.patch
serial-core-preserve-termios-c_cflag-for-console-resume.patch

queue-3.16/crypto-ux500-make-interrupt-mode-plausible.patch [new file with mode: 0644]
queue-3.16/debugfs-fix-corrupted-loop-in-debugfs_remove_recursive.patch [new file with mode: 0644]
queue-3.16/drivers-i2c-busses-use-correct-type-for-dma_map-unmap.patch [new file with mode: 0644]
queue-3.16/ext4-fix-ext4_discard_allocated_blocks-if-we-can-t-allocate-the-pa-struct.patch [new file with mode: 0644]
queue-3.16/ext4-fix-punch-hole-on-files-with-indirect-mapping.patch [new file with mode: 0644]
queue-3.16/i2c-rk3x-fix-interrupt-handling-issue.patch [new file with mode: 0644]
queue-3.16/kvm-s390-mm-fix-page-table-locking-vs.-split-pmd-lock.patch [new file with mode: 0644]
queue-3.16/kvm-x86-always-exit-on-eois-for-interrupts-listed-in-the-ioapic-redir-table.patch [new file with mode: 0644]
queue-3.16/kvm-x86-inter-privilege-level-ret-emulation-is-not-implemeneted.patch [new file with mode: 0644]
queue-3.16/serial-core-preserve-termios-c_cflag-for-console-resume.patch [new file with mode: 0644]
queue-3.16/series

diff --git a/queue-3.16/crypto-ux500-make-interrupt-mode-plausible.patch b/queue-3.16/crypto-ux500-make-interrupt-mode-plausible.patch
new file mode 100644 (file)
index 0000000..ef01e83
--- /dev/null
@@ -0,0 +1,110 @@
+From e1f8859ee265fc89bd21b4dca79e8e983a044892 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Thu, 26 Jun 2014 13:43:02 +0200
+Subject: crypto: ux500 - make interrupt mode plausible
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit e1f8859ee265fc89bd21b4dca79e8e983a044892 upstream.
+
+The interrupt handler in the ux500 crypto driver has an obviously
+incorrect way to access the data buffer, which for a while has
+caused this build warning:
+
+../ux500/cryp/cryp_core.c: In function 'cryp_interrupt_handler':
+../ux500/cryp/cryp_core.c:234:5: warning: passing argument 1 of '__fswab32' makes integer from pointer without a cast [enabled by default]
+     writel_relaxed(ctx->indata,
+     ^
+In file included from ../include/linux/swab.h:4:0,
+                 from ../include/uapi/linux/byteorder/big_endian.h:12,
+                 from ../include/linux/byteorder/big_endian.h:4,
+                 from ../arch/arm/include/uapi/asm/byteorder.h:19,
+                 from ../include/asm-generic/bitops/le.h:5,
+                 from ../arch/arm/include/asm/bitops.h:340,
+                 from ../include/linux/bitops.h:33,
+                 from ../include/linux/kernel.h:10,
+                 from ../include/linux/clk.h:16,
+                 from ../drivers/crypto/ux500/cryp/cryp_core.c:12:
+../include/uapi/linux/swab.h:57:119: note: expected '__u32' but argument is of type 'const u8 *'
+ static inline __attribute_const__ __u32 __fswab32(__u32 val)
+
+There are at least two, possibly three problems here:
+a) when writing into the FIFO, we copy the pointer rather than the
+   actual data we want to give to the hardware
+b) the data pointer is an array of 8-bit values, while the FIFO
+   is 32-bit wide, so both the read and write access fail to do
+   a proper type conversion
+c) This seems incorrect for big-endian kernels, on which we need to
+   byte-swap any register access, but not normally FIFO accesses,
+   at least the DMA case doesn't do it either.
+
+This converts the bogus loop to use the same readsl/writesl pair
+that we use for the two other modes (DMA and polling). This is
+more efficient and consistent, and probably correct for endianess.
+
+The bug has existed since the driver was first merged, and was
+probably never detected because nobody tried to use interrupt mode.
+It might make sense to backport this fix to stable kernels, depending
+on how the crypto maintainers feel about that.
+
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Cc: linux-crypto@vger.kernel.org
+Cc: Fabio Baltieri <fabio.baltieri@linaro.org>
+Cc: Linus Walleij <linus.walleij@linaro.org>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S. Miller" <davem@davemloft.net>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/crypto/ux500/cryp/cryp_core.c |   25 ++++++++++++-------------
+ 1 file changed, 12 insertions(+), 13 deletions(-)
+
+--- a/drivers/crypto/ux500/cryp/cryp_core.c
++++ b/drivers/crypto/ux500/cryp/cryp_core.c
+@@ -190,7 +190,7 @@ static void add_session_id(struct cryp_c
+ static irqreturn_t cryp_interrupt_handler(int irq, void *param)
+ {
+       struct cryp_ctx *ctx;
+-      int i;
++      int count;
+       struct cryp_device_data *device_data;
+       if (param == NULL) {
+@@ -215,12 +215,11 @@ static irqreturn_t cryp_interrupt_handle
+       if (cryp_pending_irq_src(device_data,
+                                CRYP_IRQ_SRC_OUTPUT_FIFO)) {
+               if (ctx->outlen / ctx->blocksize > 0) {
+-                      for (i = 0; i < ctx->blocksize / 4; i++) {
+-                              *(ctx->outdata) = readl_relaxed(
+-                                              &device_data->base->dout);
+-                              ctx->outdata += 4;
+-                              ctx->outlen -= 4;
+-                      }
++                      count = ctx->blocksize / 4;
++
++                      readsl(&device_data->base->dout, ctx->outdata, count);
++                      ctx->outdata += count;
++                      ctx->outlen -= count;
+                       if (ctx->outlen == 0) {
+                               cryp_disable_irq_src(device_data,
+@@ -230,12 +229,12 @@ static irqreturn_t cryp_interrupt_handle
+       } else if (cryp_pending_irq_src(device_data,
+                                       CRYP_IRQ_SRC_INPUT_FIFO)) {
+               if (ctx->datalen / ctx->blocksize > 0) {
+-                      for (i = 0 ; i < ctx->blocksize / 4; i++) {
+-                              writel_relaxed(ctx->indata,
+-                                              &device_data->base->din);
+-                              ctx->indata += 4;
+-                              ctx->datalen -= 4;
+-                      }
++                      count = ctx->blocksize / 4;
++
++                      writesl(&device_data->base->din, ctx->indata, count);
++
++                      ctx->indata += count;
++                      ctx->datalen -= count;
+                       if (ctx->datalen == 0)
+                               cryp_disable_irq_src(device_data,
diff --git a/queue-3.16/debugfs-fix-corrupted-loop-in-debugfs_remove_recursive.patch b/queue-3.16/debugfs-fix-corrupted-loop-in-debugfs_remove_recursive.patch
new file mode 100644 (file)
index 0000000..fc80f8e
--- /dev/null
@@ -0,0 +1,181 @@
+From 485d44022a152c0254dd63445fdb81c4194cbf0e Mon Sep 17 00:00:00 2001
+From: Steven Rostedt <rostedt@goodmis.org>
+Date: Mon, 9 Jun 2014 14:06:07 -0400
+Subject: debugfs: Fix corrupted loop in debugfs_remove_recursive
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+commit 485d44022a152c0254dd63445fdb81c4194cbf0e upstream.
+
+[ I'm currently running my tests on it now, and so far, after a few
+ hours it has yet to blow up. I'll run it for 24 hours which it never
+ succeeded in the past. ]
+
+The tracing code has a way to make directories within the debugfs file
+system as well as deleting them using mkdir/rmdir in the instance
+directory. This is very limited in functionality, such as there is
+no renames, and the parent directory "instance" can not be modified.
+The tracing code creates the instance directory from the debugfs code
+and then replaces the dentry->d_inode->i_op with its own to allow
+for mkdir/rmdir to work.
+
+When these are called, the d_entry and inode locks need to be released
+to call the instance creation and deletion code. That code has its own
+accounting and locking to serialize everything to prevent multiple
+users from causing harm. As the parent "instance" directory can not
+be modified this simplifies things.
+
+I created a stress test that creates several threads that randomly
+creates and deletes directories thousands of times a second. The code
+stood up to this test and I submitted it a while ago.
+
+Recently I added a new test that adds readers to the mix. While the
+instance directories were being added and deleted, readers would read
+from these directories and even enable tracing within them. This test
+was able to trigger a bug:
+
+ general protection fault: 0000 [#1] PREEMPT SMP
+ Modules linked in: ...
+ CPU: 3 PID: 17789 Comm: rmdir Tainted: G        W     3.15.0-rc2-test+ #41
+ Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS SDBLI944.86P 05/08/2007
+ task: ffff88003786ca60 ti: ffff880077018000 task.ti: ffff880077018000
+ RIP: 0010:[<ffffffff811ed5eb>]  [<ffffffff811ed5eb>] debugfs_remove_recursive+0x1bd/0x367
+ RSP: 0018:ffff880077019df8  EFLAGS: 00010246
+ RAX: 0000000000000002 RBX: ffff88006f0fe490 RCX: 0000000000000000
+ RDX: dead000000100058 RSI: 0000000000000246 RDI: ffff88003786d454
+ RBP: ffff88006f0fe640 R08: 0000000000000628 R09: 0000000000000000
+ R10: 0000000000000628 R11: ffff8800795110a0 R12: ffff88006f0fe640
+ R13: ffff88006f0fe640 R14: ffffffff81817d0b R15: ffffffff818188b7
+ FS:  00007ff13ae24700(0000) GS:ffff88007d580000(0000) knlGS:0000000000000000
+ CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+ CR2: 0000003054ec7be0 CR3: 0000000076d51000 CR4: 00000000000007e0
+ Stack:
+  ffff88007a41ebe0 dead000000100058 00000000fffffffe ffff88006f0fe640
+  0000000000000000 ffff88006f0fe678 ffff88007a41ebe0 ffff88003793a000
+  00000000fffffffe ffffffff810bde82 ffff88006f0fe640 ffff88007a41eb28
+ Call Trace:
+  [<ffffffff810bde82>] ? instance_rmdir+0x15b/0x1de
+  [<ffffffff81132e2d>] ? vfs_rmdir+0x80/0xd3
+  [<ffffffff81132f51>] ? do_rmdir+0xd1/0x139
+  [<ffffffff8124ad9e>] ? trace_hardirqs_on_thunk+0x3a/0x3c
+  [<ffffffff814fea62>] ? system_call_fastpath+0x16/0x1b
+ Code: fe ff ff 48 8d 75 30 48 89 df e8 c9 fd ff ff 85 c0 75 13 48 c7 c6 b8 cc d2 81 48 c7 c7 b0 cc d2 81 e8 8c 7a f5 ff 48 8b 54 24 08 <48> 8b 82 a8 00 00 00 48 89 d3 48 2d a8 00 00 00 48 89 44 24 08
+ RIP  [<ffffffff811ed5eb>] debugfs_remove_recursive+0x1bd/0x367
+  RSP <ffff880077019df8>
+
+It took a while, but every time it triggered, it was always in the
+same place:
+
+       list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
+
+Where the child->d_u.d_child seemed to be corrupted.  I added lots of
+trace_printk()s to see what was wrong, and sure enough, it was always
+the child's d_u.d_child field. I looked around to see what touches
+it and noticed that in __dentry_kill() which calls dentry_free():
+
+static void dentry_free(struct dentry *dentry)
+{
+       /* if dentry was never visible to RCU, immediate free is OK */
+       if (!(dentry->d_flags & DCACHE_RCUACCESS))
+               __d_free(&dentry->d_u.d_rcu);
+       else
+               call_rcu(&dentry->d_u.d_rcu, __d_free);
+}
+
+I also noticed that __dentry_kill() unlinks the child->d_u.child
+under the parent->d_lock spin_lock.
+
+Looking back at the loop in debugfs_remove_recursive() it never takes the
+parent->d_lock to do the list walk. Adding more tracing, I was able to
+prove this was the issue:
+
+ ftrace-t-15385   1.... 246662024us : dentry_kill <ffffffff81138b91>: free ffff88006d573600
+    rmdir-15409   2.... 246662024us : debugfs_remove_recursive <ffffffff811ec7e5>: child=ffff88006d573600 next=dead000000100058
+
+The dentry_kill freed ffff88006d573600 just as the remove recursive was walking
+it.
+
+In order to fix this, the list walk needs to be modified a bit to take
+the parent->d_lock. The safe version is no longer necessary, as every
+time we remove a child, the parent->d_lock must be released and the
+list walk must start over. Each time a child is removed, even though it
+may still be on the list, it should be skipped by the first check
+in the loop:
+
+               if (!debugfs_positive(child))
+                       continue;
+
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/debugfs/inode.c |   33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove);
+  */
+ void debugfs_remove_recursive(struct dentry *dentry)
+ {
+-      struct dentry *child, *next, *parent;
++      struct dentry *child, *parent;
+       if (IS_ERR_OR_NULL(dentry))
+               return;
+@@ -546,30 +546,49 @@ void debugfs_remove_recursive(struct den
+       parent = dentry;
+  down:
+       mutex_lock(&parent->d_inode->i_mutex);
+-      list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) {
++ loop:
++      /*
++       * The parent->d_subdirs is protected by the d_lock. Outside that
++       * lock, the child can be unlinked and set to be freed which can
++       * use the d_u.d_child as the rcu head and corrupt this list.
++       */
++      spin_lock(&parent->d_lock);
++      list_for_each_entry(child, &parent->d_subdirs, d_u.d_child) {
+               if (!debugfs_positive(child))
+                       continue;
+               /* perhaps simple_empty(child) makes more sense */
+               if (!list_empty(&child->d_subdirs)) {
++                      spin_unlock(&parent->d_lock);
+                       mutex_unlock(&parent->d_inode->i_mutex);
+                       parent = child;
+                       goto down;
+               }
+- up:
++
++              spin_unlock(&parent->d_lock);
++
+               if (!__debugfs_remove(child, parent))
+                       simple_release_fs(&debugfs_mount, &debugfs_mount_count);
++
++              /*
++               * The parent->d_lock protects agaist child from unlinking
++               * from d_subdirs. When releasing the parent->d_lock we can
++               * no longer trust that the next pointer is valid.
++               * Restart the loop. We'll skip this one with the
++               * debugfs_positive() check.
++               */
++              goto loop;
+       }
++      spin_unlock(&parent->d_lock);
+       mutex_unlock(&parent->d_inode->i_mutex);
+       child = parent;
+       parent = parent->d_parent;
+       mutex_lock(&parent->d_inode->i_mutex);
+-      if (child != dentry) {
+-              next = list_next_entry(child, d_u.d_child);
+-              goto up;
+-      }
++      if (child != dentry)
++              /* go up */
++              goto loop;
+       if (!__debugfs_remove(child, parent))
+               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
diff --git a/queue-3.16/drivers-i2c-busses-use-correct-type-for-dma_map-unmap.patch b/queue-3.16/drivers-i2c-busses-use-correct-type-for-dma_map-unmap.patch
new file mode 100644 (file)
index 0000000..7b4559b
--- /dev/null
@@ -0,0 +1,39 @@
+From 28772ac8711e4d7268c06e765887dd8cb6924f98 Mon Sep 17 00:00:00 2001
+From: Wolfram Sang <wsa@the-dreams.de>
+Date: Mon, 21 Jul 2014 11:42:03 +0200
+Subject: drivers/i2c/busses: use correct type for dma_map/unmap
+
+From: Wolfram Sang <wsa@the-dreams.de>
+
+commit 28772ac8711e4d7268c06e765887dd8cb6924f98 upstream.
+
+dma_{un}map_* uses 'enum dma_data_direction' not 'enum dma_transfer_direction'.
+
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Acked-by: Ludovic Desroches <ludovic.desroches@atmel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-at91.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-at91.c
++++ b/drivers/i2c/busses/i2c-at91.c
+@@ -210,7 +210,7 @@ static void at91_twi_write_data_dma_call
+       struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+       dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+-                       dev->buf_len, DMA_MEM_TO_DEV);
++                       dev->buf_len, DMA_TO_DEVICE);
+       at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+ }
+@@ -289,7 +289,7 @@ static void at91_twi_read_data_dma_callb
+       struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
+       dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
+-                       dev->buf_len, DMA_DEV_TO_MEM);
++                       dev->buf_len, DMA_FROM_DEVICE);
+       /* The last two bytes have to be read without using dma */
+       dev->buf += dev->buf_len - 2;
diff --git a/queue-3.16/ext4-fix-ext4_discard_allocated_blocks-if-we-can-t-allocate-the-pa-struct.patch b/queue-3.16/ext4-fix-ext4_discard_allocated_blocks-if-we-can-t-allocate-the-pa-struct.patch
new file mode 100644 (file)
index 0000000..a3a58f6
--- /dev/null
@@ -0,0 +1,62 @@
+From 86f0afd463215fc3e58020493482faa4ac3a4d69 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 30 Jul 2014 22:17:17 -0400
+Subject: ext4: fix ext4_discard_allocated_blocks() if we can't allocate the pa struct
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 86f0afd463215fc3e58020493482faa4ac3a4d69 upstream.
+
+If there is a failure while allocating the preallocation structure, a
+number of blocks can end up getting marked in the in-memory buddy
+bitmap, and then not getting released.  This can result in the
+following corruption getting reported by the kernel:
+
+EXT4-fs error (device sda3): ext4_mb_generate_buddy:758: group 1126,
+12793 clusters in bitmap, 12729 in gd
+
+In that case, we need to release the blocks using mb_free_blocks().
+
+Tested: fs smoke test; also demonstrated that with injected errors,
+       the file system is no longer getting corrupted
+
+Google-Bug-Id: 16657874
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c |   21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3216,8 +3216,27 @@ static void ext4_mb_collect_stats(struct
+ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
+ {
+       struct ext4_prealloc_space *pa = ac->ac_pa;
++      struct ext4_buddy e4b;
++      int err;
+-      if (pa && pa->pa_type == MB_INODE_PA)
++      if (pa == NULL) {
++              err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
++              if (err) {
++                      /*
++                       * This should never happen since we pin the
++                       * pages in the ext4_allocation_context so
++                       * ext4_mb_load_buddy() should never fail.
++                       */
++                      WARN(1, "mb_load_buddy failed (%d)", err);
++                      return;
++              }
++              ext4_lock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
++              mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
++                             ac->ac_f_ex.fe_len);
++              ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
++              return;
++      }
++      if (pa->pa_type == MB_INODE_PA)
+               pa->pa_free += ac->ac_b_ex.fe_len;
+ }
diff --git a/queue-3.16/ext4-fix-punch-hole-on-files-with-indirect-mapping.patch b/queue-3.16/ext4-fix-punch-hole-on-files-with-indirect-mapping.patch
new file mode 100644 (file)
index 0000000..0d9a89c
--- /dev/null
@@ -0,0 +1,371 @@
+From 4f579ae7de560e5f449587a6c3f02594d53d4d51 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner@redhat.com>
+Date: Tue, 15 Jul 2014 06:03:38 -0400
+Subject: ext4: fix punch hole on files with indirect mapping
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+commit 4f579ae7de560e5f449587a6c3f02594d53d4d51 upstream.
+
+Currently punch hole code on files with direct/indirect mapping has some
+problems which may lead to a data loss. For example (from Jan Kara):
+
+fallocate -n -p 10240000 4096
+
+will punch the range 10240000 - 12632064 instead of the range 1024000 -
+10244096.
+
+Also the code is a bit weird and it's not using infrastructure provided
+by indirect.c, but rather creating it's own way.
+
+This patch fixes the issues as well as making the operation to run 4
+times faster from my testing (punching out 60GB file). It uses similar
+approach used in ext4_ind_truncate() which takes advantage of
+ext4_free_branches() function.
+
+Also rename the ext4_free_hole_blocks() to something more sensible, like
+the equivalent we have for extent mapped files. Call it
+ext4_ind_remove_space().
+
+This has been tested mostly with fsx and some xfstests which are testing
+punch hole but does not require unwritten extents which are not
+supported with direct/indirect mapping. Not problems showed up even with
+1024k block size.
+
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h     |    4 
+ fs/ext4/indirect.c |  283 ++++++++++++++++++++++++++++++++++++++---------------
+ fs/ext4/inode.c    |    2 
+ 3 files changed, 206 insertions(+), 83 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2144,8 +2144,8 @@ extern ssize_t ext4_ind_direct_IO(int rw
+ extern int ext4_ind_calc_metadata_amount(struct inode *inode, sector_t lblock);
+ extern int ext4_ind_trans_blocks(struct inode *inode, int nrblocks);
+ extern void ext4_ind_truncate(handle_t *, struct inode *inode);
+-extern int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+-                               ext4_lblk_t first, ext4_lblk_t stop);
++extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
++                               ext4_lblk_t start, ext4_lblk_t end);
+ /* ioctl.c */
+ extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
+--- a/fs/ext4/indirect.c
++++ b/fs/ext4/indirect.c
+@@ -1295,97 +1295,220 @@ do_indirects:
+       }
+ }
+-static int free_hole_blocks(handle_t *handle, struct inode *inode,
+-                          struct buffer_head *parent_bh, __le32 *i_data,
+-                          int level, ext4_lblk_t first,
+-                          ext4_lblk_t count, int max)
++/**
++ *    ext4_ind_remove_space - remove space from the range
++ *    @handle: JBD handle for this transaction
++ *    @inode: inode we are dealing with
++ *    @start: First block to remove
++ *    @end:   One block after the last block to remove (exclusive)
++ *
++ *    Free the blocks in the defined range (end is exclusive endpoint of
++ *    range). This is used by ext4_punch_hole().
++ */
++int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
++                        ext4_lblk_t start, ext4_lblk_t end)
+ {
+-      struct buffer_head *bh = NULL;
++      struct ext4_inode_info *ei = EXT4_I(inode);
++      __le32 *i_data = ei->i_data;
+       int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+-      int ret = 0;
+-      int i, inc;
+-      ext4_lblk_t offset;
+-      __le32 blk;
+-
+-      inc = 1 << ((EXT4_BLOCK_SIZE_BITS(inode->i_sb) - 2) * level);
+-      for (i = 0, offset = 0; i < max; i++, i_data++, offset += inc) {
+-              if (offset >= count + first)
+-                      break;
+-              if (*i_data == 0 || (offset + inc) <= first)
+-                      continue;
+-              blk = *i_data;
+-              if (level > 0) {
+-                      ext4_lblk_t first2;
+-                      ext4_lblk_t count2;
+-
+-                      bh = sb_bread(inode->i_sb, le32_to_cpu(blk));
+-                      if (!bh) {
+-                              EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk),
+-                                                     "Read failure");
+-                              return -EIO;
+-                      }
+-                      if (first > offset) {
+-                              first2 = first - offset;
+-                              count2 = count;
++      ext4_lblk_t offsets[4], offsets2[4];
++      Indirect chain[4], chain2[4];
++      Indirect *partial, *partial2;
++      ext4_lblk_t max_block;
++      __le32 nr = 0, nr2 = 0;
++      int n = 0, n2 = 0;
++      unsigned blocksize = inode->i_sb->s_blocksize;
++
++      max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
++                                      >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
++      if (end >= max_block)
++              end = max_block;
++      if ((start >= end) || (start > max_block))
++              return 0;
++
++      n = ext4_block_to_path(inode, start, offsets, NULL);
++      n2 = ext4_block_to_path(inode, end, offsets2, NULL);
++
++      BUG_ON(n > n2);
++
++      if ((n == 1) && (n == n2)) {
++              /* We're punching only within direct block range */
++              ext4_free_data(handle, inode, NULL, i_data + offsets[0],
++                             i_data + offsets2[0]);
++              return 0;
++      } else if (n2 > n) {
++              /*
++               * Start and end are on a different levels so we're going to
++               * free partial block at start, and partial block at end of
++               * the range. If there are some levels in between then
++               * do_indirects label will take care of that.
++               */
++
++              if (n == 1) {
++                      /*
++                       * Start is at the direct block level, free
++                       * everything to the end of the level.
++                       */
++                      ext4_free_data(handle, inode, NULL, i_data + offsets[0],
++                                     i_data + EXT4_NDIR_BLOCKS);
++                      goto end_range;
++              }
++
++
++              partial = ext4_find_shared(inode, n, offsets, chain, &nr);
++              if (nr) {
++                      if (partial == chain) {
++                              /* Shared branch grows from the inode */
++                              ext4_free_branches(handle, inode, NULL,
++                                         &nr, &nr+1, (chain+n-1) - partial);
++                              *partial->p = 0;
+                       } else {
+-                              first2 = 0;
+-                              count2 = count - (offset - first);
++                              /* Shared branch grows from an indirect block */
++                              BUFFER_TRACE(partial->bh, "get_write_access");
++                              ext4_free_branches(handle, inode, partial->bh,
++                                      partial->p,
++                                      partial->p+1, (chain+n-1) - partial);
+                       }
+-                      ret = free_hole_blocks(handle, inode, bh,
+-                                             (__le32 *)bh->b_data, level - 1,
+-                                             first2, count2,
+-                                             inode->i_sb->s_blocksize >> 2);
+-                      if (ret) {
+-                              brelse(bh);
+-                              goto err;
++              }
++
++              /*
++               * Clear the ends of indirect blocks on the shared branch
++               * at the start of the range
++               */
++              while (partial > chain) {
++                      ext4_free_branches(handle, inode, partial->bh,
++                              partial->p + 1,
++                              (__le32 *)partial->bh->b_data+addr_per_block,
++                              (chain+n-1) - partial);
++                      BUFFER_TRACE(partial->bh, "call brelse");
++                      brelse(partial->bh);
++                      partial--;
++              }
++
++end_range:
++              partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
++              if (nr2) {
++                      if (partial2 == chain2) {
++                              /*
++                               * Remember, end is exclusive so here we're at
++                               * the start of the next level we're not going
++                               * to free. Everything was covered by the start
++                               * of the range.
++                               */
++                              return 0;
++                      } else {
++                              /* Shared branch grows from an indirect block */
++                              partial2--;
+                       }
++              } else {
++                      /*
++                       * ext4_find_shared returns Indirect structure which
++                       * points to the last element which should not be
++                       * removed by truncate. But this is end of the range
++                       * in punch_hole so we need to point to the next element
++                       */
++                      partial2->p++;
+               }
+-              if (level == 0 ||
+-                  (bh && all_zeroes((__le32 *)bh->b_data,
+-                                    (__le32 *)bh->b_data + addr_per_block))) {
+-                      ext4_free_data(handle, inode, parent_bh,
+-                                     i_data, i_data + 1);
++
++              /*
++               * Clear the ends of indirect blocks on the shared branch
++               * at the end of the range
++               */
++              while (partial2 > chain2) {
++                      ext4_free_branches(handle, inode, partial2->bh,
++                                         (__le32 *)partial2->bh->b_data,
++                                         partial2->p,
++                                         (chain2+n2-1) - partial2);
++                      BUFFER_TRACE(partial2->bh, "call brelse");
++                      brelse(partial2->bh);
++                      partial2--;
+               }
+-              brelse(bh);
+-              bh = NULL;
++              goto do_indirects;
+       }
+-err:
+-      return ret;
+-}
+-
+-int ext4_free_hole_blocks(handle_t *handle, struct inode *inode,
+-                        ext4_lblk_t first, ext4_lblk_t stop)
+-{
+-      int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb);
+-      int level, ret = 0;
+-      int num = EXT4_NDIR_BLOCKS;
+-      ext4_lblk_t count, max = EXT4_NDIR_BLOCKS;
+-      __le32 *i_data = EXT4_I(inode)->i_data;
+-
+-      count = stop - first;
+-      for (level = 0; level < 4; level++, max *= addr_per_block) {
+-              if (first < max) {
+-                      ret = free_hole_blocks(handle, inode, NULL, i_data,
+-                                             level, first, count, num);
+-                      if (ret)
+-                              goto err;
+-                      if (count > max - first)
+-                              count -= max - first;
+-                      else
+-                              break;
+-                      first = 0;
+-              } else {
+-                      first -= max;
++      /* Punch happened within the same level (n == n2) */
++      partial = ext4_find_shared(inode, n, offsets, chain, &nr);
++      partial2 = ext4_find_shared(inode, n2, offsets2, chain2, &nr2);
++      /*
++       * ext4_find_shared returns Indirect structure which
++       * points to the last element which should not be
++       * removed by truncate. But this is end of the range
++       * in punch_hole so we need to point to the next element
++       */
++      partial2->p++;
++      while ((partial > chain) || (partial2 > chain2)) {
++              /* We're at the same block, so we're almost finished */
++              if ((partial->bh && partial2->bh) &&
++                  (partial->bh->b_blocknr == partial2->bh->b_blocknr)) {
++                      if ((partial > chain) && (partial2 > chain2)) {
++                              ext4_free_branches(handle, inode, partial->bh,
++                                                 partial->p + 1,
++                                                 partial2->p,
++                                                 (chain+n-1) - partial);
++                              BUFFER_TRACE(partial->bh, "call brelse");
++                              brelse(partial->bh);
++                              BUFFER_TRACE(partial2->bh, "call brelse");
++                              brelse(partial2->bh);
++                      }
++                      return 0;
++              }
++              /*
++               * Clear the ends of indirect blocks on the shared branch
++               * at the start of the range
++               */
++              if (partial > chain) {
++                      ext4_free_branches(handle, inode, partial->bh,
++                                 partial->p + 1,
++                                 (__le32 *)partial->bh->b_data+addr_per_block,
++                                 (chain+n-1) - partial);
++                      BUFFER_TRACE(partial->bh, "call brelse");
++                      brelse(partial->bh);
++                      partial--;
+               }
+-              i_data += num;
+-              if (level == 0) {
+-                      num = 1;
+-                      max = 1;
++              /*
++               * Clear the ends of indirect blocks on the shared branch
++               * at the end of the range
++               */
++              if (partial2 > chain2) {
++                      ext4_free_branches(handle, inode, partial2->bh,
++                                         (__le32 *)partial2->bh->b_data,
++                                         partial2->p,
++                                         (chain2+n-1) - partial2);
++                      BUFFER_TRACE(partial2->bh, "call brelse");
++                      brelse(partial2->bh);
++                      partial2--;
+               }
+       }
+-err:
+-      return ret;
++do_indirects:
++      /* Kill the remaining (whole) subtrees */
++      switch (offsets[0]) {
++      default:
++              if (++n >= n2)
++                      return 0;
++              nr = i_data[EXT4_IND_BLOCK];
++              if (nr) {
++                      ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 1);
++                      i_data[EXT4_IND_BLOCK] = 0;
++              }
++      case EXT4_IND_BLOCK:
++              if (++n >= n2)
++                      return 0;
++              nr = i_data[EXT4_DIND_BLOCK];
++              if (nr) {
++                      ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 2);
++                      i_data[EXT4_DIND_BLOCK] = 0;
++              }
++      case EXT4_DIND_BLOCK:
++              if (++n >= n2)
++                      return 0;
++              nr = i_data[EXT4_TIND_BLOCK];
++              if (nr) {
++                      ext4_free_branches(handle, inode, NULL, &nr, &nr+1, 3);
++                      i_data[EXT4_TIND_BLOCK] = 0;
++              }
++      case EXT4_TIND_BLOCK:
++              ;
++      }
++      return 0;
+ }
+-
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3624,7 +3624,7 @@ int ext4_punch_hole(struct inode *inode,
+               ret = ext4_ext_remove_space(inode, first_block,
+                                           stop_block - 1);
+       else
+-              ret = ext4_free_hole_blocks(handle, inode, first_block,
++              ret = ext4_ind_remove_space(handle, inode, first_block,
+                                           stop_block);
+       up_write(&EXT4_I(inode)->i_data_sem);
diff --git a/queue-3.16/i2c-rk3x-fix-interrupt-handling-issue.patch b/queue-3.16/i2c-rk3x-fix-interrupt-handling-issue.patch
new file mode 100644 (file)
index 0000000..ee76921
--- /dev/null
@@ -0,0 +1,35 @@
+From 9c5f7cad3acc69ce623d04d646950183a759949e Mon Sep 17 00:00:00 2001
+From: addy ke <addy.ke@rock-chips.com>
+Date: Fri, 8 Aug 2014 17:41:40 +0800
+Subject: i2c: rk3x: fix interrupt handling issue
+
+From: addy ke <addy.ke@rock-chips.com>
+
+commit 9c5f7cad3acc69ce623d04d646950183a759949e upstream.
+
+If slave holds scl, I2C_IPD[7] will be set 1 by controller
+for debugging. Driver must ignore it.
+
+[    5.752391] rk3x-i2c ff160000.i2c: unexpected irq in WRITE: 0x80
+[    5.939027] rk3x-i2c ff160000.i2c: timeout, ipd: 0x80, state: 4
+
+Signed-off-by: Addy Ke <addy.ke@rock-chips.com>
+Reviewed-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-rk3x.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/i2c/busses/i2c-rk3x.c
++++ b/drivers/i2c/busses/i2c-rk3x.c
+@@ -399,7 +399,7 @@ static irqreturn_t rk3x_i2c_irq(int irqn
+       }
+       /* is there anything left to handle? */
+-      if (unlikely(ipd == 0))
++      if (unlikely((ipd & REG_INT_ALL) == 0))
+               goto out;
+       switch (i2c->state) {
diff --git a/queue-3.16/kvm-s390-mm-fix-page-table-locking-vs.-split-pmd-lock.patch b/queue-3.16/kvm-s390-mm-fix-page-table-locking-vs.-split-pmd-lock.patch
new file mode 100644 (file)
index 0000000..1f2da91
--- /dev/null
@@ -0,0 +1,51 @@
+From 55e4283c3eb1d850893f645dd695c9c75d5fa1fc Mon Sep 17 00:00:00 2001
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+Date: Fri, 25 Jul 2014 14:23:29 +0200
+Subject: KVM: s390/mm: Fix page table locking vs. split pmd lock
+
+From: Christian Borntraeger <borntraeger@de.ibm.com>
+
+commit 55e4283c3eb1d850893f645dd695c9c75d5fa1fc upstream.
+
+commit ec66ad66a0de87866be347b5ecc83bd46427f53b (s390/mm: enable
+split page table lock for PMD level) activated the split pmd lock
+for s390. Turns out that we missed one place: We also have to take
+the pmd lock instead of the page table lock when we reallocate the
+page tables (==> changing entries in the PMD) during sie enablement.
+
+Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/s390/mm/pgtable.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/mm/pgtable.c
++++ b/arch/s390/mm/pgtable.c
+@@ -1279,6 +1279,7 @@ static unsigned long page_table_realloc_
+ {
+       unsigned long next, *table, *new;
+       struct page *page;
++      spinlock_t *ptl;
+       pmd_t *pmd;
+       pmd = pmd_offset(pud, addr);
+@@ -1296,7 +1297,7 @@ again:
+               if (!new)
+                       return -ENOMEM;
+-              spin_lock(&mm->page_table_lock);
++              ptl = pmd_lock(mm, pmd);
+               if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
+                       /* Nuke pmd entry pointing to the "short" page table */
+                       pmdp_flush_lazy(mm, addr, pmd);
+@@ -1310,7 +1311,7 @@ again:
+                       page_table_free_rcu(tlb, table);
+                       new = NULL;
+               }
+-              spin_unlock(&mm->page_table_lock);
++              spin_unlock(ptl);
+               if (new) {
+                       page_table_free_pgste(new);
+                       goto again;
diff --git a/queue-3.16/kvm-x86-always-exit-on-eois-for-interrupts-listed-in-the-ioapic-redir-table.patch b/queue-3.16/kvm-x86-always-exit-on-eois-for-interrupts-listed-in-the-ioapic-redir-table.patch
new file mode 100644 (file)
index 0000000..4d4edaa
--- /dev/null
@@ -0,0 +1,67 @@
+From 0f6c0a740b7d3e1f3697395922d674000f83d060 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 30 Jul 2014 18:07:24 +0200
+Subject: KVM: x86: always exit on EOIs for interrupts listed in the IOAPIC redir table
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 0f6c0a740b7d3e1f3697395922d674000f83d060 upstream.
+
+Currently, the EOI exit bitmap (used for APICv) does not include
+interrupts that are masked.  However, this can cause a bug that manifests
+as an interrupt storm inside the guest.  Alex Williamson reported the
+bug and is the one who really debugged this; I only wrote the patch. :)
+
+The scenario involves a multi-function PCI device with OHCI and EHCI
+USB functions and an audio function, all assigned to the guest, where
+both USB functions use legacy INTx interrupts.
+
+As soon as the guest boots, interrupts for these devices turn into an
+interrupt storm in the guest; the host does not see the interrupt storm.
+Basically the EOI path does not work, and the guest continues to see the
+interrupt over and over, even after it attempts to mask it at the APIC.
+The bug is only visible with older kernels (RHEL6.5, based on 2.6.32
+with not many changes in the area of APIC/IOAPIC handling).
+
+Alex then tried forcing bit 59 (corresponding to the USB functions' IRQ)
+on in the eoi_exit_bitmap and TMR, and things then work.  What happens
+is that VFIO asserts IRQ11, then KVM recomputes the EOI exit bitmap.
+It does not have set bit 59 because the RTE was masked, so the IOAPIC
+never sees the EOI and the interrupt continues to fire in the guest.
+
+My guess was that the guest is masking the interrupt in the redirection
+table in the interrupt routine, i.e. while the interrupt is set in a
+LAPIC's ISR, The simplest fix is to ignore the masking state, we would
+rather have an unnecessary exit rather than a missed IRQ ACK and anyway
+IOAPIC interrupts are not as performance-sensitive as for example MSIs.
+Alex tested this patch and it fixed his bug.
+
+[Thanks to Alex for his precise description of the problem
+ and initial debugging effort.  A lot of the text above is
+ based on emails exchanged with him.]
+
+Reported-by: Alex Williamson <alex.williamson@redhat.com>
+Tested-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ virt/kvm/ioapic.c |    7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/virt/kvm/ioapic.c
++++ b/virt/kvm/ioapic.c
+@@ -254,10 +254,9 @@ void kvm_ioapic_scan_entry(struct kvm_vc
+       spin_lock(&ioapic->lock);
+       for (index = 0; index < IOAPIC_NUM_PINS; index++) {
+               e = &ioapic->redirtbl[index];
+-              if (!e->fields.mask &&
+-                      (e->fields.trig_mode == IOAPIC_LEVEL_TRIG ||
+-                       kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC,
+-                               index) || index == RTC_GSI)) {
++              if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG ||
++                  kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index) ||
++                  index == RTC_GSI) {
+                       if (kvm_apic_match_dest(vcpu, NULL, 0,
+                               e->fields.dest_id, e->fields.dest_mode)) {
+                               __set_bit(e->fields.vector,
diff --git a/queue-3.16/kvm-x86-inter-privilege-level-ret-emulation-is-not-implemeneted.patch b/queue-3.16/kvm-x86-inter-privilege-level-ret-emulation-is-not-implemeneted.patch
new file mode 100644 (file)
index 0000000..61e228c
--- /dev/null
@@ -0,0 +1,41 @@
+From 9e8919ae793f4edfaa29694a70f71a515ae9942a Mon Sep 17 00:00:00 2001
+From: Nadav Amit <namit@cs.technion.ac.il>
+Date: Sun, 15 Jun 2014 16:12:59 +0300
+Subject: KVM: x86: Inter-privilege level ret emulation is not implemeneted
+
+From: Nadav Amit <namit@cs.technion.ac.il>
+
+commit 9e8919ae793f4edfaa29694a70f71a515ae9942a upstream.
+
+Return unhandlable error on inter-privilege level ret instruction.  This is
+since the current emulation does not check the privilege level correctly when
+loading the CS, and does not pop RSP/SS as needed.
+
+Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/emulate.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -2017,6 +2017,7 @@ static int em_ret_far(struct x86_emulate
+ {
+       int rc;
+       unsigned long cs;
++      int cpl = ctxt->ops->cpl(ctxt);
+       rc = emulate_pop(ctxt, &ctxt->_eip, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+@@ -2026,6 +2027,9 @@ static int em_ret_far(struct x86_emulate
+       rc = emulate_pop(ctxt, &cs, ctxt->op_bytes);
+       if (rc != X86EMUL_CONTINUE)
+               return rc;
++      /* Outer-privilege level return is not implemented */
++      if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl)
++              return X86EMUL_UNHANDLEABLE;
+       rc = load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS);
+       return rc;
+ }
diff --git a/queue-3.16/serial-core-preserve-termios-c_cflag-for-console-resume.patch b/queue-3.16/serial-core-preserve-termios-c_cflag-for-console-resume.patch
new file mode 100644 (file)
index 0000000..b5a4459
--- /dev/null
@@ -0,0 +1,40 @@
+From ae84db9661cafc63d179e1d985a2c5b841ff0ac4 Mon Sep 17 00:00:00 2001
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Wed, 9 Jul 2014 09:21:14 -0400
+Subject: serial: core: Preserve termios c_cflag for console resume
+
+From: Peter Hurley <peter@hurleysoftware.com>
+
+commit ae84db9661cafc63d179e1d985a2c5b841ff0ac4 upstream.
+
+When a tty is opened for the serial console, the termios c_cflag
+settings are inherited from the console line settings.
+However, if the tty is subsequently closed, the termios settings
+are lost. This results in a garbled console if the console is later
+suspended and resumed.
+
+Preserve the termios c_cflag for the serial console when the tty
+is shutdown; this reflects the most recent line settings.
+
+Fixes: Bugzilla #69751, 'serial console does not wake from S3'
+Reported-by: Valerio Vanni <valerio.vanni@inwind.it>
+Acked-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/serial_core.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -243,6 +243,9 @@ static void uart_shutdown(struct tty_str
+               /*
+                * Turn off DTR and RTS early.
+                */
++              if (uart_console(uport) && tty)
++                      uport->cons->cflag = tty->termios.c_cflag;
++
+               if (!tty || (tty->termios.c_cflag & HUPCL))
+                       uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
index 7187912ff8d8c22f6610956f765b3fa847280215..ce3e6b42d667e830a471abe8a0a92d54b4f31c34 100644 (file)
@@ -46,3 +46,13 @@ hwmon-ads1015-fix-out-of-bounds-array-access.patch
 hwmon-dme1737-prevent-overflow-problem-when-writing-large-limits.patch
 hwmon-lm92-prevent-overflow-problem-when-writing-large-limits.patch
 tpm-add-missing-tpm_do_selftest-to-st33-i2c-driver.patch
+drivers-i2c-busses-use-correct-type-for-dma_map-unmap.patch
+i2c-rk3x-fix-interrupt-handling-issue.patch
+ext4-fix-punch-hole-on-files-with-indirect-mapping.patch
+ext4-fix-ext4_discard_allocated_blocks-if-we-can-t-allocate-the-pa-struct.patch
+serial-core-preserve-termios-c_cflag-for-console-resume.patch
+crypto-ux500-make-interrupt-mode-plausible.patch
+debugfs-fix-corrupted-loop-in-debugfs_remove_recursive.patch
+kvm-x86-inter-privilege-level-ret-emulation-is-not-implemeneted.patch
+kvm-x86-always-exit-on-eois-for-interrupts-listed-in-the-ioapic-redir-table.patch
+kvm-s390-mm-fix-page-table-locking-vs.-split-pmd-lock.patch