]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 09:24:22 +0000 (11:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 09:24:22 +0000 (11:24 +0200)
added patches:
bcache-remove-unnecessary-null-point-check-in-node-allocations.patch
ext4-remove-ext4-locking-of-moved-directory.patch
fs-avoid-empty-option-when-generating-legacy-mount-string.patch
fs-establish-locking-order-for-unrelated-directories.patch
fs-lock-moved-directories.patch
integrity-fix-possible-multiple-allocation-in-integrity_inode_get.patch
jffs2-reduce-stack-usage-in-jffs2_build_xattr_subsystem.patch
mmc-core-disable-trim-on-kingston-emmc04g-m627.patch
mmc-core-disable-trim-on-micron-mtfc4gacajcn-1m.patch
mmc-sdhci-fix-dma-configure-compatibility-issue-when-64bit-dma-mode-is-used.patch
nfsd-add-encoding-of-op_recall-flag-for-write-delegation.patch
revert-f2fs-fix-potential-corruption-when-moving-a-directory.patch
wifi-ath10k-serialize-wake_tx_queue-ops.patch

14 files changed:
queue-5.4/bcache-remove-unnecessary-null-point-check-in-node-allocations.patch [new file with mode: 0644]
queue-5.4/ext4-remove-ext4-locking-of-moved-directory.patch [new file with mode: 0644]
queue-5.4/fs-avoid-empty-option-when-generating-legacy-mount-string.patch [new file with mode: 0644]
queue-5.4/fs-establish-locking-order-for-unrelated-directories.patch [new file with mode: 0644]
queue-5.4/fs-lock-moved-directories.patch [new file with mode: 0644]
queue-5.4/integrity-fix-possible-multiple-allocation-in-integrity_inode_get.patch [new file with mode: 0644]
queue-5.4/jffs2-reduce-stack-usage-in-jffs2_build_xattr_subsystem.patch [new file with mode: 0644]
queue-5.4/mmc-core-disable-trim-on-kingston-emmc04g-m627.patch [new file with mode: 0644]
queue-5.4/mmc-core-disable-trim-on-micron-mtfc4gacajcn-1m.patch [new file with mode: 0644]
queue-5.4/mmc-sdhci-fix-dma-configure-compatibility-issue-when-64bit-dma-mode-is-used.patch [new file with mode: 0644]
queue-5.4/nfsd-add-encoding-of-op_recall-flag-for-write-delegation.patch [new file with mode: 0644]
queue-5.4/revert-f2fs-fix-potential-corruption-when-moving-a-directory.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/wifi-ath10k-serialize-wake_tx_queue-ops.patch [new file with mode: 0644]

diff --git a/queue-5.4/bcache-remove-unnecessary-null-point-check-in-node-allocations.patch b/queue-5.4/bcache-remove-unnecessary-null-point-check-in-node-allocations.patch
new file mode 100644 (file)
index 0000000..342fba6
--- /dev/null
@@ -0,0 +1,92 @@
+From 028ddcac477b691dd9205c92f991cc15259d033e Mon Sep 17 00:00:00 2001
+From: Zheng Wang <zyytlz.wz@163.com>
+Date: Thu, 15 Jun 2023 20:12:21 +0800
+Subject: bcache: Remove unnecessary NULL point check in node allocations
+
+From: Zheng Wang <zyytlz.wz@163.com>
+
+commit 028ddcac477b691dd9205c92f991cc15259d033e upstream.
+
+Due to the previous fix of __bch_btree_node_alloc, the return value will
+never be a NULL pointer. So IS_ERR is enough to handle the failure
+situation. Fix it by replacing IS_ERR_OR_NULL check by an IS_ERR check.
+
+Fixes: cafe56359144 ("bcache: A block layer cache")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zheng Wang <zyytlz.wz@163.com>
+Signed-off-by: Coly Li <colyli@suse.de>
+Link: https://lore.kernel.org/r/20230615121223.22502-5-colyli@suse.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/md/bcache/btree.c |   10 +++++-----
+ drivers/md/bcache/super.c |    4 ++--
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/md/bcache/btree.c
++++ b/drivers/md/bcache/btree.c
+@@ -1186,7 +1186,7 @@ static struct btree *btree_node_alloc_re
+ {
+       struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
+-      if (!IS_ERR_OR_NULL(n)) {
++      if (!IS_ERR(n)) {
+               mutex_lock(&n->write_lock);
+               bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
+               bkey_copy_key(&n->key, &b->key);
+@@ -1389,7 +1389,7 @@ static int btree_gc_coalesce(struct btre
+       memset(new_nodes, 0, sizeof(new_nodes));
+       closure_init_stack(&cl);
+-      while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b))
++      while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b))
+               keys += r[nodes++].keys;
+       blocks = btree_default_blocks(b->c) * 2 / 3;
+@@ -1401,7 +1401,7 @@ static int btree_gc_coalesce(struct btre
+       for (i = 0; i < nodes; i++) {
+               new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL);
+-              if (IS_ERR_OR_NULL(new_nodes[i]))
++              if (IS_ERR(new_nodes[i]))
+                       goto out_nocoalesce;
+       }
+@@ -1536,7 +1536,7 @@ out_nocoalesce:
+       bch_keylist_free(&keylist);
+       for (i = 0; i < nodes; i++)
+-              if (!IS_ERR_OR_NULL(new_nodes[i])) {
++              if (!IS_ERR(new_nodes[i])) {
+                       btree_node_free(new_nodes[i]);
+                       rw_unlock(true, new_nodes[i]);
+               }
+@@ -1718,7 +1718,7 @@ static int bch_btree_gc_root(struct btre
+       if (should_rewrite) {
+               n = btree_node_alloc_replacement(b, NULL);
+-              if (!IS_ERR_OR_NULL(n)) {
++              if (!IS_ERR(n)) {
+                       bch_btree_node_write_sync(n);
+                       bch_btree_set_root(n);
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -1633,7 +1633,7 @@ static void cache_set_flush(struct closu
+       if (!IS_ERR_OR_NULL(c->gc_thread))
+               kthread_stop(c->gc_thread);
+-      if (!IS_ERR_OR_NULL(c->root))
++      if (!IS_ERR(c->root))
+               list_add(&c->root->list, &c->btree_cache);
+       /*
+@@ -2000,7 +2000,7 @@ static int run_cache_set(struct cache_se
+               err = "cannot allocate new btree root";
+               c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
+-              if (IS_ERR_OR_NULL(c->root))
++              if (IS_ERR(c->root))
+                       goto err;
+               mutex_lock(&c->root->write_lock);
diff --git a/queue-5.4/ext4-remove-ext4-locking-of-moved-directory.patch b/queue-5.4/ext4-remove-ext4-locking-of-moved-directory.patch
new file mode 100644 (file)
index 0000000..c633876
--- /dev/null
@@ -0,0 +1,59 @@
+From 3658840cd363f2be094f5dfd2f0b174a9055dd0f Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 1 Jun 2023 12:58:21 +0200
+Subject: ext4: Remove ext4 locking of moved directory
+
+From: Jan Kara <jack@suse.cz>
+
+commit 3658840cd363f2be094f5dfd2f0b174a9055dd0f upstream.
+
+Remove locking of moved directory in ext4_rename2(). We will take care
+of it in VFS instead. This effectively reverts commit 0813299c586b
+("ext4: Fix possible corruption when moving a directory") and followup
+fixes.
+
+CC: Ted Tso <tytso@mit.edu>
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230601105830.13168-1-jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/namei.c |   17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -3795,19 +3795,10 @@ static int ext4_rename(struct inode *old
+                       return retval;
+       }
+-      /*
+-       * We need to protect against old.inode directory getting converted
+-       * from inline directory format into a normal one.
+-       */
+-      if (S_ISDIR(old.inode->i_mode))
+-              inode_lock_nested(old.inode, I_MUTEX_NONDIR2);
+-
+       old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de,
+                                &old.inlined);
+-      if (IS_ERR(old.bh)) {
+-              retval = PTR_ERR(old.bh);
+-              goto unlock_moved_dir;
+-      }
++      if (IS_ERR(old.bh))
++              return PTR_ERR(old.bh);
+       /*
+        *  Check for inode number is _not_ due to possible IO errors.
+@@ -3968,10 +3959,6 @@ release_bh:
+       brelse(old.bh);
+       brelse(new.bh);
+-unlock_moved_dir:
+-      if (S_ISDIR(old.inode->i_mode))
+-              inode_unlock(old.inode);
+-
+       return retval;
+ }
diff --git a/queue-5.4/fs-avoid-empty-option-when-generating-legacy-mount-string.patch b/queue-5.4/fs-avoid-empty-option-when-generating-legacy-mount-string.patch
new file mode 100644 (file)
index 0000000..1e106d6
--- /dev/null
@@ -0,0 +1,43 @@
+From 62176420274db5b5127cd7a0083a9aeb461756ee Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <linux@weissschuh.net>
+Date: Wed, 7 Jun 2023 19:28:48 +0200
+Subject: fs: avoid empty option when generating legacy mount string
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+commit 62176420274db5b5127cd7a0083a9aeb461756ee upstream.
+
+As each option string fragment is always prepended with a comma it would
+happen that the whole string always starts with a comma. This could be
+interpreted by filesystem drivers as an empty option and may produce
+errors.
+
+For example the NTFS driver from ntfs.ko behaves like this and fails
+when mounted via the new API.
+
+Link: https://github.com/util-linux/util-linux/issues/2298
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Fixes: 3e1aeb00e6d1 ("vfs: Implement a filesystem superblock creation/configuration context")
+Cc: stable@vger.kernel.org
+Message-Id: <20230607-fs-empty-option-v1-1-20c8dbf4671b@weissschuh.net>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fs_context.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/fs_context.c
++++ b/fs/fs_context.c
+@@ -598,7 +598,8 @@ static int legacy_parse_param(struct fs_
+                       return -ENOMEM;
+       }
+-      ctx->legacy_data[size++] = ',';
++      if (size)
++              ctx->legacy_data[size++] = ',';
+       len = strlen(param->key);
+       memcpy(ctx->legacy_data + size, param->key, len);
+       size += len;
diff --git a/queue-5.4/fs-establish-locking-order-for-unrelated-directories.patch b/queue-5.4/fs-establish-locking-order-for-unrelated-directories.patch
new file mode 100644 (file)
index 0000000..1702336
--- /dev/null
@@ -0,0 +1,104 @@
+From f23ce757185319886ca80c4864ce5f81ac6cc9e9 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 1 Jun 2023 12:58:24 +0200
+Subject: fs: Establish locking order for unrelated directories
+
+From: Jan Kara <jack@suse.cz>
+
+commit f23ce757185319886ca80c4864ce5f81ac6cc9e9 upstream.
+
+Currently the locking order of inode locks for directories that are not
+in ancestor relationship is not defined because all operations that
+needed to lock two directories like this were serialized by
+sb->s_vfs_rename_mutex. However some filesystems need to lock two
+subdirectories for RENAME_EXCHANGE operations and for this we need the
+locking order established even for two tree-unrelated directories.
+Provide a helper function lock_two_inodes() that establishes lock
+ordering for any two inodes and use it in lock_two_directories().
+
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230601105830.13168-4-jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/inode.c    |   42 ++++++++++++++++++++++++++++++++++++++++++
+ fs/internal.h |    2 ++
+ fs/namei.c    |    4 ++--
+ 3 files changed, 46 insertions(+), 2 deletions(-)
+
+--- a/fs/inode.c
++++ b/fs/inode.c
+@@ -1013,6 +1013,48 @@ void discard_new_inode(struct inode *ino
+ EXPORT_SYMBOL(discard_new_inode);
+ /**
++ * lock_two_inodes - lock two inodes (may be regular files but also dirs)
++ *
++ * Lock any non-NULL argument. The caller must make sure that if he is passing
++ * in two directories, one is not ancestor of the other.  Zero, one or two
++ * objects may be locked by this function.
++ *
++ * @inode1: first inode to lock
++ * @inode2: second inode to lock
++ * @subclass1: inode lock subclass for the first lock obtained
++ * @subclass2: inode lock subclass for the second lock obtained
++ */
++void lock_two_inodes(struct inode *inode1, struct inode *inode2,
++                   unsigned subclass1, unsigned subclass2)
++{
++      if (!inode1 || !inode2) {
++              /*
++               * Make sure @subclass1 will be used for the acquired lock.
++               * This is not strictly necessary (no current caller cares) but
++               * let's keep things consistent.
++               */
++              if (!inode1)
++                      swap(inode1, inode2);
++              goto lock;
++      }
++
++      /*
++       * If one object is directory and the other is not, we must make sure
++       * to lock directory first as the other object may be its child.
++       */
++      if (S_ISDIR(inode2->i_mode) == S_ISDIR(inode1->i_mode)) {
++              if (inode1 > inode2)
++                      swap(inode1, inode2);
++      } else if (!S_ISDIR(inode1->i_mode))
++              swap(inode1, inode2);
++lock:
++      if (inode1)
++              inode_lock_nested(inode1, subclass1);
++      if (inode2 && inode2 != inode1)
++              inode_lock_nested(inode2, subclass2);
++}
++
++/**
+  * lock_two_nondirectories - take two i_mutexes on non-directory objects
+  *
+  * Lock any non-NULL argument that is not a directory.
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -138,6 +138,8 @@ extern int vfs_open(const struct path *,
+ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
+ extern void inode_add_lru(struct inode *inode);
+ extern int dentry_needs_remove_privs(struct dentry *dentry);
++void lock_two_inodes(struct inode *inode1, struct inode *inode2,
++                   unsigned subclass1, unsigned subclass2);
+ /*
+  * fs-writeback.c
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2870,8 +2870,8 @@ struct dentry *lock_rename(struct dentry
+               return p;
+       }
+-      inode_lock_nested(p1->d_inode, I_MUTEX_PARENT);
+-      inode_lock_nested(p2->d_inode, I_MUTEX_PARENT2);
++      lock_two_inodes(p1->d_inode, p2->d_inode,
++                      I_MUTEX_PARENT, I_MUTEX_PARENT2);
+       return NULL;
+ }
+ EXPORT_SYMBOL(lock_rename);
diff --git a/queue-5.4/fs-lock-moved-directories.patch b/queue-5.4/fs-lock-moved-directories.patch
new file mode 100644 (file)
index 0000000..4e5219a
--- /dev/null
@@ -0,0 +1,126 @@
+From 28eceeda130f5058074dd007d9c59d2e8bc5af2e Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 1 Jun 2023 12:58:25 +0200
+Subject: fs: Lock moved directories
+
+From: Jan Kara <jack@suse.cz>
+
+commit 28eceeda130f5058074dd007d9c59d2e8bc5af2e upstream.
+
+When a directory is moved to a different directory, some filesystems
+(udf, ext4, ocfs2, f2fs, and likely gfs2, reiserfs, and others) need to
+update their pointer to the parent and this must not race with other
+operations on the directory. Lock the directories when they are moved.
+Although not all filesystems need this locking, we perform it in
+vfs_rename() because getting the lock ordering right is really difficult
+and we don't want to expose these locking details to filesystems.
+
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230601105830.13168-5-jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/filesystems/directory-locking.rst |   26 ++++++++++++------------
+ fs/namei.c                                      |   22 ++++++++++++--------
+ 2 files changed, 28 insertions(+), 20 deletions(-)
+
+--- a/Documentation/filesystems/directory-locking.rst
++++ b/Documentation/filesystems/directory-locking.rst
+@@ -22,12 +22,11 @@ exclusive.
+ 3) object removal.  Locking rules: caller locks parent, finds victim,
+ locks victim and calls the method.  Locks are exclusive.
+-4) rename() that is _not_ cross-directory.  Locking rules: caller locks
+-the parent and finds source and target.  In case of exchange (with
+-RENAME_EXCHANGE in flags argument) lock both.  In any case,
+-if the target already exists, lock it.  If the source is a non-directory,
+-lock it.  If we need to lock both, lock them in inode pointer order.
+-Then call the method.  All locks are exclusive.
++4) rename() that is _not_ cross-directory.  Locking rules: caller locks the
++parent and finds source and target.  We lock both (provided they exist).  If we
++need to lock two inodes of different type (dir vs non-dir), we lock directory
++first.  If we need to lock two inodes of the same type, lock them in inode
++pointer order.  Then call the method.  All locks are exclusive.
+ NB: we might get away with locking the the source (and target in exchange
+ case) shared.
+@@ -44,15 +43,17 @@ All locks are exclusive.
+ rules:
+       * lock the filesystem
+-      * lock parents in "ancestors first" order.
++      * lock parents in "ancestors first" order. If one is not ancestor of
++        the other, lock them in inode pointer order.
+       * find source and target.
+       * if old parent is equal to or is a descendent of target
+         fail with -ENOTEMPTY
+       * if new parent is equal to or is a descendent of source
+         fail with -ELOOP
+-      * If it's an exchange, lock both the source and the target.
+-      * If the target exists, lock it.  If the source is a non-directory,
+-        lock it.  If we need to lock both, do so in inode pointer order.
++      * Lock both the source and the target provided they exist. If we
++        need to lock two inodes of different type (dir vs non-dir), we lock
++        the directory first. If we need to lock two inodes of the same type,
++        lock them in inode pointer order.
+       * call the method.
+ All ->i_rwsem are taken exclusive.  Again, we might get away with locking
+@@ -66,8 +67,9 @@ If no directory is its own ancestor, the
+ Proof:
+-      First of all, at any moment we have a partial ordering of the
+-      objects - A < B iff A is an ancestor of B.
++      First of all, at any moment we have a linear ordering of the
++      objects - A < B iff (A is an ancestor of B) or (B is not an ancestor
++        of A and ptr(A) < ptr(B)).
+       That ordering can change.  However, the following is true:
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -4367,7 +4367,7 @@ SYSCALL_DEFINE2(link, const char __user
+  *       sb->s_vfs_rename_mutex. We might be more accurate, but that's another
+  *       story.
+  *    c) we have to lock _four_ objects - parents and victim (if it exists),
+- *       and source (if it is not a directory).
++ *       and source.
+  *       And that - after we got ->i_mutex on parents (until then we don't know
+  *       whether the target exists).  Solution: try to be smart with locking
+  *       order for inodes.  We rely on the fact that tree topology may change
+@@ -4444,10 +4444,16 @@ int vfs_rename(struct inode *old_dir, st
+       take_dentry_name_snapshot(&old_name, old_dentry);
+       dget(new_dentry);
+-      if (!is_dir || (flags & RENAME_EXCHANGE))
+-              lock_two_nondirectories(source, target);
+-      else if (target)
+-              inode_lock(target);
++      /*
++       * Lock all moved children. Moved directories may need to change parent
++       * pointer so they need the lock to prevent against concurrent
++       * directory changes moving parent pointer. For regular files we've
++       * historically always done this. The lockdep locking subclasses are
++       * somewhat arbitrary but RENAME_EXCHANGE in particular can swap
++       * regular files and directories so it's difficult to tell which
++       * subclasses to use.
++       */
++      lock_two_inodes(source, target, I_MUTEX_NORMAL, I_MUTEX_NONDIR2);
+       error = -EBUSY;
+       if (is_local_mountpoint(old_dentry) || is_local_mountpoint(new_dentry))
+@@ -4491,9 +4497,9 @@ int vfs_rename(struct inode *old_dir, st
+                       d_exchange(old_dentry, new_dentry);
+       }
+ out:
+-      if (!is_dir || (flags & RENAME_EXCHANGE))
+-              unlock_two_nondirectories(source, target);
+-      else if (target)
++      if (source)
++              inode_unlock(source);
++      if (target)
+               inode_unlock(target);
+       dput(new_dentry);
+       if (!error) {
diff --git a/queue-5.4/integrity-fix-possible-multiple-allocation-in-integrity_inode_get.patch b/queue-5.4/integrity-fix-possible-multiple-allocation-in-integrity_inode_get.patch
new file mode 100644 (file)
index 0000000..5c5d648
--- /dev/null
@@ -0,0 +1,62 @@
+From 9df6a4870dc371136e90330cfbbc51464ee66993 Mon Sep 17 00:00:00 2001
+From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+Date: Thu, 1 Jun 2023 14:42:44 +0800
+Subject: integrity: Fix possible multiple allocation in integrity_inode_get()
+
+From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+
+commit 9df6a4870dc371136e90330cfbbc51464ee66993 upstream.
+
+When integrity_inode_get() is querying and inserting the cache, there
+is a conditional race in the concurrent environment.
+
+The race condition is the result of not properly implementing
+"double-checked locking". In this case, it first checks to see if the
+iint cache record exists before taking the lock, but doesn't check
+again after taking the integrity_iint_lock.
+
+Fixes: bf2276d10ce5 ("ima: allocating iint improvements")
+Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+Cc: Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
+Cc: <stable@vger.kernel.org> # v3.10+
+Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/integrity/iint.c |   15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/security/integrity/iint.c
++++ b/security/integrity/iint.c
+@@ -43,12 +43,10 @@ static struct integrity_iint_cache *__in
+               else if (inode > iint->inode)
+                       n = n->rb_right;
+               else
+-                      break;
++                      return iint;
+       }
+-      if (!n)
+-              return NULL;
+-      return iint;
++      return NULL;
+ }
+ /*
+@@ -121,10 +119,15 @@ struct integrity_iint_cache *integrity_i
+               parent = *p;
+               test_iint = rb_entry(parent, struct integrity_iint_cache,
+                                    rb_node);
+-              if (inode < test_iint->inode)
++              if (inode < test_iint->inode) {
+                       p = &(*p)->rb_left;
+-              else
++              } else if (inode > test_iint->inode) {
+                       p = &(*p)->rb_right;
++              } else {
++                      write_unlock(&integrity_iint_lock);
++                      kmem_cache_free(iint_cache, iint);
++                      return test_iint;
++              }
+       }
+       iint->inode = inode;
diff --git a/queue-5.4/jffs2-reduce-stack-usage-in-jffs2_build_xattr_subsystem.patch b/queue-5.4/jffs2-reduce-stack-usage-in-jffs2_build_xattr_subsystem.patch
new file mode 100644 (file)
index 0000000..7ffa203
--- /dev/null
@@ -0,0 +1,128 @@
+From 1168f095417643f663caa341211e117db552989f Mon Sep 17 00:00:00 2001
+From: Fabian Frederick <fabf@skynet.be>
+Date: Sat, 6 May 2023 06:56:12 +0200
+Subject: jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
+
+From: Fabian Frederick <fabf@skynet.be>
+
+commit 1168f095417643f663caa341211e117db552989f upstream.
+
+Use kcalloc() for allocation/flush of 128 pointers table to
+reduce stack usage.
+
+Function now returns -ENOMEM or 0 on success.
+
+stackusage
+Before:
+./fs/jffs2/xattr.c:775  jffs2_build_xattr_subsystem     1208
+dynamic,bounded
+
+After:
+./fs/jffs2/xattr.c:775  jffs2_build_xattr_subsystem     192
+dynamic,bounded
+
+Also update definition when CONFIG_JFFS2_FS_XATTR is not enabled
+
+Tested with an MTD mount point and some user set/getfattr.
+
+Many current target on OpenWRT also suffer from a compilation warning
+(that become an error with CONFIG_WERROR) with the following output:
+
+fs/jffs2/xattr.c: In function 'jffs2_build_xattr_subsystem':
+fs/jffs2/xattr.c:887:1: error: the frame size of 1088 bytes is larger than 1024 bytes [-Werror=frame-larger-than=]
+  887 | }
+      | ^
+
+Using dynamic allocation fix this compilation warning.
+
+Fixes: c9f700f840bd ("[JFFS2][XATTR] using 'delete marker' for xdatum/xref deletion")
+Reported-by: Tim Gardner <tim.gardner@canonical.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Ron Economos <re@w6rz.net>
+Reported-by: Nathan Chancellor <nathan@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Fabian Frederick <fabf@skynet.be>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Cc: stable@vger.kernel.org
+Message-Id: <20230506045612.16616-1-ansuelsmth@gmail.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jffs2/build.c |    5 ++++-
+ fs/jffs2/xattr.c |   13 +++++++++----
+ fs/jffs2/xattr.h |    4 ++--
+ 3 files changed, 15 insertions(+), 7 deletions(-)
+
+--- a/fs/jffs2/build.c
++++ b/fs/jffs2/build.c
+@@ -211,7 +211,10 @@ static int jffs2_build_filesystem(struct
+               ic->scan_dents = NULL;
+               cond_resched();
+       }
+-      jffs2_build_xattr_subsystem(c);
++      ret = jffs2_build_xattr_subsystem(c);
++      if (ret)
++              goto exit;
++
+       c->flags &= ~JFFS2_SB_FLAG_BUILDING;
+       dbg_fsbuild("FS build complete\n");
+--- a/fs/jffs2/xattr.c
++++ b/fs/jffs2/xattr.c
+@@ -772,10 +772,10 @@ void jffs2_clear_xattr_subsystem(struct
+ }
+ #define XREF_TMPHASH_SIZE     (128)
+-void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
++int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
+ {
+       struct jffs2_xattr_ref *ref, *_ref;
+-      struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
++      struct jffs2_xattr_ref **xref_tmphash;
+       struct jffs2_xattr_datum *xd, *_xd;
+       struct jffs2_inode_cache *ic;
+       struct jffs2_raw_node_ref *raw;
+@@ -784,9 +784,12 @@ void jffs2_build_xattr_subsystem(struct
+       BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
++      xref_tmphash = kcalloc(XREF_TMPHASH_SIZE,
++                             sizeof(struct jffs2_xattr_ref *), GFP_KERNEL);
++      if (!xref_tmphash)
++              return -ENOMEM;
++
+       /* Phase.1 : Merge same xref */
+-      for (i=0; i < XREF_TMPHASH_SIZE; i++)
+-              xref_tmphash[i] = NULL;
+       for (ref=c->xref_temp; ref; ref=_ref) {
+               struct jffs2_xattr_ref *tmp;
+@@ -884,6 +887,8 @@ void jffs2_build_xattr_subsystem(struct
+                    "%u of xref (%u dead, %u orphan) found.\n",
+                    xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
+                    xref_count, xref_dead_count, xref_orphan_count);
++      kfree(xref_tmphash);
++      return 0;
+ }
+ struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+--- a/fs/jffs2/xattr.h
++++ b/fs/jffs2/xattr.h
+@@ -71,7 +71,7 @@ static inline int is_xattr_ref_dead(stru
+ #ifdef CONFIG_JFFS2_FS_XATTR
+ extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
+-extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
++extern int jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
+ extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
+ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+@@ -103,7 +103,7 @@ extern ssize_t jffs2_listxattr(struct de
+ #else
+ #define jffs2_init_xattr_subsystem(c)
+-#define jffs2_build_xattr_subsystem(c)
++#define jffs2_build_xattr_subsystem(c)                (0)
+ #define jffs2_clear_xattr_subsystem(c)
+ #define jffs2_xattr_do_crccheck_inode(c, ic)
diff --git a/queue-5.4/mmc-core-disable-trim-on-kingston-emmc04g-m627.patch b/queue-5.4/mmc-core-disable-trim-on-kingston-emmc04g-m627.patch
new file mode 100644 (file)
index 0000000..c77405a
--- /dev/null
@@ -0,0 +1,46 @@
+From f1738a1f816233e6dfc2407f24a31d596643fd90 Mon Sep 17 00:00:00 2001
+From: Robert Marko <robimarko@gmail.com>
+Date: Mon, 19 Jun 2023 21:35:58 +0200
+Subject: mmc: core: disable TRIM on Kingston EMMC04G-M627
+
+From: Robert Marko <robimarko@gmail.com>
+
+commit f1738a1f816233e6dfc2407f24a31d596643fd90 upstream.
+
+It seems that Kingston EMMC04G-M627 despite advertising TRIM support does
+not work when the core is trying to use REQ_OP_WRITE_ZEROES.
+
+We are seeing I/O errors in OpenWrt under 6.1 on Zyxel NBG7815 that we did
+not previously have and tracked it down to REQ_OP_WRITE_ZEROES.
+
+Trying to use fstrim seems to also throw errors like:
+[93010.835112] I/O error, dev loop0, sector 16902 op 0x3:(DISCARD) flags 0x800 phys_seg 1 prio class 2
+
+Disabling TRIM makes the error go away, so lets add a quirk for this eMMC
+to disable TRIM.
+
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230619193621.437358-1-robimarko@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/quirks.h |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/mmc/core/quirks.h
++++ b/drivers/mmc/core/quirks.h
+@@ -91,6 +91,13 @@ static const struct mmc_fixup mmc_blk_fi
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       /*
++       * Kingston EMMC04G-M627 advertises TRIM but it does not seems to
++       * support being used to offload WRITE_ZEROES.
++       */
++      MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc,
++                MMC_QUIRK_TRIM_BROKEN),
++
++      /*
+        *  On Some Kingston eMMCs, performing trim can result in
+        *  unrecoverable data conrruption occasionally due to a firmware bug.
+        */
diff --git a/queue-5.4/mmc-core-disable-trim-on-micron-mtfc4gacajcn-1m.patch b/queue-5.4/mmc-core-disable-trim-on-micron-mtfc4gacajcn-1m.patch
new file mode 100644 (file)
index 0000000..6730eea
--- /dev/null
@@ -0,0 +1,44 @@
+From dbfbddcddcebc9ce8a08757708d4e4a99d238e44 Mon Sep 17 00:00:00 2001
+From: Robert Marko <robimarko@gmail.com>
+Date: Tue, 30 May 2023 23:32:59 +0200
+Subject: mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
+
+From: Robert Marko <robimarko@gmail.com>
+
+commit dbfbddcddcebc9ce8a08757708d4e4a99d238e44 upstream.
+
+It seems that Micron MTFC4GACAJCN-1M despite advertising TRIM support does
+not work when the core is trying to use REQ_OP_WRITE_ZEROES.
+
+We are seeing the following errors in OpenWrt under 6.1 on Qnap Qhora 301W
+that we did not previously have and tracked it down to REQ_OP_WRITE_ZEROES:
+[   18.085950] I/O error, dev loop0, sector 596 op 0x9:(WRITE_ZEROES) flags 0x800 phys_seg 0 prio class 2
+
+Disabling TRIM makes the error go away, so lets add a quirk for this eMMC
+to disable TRIM.
+
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230530213259.1776512-1-robimarko@gmail.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/core/quirks.h |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/mmc/core/quirks.h
++++ b/drivers/mmc/core/quirks.h
+@@ -98,6 +98,13 @@ static const struct mmc_fixup mmc_blk_fi
+                 MMC_QUIRK_TRIM_BROKEN),
+       /*
++       * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to
++       * support being used to offload WRITE_ZEROES.
++       */
++      MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc,
++                MMC_QUIRK_TRIM_BROKEN),
++
++      /*
+        *  On Some Kingston eMMCs, performing trim can result in
+        *  unrecoverable data conrruption occasionally due to a firmware bug.
+        */
diff --git a/queue-5.4/mmc-sdhci-fix-dma-configure-compatibility-issue-when-64bit-dma-mode-is-used.patch b/queue-5.4/mmc-sdhci-fix-dma-configure-compatibility-issue-when-64bit-dma-mode-is-used.patch
new file mode 100644 (file)
index 0000000..12bbf97
--- /dev/null
@@ -0,0 +1,58 @@
+From 20dbd07ef0a8bc29eb03d6a95258ac8934cbe52d Mon Sep 17 00:00:00 2001
+From: Chevron Li <chevron.li@bayhubtech.com>
+Date: Tue, 23 May 2023 19:11:14 +0800
+Subject: mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is used.
+
+From: Chevron Li <chevron.li@bayhubtech.com>
+
+commit 20dbd07ef0a8bc29eb03d6a95258ac8934cbe52d upstream.
+
+Bayhub SD host has hardware limitation:
+1.The upper 32bit address is inhibited to be written at SD Host Register
+  [03E][13]=0 (32bits addressing) mode, is admitted to be written only at
+  SD Host Register [03E][13]=1 (64bits addressing) mode.
+2.Because of above item#1, need to configure SD Host Register [03E][13] to
+  1(64bits addressing mode) before set 64bit ADMA system address's higher
+  32bits SD Host Register [05F~05C] if 64 bits addressing mode is used.
+
+The hardware limitation is reasonable for below reasons:
+1.Normal flow should set DMA working mode first, then do
+  DMA-transfer-related configuration, such as system address.
+2.The hardware limitation may avoid the software to configure wrong higher
+  32bit address at 32bits addressing mode although it is redundant.
+
+The change that set 32bits/64bits addressing mode before set ADMA address,
+  has no side-effect to other host IPs for below reason:
+The setting order is reasonable and standard: DMA Mode setting first and
+  then DMA address setting. It meets all DMA setting sequence.
+
+Signed-off-by: Chevron Li <chevron.li@bayhubtech.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230523111114.18124-1-chevron_li@126.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mmc/host/sdhci.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -1104,6 +1104,8 @@ static void sdhci_prepare_data(struct sd
+               }
+       }
++      sdhci_config_dma(host);
++
+       if (host->flags & SDHCI_REQ_USE_DMA) {
+               int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED);
+@@ -1123,8 +1125,6 @@ static void sdhci_prepare_data(struct sd
+               }
+       }
+-      sdhci_config_dma(host);
+-
+       if (!(host->flags & SDHCI_REQ_USE_DMA)) {
+               int flags;
diff --git a/queue-5.4/nfsd-add-encoding-of-op_recall-flag-for-write-delegation.patch b/queue-5.4/nfsd-add-encoding-of-op_recall-flag-for-write-delegation.patch
new file mode 100644 (file)
index 0000000..560fb05
--- /dev/null
@@ -0,0 +1,32 @@
+From 58f5d894006d82ed7335e1c37182fbc5f08c2f51 Mon Sep 17 00:00:00 2001
+From: Dai Ngo <dai.ngo@oracle.com>
+Date: Tue, 6 Jun 2023 16:41:02 -0700
+Subject: NFSD: add encoding of op_recall flag for write delegation
+
+From: Dai Ngo <dai.ngo@oracle.com>
+
+commit 58f5d894006d82ed7335e1c37182fbc5f08c2f51 upstream.
+
+Modified nfsd4_encode_open to encode the op_recall flag properly
+for OPEN result with write delegation granted.
+
+Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/nfsd/nfs4xdr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3409,7 +3409,7 @@ nfsd4_encode_open(struct nfsd4_compoundr
+               p = xdr_reserve_space(xdr, 32);
+               if (!p)
+                       return nfserr_resource;
+-              *p++ = cpu_to_be32(0);
++              *p++ = cpu_to_be32(open->op_recall);
+               /*
+                * TODO: space_limit's in delegations
diff --git a/queue-5.4/revert-f2fs-fix-potential-corruption-when-moving-a-directory.patch b/queue-5.4/revert-f2fs-fix-potential-corruption-when-moving-a-directory.patch
new file mode 100644 (file)
index 0000000..239c487
--- /dev/null
@@ -0,0 +1,66 @@
+From cde3c9d7e2a359e337216855dcb333a19daaa436 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 1 Jun 2023 12:58:23 +0200
+Subject: Revert "f2fs: fix potential corruption when moving a directory"
+
+From: Jan Kara <jack@suse.cz>
+
+commit cde3c9d7e2a359e337216855dcb333a19daaa436 upstream.
+
+This reverts commit d94772154e524b329a168678836745d2773a6e02. The
+locking is going to be provided by VFS.
+
+CC: Jaegeuk Kim <jaegeuk@kernel.org>
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230601105830.13168-3-jack@suse.cz>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/namei.c |   16 +---------------
+ 1 file changed, 1 insertion(+), 15 deletions(-)
+
+--- a/fs/f2fs/namei.c
++++ b/fs/f2fs/namei.c
+@@ -892,20 +892,12 @@ static int f2fs_rename(struct inode *old
+                       goto out;
+       }
+-      /*
+-       * Copied from ext4_rename: we need to protect against old.inode
+-       * directory getting converted from inline directory format into
+-       * a normal one.
+-       */
+-      if (S_ISDIR(old_inode->i_mode))
+-              inode_lock_nested(old_inode, I_MUTEX_NONDIR2);
+-
+       err = -ENOENT;
+       old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
+       if (!old_entry) {
+               if (IS_ERR(old_page))
+                       err = PTR_ERR(old_page);
+-              goto out_unlock_old;
++              goto out;
+       }
+       if (S_ISDIR(old_inode->i_mode)) {
+@@ -1033,9 +1025,6 @@ static int f2fs_rename(struct inode *old
+       f2fs_unlock_op(sbi);
+-      if (S_ISDIR(old_inode->i_mode))
+-              inode_unlock(old_inode);
+-
+       if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+               f2fs_sync_fs(sbi->sb, 1);
+@@ -1051,9 +1040,6 @@ out_dir:
+               f2fs_put_page(old_dir_page, 0);
+ out_old:
+       f2fs_put_page(old_page, 0);
+-out_unlock_old:
+-      if (S_ISDIR(old_inode->i_mode))
+-              inode_unlock(old_inode);
+ out:
+       if (whiteout)
+               iput(whiteout);
index b61187703324db6ad09b2378ef931d47c77f4264..e6ba18128f3775454b8ee98565e681b526b0fb73 100644 (file)
@@ -162,3 +162,16 @@ sh-dma-fix-dma-channel-offset-calculation.patch
 i2c-xiic-defer-xiic_wakeup-and-__xiic_start_xfer-in-.patch
 i2c-xiic-don-t-try-to-handle-more-interrupt-events-a.patch
 alsa-jack-fix-mutex-call-in-snd_jack_report.patch
+nfsd-add-encoding-of-op_recall-flag-for-write-delegation.patch
+mmc-core-disable-trim-on-kingston-emmc04g-m627.patch
+mmc-core-disable-trim-on-micron-mtfc4gacajcn-1m.patch
+mmc-sdhci-fix-dma-configure-compatibility-issue-when-64bit-dma-mode-is-used.patch
+wifi-ath10k-serialize-wake_tx_queue-ops.patch
+bcache-remove-unnecessary-null-point-check-in-node-allocations.patch
+integrity-fix-possible-multiple-allocation-in-integrity_inode_get.patch
+jffs2-reduce-stack-usage-in-jffs2_build_xattr_subsystem.patch
+fs-avoid-empty-option-when-generating-legacy-mount-string.patch
+ext4-remove-ext4-locking-of-moved-directory.patch
+revert-f2fs-fix-potential-corruption-when-moving-a-directory.patch
+fs-establish-locking-order-for-unrelated-directories.patch
+fs-lock-moved-directories.patch
diff --git a/queue-5.4/wifi-ath10k-serialize-wake_tx_queue-ops.patch b/queue-5.4/wifi-ath10k-serialize-wake_tx_queue-ops.patch
new file mode 100644 (file)
index 0000000..6692e80
--- /dev/null
@@ -0,0 +1,86 @@
+From b719ebc37a1eacd4fd4f1264f731b016e5ec0c6e Mon Sep 17 00:00:00 2001
+From: Alexander Wetzel <alexander@wetzel-home.de>
+Date: Thu, 23 Mar 2023 17:55:27 +0100
+Subject: wifi: ath10k: Serialize wake_tx_queue ops
+
+From: Alexander Wetzel <alexander@wetzel-home.de>
+
+commit b719ebc37a1eacd4fd4f1264f731b016e5ec0c6e upstream.
+
+Serialize the ath10k implementation of the wake_tx_queue ops.
+ath10k_mac_op_wake_tx_queue() must not run concurrent since it's using
+ieee80211_txq_schedule_start().
+
+The intend of this patch is to sort out an issue discovered in the discussion
+referred to by the Link tag.
+
+I can't test it with real hardware and thus just implemented the per-ac queue
+lock Felix suggested. One obvious alternative to the per-ac lock would be to
+bring back the txqs_lock commit bb2edb733586 ("ath10k: migrate to mac80211 txq
+scheduling") dropped.
+
+Fixes: bb2edb733586 ("ath10k: migrate to mac80211 txq scheduling")
+Reported-by: Felix Fietkau <nbd@nbd.name>
+Link: https://lore.kernel.org/r/519b5bb9-8899-ae7c-4eff-f3116cdfdb56@nbd.name
+CC: <stable@vger.kernel.org>
+Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230323165527.156414-1-alexander@wetzel-home.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/core.c |    3 +++
+ drivers/net/wireless/ath/ath10k/core.h |    3 +++
+ drivers/net/wireless/ath/ath10k/mac.c  |    6 ++++--
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -3195,6 +3195,9 @@ struct ath10k *ath10k_core_create(size_t
+       mutex_init(&ar->dump_mutex);
+       spin_lock_init(&ar->data_lock);
++      for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++)
++              spin_lock_init(&ar->queue_lock[ac]);
++
+       INIT_LIST_HEAD(&ar->peers);
+       init_waitqueue_head(&ar->peer_mapping_wq);
+       init_waitqueue_head(&ar->htt.empty_tx_wq);
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -1089,6 +1089,9 @@ struct ath10k {
+       /* protects shared structure data */
+       spinlock_t data_lock;
++      /* serialize wake_tx_queue calls per ac */
++      spinlock_t queue_lock[IEEE80211_NUM_ACS];
++
+       struct list_head arvifs;
+       struct list_head peers;
+       struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -4406,13 +4406,14 @@ static void ath10k_mac_op_wake_tx_queue(
+ {
+       struct ath10k *ar = hw->priv;
+       int ret;
+-      u8 ac;
++      u8 ac = txq->ac;
+       ath10k_htt_tx_txq_update(hw, txq);
+       if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH)
+               return;
+-      ac = txq->ac;
++      spin_lock_bh(&ar->queue_lock[ac]);
++
+       ieee80211_txq_schedule_start(hw, ac);
+       txq = ieee80211_next_txq(hw, ac);
+       if (!txq)
+@@ -4427,6 +4428,7 @@ static void ath10k_mac_op_wake_tx_queue(
+       ath10k_htt_tx_txq_update(hw, txq);
+ out:
+       ieee80211_txq_schedule_end(hw, ac);
++      spin_unlock_bh(&ar->queue_lock[ac]);
+ }
+ /* Must not be called with conf_mutex held as workers can use that also. */