]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Mar 2021 14:15:26 +0000 (15:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 7 Mar 2021 14:15:26 +0000 (15:15 +0100)
added patches:
btrfs-fix-raid6-qstripe-kmap.patch
btrfs-fix-warning-when-creating-a-directory-with-smack-enabled.patch
btrfs-free-correct-amount-of-space-in-btrfs_delayed_inode_reserve_metadata.patch
btrfs-raid56-simplify-tracking-of-q-stripe-presence.patch
btrfs-unlock-extents-in-btrfs_zero_range-in-case-of-quota-reservation-errors.patch
btrfs-validate-qgroup-inherit-for-snap_create_v2-ioctl.patch
dm-bufio-subtract-the-number-of-initial-sectors-in-dm_bufio_get_device_size.patch
dm-verity-fix-fec-for-rs-roots-unaligned-to-block-size.patch
drm-amdgpu-fix-parameter-error-of-rreg32_pcie-in-amdgpu_regs_pcie.patch
pm-runtime-update-device-status-before-letting-suppliers-suspend.patch
tpm-tpm_tis-decorate-tpm_get_timeouts-with-request_locality.patch
tpm-tpm_tis-decorate-tpm_tis_gen_interrupt-with-request_locality.patch

12 files changed:
queue-5.4/btrfs-fix-raid6-qstripe-kmap.patch [new file with mode: 0644]
queue-5.4/btrfs-fix-warning-when-creating-a-directory-with-smack-enabled.patch [new file with mode: 0644]
queue-5.4/btrfs-free-correct-amount-of-space-in-btrfs_delayed_inode_reserve_metadata.patch [new file with mode: 0644]
queue-5.4/btrfs-raid56-simplify-tracking-of-q-stripe-presence.patch [new file with mode: 0644]
queue-5.4/btrfs-unlock-extents-in-btrfs_zero_range-in-case-of-quota-reservation-errors.patch [new file with mode: 0644]
queue-5.4/btrfs-validate-qgroup-inherit-for-snap_create_v2-ioctl.patch [new file with mode: 0644]
queue-5.4/dm-bufio-subtract-the-number-of-initial-sectors-in-dm_bufio_get_device_size.patch [new file with mode: 0644]
queue-5.4/dm-verity-fix-fec-for-rs-roots-unaligned-to-block-size.patch [new file with mode: 0644]
queue-5.4/drm-amdgpu-fix-parameter-error-of-rreg32_pcie-in-amdgpu_regs_pcie.patch [new file with mode: 0644]
queue-5.4/pm-runtime-update-device-status-before-letting-suppliers-suspend.patch [new file with mode: 0644]
queue-5.4/tpm-tpm_tis-decorate-tpm_get_timeouts-with-request_locality.patch [new file with mode: 0644]
queue-5.4/tpm-tpm_tis-decorate-tpm_tis_gen_interrupt-with-request_locality.patch [new file with mode: 0644]

diff --git a/queue-5.4/btrfs-fix-raid6-qstripe-kmap.patch b/queue-5.4/btrfs-fix-raid6-qstripe-kmap.patch
new file mode 100644 (file)
index 0000000..fedd94f
--- /dev/null
@@ -0,0 +1,94 @@
+From d70cef0d46729808dc53f145372c02b145c92604 Mon Sep 17 00:00:00 2001
+From: Ira Weiny <ira.weiny@intel.com>
+Date: Wed, 27 Jan 2021 22:15:03 -0800
+Subject: btrfs: fix raid6 qstripe kmap
+
+From: Ira Weiny <ira.weiny@intel.com>
+
+commit d70cef0d46729808dc53f145372c02b145c92604 upstream.
+
+When a qstripe is required an extra page is allocated and mapped.  There
+were 3 problems:
+
+1) There is no corresponding call of kunmap() for the qstripe page.
+2) There is no reason to map the qstripe page more than once if the
+   number of bits set in rbio->dbitmap is greater than one.
+3) There is no reason to map the parity page and unmap it each time
+   through the loop.
+
+The page memory can continue to be reused with a single mapping on each
+iteration by raid6_call.gen_syndrome() without remapping.  So map the
+page for the duration of the loop.
+
+Similarly, improve the algorithm by mapping the parity page just 1 time.
+
+Fixes: 5a6ac9eacb49 ("Btrfs, raid56: support parity scrub on raid56")
+CC: stable@vger.kernel.org # 4.4.x: c17af96554a8: btrfs: raid56: simplify tracking of Q stripe presence
+CC: stable@vger.kernel.org # 4.4.x
+Signed-off-by: Ira Weiny <ira.weiny@intel.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/raid56.c |   21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -2390,16 +2390,21 @@ static noinline void finish_parity_scrub
+       SetPageUptodate(p_page);
+       if (has_qstripe) {
++              /* RAID6, allocate and map temp space for the Q stripe */
+               q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+               if (!q_page) {
+                       __free_page(p_page);
+                       goto cleanup;
+               }
+               SetPageUptodate(q_page);
++              pointers[rbio->real_stripes - 1] = kmap(q_page);
+       }
+       atomic_set(&rbio->error, 0);
++      /* Map the parity stripe just once */
++      pointers[nr_data] = kmap(p_page);
++
+       for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) {
+               struct page *p;
+               void *parity;
+@@ -2409,16 +2414,8 @@ static noinline void finish_parity_scrub
+                       pointers[stripe] = kmap(p);
+               }
+-              /* then add the parity stripe */
+-              pointers[stripe++] = kmap(p_page);
+-
+               if (has_qstripe) {
+-                      /*
+-                       * raid6, add the qstripe and call the
+-                       * library function to fill in our p/q
+-                       */
+-                      pointers[stripe++] = kmap(q_page);
+-
++                      /* RAID6, call the library function to fill in our P/Q */
+                       raid6_call.gen_syndrome(rbio->real_stripes, PAGE_SIZE,
+                                               pointers);
+               } else {
+@@ -2439,12 +2436,14 @@ static noinline void finish_parity_scrub
+               for (stripe = 0; stripe < nr_data; stripe++)
+                       kunmap(page_in_rbio(rbio, stripe, pagenr, 0));
+-              kunmap(p_page);
+       }
++      kunmap(p_page);
+       __free_page(p_page);
+-      if (q_page)
++      if (q_page) {
++              kunmap(q_page);
+               __free_page(q_page);
++      }
+ writeback:
+       /*
diff --git a/queue-5.4/btrfs-fix-warning-when-creating-a-directory-with-smack-enabled.patch b/queue-5.4/btrfs-fix-warning-when-creating-a-directory-with-smack-enabled.patch
new file mode 100644 (file)
index 0000000..65aca97
--- /dev/null
@@ -0,0 +1,146 @@
+From fd57a98d6f0c98fa295813087f13afb26c224e73 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 26 Feb 2021 17:51:44 +0000
+Subject: btrfs: fix warning when creating a directory with smack enabled
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit fd57a98d6f0c98fa295813087f13afb26c224e73 upstream.
+
+When we have smack enabled, during the creation of a directory smack may
+attempt to add a "smack transmute" xattr on the inode, which results in
+the following warning and trace:
+
+  WARNING: CPU: 3 PID: 2548 at fs/btrfs/transaction.c:537 start_transaction+0x489/0x4f0
+  Modules linked in: nft_objref nf_conntrack_netbios_ns (...)
+  CPU: 3 PID: 2548 Comm: mkdir Not tainted 5.9.0-rc2smack+ #81
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
+  RIP: 0010:start_transaction+0x489/0x4f0
+  Code: e9 be fc ff ff (...)
+  RSP: 0018:ffffc90001887d10 EFLAGS: 00010202
+  RAX: ffff88816f1e0000 RBX: 0000000000000201 RCX: 0000000000000003
+  RDX: 0000000000000201 RSI: 0000000000000002 RDI: ffff888177849000
+  RBP: ffff888177849000 R08: 0000000000000001 R09: 0000000000000004
+  R10: ffffffff825e8f7a R11: 0000000000000003 R12: ffffffffffffffe2
+  R13: 0000000000000000 R14: ffff88803d884270 R15: ffff8881680d8000
+  FS:  00007f67317b8440(0000) GS:ffff88817bcc0000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 00007f67247a22a8 CR3: 000000004bfbc002 CR4: 0000000000370ee0
+  DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+  DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+  Call Trace:
+   ? slab_free_freelist_hook+0xea/0x1b0
+   ? trace_hardirqs_on+0x1c/0xe0
+   btrfs_setxattr_trans+0x3c/0xf0
+   __vfs_setxattr+0x63/0x80
+   smack_d_instantiate+0x2d3/0x360
+   security_d_instantiate+0x29/0x40
+   d_instantiate_new+0x38/0x90
+   btrfs_mkdir+0x1cf/0x1e0
+   vfs_mkdir+0x14f/0x200
+   do_mkdirat+0x6d/0x110
+   do_syscall_64+0x2d/0x40
+   entry_SYSCALL_64_after_hwframe+0x44/0xa9
+  RIP: 0033:0x7f673196ae6b
+  Code: 8b 05 11 (...)
+  RSP: 002b:00007ffc3c679b18 EFLAGS: 00000246 ORIG_RAX: 0000000000000053
+  RAX: ffffffffffffffda RBX: 00000000000001ff RCX: 00007f673196ae6b
+  RDX: 0000000000000000 RSI: 00000000000001ff RDI: 00007ffc3c67a30d
+  RBP: 00007ffc3c67a30d R08: 00000000000001ff R09: 0000000000000000
+  R10: 000055d3e39fe930 R11: 0000000000000246 R12: 0000000000000000
+  R13: 00007ffc3c679cd8 R14: 00007ffc3c67a30d R15: 00007ffc3c679ce0
+  irq event stamp: 11029
+  hardirqs last  enabled at (11037): [<ffffffff81153fe6>] console_unlock+0x486/0x670
+  hardirqs last disabled at (11044): [<ffffffff81153c01>] console_unlock+0xa1/0x670
+  softirqs last  enabled at (8864): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+  softirqs last disabled at (8851): [<ffffffff81e0102f>] asm_call_on_stack+0xf/0x20
+
+This happens because at btrfs_mkdir() we call d_instantiate_new() while
+holding a transaction handle, which results in the following call chain:
+
+  btrfs_mkdir()
+     trans = btrfs_start_transaction(root, 5);
+
+     d_instantiate_new()
+        smack_d_instantiate()
+            __vfs_setxattr()
+                btrfs_setxattr_trans()
+                   btrfs_start_transaction()
+                      start_transaction()
+                         WARN_ON()
+                           --> a tansaction start has TRANS_EXTWRITERS
+                               set in its type
+                         h->orig_rsv = h->block_rsv
+                         h->block_rsv = NULL
+
+     btrfs_end_transaction(trans)
+
+Besides the warning triggered at start_transaction, we set the handle's
+block_rsv to NULL which may cause some surprises later on.
+
+So fix this by making btrfs_setxattr_trans() not start a transaction when
+we already have a handle on one, stored in current->journal_info, and use
+that handle. We are good to use the handle because at btrfs_mkdir() we did
+reserve space for the xattr and the inode item.
+
+Reported-by: Casey Schaufler <casey@schaufler-ca.com>
+CC: stable@vger.kernel.org # 5.4+
+Acked-by: Casey Schaufler <casey@schaufler-ca.com>
+Tested-by: Casey Schaufler <casey@schaufler-ca.com>
+Link: https://lore.kernel.org/linux-btrfs/434d856f-bd7b-4889-a6ec-e81aaebfa735@schaufler-ca.com/
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/xattr.c |   31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/xattr.c
++++ b/fs/btrfs/xattr.c
+@@ -227,11 +227,33 @@ int btrfs_setxattr_trans(struct inode *i
+ {
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
++      const bool start_trans = (current->journal_info == NULL);
+       int ret;
+-      trans = btrfs_start_transaction(root, 2);
+-      if (IS_ERR(trans))
+-              return PTR_ERR(trans);
++      if (start_trans) {
++              /*
++               * 1 unit for inserting/updating/deleting the xattr
++               * 1 unit for the inode item update
++               */
++              trans = btrfs_start_transaction(root, 2);
++              if (IS_ERR(trans))
++                      return PTR_ERR(trans);
++      } else {
++              /*
++               * This can happen when smack is enabled and a directory is being
++               * created. It happens through d_instantiate_new(), which calls
++               * smack_d_instantiate(), which in turn calls __vfs_setxattr() to
++               * set the transmute xattr (XATTR_NAME_SMACKTRANSMUTE) on the
++               * inode. We have already reserved space for the xattr and inode
++               * update at btrfs_mkdir(), so just use the transaction handle.
++               * We don't join or start a transaction, as that will reset the
++               * block_rsv of the handle and trigger a warning for the start
++               * case.
++               */
++              ASSERT(strncmp(name, XATTR_SECURITY_PREFIX,
++                             XATTR_SECURITY_PREFIX_LEN) == 0);
++              trans = current->journal_info;
++      }
+       ret = btrfs_setxattr(trans, inode, name, value, size, flags);
+       if (ret)
+@@ -242,7 +264,8 @@ int btrfs_setxattr_trans(struct inode *i
+       ret = btrfs_update_inode(trans, root, inode);
+       BUG_ON(ret);
+ out:
+-      btrfs_end_transaction(trans);
++      if (start_trans)
++              btrfs_end_transaction(trans);
+       return ret;
+ }
diff --git a/queue-5.4/btrfs-free-correct-amount-of-space-in-btrfs_delayed_inode_reserve_metadata.patch b/queue-5.4/btrfs-free-correct-amount-of-space-in-btrfs_delayed_inode_reserve_metadata.patch
new file mode 100644 (file)
index 0000000..b6b54b0
--- /dev/null
@@ -0,0 +1,37 @@
+From 0f9c03d824f6f522d3bc43629635c9765546ebc5 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Mon, 22 Feb 2021 18:40:42 +0200
+Subject: btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 0f9c03d824f6f522d3bc43629635c9765546ebc5 upstream.
+
+Following commit f218ea6c4792 ("btrfs: delayed-inode: Remove wrong
+qgroup meta reservation calls") this function now reserves num_bytes,
+rather than the fixed amount of nodesize. As such this requires the
+same amount to be freed in case of failure. Fix this by adjusting
+the amount we are freeing.
+
+Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls")
+CC: stable@vger.kernel.org # 4.19+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/delayed-inode.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -649,7 +649,7 @@ static int btrfs_delayed_inode_reserve_m
+                                                     btrfs_ino(inode),
+                                                     num_bytes, 1);
+               } else {
+-                      btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize);
++                      btrfs_qgroup_free_meta_prealloc(root, num_bytes);
+               }
+               return ret;
+       }
diff --git a/queue-5.4/btrfs-raid56-simplify-tracking-of-q-stripe-presence.patch b/queue-5.4/btrfs-raid56-simplify-tracking-of-q-stripe-presence.patch
new file mode 100644 (file)
index 0000000..63c2e1a
--- /dev/null
@@ -0,0 +1,126 @@
+From c17af96554a8a8777cbb0fd53b8497250e548b43 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Wed, 19 Feb 2020 15:17:20 +0100
+Subject: btrfs: raid56: simplify tracking of Q stripe presence
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: David Sterba <dsterba@suse.com>
+
+commit c17af96554a8a8777cbb0fd53b8497250e548b43 upstream.
+
+There are temporary variables tracking the index of P and Q stripes, but
+none of them is really used as such, merely for determining if the Q
+stripe is present. This leads to compiler warnings with
+-Wunused-but-set-variable and has been reported several times.
+
+fs/btrfs/raid56.c: In function ‘finish_rmw’:
+fs/btrfs/raid56.c:1199:6: warning: variable ‘p_stripe’ set but not used [-Wunused-but-set-variable]
+ 1199 |  int p_stripe = -1;
+      |      ^~~~~~~~
+fs/btrfs/raid56.c: In function ‘finish_parity_scrub’:
+fs/btrfs/raid56.c:2356:6: warning: variable ‘p_stripe’ set but not used [-Wunused-but-set-variable]
+ 2356 |  int p_stripe = -1;
+      |      ^~~~~~~~
+
+Replace the two variables with one that has a clear meaning and also get
+rid of the warnings. The logic that verifies that there are only 2
+valid cases is unchanged.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/raid56.c |   37 +++++++++++++++----------------------
+ 1 file changed, 15 insertions(+), 22 deletions(-)
+
+--- a/fs/btrfs/raid56.c
++++ b/fs/btrfs/raid56.c
+@@ -1198,22 +1198,19 @@ static noinline void finish_rmw(struct b
+       int nr_data = rbio->nr_data;
+       int stripe;
+       int pagenr;
+-      int p_stripe = -1;
+-      int q_stripe = -1;
++      bool has_qstripe;
+       struct bio_list bio_list;
+       struct bio *bio;
+       int ret;
+       bio_list_init(&bio_list);
+-      if (rbio->real_stripes - rbio->nr_data == 1) {
+-              p_stripe = rbio->real_stripes - 1;
+-      } else if (rbio->real_stripes - rbio->nr_data == 2) {
+-              p_stripe = rbio->real_stripes - 2;
+-              q_stripe = rbio->real_stripes - 1;
+-      } else {
++      if (rbio->real_stripes - rbio->nr_data == 1)
++              has_qstripe = false;
++      else if (rbio->real_stripes - rbio->nr_data == 2)
++              has_qstripe = true;
++      else
+               BUG();
+-      }
+       /* at this point we either have a full stripe,
+        * or we've read the full stripe from the drive.
+@@ -1257,7 +1254,7 @@ static noinline void finish_rmw(struct b
+               SetPageUptodate(p);
+               pointers[stripe++] = kmap(p);
+-              if (q_stripe != -1) {
++              if (has_qstripe) {
+                       /*
+                        * raid6, add the qstripe and call the
+@@ -2355,8 +2352,7 @@ static noinline void finish_parity_scrub
+       int nr_data = rbio->nr_data;
+       int stripe;
+       int pagenr;
+-      int p_stripe = -1;
+-      int q_stripe = -1;
++      bool has_qstripe;
+       struct page *p_page = NULL;
+       struct page *q_page = NULL;
+       struct bio_list bio_list;
+@@ -2366,14 +2362,12 @@ static noinline void finish_parity_scrub
+       bio_list_init(&bio_list);
+-      if (rbio->real_stripes - rbio->nr_data == 1) {
+-              p_stripe = rbio->real_stripes - 1;
+-      } else if (rbio->real_stripes - rbio->nr_data == 2) {
+-              p_stripe = rbio->real_stripes - 2;
+-              q_stripe = rbio->real_stripes - 1;
+-      } else {
++      if (rbio->real_stripes - rbio->nr_data == 1)
++              has_qstripe = false;
++      else if (rbio->real_stripes - rbio->nr_data == 2)
++              has_qstripe = true;
++      else
+               BUG();
+-      }
+       if (bbio->num_tgtdevs && bbio->tgtdev_map[rbio->scrubp]) {
+               is_replace = 1;
+@@ -2395,7 +2389,7 @@ static noinline void finish_parity_scrub
+               goto cleanup;
+       SetPageUptodate(p_page);
+-      if (q_stripe != -1) {
++      if (has_qstripe) {
+               q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
+               if (!q_page) {
+                       __free_page(p_page);
+@@ -2418,8 +2412,7 @@ static noinline void finish_parity_scrub
+               /* then add the parity stripe */
+               pointers[stripe++] = kmap(p_page);
+-              if (q_stripe != -1) {
+-
++              if (has_qstripe) {
+                       /*
+                        * raid6, add the qstripe and call the
+                        * library function to fill in our p/q
diff --git a/queue-5.4/btrfs-unlock-extents-in-btrfs_zero_range-in-case-of-quota-reservation-errors.patch b/queue-5.4/btrfs-unlock-extents-in-btrfs_zero_range-in-case-of-quota-reservation-errors.patch
new file mode 100644 (file)
index 0000000..0bcb5dc
--- /dev/null
@@ -0,0 +1,40 @@
+From 4f6a49de64fd1b1dba5229c02047376da7cf24fd Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nborisov@suse.com>
+Date: Tue, 23 Feb 2021 15:20:42 +0200
+Subject: btrfs: unlock extents in btrfs_zero_range in case of quota reservation errors
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+commit 4f6a49de64fd1b1dba5229c02047376da7cf24fd upstream.
+
+If btrfs_qgroup_reserve_data returns an error (i.e quota limit reached)
+the handling logic directly goes to the 'out' label without first
+unlocking the extent range between lockstart, lockend. This results in
+deadlocks as other processes try to lock the same extent.
+
+Fixes: a7f8b1c2ac21 ("btrfs: file: reserve qgroup space after the hole punch range is locked")
+CC: stable@vger.kernel.org # 5.10+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/file.c |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -3151,8 +3151,11 @@ reserve_space:
+                       goto out;
+               ret = btrfs_qgroup_reserve_data(inode, &data_reserved,
+                                               alloc_start, bytes_to_reserve);
+-              if (ret)
++              if (ret) {
++                      unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart,
++                                           lockend, &cached_state);
+                       goto out;
++              }
+               ret = btrfs_prealloc_file_range(inode, mode, alloc_start,
+                                               alloc_end - alloc_start,
+                                               i_blocksize(inode),
diff --git a/queue-5.4/btrfs-validate-qgroup-inherit-for-snap_create_v2-ioctl.patch b/queue-5.4/btrfs-validate-qgroup-inherit-for-snap_create_v2-ioctl.patch
new file mode 100644 (file)
index 0000000..1b39617
--- /dev/null
@@ -0,0 +1,60 @@
+From 5011c5a663b9c6d6aff3d394f11049b371199627 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dancarpenter@oracle.com>
+Date: Wed, 17 Feb 2021 09:04:34 +0300
+Subject: btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+
+From: Dan Carpenter <dancarpenter@oracle.com>
+
+commit 5011c5a663b9c6d6aff3d394f11049b371199627 upstream.
+
+The problem is we're copying "inherit" from user space but we don't
+necessarily know that we're copying enough data for a 64 byte
+struct.  Then the next problem is that 'inherit' has a variable size
+array at the end, and we have to verify that array is the size we
+expected.
+
+Fixes: 6f72c7e20dba ("Btrfs: add qgroup inheritance")
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ioctl.c |   19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -1907,7 +1907,10 @@ static noinline int btrfs_ioctl_snap_cre
+       if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
+               readonly = true;
+       if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+-              if (vol_args->size > PAGE_SIZE) {
++              u64 nums;
++
++              if (vol_args->size < sizeof(*inherit) ||
++                  vol_args->size > PAGE_SIZE) {
+                       ret = -EINVAL;
+                       goto free_args;
+               }
+@@ -1916,6 +1919,20 @@ static noinline int btrfs_ioctl_snap_cre
+                       ret = PTR_ERR(inherit);
+                       goto free_args;
+               }
++
++              if (inherit->num_qgroups > PAGE_SIZE ||
++                  inherit->num_ref_copies > PAGE_SIZE ||
++                  inherit->num_excl_copies > PAGE_SIZE) {
++                      ret = -EINVAL;
++                      goto free_inherit;
++              }
++
++              nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
++                     2 * inherit->num_excl_copies;
++              if (vol_args->size != struct_size(inherit, qgroups, nums)) {
++                      ret = -EINVAL;
++                      goto free_inherit;
++              }
+       }
+       ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
diff --git a/queue-5.4/dm-bufio-subtract-the-number-of-initial-sectors-in-dm_bufio_get_device_size.patch b/queue-5.4/dm-bufio-subtract-the-number-of-initial-sectors-in-dm_bufio_get_device_size.patch
new file mode 100644 (file)
index 0000000..8599dc3
--- /dev/null
@@ -0,0 +1,40 @@
+From a14e5ec66a7a66e57b24e2469f9212a78460207e Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+Date: Tue, 23 Feb 2021 21:21:20 +0100
+Subject: dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+commit a14e5ec66a7a66e57b24e2469f9212a78460207e upstream.
+
+dm_bufio_get_device_size returns the device size in blocks. Before
+returning the value, we must subtract the nubmer of starting
+sectors. The number of starting sectors may not be divisible by block
+size.
+
+Note that currently, no target is using dm_bufio_set_sector_offset and
+dm_bufio_get_device_size simultaneously, so this change has no effect.
+However, an upcoming dm-verity-fec fix needs this change.
+
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Reviewed-by: Milan Broz <gmazyland@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-bufio.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1438,6 +1438,10 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_siz
+ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
+ {
+       sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
++      if (s >= c->start)
++              s -= c->start;
++      else
++              s = 0;
+       if (likely(c->sectors_per_block_bits >= 0))
+               s >>= c->sectors_per_block_bits;
+       else
diff --git a/queue-5.4/dm-verity-fix-fec-for-rs-roots-unaligned-to-block-size.patch b/queue-5.4/dm-verity-fix-fec-for-rs-roots-unaligned-to-block-size.patch
new file mode 100644 (file)
index 0000000..6d8b8ee
--- /dev/null
@@ -0,0 +1,142 @@
+From df7b59ba9245c4a3115ebaa905e3e5719a3810da Mon Sep 17 00:00:00 2001
+From: Milan Broz <gmazyland@gmail.com>
+Date: Tue, 23 Feb 2021 21:21:21 +0100
+Subject: dm verity: fix FEC for RS roots unaligned to block size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Milan Broz <gmazyland@gmail.com>
+
+commit df7b59ba9245c4a3115ebaa905e3e5719a3810da upstream.
+
+Optional Forward Error Correction (FEC) code in dm-verity uses
+Reed-Solomon code and should support roots from 2 to 24.
+
+The error correction parity bytes (of roots lengths per RS block) are
+stored on a separate device in sequence without any padding.
+
+Currently, to access FEC device, the dm-verity-fec code uses dm-bufio
+client with block size set to verity data block (usually 4096 or 512
+bytes).
+
+Because this block size is not divisible by some (most!) of the roots
+supported lengths, data repair cannot work for partially stored parity
+bytes.
+
+This fix changes FEC device dm-bufio block size to "roots << SECTOR_SHIFT"
+where we can be sure that the full parity data is always available.
+(There cannot be partial FEC blocks because parity must cover whole
+sectors.)
+
+Because the optional FEC starting offset could be unaligned to this
+new block size, we have to use dm_bufio_set_sector_offset() to
+configure it.
+
+The problem is easily reproduced using veritysetup, e.g. for roots=13:
+
+  # create verity device with RS FEC
+  dd if=/dev/urandom of=data.img bs=4096 count=8 status=none
+  veritysetup format data.img hash.img --fec-device=fec.img --fec-roots=13 | awk '/^Root hash/{ print $3 }' >roothash
+
+  # create an erasure that should be always repairable with this roots setting
+  dd if=/dev/zero of=data.img conv=notrunc bs=1 count=8 seek=4088 status=none
+
+  # try to read it through dm-verity
+  veritysetup open data.img test hash.img --fec-device=fec.img --fec-roots=13 $(cat roothash)
+  dd if=/dev/mapper/test of=/dev/null bs=4096 status=noxfer
+  # wait for possible recursive recovery in kernel
+  udevadm settle
+  veritysetup close test
+
+With this fix, errors are properly repaired.
+  device-mapper: verity-fec: 7:1: FEC 0: corrected 8 errors
+  ...
+
+Without it, FEC code usually ends on unrecoverable failure in RS decoder:
+  device-mapper: verity-fec: 7:1: FEC 0: failed to correct: -74
+  ...
+
+This problem is present in all kernels since the FEC code's
+introduction (kernel 4.5).
+
+It is thought that this problem is not visible in Android ecosystem
+because it always uses a default RS roots=2.
+
+Depends-on: a14e5ec66a7a ("dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size")
+Signed-off-by: Milan Broz <gmazyland@gmail.com>
+Tested-by: Jérôme Carretero <cJ-ko@zougloub.eu>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Cc: stable@vger.kernel.org # 4.5+
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/dm-verity-fec.c |   23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/drivers/md/dm-verity-fec.c
++++ b/drivers/md/dm-verity-fec.c
+@@ -61,19 +61,18 @@ static int fec_decode_rs8(struct dm_veri
+ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
+                          unsigned *offset, struct dm_buffer **buf)
+ {
+-      u64 position, block;
++      u64 position, block, rem;
+       u8 *res;
+       position = (index + rsb) * v->fec->roots;
+-      block = position >> v->data_dev_block_bits;
+-      *offset = (unsigned)(position - (block << v->data_dev_block_bits));
++      block = div64_u64_rem(position, v->fec->roots << SECTOR_SHIFT, &rem);
++      *offset = (unsigned)rem;
+-      res = dm_bufio_read(v->fec->bufio, v->fec->start + block, buf);
++      res = dm_bufio_read(v->fec->bufio, block, buf);
+       if (IS_ERR(res)) {
+               DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
+                     v->data_dev->name, (unsigned long long)rsb,
+-                    (unsigned long long)(v->fec->start + block),
+-                    PTR_ERR(res));
++                    (unsigned long long)block, PTR_ERR(res));
+               *buf = NULL;
+       }
+@@ -155,7 +154,7 @@ static int fec_decode_bufs(struct dm_ver
+               /* read the next block when we run out of parity bytes */
+               offset += v->fec->roots;
+-              if (offset >= 1 << v->data_dev_block_bits) {
++              if (offset >= v->fec->roots << SECTOR_SHIFT) {
+                       dm_bufio_release(buf);
+                       par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
+@@ -674,7 +673,7 @@ int verity_fec_ctr(struct dm_verity *v)
+ {
+       struct dm_verity_fec *f = v->fec;
+       struct dm_target *ti = v->ti;
+-      u64 hash_blocks;
++      u64 hash_blocks, fec_blocks;
+       int ret;
+       if (!verity_fec_is_enabled(v)) {
+@@ -744,15 +743,17 @@ int verity_fec_ctr(struct dm_verity *v)
+       }
+       f->bufio = dm_bufio_client_create(f->dev->bdev,
+-                                        1 << v->data_dev_block_bits,
++                                        f->roots << SECTOR_SHIFT,
+                                         1, 0, NULL, NULL);
+       if (IS_ERR(f->bufio)) {
+               ti->error = "Cannot initialize FEC bufio client";
+               return PTR_ERR(f->bufio);
+       }
+-      if (dm_bufio_get_device_size(f->bufio) <
+-          ((f->start + f->rounds * f->roots) >> v->data_dev_block_bits)) {
++      dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));
++
++      fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
++      if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
+               ti->error = "FEC device is too small";
+               return -E2BIG;
+       }
diff --git a/queue-5.4/drm-amdgpu-fix-parameter-error-of-rreg32_pcie-in-amdgpu_regs_pcie.patch b/queue-5.4/drm-amdgpu-fix-parameter-error-of-rreg32_pcie-in-amdgpu_regs_pcie.patch
new file mode 100644 (file)
index 0000000..c14ecfa
--- /dev/null
@@ -0,0 +1,40 @@
+From 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff Mon Sep 17 00:00:00 2001
+From: Kevin Wang <kevin1.wang@amd.com>
+Date: Tue, 2 Mar 2021 15:54:00 +0800
+Subject: drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+
+From: Kevin Wang <kevin1.wang@amd.com>
+
+commit 1aa46901ee51c1c5779b3b239ea0374a50c6d9ff upstream.
+
+the register offset isn't needed division by 4 to pass RREG32_PCIE()
+
+Signed-off-by: Kevin Wang <kevin1.wang@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+@@ -240,7 +240,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+       while (size) {
+               uint32_t value;
+-              value = RREG32_PCIE(*pos >> 2);
++              value = RREG32_PCIE(*pos);
+               r = put_user(value, (uint32_t *)buf);
+               if (r)
+                       return r;
+@@ -283,7 +283,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
+               if (r)
+                       return r;
+-              WREG32_PCIE(*pos >> 2, value);
++              WREG32_PCIE(*pos, value);
+               result += 4;
+               buf += 4;
diff --git a/queue-5.4/pm-runtime-update-device-status-before-letting-suppliers-suspend.patch b/queue-5.4/pm-runtime-update-device-status-before-letting-suppliers-suspend.patch
new file mode 100644 (file)
index 0000000..13b52e9
--- /dev/null
@@ -0,0 +1,122 @@
+From 44cc89f764646b2f1f2ea5d1a08b230131707851 Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 25 Feb 2021 19:23:27 +0100
+Subject: PM: runtime: Update device status before letting suppliers suspend
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 44cc89f764646b2f1f2ea5d1a08b230131707851 upstream.
+
+Because the PM-runtime status of the device is not updated in
+__rpm_callback(), attempts to suspend the suppliers of the given
+device triggered by rpm_put_suppliers() called by it may fail.
+
+Fix this by making __rpm_callback() update the device's status to
+RPM_SUSPENDED before calling rpm_put_suppliers() if the current
+status of the device is RPM_SUSPENDING and the callback just invoked
+by it has returned 0 (success).
+
+While at it, modify the code in __rpm_callback() to always check
+the device's PM-runtime status under its PM lock.
+
+Link: https://lore.kernel.org/linux-pm/CAPDyKFqm06KDw_p8WXsM4dijDbho4bb6T4k50UqqvR1_COsp8g@mail.gmail.com/
+Fixes: 21d5c57b3726 ("PM / runtime: Use device links")
+Reported-by: Elaine Zhang <zhangqing@rock-chips.com>
+Diagnosed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Tested-by: Elaine Zhang <zhangiqng@rock-chips.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Cc: 4.10+ <stable@vger.kernel.org> # 4.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/power/runtime.c |   62 +++++++++++++++++++++++++------------------
+ 1 file changed, 37 insertions(+), 25 deletions(-)
+
+--- a/drivers/base/power/runtime.c
++++ b/drivers/base/power/runtime.c
+@@ -325,22 +325,22 @@ static void rpm_put_suppliers(struct dev
+ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
+       __releases(&dev->power.lock) __acquires(&dev->power.lock)
+ {
+-      int retval, idx;
+       bool use_links = dev->power.links_count > 0;
++      bool get = false;
++      int retval, idx;
++      bool put;
+       if (dev->power.irq_safe) {
+               spin_unlock(&dev->power.lock);
++      } else if (!use_links) {
++              spin_unlock_irq(&dev->power.lock);
+       } else {
++              get = dev->power.runtime_status == RPM_RESUMING;
++
+               spin_unlock_irq(&dev->power.lock);
+-              /*
+-               * Resume suppliers if necessary.
+-               *
+-               * The device's runtime PM status cannot change until this
+-               * routine returns, so it is safe to read the status outside of
+-               * the lock.
+-               */
+-              if (use_links && dev->power.runtime_status == RPM_RESUMING) {
++              /* Resume suppliers if necessary. */
++              if (get) {
+                       idx = device_links_read_lock();
+                       retval = rpm_get_suppliers(dev);
+@@ -355,24 +355,36 @@ static int __rpm_callback(int (*cb)(stru
+       if (dev->power.irq_safe) {
+               spin_lock(&dev->power.lock);
+-      } else {
+-              /*
+-               * If the device is suspending and the callback has returned
+-               * success, drop the usage counters of the suppliers that have
+-               * been reference counted on its resume.
+-               *
+-               * Do that if resume fails too.
+-               */
+-              if (use_links
+-                  && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
+-                  || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+-                      idx = device_links_read_lock();
++              return retval;
++      }
+- fail:
+-                      rpm_put_suppliers(dev);
++      spin_lock_irq(&dev->power.lock);
+-                      device_links_read_unlock(idx);
+-              }
++      if (!use_links)
++              return retval;
++
++      /*
++       * If the device is suspending and the callback has returned success,
++       * drop the usage counters of the suppliers that have been reference
++       * counted on its resume.
++       *
++       * Do that if the resume fails too.
++       */
++      put = dev->power.runtime_status == RPM_SUSPENDING && !retval;
++      if (put)
++              __update_runtime_status(dev, RPM_SUSPENDED);
++      else
++              put = get && retval;
++
++      if (put) {
++              spin_unlock_irq(&dev->power.lock);
++
++              idx = device_links_read_lock();
++
++fail:
++              rpm_put_suppliers(dev);
++
++              device_links_read_unlock(idx);
+               spin_lock_irq(&dev->power.lock);
+       }
diff --git a/queue-5.4/tpm-tpm_tis-decorate-tpm_get_timeouts-with-request_locality.patch b/queue-5.4/tpm-tpm_tis-decorate-tpm_get_timeouts-with-request_locality.patch
new file mode 100644 (file)
index 0000000..790d715
--- /dev/null
@@ -0,0 +1,66 @@
+From a5665ec2affdba21bff3b0d4d3aed83b3951e8ff Mon Sep 17 00:00:00 2001
+From: Jarkko Sakkinen <jarkko@kernel.org>
+Date: Sat, 20 Feb 2021 00:55:59 +0200
+Subject: tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+commit a5665ec2affdba21bff3b0d4d3aed83b3951e8ff upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[    4.324298] TPM returned invalid status
+[    4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_get_timeouts() with request_locality() and release_locality().
+
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: stable@vger.kernel.org
+Reported-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -939,11 +939,21 @@ int tpm_tis_core_init(struct device *dev
+       init_waitqueue_head(&priv->read_queue);
+       init_waitqueue_head(&priv->int_queue);
+       if (irq != -1) {
+-              /* Before doing irq testing issue a command to the TPM in polling mode
++              /*
++               * Before doing irq testing issue a command to the TPM in polling mode
+                * to make sure it works. May as well use that command to set the
+                * proper timeouts for the driver.
+                */
+-              if (tpm_get_timeouts(chip)) {
++
++              rc = request_locality(chip, 0);
++              if (rc < 0)
++                      goto out_err;
++
++              rc = tpm_get_timeouts(chip);
++
++              release_locality(chip, 0);
++
++              if (rc) {
+                       dev_err(dev, "Could not get TPM timeouts and durations\n");
+                       rc = -ENODEV;
+                       goto out_err;
diff --git a/queue-5.4/tpm-tpm_tis-decorate-tpm_tis_gen_interrupt-with-request_locality.patch b/queue-5.4/tpm-tpm_tis-decorate-tpm_tis_gen_interrupt-with-request_locality.patch
new file mode 100644 (file)
index 0000000..d2f9657
--- /dev/null
@@ -0,0 +1,69 @@
+From d53a6adfb553969809eb2b736a976ebb5146cd95 Mon Sep 17 00:00:00 2001
+From: Lukasz Majczak <lma@semihalf.com>
+Date: Tue, 16 Feb 2021 10:17:49 +0200
+Subject: tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+
+From: Lukasz Majczak <lma@semihalf.com>
+
+commit d53a6adfb553969809eb2b736a976ebb5146cd95 upstream.
+
+This is shown with Samsung Chromebook Pro (Caroline) with TPM 1.2
+(SLB 9670):
+
+[    4.324298] TPM returned invalid status
+[    4.324806] WARNING: CPU: 2 PID: 1 at drivers/char/tpm/tpm_tis_core.c:275 tpm_tis_status+0x86/0x8f
+
+Background
+==========
+
+TCG PC Client Platform TPM Profile (PTP) Specification, paragraph 6.1 FIFO
+Interface Locality Usage per Register, Table 39 Register Behavior Based on
+Locality Setting for FIFO - a read attempt to TPM_STS_x Registers returns
+0xFF in case of lack of locality.
+
+The fix
+=======
+
+Decorate tpm_tis_gen_interrupt() with request_locality() and
+release_locality().
+
+Cc: Laurent Bigonville <bigon@debian.org>
+Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: stable@vger.kernel.org
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Signed-off-by: Lukasz Majczak <lma@semihalf.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/char/tpm/tpm_tis_core.c |   16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -618,12 +618,22 @@ static int tpm_tis_gen_interrupt(struct
+       const char *desc = "attempting to generate an interrupt";
+       u32 cap2;
+       cap_t cap;
++      int ret;
++      /* TPM 2.0 */
+       if (chip->flags & TPM_CHIP_FLAG_TPM2)
+               return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
+-      else
+-              return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
+-                                0);
++
++      /* TPM 1.2 */
++      ret = request_locality(chip, 0);
++      if (ret < 0)
++              return ret;
++
++      ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
++
++      release_locality(chip, 0);
++
++      return ret;
+ }
+ /* Register the IRQ and issue a command that will cause an interrupt. If an