]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 May 2021 08:29:36 +0000 (10:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 May 2021 08:29:36 +0000 (10:29 +0200)
added patches:
ext4-allow-the-dax-flag-to-be-set-and-cleared-on-inline-directories.patch
ext4-always-panic-when-errors-panic-is-specified.patch
ext4-annotate-data-race-in-jbd2_journal_dirty_metadata.patch
ext4-annotate-data-race-in-start_this_handle.patch
ext4-do-not-set-sb_active-in-ext4_orphan_cleanup.patch
ext4-fix-check-to-prevent-false-positive-report-of-incorrect-used-inodes.patch
ext4-fix-error-code-in-ext4_commit_super.patch
ext4-fix-error-return-code-in-ext4_fc_perform_commit.patch
ext4-fix-ext4_error_err-save-negative-errno-into-superblock.patch
ext4-fix-occasional-generic-418-failure.patch
io_uring-check-current-io_uring-in-io_uring_cancel_sqpoll.patch
io_uring-fix-shared-sqpoll-cancellation-hangs.patch
io_uring-fix-work_exit-sqpoll-cancellations.patch
io_uring-remove-extra-sqpoll-submission-halting.patch
kbuild-update-config_data.gz-only-when-the-content-of-.config-is-changed.patch
media-coda-fix-macroblocks-count-control-usage.patch
media-dvb-usb-fix-memory-leak-at-error-in-dvb_usb_device_init.patch
media-dvb-usb-fix-use-after-free-access.patch
media-dvbdev-fix-memory-leak-in-dvb_media_device_free.patch
media-staging-intel-ipu3-fix-memory-leak-in-imu_fmt.patch
media-staging-intel-ipu3-fix-race-condition-during-set_fmt.patch
media-staging-intel-ipu3-fix-set_fmt-error-handling.patch
media-v4l2-ctrls-fix-reference-to-freed-memory.patch
media-venus-hfi_cmds-support-plane-actual-info-property-from-v1.patch
media-venus-hfi_parser-check-for-instance-after-hfi-platform-get.patch
media-venus-hfi_parser-don-t-initialize-parser-on-v1.patch
media-venus-pm_helpers-set-opp-clock-name-for-v1.patch
media-venus-venc_ctrls-change-default-header-mode.patch
pci-dwc-move-iatu-detection-earlier.patch
rsi-use-resume_noirq-for-sdio.patch
tty-fix-memory-leak-in-vc_deallocate.patch
usb-dwc2-fix-session-request-interrupt-handler.patch
usb-dwc3-core-do-core-softreset-when-switch-mode.patch
usb-dwc3-gadget-fix-start_transfer-link-state-check.patch
usb-dwc3-gadget-remove-fs-binterval_m1-limitation.patch
usb-gadget-dummy_hcd-fix-gpf-in-gadget_setup.patch
usb-gadget-fix-double-free-of-device-descriptor-pointers.patch
usb-gadget-function-f_fs-string-table-fix-for-multiple-languages.patch

39 files changed:
queue-5.12/ext4-allow-the-dax-flag-to-be-set-and-cleared-on-inline-directories.patch [new file with mode: 0644]
queue-5.12/ext4-always-panic-when-errors-panic-is-specified.patch [new file with mode: 0644]
queue-5.12/ext4-annotate-data-race-in-jbd2_journal_dirty_metadata.patch [new file with mode: 0644]
queue-5.12/ext4-annotate-data-race-in-start_this_handle.patch [new file with mode: 0644]
queue-5.12/ext4-do-not-set-sb_active-in-ext4_orphan_cleanup.patch [new file with mode: 0644]
queue-5.12/ext4-fix-check-to-prevent-false-positive-report-of-incorrect-used-inodes.patch [new file with mode: 0644]
queue-5.12/ext4-fix-error-code-in-ext4_commit_super.patch [new file with mode: 0644]
queue-5.12/ext4-fix-error-return-code-in-ext4_fc_perform_commit.patch [new file with mode: 0644]
queue-5.12/ext4-fix-ext4_error_err-save-negative-errno-into-superblock.patch [new file with mode: 0644]
queue-5.12/ext4-fix-occasional-generic-418-failure.patch [new file with mode: 0644]
queue-5.12/io_uring-check-current-io_uring-in-io_uring_cancel_sqpoll.patch [new file with mode: 0644]
queue-5.12/io_uring-fix-shared-sqpoll-cancellation-hangs.patch [new file with mode: 0644]
queue-5.12/io_uring-fix-work_exit-sqpoll-cancellations.patch [new file with mode: 0644]
queue-5.12/io_uring-remove-extra-sqpoll-submission-halting.patch [new file with mode: 0644]
queue-5.12/kbuild-update-config_data.gz-only-when-the-content-of-.config-is-changed.patch [new file with mode: 0644]
queue-5.12/media-coda-fix-macroblocks-count-control-usage.patch [new file with mode: 0644]
queue-5.12/media-dvb-usb-fix-memory-leak-at-error-in-dvb_usb_device_init.patch [new file with mode: 0644]
queue-5.12/media-dvb-usb-fix-use-after-free-access.patch [new file with mode: 0644]
queue-5.12/media-dvbdev-fix-memory-leak-in-dvb_media_device_free.patch [new file with mode: 0644]
queue-5.12/media-staging-intel-ipu3-fix-memory-leak-in-imu_fmt.patch [new file with mode: 0644]
queue-5.12/media-staging-intel-ipu3-fix-race-condition-during-set_fmt.patch [new file with mode: 0644]
queue-5.12/media-staging-intel-ipu3-fix-set_fmt-error-handling.patch [new file with mode: 0644]
queue-5.12/media-v4l2-ctrls-fix-reference-to-freed-memory.patch [new file with mode: 0644]
queue-5.12/media-venus-hfi_cmds-support-plane-actual-info-property-from-v1.patch [new file with mode: 0644]
queue-5.12/media-venus-hfi_parser-check-for-instance-after-hfi-platform-get.patch [new file with mode: 0644]
queue-5.12/media-venus-hfi_parser-don-t-initialize-parser-on-v1.patch [new file with mode: 0644]
queue-5.12/media-venus-pm_helpers-set-opp-clock-name-for-v1.patch [new file with mode: 0644]
queue-5.12/media-venus-venc_ctrls-change-default-header-mode.patch [new file with mode: 0644]
queue-5.12/pci-dwc-move-iatu-detection-earlier.patch [new file with mode: 0644]
queue-5.12/rsi-use-resume_noirq-for-sdio.patch [new file with mode: 0644]
queue-5.12/series
queue-5.12/tty-fix-memory-leak-in-vc_deallocate.patch [new file with mode: 0644]
queue-5.12/usb-dwc2-fix-session-request-interrupt-handler.patch [new file with mode: 0644]
queue-5.12/usb-dwc3-core-do-core-softreset-when-switch-mode.patch [new file with mode: 0644]
queue-5.12/usb-dwc3-gadget-fix-start_transfer-link-state-check.patch [new file with mode: 0644]
queue-5.12/usb-dwc3-gadget-remove-fs-binterval_m1-limitation.patch [new file with mode: 0644]
queue-5.12/usb-gadget-dummy_hcd-fix-gpf-in-gadget_setup.patch [new file with mode: 0644]
queue-5.12/usb-gadget-fix-double-free-of-device-descriptor-pointers.patch [new file with mode: 0644]
queue-5.12/usb-gadget-function-f_fs-string-table-fix-for-multiple-languages.patch [new file with mode: 0644]

diff --git a/queue-5.12/ext4-allow-the-dax-flag-to-be-set-and-cleared-on-inline-directories.patch b/queue-5.12/ext4-allow-the-dax-flag-to-be-set-and-cleared-on-inline-directories.patch
new file mode 100644 (file)
index 0000000..98e3ddc
--- /dev/null
@@ -0,0 +1,49 @@
+From 4811d9929cdae4238baf5b2522247bd2f9fa7b50 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Mon, 12 Apr 2021 17:19:00 -0400
+Subject: ext4: allow the dax flag to be set and cleared on inline directories
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 4811d9929cdae4238baf5b2522247bd2f9fa7b50 upstream.
+
+This is needed to allow generic/607 to pass for file systems with the
+inline data_feature enabled, and it allows the use of file systems
+where the directories use inline_data, while the files are accessed
+via DAX.
+
+Cc: stable@kernel.org
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/ialloc.c |    3 ++-
+ fs/ext4/ioctl.c  |    6 ++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1292,7 +1292,8 @@ got:
+       ei->i_extra_isize = sbi->s_want_extra_isize;
+       ei->i_inline_off = 0;
+-      if (ext4_has_feature_inline_data(sb))
++      if (ext4_has_feature_inline_data(sb) &&
++          (!(ei->i_flags & EXT4_DAX_FL) || S_ISDIR(mode)))
+               ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
+       ret = inode;
+       err = dquot_alloc_inode(inode);
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -315,6 +315,12 @@ static void ext4_dax_dontcache(struct in
+ static bool dax_compatible(struct inode *inode, unsigned int oldflags,
+                          unsigned int flags)
+ {
++      /* Allow the DAX flag to be changed on inline directories */
++      if (S_ISDIR(inode->i_mode)) {
++              flags &= ~EXT4_INLINE_DATA_FL;
++              oldflags &= ~EXT4_INLINE_DATA_FL;
++      }
++
+       if (flags & EXT4_DAX_FL) {
+               if ((oldflags & EXT4_DAX_MUT_EXCL) ||
+                    ext4_test_inode_state(inode,
diff --git a/queue-5.12/ext4-always-panic-when-errors-panic-is-specified.patch b/queue-5.12/ext4-always-panic-when-errors-panic-is-specified.patch
new file mode 100644 (file)
index 0000000..6d71ac9
--- /dev/null
@@ -0,0 +1,66 @@
+From ac2f7ca51b0929461ea49918f27c11b680f28995 Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Thu, 1 Apr 2021 16:19:03 +0800
+Subject: ext4: always panic when errors=panic is specified
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit ac2f7ca51b0929461ea49918f27c11b680f28995 upstream.
+
+Before commit 014c9caa29d3 ("ext4: make ext4_abort() use
+__ext4_error()"), the following series of commands would trigger a
+panic:
+
+1. mount /dev/sda -o ro,errors=panic test
+2. mount /dev/sda -o remount,abort test
+
+After commit 014c9caa29d3, remounting a file system using the test
+mount option "abort" will no longer trigger a panic.  This commit will
+restore the behaviour immediately before commit 014c9caa29d3.
+(However, note that the Linux kernel's behavior has not been
+consistent; some previous kernel versions, including 5.4 and 4.19
+similarly did not panic after using the mount option "abort".)
+
+This also makes a change to long-standing behaviour; namely, the
+following series commands will now cause a panic, when previously it
+did not:
+
+1. mount /dev/sda -o ro,errors=panic test
+2. echo test > /sys/fs/ext4/sda/trigger_fs_error
+
+However, this makes ext4's behaviour much more consistent, so this is
+a good thing.
+
+Cc: stable@kernel.org
+Fixes: 014c9caa29d3 ("ext4: make ext4_abort() use __ext4_error()")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Link: https://lore.kernel.org/r/20210401081903.3421208-1-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -667,9 +667,6 @@ static void ext4_handle_error(struct sup
+                       ext4_commit_super(sb);
+       }
+-      if (sb_rdonly(sb) || continue_fs)
+-              return;
+-
+       /*
+        * We force ERRORS_RO behavior when system is rebooting. Otherwise we
+        * could panic during 'reboot -f' as the underlying device got already
+@@ -679,6 +676,10 @@ static void ext4_handle_error(struct sup
+               panic("EXT4-fs (device %s): panic forced after error\n",
+                       sb->s_id);
+       }
++
++      if (sb_rdonly(sb) || continue_fs)
++              return;
++
+       ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
+       /*
+        * Make sure updated value of ->s_mount_flags will be visible before
diff --git a/queue-5.12/ext4-annotate-data-race-in-jbd2_journal_dirty_metadata.patch b/queue-5.12/ext4-annotate-data-race-in-jbd2_journal_dirty_metadata.patch
new file mode 100644 (file)
index 0000000..66b5ba4
--- /dev/null
@@ -0,0 +1,48 @@
+From 83fe6b18b8d04c6c849379005e1679bac9752466 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 6 Apr 2021 18:18:00 +0200
+Subject: ext4: annotate data race in jbd2_journal_dirty_metadata()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 83fe6b18b8d04c6c849379005e1679bac9752466 upstream.
+
+Assertion checks in jbd2_journal_dirty_metadata() are known to be racy
+but we don't want to be grabbing locks just for them.  We thus recheck
+them under b_state_lock only if it looks like they would fail. Annotate
+the checks with data_race().
+
+Cc: stable@kernel.org
+Reported-by: Hao Sun <sunhao.th@gmail.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210406161804.20150-2-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/transaction.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1479,8 +1479,8 @@ int jbd2_journal_dirty_metadata(handle_t
+        * crucial to catch bugs so let's do a reliable check until the
+        * lockless handling is fully proven.
+        */
+-      if (jh->b_transaction != transaction &&
+-          jh->b_next_transaction != transaction) {
++      if (data_race(jh->b_transaction != transaction &&
++          jh->b_next_transaction != transaction)) {
+               spin_lock(&jh->b_state_lock);
+               J_ASSERT_JH(jh, jh->b_transaction == transaction ||
+                               jh->b_next_transaction == transaction);
+@@ -1488,8 +1488,8 @@ int jbd2_journal_dirty_metadata(handle_t
+       }
+       if (jh->b_modified == 1) {
+               /* If it's in our transaction it must be in BJ_Metadata list. */
+-              if (jh->b_transaction == transaction &&
+-                  jh->b_jlist != BJ_Metadata) {
++              if (data_race(jh->b_transaction == transaction &&
++                  jh->b_jlist != BJ_Metadata)) {
+                       spin_lock(&jh->b_state_lock);
+                       if (jh->b_transaction == transaction &&
+                           jh->b_jlist != BJ_Metadata)
diff --git a/queue-5.12/ext4-annotate-data-race-in-start_this_handle.patch b/queue-5.12/ext4-annotate-data-race-in-start_this_handle.patch
new file mode 100644 (file)
index 0000000..60010ce
--- /dev/null
@@ -0,0 +1,39 @@
+From 3b1833e92baba135923af4a07e73fe6e54be5a2f Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Tue, 6 Apr 2021 18:17:59 +0200
+Subject: ext4: annotate data race in start_this_handle()
+
+From: Jan Kara <jack@suse.cz>
+
+commit 3b1833e92baba135923af4a07e73fe6e54be5a2f upstream.
+
+Access to journal->j_running_transaction is not protected by appropriate
+lock and thus is racy. We are well aware of that and the code handles
+the race properly. Just add a comment and data_race() annotation.
+
+Cc: stable@kernel.org
+Reported-by: syzbot+30774a6acf6a2cf6d535@syzkaller.appspotmail.com
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210406161804.20150-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/jbd2/transaction.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -349,7 +349,12 @@ static int start_this_handle(journal_t *
+       }
+ alloc_transaction:
+-      if (!journal->j_running_transaction) {
++      /*
++       * This check is racy but it is just an optimization of allocating new
++       * transaction early if there are high chances we'll need it. If we
++       * guess wrong, we'll retry or free unused transaction.
++       */
++      if (!data_race(journal->j_running_transaction)) {
+               /*
+                * If __GFP_FS is not present, then we may be being called from
+                * inside the fs writeback layer, so we MUST NOT fail.
diff --git a/queue-5.12/ext4-do-not-set-sb_active-in-ext4_orphan_cleanup.patch b/queue-5.12/ext4-do-not-set-sb_active-in-ext4_orphan_cleanup.patch
new file mode 100644 (file)
index 0000000..7ca4ebc
--- /dev/null
@@ -0,0 +1,49 @@
+From 72ffb49a7b623c92a37657eda7cc46a06d3e8398 Mon Sep 17 00:00:00 2001
+From: Zhang Yi <yi.zhang@huawei.com>
+Date: Wed, 31 Mar 2021 11:31:38 +0800
+Subject: ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+commit 72ffb49a7b623c92a37657eda7cc46a06d3e8398 upstream.
+
+When CONFIG_QUOTA is enabled, if we failed to mount the filesystem due
+to some error happens behind ext4_orphan_cleanup(), it will end up
+triggering a after free issue of super_block. The problem is that
+ext4_orphan_cleanup() will set SB_ACTIVE flag if CONFIG_QUOTA is
+enabled, after we cleanup the truncated inodes, the last iput() will put
+them into the lru list, and these inodes' pages may probably dirty and
+will be write back by the writeback thread, so it could be raced by
+freeing super_block in the error path of mount_bdev().
+
+After check the setting of SB_ACTIVE flag in ext4_orphan_cleanup(), it
+was used to ensure updating the quota file properly, but evict inode and
+trash data immediately in the last iput does not affect the quotafile,
+so setting the SB_ACTIVE flag seems not required[1]. Fix this issue by
+just remove the SB_ACTIVE setting.
+
+[1] https://lore.kernel.org/linux-ext4/99cce8ca-e4a0-7301-840f-2ace67c551f3@huawei.com/T/#m04990cfbc4f44592421736b504afcc346b2a7c00
+
+Cc: stable@kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Tested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210331033138.918975-1-yi.zhang@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3023,9 +3023,6 @@ static void ext4_orphan_cleanup(struct s
+               sb->s_flags &= ~SB_RDONLY;
+       }
+ #ifdef CONFIG_QUOTA
+-      /* Needed for iput() to work correctly and not trash data */
+-      sb->s_flags |= SB_ACTIVE;
+-
+       /*
+        * Turn on quotas which were not enabled for read-only mounts if
+        * filesystem has quota feature, so that they are updated correctly.
diff --git a/queue-5.12/ext4-fix-check-to-prevent-false-positive-report-of-incorrect-used-inodes.patch b/queue-5.12/ext4-fix-check-to-prevent-false-positive-report-of-incorrect-used-inodes.patch
new file mode 100644 (file)
index 0000000..7f4f500
--- /dev/null
@@ -0,0 +1,96 @@
+From a149d2a5cabbf6507a7832a1c4fd2593c55fd450 Mon Sep 17 00:00:00 2001
+From: Zhang Yi <yi.zhang@huawei.com>
+Date: Wed, 31 Mar 2021 20:15:16 +0800
+Subject: ext4: fix check to prevent false positive report of incorrect used inodes
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+commit a149d2a5cabbf6507a7832a1c4fd2593c55fd450 upstream.
+
+Commit <50122847007> ("ext4: fix check to prevent initializing reserved
+inodes") check the block group zero and prevent initializing reserved
+inodes. But in some special cases, the reserved inode may not all belong
+to the group zero, it may exist into the second group if we format
+filesystem below.
+
+  mkfs.ext4 -b 4096 -g 8192 -N 1024 -I 4096 /dev/sda
+
+So, it will end up triggering a false positive report of a corrupted
+file system. This patch fix it by avoid check reserved inodes if no free
+inode blocks will be zeroed.
+
+Cc: stable@kernel.org
+Fixes: 50122847007 ("ext4: fix check to prevent initializing reserved inodes")
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Suggested-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20210331121516.2243099-1-yi.zhang@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/ialloc.c |   48 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 32 insertions(+), 16 deletions(-)
+
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1513,6 +1513,7 @@ int ext4_init_inode_table(struct super_b
+       handle_t *handle;
+       ext4_fsblk_t blk;
+       int num, ret = 0, used_blks = 0;
++      unsigned long used_inos = 0;
+       /* This should not happen, but just to be sure check this */
+       if (sb_rdonly(sb)) {
+@@ -1543,22 +1544,37 @@ int ext4_init_inode_table(struct super_b
+        * used inodes so we need to skip blocks with used inodes in
+        * inode table.
+        */
+-      if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)))
+-              used_blks = DIV_ROUND_UP((EXT4_INODES_PER_GROUP(sb) -
+-                          ext4_itable_unused_count(sb, gdp)),
+-                          sbi->s_inodes_per_block);
+-
+-      if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) ||
+-          ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) -
+-                             ext4_itable_unused_count(sb, gdp)) <
+-                            EXT4_FIRST_INO(sb)))) {
+-              ext4_error(sb, "Something is wrong with group %u: "
+-                         "used itable blocks: %d; "
+-                         "itable unused count: %u",
+-                         group, used_blks,
+-                         ext4_itable_unused_count(sb, gdp));
+-              ret = 1;
+-              goto err_out;
++      if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) {
++              used_inos = EXT4_INODES_PER_GROUP(sb) -
++                          ext4_itable_unused_count(sb, gdp);
++              used_blks = DIV_ROUND_UP(used_inos, sbi->s_inodes_per_block);
++
++              /* Bogus inode unused count? */
++              if (used_blks < 0 || used_blks > sbi->s_itb_per_group) {
++                      ext4_error(sb, "Something is wrong with group %u: "
++                                 "used itable blocks: %d; "
++                                 "itable unused count: %u",
++                                 group, used_blks,
++                                 ext4_itable_unused_count(sb, gdp));
++                      ret = 1;
++                      goto err_out;
++              }
++
++              used_inos += group * EXT4_INODES_PER_GROUP(sb);
++              /*
++               * Are there some uninitialized inodes in the inode table
++               * before the first normal inode?
++               */
++              if ((used_blks != sbi->s_itb_per_group) &&
++                   (used_inos < EXT4_FIRST_INO(sb))) {
++                      ext4_error(sb, "Something is wrong with group %u: "
++                                 "itable unused count: %u; "
++                                 "itables initialized count: %ld",
++                                 group, ext4_itable_unused_count(sb, gdp),
++                                 used_inos);
++                      ret = 1;
++                      goto err_out;
++              }
+       }
+       blk = ext4_inode_table(sb, gdp) + used_blks;
diff --git a/queue-5.12/ext4-fix-error-code-in-ext4_commit_super.patch b/queue-5.12/ext4-fix-error-code-in-ext4_commit_super.patch
new file mode 100644 (file)
index 0000000..78bd283
--- /dev/null
@@ -0,0 +1,38 @@
+From f88f1466e2a2e5ca17dfada436d3efa1b03a3972 Mon Sep 17 00:00:00 2001
+From: Fengnan Chang <changfengnan@vivo.com>
+Date: Fri, 2 Apr 2021 18:16:31 +0800
+Subject: ext4: fix error code in ext4_commit_super
+
+From: Fengnan Chang <changfengnan@vivo.com>
+
+commit f88f1466e2a2e5ca17dfada436d3efa1b03a3972 upstream.
+
+We should set the error code when ext4_commit_super check argument failed.
+Found in code review.
+Fixes: c4be0c1dc4cdc ("filesystem freeze: add error handling of write_super_lockfs/unlockfs").
+
+Cc: stable@kernel.org
+Signed-off-by: Fengnan Chang <changfengnan@vivo.com>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20210402101631.561-1-changfengnan@vivo.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -5559,8 +5559,10 @@ static int ext4_commit_super(struct supe
+       struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
+       int error = 0;
+-      if (!sbh || block_device_ejected(sb))
+-              return error;
++      if (!sbh)
++              return -EINVAL;
++      if (block_device_ejected(sb))
++              return -ENODEV;
+       ext4_update_super(sb);
diff --git a/queue-5.12/ext4-fix-error-return-code-in-ext4_fc_perform_commit.patch b/queue-5.12/ext4-fix-error-return-code-in-ext4_fc_perform_commit.patch
new file mode 100644 (file)
index 0000000..02530f5
--- /dev/null
@@ -0,0 +1,37 @@
+From e1262cd2e68a0870fb9fc95eb202d22e8f0074b7 Mon Sep 17 00:00:00 2001
+From: Xu Yihang <xuyihang@huawei.com>
+Date: Thu, 8 Apr 2021 15:00:33 +0800
+Subject: ext4: fix error return code in ext4_fc_perform_commit()
+
+From: Xu Yihang <xuyihang@huawei.com>
+
+commit e1262cd2e68a0870fb9fc95eb202d22e8f0074b7 upstream.
+
+In case of if not ext4_fc_add_tlv branch, an error return code is missing.
+
+Cc: stable@kernel.org
+Fixes: aa75f4d3daae ("ext4: main fast-commit commit path")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Xu Yihang <xuyihang@huawei.com>
+Reviewed-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
+Link: https://lore.kernel.org/r/20210408070033.123047-1-xuyihang@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1088,8 +1088,10 @@ static int ext4_fc_perform_commit(journa
+               head.fc_tid = cpu_to_le32(
+                       sbi->s_journal->j_running_transaction->t_tid);
+               if (!ext4_fc_add_tlv(sb, EXT4_FC_TAG_HEAD, sizeof(head),
+-                      (u8 *)&head, &crc))
++                      (u8 *)&head, &crc)) {
++                      ret = -ENOSPC;
+                       goto out;
++              }
+       }
+       spin_lock(&sbi->s_fc_lock);
diff --git a/queue-5.12/ext4-fix-ext4_error_err-save-negative-errno-into-superblock.patch b/queue-5.12/ext4-fix-ext4_error_err-save-negative-errno-into-superblock.patch
new file mode 100644 (file)
index 0000000..9321309
--- /dev/null
@@ -0,0 +1,35 @@
+From 6810fad956df9e5467e8e8a5ac66fda0836c71fa Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Tue, 6 Apr 2021 10:53:31 +0800
+Subject: ext4: fix ext4_error_err save negative errno into superblock
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit 6810fad956df9e5467e8e8a5ac66fda0836c71fa upstream.
+
+Fix As write_mmp_block() so that it returns -EIO instead of 1, so that
+the correct error gets saved into the superblock.
+
+Cc: stable@kernel.org
+Fixes: 54d3adbc29f0 ("ext4: save all error info in save_error_info() and drop ext4_set_errno()")
+Reported-by: Liu Zhi Qiang <liuzhiqiang26@huawei.com>
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20210406025331.148343-1-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/mmp.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/mmp.c
++++ b/fs/ext4/mmp.c
+@@ -56,7 +56,7 @@ static int write_mmp_block(struct super_
+       wait_on_buffer(bh);
+       sb_end_write(sb);
+       if (unlikely(!buffer_uptodate(bh)))
+-              return 1;
++              return -EIO;
+       return 0;
+ }
diff --git a/queue-5.12/ext4-fix-occasional-generic-418-failure.patch b/queue-5.12/ext4-fix-occasional-generic-418-failure.patch
new file mode 100644 (file)
index 0000000..445c416
--- /dev/null
@@ -0,0 +1,80 @@
+From 5899593f51e63dde2f07c67358bd65a641585abb Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 15 Apr 2021 17:54:17 +0200
+Subject: ext4: Fix occasional generic/418 failure
+
+From: Jan Kara <jack@suse.cz>
+
+commit 5899593f51e63dde2f07c67358bd65a641585abb upstream.
+
+Eric has noticed that after pagecache read rework, generic/418 is
+occasionally failing for ext4 when blocksize < pagesize. In fact, the
+pagecache rework just made hard to hit race in ext4 more likely. The
+problem is that since ext4 conversion of direct IO writes to iomap
+framework (commit 378f32bab371), we update inode size after direct IO
+write only after invalidating page cache. Thus if buffered read sneaks
+at unfortunate moment like:
+
+CPU1 - write at offset 1k                       CPU2 - read from offset 0
+iomap_dio_rw(..., IOMAP_DIO_FORCE_WAIT);
+                                                ext4_readpage();
+ext4_handle_inode_extension()
+
+the read will zero out tail of the page as it still sees smaller inode
+size and thus page cache becomes inconsistent with on-disk contents with
+all the consequences.
+
+Fix the problem by moving inode size update into end_io handler which
+gets called before the page cache is invalidated.
+
+Reported-and-tested-by: Eric Whitney <enwlinux@gmail.com>
+Fixes: 378f32bab371 ("ext4: introduce direct I/O write using iomap infrastructure")
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Acked-by: Dave Chinner <dchinner@redhat.com>
+Link: https://lore.kernel.org/r/20210415155417.4734-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/file.c |   25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -371,15 +371,32 @@ truncate:
+ static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size,
+                                int error, unsigned int flags)
+ {
+-      loff_t offset = iocb->ki_pos;
++      loff_t pos = iocb->ki_pos;
+       struct inode *inode = file_inode(iocb->ki_filp);
+       if (error)
+               return error;
+-      if (size && flags & IOMAP_DIO_UNWRITTEN)
+-              return ext4_convert_unwritten_extents(NULL, inode,
+-                                                    offset, size);
++      if (size && flags & IOMAP_DIO_UNWRITTEN) {
++              error = ext4_convert_unwritten_extents(NULL, inode, pos, size);
++              if (error < 0)
++                      return error;
++      }
++      /*
++       * If we are extending the file, we have to update i_size here before
++       * page cache gets invalidated in iomap_dio_rw(). Otherwise racing
++       * buffered reads could zero out too much from page cache pages. Update
++       * of on-disk size will happen later in ext4_dio_write_iter() where
++       * we have enough information to also perform orphan list handling etc.
++       * Note that we perform all extending writes synchronously under
++       * i_rwsem held exclusively so i_size update is safe here in that case.
++       * If the write was not extending, we cannot see pos > i_size here
++       * because operations reducing i_size like truncate wait for all
++       * outstanding DIO before updating i_size.
++       */
++      pos += size;
++      if (pos > i_size_read(inode))
++              i_size_write(inode, pos);
+       return 0;
+ }
diff --git a/queue-5.12/io_uring-check-current-io_uring-in-io_uring_cancel_sqpoll.patch b/queue-5.12/io_uring-check-current-io_uring-in-io_uring_cancel_sqpoll.patch
new file mode 100644 (file)
index 0000000..cc4d38e
--- /dev/null
@@ -0,0 +1,43 @@
+From 6d042ffb598ed83e7d5623cc961d249def5b9829 Mon Sep 17 00:00:00 2001
+From: Palash Oswal <hello@oswalpalash.com>
+Date: Tue, 27 Apr 2021 18:21:49 +0530
+Subject: io_uring: Check current->io_uring in io_uring_cancel_sqpoll
+
+From: Palash Oswal <hello@oswalpalash.com>
+
+commit 6d042ffb598ed83e7d5623cc961d249def5b9829 upstream.
+
+syzkaller identified KASAN: null-ptr-deref Write in
+io_uring_cancel_sqpoll.
+
+io_uring_cancel_sqpoll is called by io_sq_thread before calling
+io_uring_alloc_task_context. This leads to current->io_uring being NULL.
+io_uring_cancel_sqpoll should not have to deal with threads where
+current->io_uring is NULL.
+
+In order to cast a wider safety net, perform input sanitisation directly
+in io_uring_cancel_sqpoll and return for NULL value of current->io_uring.
+This is safe since if current->io_uring isn't set, then there's no way
+for the task to have submitted any requests.
+
+Reported-by: syzbot+be51ca5a4d97f017cd50@syzkaller.appspotmail.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Palash Oswal <hello@oswalpalash.com>
+Link: https://lore.kernel.org/r/20210427125148.21816-1-hello@oswalpalash.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -9005,6 +9005,8 @@ static void io_uring_cancel_sqpoll(struc
+       s64 inflight;
+       DEFINE_WAIT(wait);
++      if (!current->io_uring)
++              return;
+       WARN_ON_ONCE(!sqd || sqd->thread != current);
+       atomic_inc(&tctx->in_idle);
diff --git a/queue-5.12/io_uring-fix-shared-sqpoll-cancellation-hangs.patch b/queue-5.12/io_uring-fix-shared-sqpoll-cancellation-hangs.patch
new file mode 100644 (file)
index 0000000..7a225b3
--- /dev/null
@@ -0,0 +1,132 @@
+From 734551df6f9bedfbefcd113ede665945e9de0b99 Mon Sep 17 00:00:00 2001
+From: Pavel Begunkov <asml.silence@gmail.com>
+Date: Sun, 18 Apr 2021 14:52:09 +0100
+Subject: io_uring: fix shared sqpoll cancellation hangs
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit 734551df6f9bedfbefcd113ede665945e9de0b99 upstream.
+
+[  736.982891] INFO: task iou-sqp-4294:4295 blocked for more than 122 seconds.
+[  736.982897] Call Trace:
+[  736.982901]  schedule+0x68/0xe0
+[  736.982903]  io_uring_cancel_sqpoll+0xdb/0x110
+[  736.982908]  io_sqpoll_cancel_cb+0x24/0x30
+[  736.982911]  io_run_task_work_head+0x28/0x50
+[  736.982913]  io_sq_thread+0x4e3/0x720
+
+We call io_uring_cancel_sqpoll() one by one for each ctx either in
+sq_thread() itself or via task works, and it's intended to cancel all
+requests of a specified context. However the function uses per-task
+counters to track the number of inflight requests, so it counts more
+requests than available via currect io_uring ctx and goes to sleep for
+them to appear (e.g. from IRQ), that will never happen.
+
+Cancel a bit more than before, i.e. all ctxs that share sqpoll
+and continue to use shared counters. Don't forget that we should not
+remove ctx from the list before running that task_work sqpoll-cancel,
+otherwise the function wouldn't be able to find the context and will
+hang.
+
+Reported-by: Joakim Hassila <joj@mac.com>
+Reported-by: Jens Axboe <axboe@kernel.dk>
+Fixes: 37d1e2e3642e2 ("io_uring: move SQPOLL thread io-wq forked worker")
+Cc: stable@vger.kernel.org
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/1bded7e6c6b32e0bae25fce36be2868e46b116a0.1618752958.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c |   27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -1008,7 +1008,7 @@ static void io_uring_del_task_file(unsig
+ static void io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
+                                        struct task_struct *task,
+                                        struct files_struct *files);
+-static void io_uring_cancel_sqpoll(struct io_ring_ctx *ctx);
++static void io_uring_cancel_sqpoll(struct io_sq_data *sqd);
+ static void destroy_fixed_rsrc_ref_node(struct fixed_rsrc_ref_node *ref_node);
+ static struct fixed_rsrc_ref_node *alloc_fixed_rsrc_ref_node(
+                       struct io_ring_ctx *ctx);
+@@ -6836,15 +6836,14 @@ static int io_sq_thread(void *data)
+               timeout = jiffies + sqd->sq_thread_idle;
+       }
+-      list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
+-              io_uring_cancel_sqpoll(ctx);
++      io_uring_cancel_sqpoll(sqd);
+       sqd->thread = NULL;
+       list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
+               io_ring_set_wakeup_flag(ctx);
+-      mutex_unlock(&sqd->lock);
+-
+       io_run_task_work();
+       io_run_task_work_head(&sqd->park_task_work);
++      mutex_unlock(&sqd->lock);
++
+       complete(&sqd->exited);
+       do_exit(0);
+ }
+@@ -8931,11 +8930,11 @@ static s64 tctx_inflight(struct io_uring
+ static void io_sqpoll_cancel_cb(struct callback_head *cb)
+ {
+       struct io_tctx_exit *work = container_of(cb, struct io_tctx_exit, task_work);
+-      struct io_ring_ctx *ctx = work->ctx;
+-      struct io_sq_data *sqd = ctx->sq_data;
++      struct io_sq_data *sqd = work->ctx->sq_data;
+       if (sqd->thread)
+-              io_uring_cancel_sqpoll(ctx);
++              io_uring_cancel_sqpoll(sqd);
++      list_del_init(&work->ctx->sqd_list);
+       complete(&work->completion);
+ }
+@@ -8946,7 +8945,6 @@ static void io_sqpoll_cancel_sync(struct
+       struct task_struct *task;
+       io_sq_thread_park(sqd);
+-      list_del_init(&ctx->sqd_list);
+       io_sqd_update_thread_idle(sqd);
+       task = sqd->thread;
+       if (task) {
+@@ -8954,6 +8952,8 @@ static void io_sqpoll_cancel_sync(struct
+               init_task_work(&work.task_work, io_sqpoll_cancel_cb);
+               io_task_work_add_head(&sqd->park_task_work, &work.task_work);
+               wake_up_process(task);
++      } else {
++              list_del_init(&ctx->sqd_list);
+       }
+       io_sq_thread_unpark(sqd);
+@@ -8987,14 +8987,14 @@ void __io_uring_files_cancel(struct file
+ }
+ /* should only be called by SQPOLL task */
+-static void io_uring_cancel_sqpoll(struct io_ring_ctx *ctx)
++static void io_uring_cancel_sqpoll(struct io_sq_data *sqd)
+ {
+-      struct io_sq_data *sqd = ctx->sq_data;
+       struct io_uring_task *tctx = current->io_uring;
++      struct io_ring_ctx *ctx;
+       s64 inflight;
+       DEFINE_WAIT(wait);
+-      WARN_ON_ONCE(!sqd || ctx->sq_data->thread != current);
++      WARN_ON_ONCE(!sqd || sqd->thread != current);
+       atomic_inc(&tctx->in_idle);
+       do {
+@@ -9002,7 +9002,8 @@ static void io_uring_cancel_sqpoll(struc
+               inflight = tctx_inflight(tctx);
+               if (!inflight)
+                       break;
+-              io_uring_try_cancel_requests(ctx, current, NULL);
++              list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
++                      io_uring_try_cancel_requests(ctx, current, NULL);
+               prepare_to_wait(&tctx->wait, &wait, TASK_UNINTERRUPTIBLE);
+               /*
diff --git a/queue-5.12/io_uring-fix-work_exit-sqpoll-cancellations.patch b/queue-5.12/io_uring-fix-work_exit-sqpoll-cancellations.patch
new file mode 100644 (file)
index 0000000..acbdcfe
--- /dev/null
@@ -0,0 +1,78 @@
+From 28090c133869b461c5366195a856d73469ab87d9 Mon Sep 17 00:00:00 2001
+From: Pavel Begunkov <asml.silence@gmail.com>
+Date: Sun, 25 Apr 2021 23:34:45 +0100
+Subject: io_uring: fix work_exit sqpoll cancellations
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit 28090c133869b461c5366195a856d73469ab87d9 upstream.
+
+After closing an SQPOLL ring, io_ring_exit_work() kicks in and starts
+doing cancellations via io_uring_try_cancel_requests(). It will go
+through io_uring_try_cancel_iowq(), which uses ctx->tctx_list, but as
+SQPOLL task don't have a ctx note, its io-wq won't be reachable and so
+is left not cancelled.
+
+It will eventually cancelled when one of the tasks dies, but if a thread
+group survives for long and changes rings, it will spawn lots of
+unreclaimed resources and live locked works.
+
+Cancel SQPOLL task's io-wq separately in io_ring_exit_work().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/a71a7fe345135d684025bb529d5cb1d8d6b46e10.1619389911.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c |   25 ++++++++++++++++++-------
+ 1 file changed, 18 insertions(+), 7 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -8571,6 +8571,13 @@ static void io_tctx_exit_cb(struct callb
+       complete(&work->completion);
+ }
++static bool io_cancel_ctx_cb(struct io_wq_work *work, void *data)
++{
++      struct io_kiocb *req = container_of(work, struct io_kiocb, work);
++
++      return req->ctx == data;
++}
++
+ static void io_ring_exit_work(struct work_struct *work)
+ {
+       struct io_ring_ctx *ctx = container_of(work, struct io_ring_ctx, exit_work);
+@@ -8587,6 +8594,17 @@ static void io_ring_exit_work(struct wor
+        */
+       do {
+               io_uring_try_cancel_requests(ctx, NULL, NULL);
++              if (ctx->sq_data) {
++                      struct io_sq_data *sqd = ctx->sq_data;
++                      struct task_struct *tsk;
++
++                      io_sq_thread_park(sqd);
++                      tsk = sqd->thread;
++                      if (tsk && tsk->io_uring && tsk->io_uring->io_wq)
++                              io_wq_cancel_cb(tsk->io_uring->io_wq,
++                                              io_cancel_ctx_cb, ctx, true);
++                      io_sq_thread_unpark(sqd);
++              }
+               WARN_ON_ONCE(time_after(jiffies, timeout));
+       } while (!wait_for_completion_timeout(&ctx->ref_comp, HZ/20));
+@@ -8731,13 +8749,6 @@ static bool io_cancel_defer_files(struct
+       return true;
+ }
+-static bool io_cancel_ctx_cb(struct io_wq_work *work, void *data)
+-{
+-      struct io_kiocb *req = container_of(work, struct io_kiocb, work);
+-
+-      return req->ctx == data;
+-}
+-
+ static bool io_uring_try_cancel_iowq(struct io_ring_ctx *ctx)
+ {
+       struct io_tctx_node *node;
diff --git a/queue-5.12/io_uring-remove-extra-sqpoll-submission-halting.patch b/queue-5.12/io_uring-remove-extra-sqpoll-submission-halting.patch
new file mode 100644 (file)
index 0000000..a2c1523
--- /dev/null
@@ -0,0 +1,51 @@
+From 3b763ba1c77da5806e4fdc5684285814fe970c98 Mon Sep 17 00:00:00 2001
+From: Pavel Begunkov <asml.silence@gmail.com>
+Date: Sun, 18 Apr 2021 14:52:08 +0100
+Subject: io_uring: remove extra sqpoll submission halting
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit 3b763ba1c77da5806e4fdc5684285814fe970c98 upstream.
+
+SQPOLL task won't submit requests for a context that is currently dying,
+so no need to remove ctx from sqd_list prior the main loop of
+io_ring_exit_work(). Kill it, will be removed by io_sq_thread_finish()
+and only brings confusion and lockups.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/f220c2b786ba0f9499bebc9f3cd9714d29efb6a5.1618752958.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/io_uring.c |   12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -6710,6 +6710,10 @@ static int __io_sq_thread(struct io_ring
+               if (!list_empty(&ctx->iopoll_list))
+                       io_do_iopoll(ctx, &nr_events, 0);
++              /*
++               * Don't submit if refs are dying, good for io_uring_register(),
++               * but also it is relied upon by io_ring_exit_work()
++               */
+               if (to_submit && likely(!percpu_ref_is_dying(&ctx->refs)) &&
+                   !(ctx->flags & IORING_SETUP_R_DISABLED))
+                       ret = io_submit_sqes(ctx, to_submit);
+@@ -8576,14 +8580,6 @@ static void io_ring_exit_work(struct wor
+       struct io_tctx_node *node;
+       int ret;
+-      /* prevent SQPOLL from submitting new requests */
+-      if (ctx->sq_data) {
+-              io_sq_thread_park(ctx->sq_data);
+-              list_del_init(&ctx->sqd_list);
+-              io_sqd_update_thread_idle(ctx->sq_data);
+-              io_sq_thread_unpark(ctx->sq_data);
+-      }
+-
+       /*
+        * If we're doing polled IO and end up having requests being
+        * submitted async (out-of-line), then completions can come in while
diff --git a/queue-5.12/kbuild-update-config_data.gz-only-when-the-content-of-.config-is-changed.patch b/queue-5.12/kbuild-update-config_data.gz-only-when-the-content-of-.config-is-changed.patch
new file mode 100644 (file)
index 0000000..70165ef
--- /dev/null
@@ -0,0 +1,88 @@
+From 46b41d5dd8019b264717978c39c43313a524d033 Mon Sep 17 00:00:00 2001
+From: Masahiro Yamada <masahiroy@kernel.org>
+Date: Sun, 25 Apr 2021 15:24:07 +0900
+Subject: kbuild: update config_data.gz only when the content of .config is changed
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+commit 46b41d5dd8019b264717978c39c43313a524d033 upstream.
+
+If the timestamp of the .config file is updated, config_data.gz is
+regenerated, then vmlinux is re-linked. This occurs even if the content
+of the .config has not changed at all.
+
+This issue was mitigated by commit 67424f61f813 ("kconfig: do not write
+.config if the content is the same"); Kconfig does not update the
+.config when it ends up with the identical configuration.
+
+The issue is remaining when the .config is created by *_defconfig with
+some config fragment(s) applied on top.
+
+This is typical for powerpc and mips, where several *_defconfig targets
+are constructed by using merge_config.sh.
+
+One workaround is to have the copy of the .config. The filechk rule
+updates the copy, kernel/config_data, by checking the content instead
+of the timestamp.
+
+With this commit, the second run with the same configuration avoids
+the needless rebuilds.
+
+  $ make ARCH=mips defconfig all
+   [ snip ]
+  $ make ARCH=mips defconfig all
+  *** Default configuration is based on target '32r2el_defconfig'
+  Using ./arch/mips/configs/generic_defconfig as base
+  Merging arch/mips/configs/generic/32r2.config
+  Merging arch/mips/configs/generic/el.config
+  Merging ./arch/mips/configs/generic/board-boston.config
+  Merging ./arch/mips/configs/generic/board-ni169445.config
+  Merging ./arch/mips/configs/generic/board-ocelot.config
+  Merging ./arch/mips/configs/generic/board-ranchu.config
+  Merging ./arch/mips/configs/generic/board-sead-3.config
+  Merging ./arch/mips/configs/generic/board-xilfpga.config
+  #
+  # configuration written to .config
+  #
+    SYNC    include/config/auto.conf
+    CALL    scripts/checksyscalls.sh
+    CALL    scripts/atomic/check-atomics.sh
+    CHK     include/generated/compile.h
+    CHK     include/generated/autoksyms.h
+
+Reported-by: Elliot Berman <eberman@codeaurora.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/.gitignore |    1 +
+ kernel/Makefile   |    9 +++++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+--- a/kernel/.gitignore
++++ b/kernel/.gitignore
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
++/config_data
+ kheaders.md5
+ timeconst.h
+ hz.bc
+--- a/kernel/Makefile
++++ b/kernel/Makefile
+@@ -138,10 +138,15 @@ obj-$(CONFIG_SCF_TORTURE_TEST) += scftor
+ $(obj)/configs.o: $(obj)/config_data.gz
+-targets += config_data.gz
+-$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE
++targets += config_data config_data.gz
++$(obj)/config_data.gz: $(obj)/config_data FORCE
+       $(call if_changed,gzip)
++filechk_cat = cat $<
++
++$(obj)/config_data: $(KCONFIG_CONFIG) FORCE
++      $(call filechk,cat)
++
+ $(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz
+ quiet_cmd_genikh = CHK     $(obj)/kheaders_data.tar.xz
diff --git a/queue-5.12/media-coda-fix-macroblocks-count-control-usage.patch b/queue-5.12/media-coda-fix-macroblocks-count-control-usage.patch
new file mode 100644 (file)
index 0000000..95f24d6
--- /dev/null
@@ -0,0 +1,40 @@
+From 0b276e470a4d43e1365d3eb53c608a3d208cabd4 Mon Sep 17 00:00:00 2001
+From: Marco Felsch <m.felsch@pengutronix.de>
+Date: Fri, 5 Mar 2021 09:23:54 +0100
+Subject: media: coda: fix macroblocks count control usage
+
+From: Marco Felsch <m.felsch@pengutronix.de>
+
+commit 0b276e470a4d43e1365d3eb53c608a3d208cabd4 upstream.
+
+Commit b2d3bef1aa78 ("media: coda: Add a V4L2 user for control error
+macroblocks count") add the control for the decoder devices. But
+during streamon() this ioctl gets called for all (encoder and decoder)
+devices and on encoder devices this causes a null pointer exception.
+
+Fix this by setting the control only if it is really accessible.
+
+Fixes: b2d3bef1aa78 ("media: coda: Add a V4L2 user for control error macroblocks count")
+Signed-off-by: Marco Felsch <m.felsch@pengutronix.de>
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/coda/coda-common.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/coda/coda-common.c
++++ b/drivers/media/platform/coda/coda-common.c
+@@ -2062,7 +2062,9 @@ static int coda_start_streaming(struct v
+       if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
+               ctx->params.gop_size = 1;
+       ctx->gopcounter = ctx->params.gop_size - 1;
+-      v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0);
++      /* Only decoders have this control */
++      if (ctx->mb_err_cnt_ctrl)
++              v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0);
+       ret = ctx->ops->start_streaming(ctx);
+       if (ctx->inst_type == CODA_INST_DECODER) {
diff --git a/queue-5.12/media-dvb-usb-fix-memory-leak-at-error-in-dvb_usb_device_init.patch b/queue-5.12/media-dvb-usb-fix-memory-leak-at-error-in-dvb_usb_device_init.patch
new file mode 100644 (file)
index 0000000..8c6ee88
--- /dev/null
@@ -0,0 +1,120 @@
+From 13a79f14ab285120bc4977e00a7c731e8143f548 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2021 09:32:46 +0100
+Subject: media: dvb-usb: Fix memory leak at error in dvb_usb_device_init()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 13a79f14ab285120bc4977e00a7c731e8143f548 upstream.
+
+dvb_usb_device_init() allocates a dvb_usb_device object, but it
+doesn't release the object by itself even at errors.  The object is
+released in the callee side (dvb_usb_init()) in some error cases via
+dvb_usb_exit() call, but it also missed the object free in other error
+paths.  And, the caller (it's only dvb_usb_device_init()) doesn't seem
+caring the resource management as well, hence those memories are
+leaked.
+
+This patch assures releasing the memory at the error path in
+dvb_usb_device_init().  Now dvb_usb_init() frees the resources it
+allocated but leaves the passed dvb_usb_device object intact.  In
+turn, the dvb_usb_device object is released in dvb_usb_device_init()
+instead.
+We could use dvb_usb_exit() function for releasing everything in the
+callee (as it was used for some error cases in the original code), but
+releasing the passed object in the callee is non-intuitive and
+error-prone.  So I took this approach (which is more standard in Linus
+kernel code) although it ended with a bit more open codes.
+
+Along with the change, the patch makes sure that USB intfdata is reset
+and don't return the bogus pointer to the caller of
+dvb_usb_device_init() at the error path, too.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/usb/dvb-usb/dvb-usb-init.c |   47 ++++++++++++++++++++-----------
+ 1 file changed, 31 insertions(+), 16 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
+@@ -170,22 +170,20 @@ static int dvb_usb_init(struct dvb_usb_d
+               if (d->props.priv_init != NULL) {
+                       ret = d->props.priv_init(d);
+-                      if (ret != 0) {
+-                              kfree(d->priv);
+-                              d->priv = NULL;
+-                              return ret;
+-                      }
++                      if (ret != 0)
++                              goto err_priv_init;
+               }
+       }
+       /* check the capabilities and set appropriate variables */
+       dvb_usb_device_power_ctrl(d, 1);
+-      if ((ret = dvb_usb_i2c_init(d)) ||
+-              (ret = dvb_usb_adapter_init(d, adapter_nums))) {
+-              dvb_usb_exit(d);
+-              return ret;
+-      }
++      ret = dvb_usb_i2c_init(d);
++      if (ret)
++              goto err_i2c_init;
++      ret = dvb_usb_adapter_init(d, adapter_nums);
++      if (ret)
++              goto err_adapter_init;
+       if ((ret = dvb_usb_remote_init(d)))
+               err("could not initialize remote control.");
+@@ -193,6 +191,17 @@ static int dvb_usb_init(struct dvb_usb_d
+       dvb_usb_device_power_ctrl(d, 0);
+       return 0;
++
++err_adapter_init:
++      dvb_usb_adapter_exit(d);
++err_i2c_init:
++      dvb_usb_i2c_exit(d);
++      if (d->priv && d->props.priv_destroy)
++              d->props.priv_destroy(d);
++err_priv_init:
++      kfree(d->priv);
++      d->priv = NULL;
++      return ret;
+ }
+ /* determine the name and the state of the just found USB device */
+@@ -296,15 +305,21 @@ int dvb_usb_device_init(struct usb_inter
+       usb_set_intfdata(intf, d);
+-      if (du != NULL)
++      ret = dvb_usb_init(d, adapter_nums);
++      if (ret) {
++              info("%s error while loading driver (%d)", desc->name, ret);
++              goto error;
++      }
++
++      if (du)
+               *du = d;
+-      ret = dvb_usb_init(d, adapter_nums);
++      info("%s successfully initialized and connected.", desc->name);
++      return 0;
+-      if (ret == 0)
+-              info("%s successfully initialized and connected.", desc->name);
+-      else
+-              info("%s error while loading driver (%d)", desc->name, ret);
++ error:
++      usb_set_intfdata(intf, NULL);
++      kfree(d);
+       return ret;
+ }
+ EXPORT_SYMBOL(dvb_usb_device_init);
diff --git a/queue-5.12/media-dvb-usb-fix-use-after-free-access.patch b/queue-5.12/media-dvb-usb-fix-use-after-free-access.patch
new file mode 100644 (file)
index 0000000..0790a7b
--- /dev/null
@@ -0,0 +1,76 @@
+From c49206786ee252f28b7d4d155d1fff96f145a05d Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2021 09:32:47 +0100
+Subject: media: dvb-usb: Fix use-after-free access
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit c49206786ee252f28b7d4d155d1fff96f145a05d upstream.
+
+dvb_usb_device_init() copies the properties to the own data, so that
+the callers can release the original properties later (as done in the
+commit 299c7007e936 ("media: dw2102: Fix memleak on sequence of
+probes")).  However, it also stores dev->desc pointer that is a
+reference to the original properties data.  Since dev->desc is
+referred later, it may result in use-after-free, in the worst case,
+leading to a kernel Oops as reported.
+
+This patch addresses the problem by allocating and copying the
+properties at first, then get the desc from the copied properties.
+
+Reported-and-tested-by: Stefan Seyfried <seife+kernel@b1-systems.com>
+BugLink: http://bugzilla.opensuse.org/show_bug.cgi?id=1181104
+
+Reviewed-by: Robert Foss <robert.foss@linaro.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/usb/dvb-usb/dvb-usb-init.c |   23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
+@@ -267,27 +267,30 @@ int dvb_usb_device_init(struct usb_inter
+       if (du != NULL)
+               *du = NULL;
+-      if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
++      d = kzalloc(sizeof(*d), GFP_KERNEL);
++      if (!d) {
++              err("no memory for 'struct dvb_usb_device'");
++              return -ENOMEM;
++      }
++
++      memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
++
++      desc = dvb_usb_find_device(udev, &d->props, &cold);
++      if (!desc) {
+               deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
+-              return -ENODEV;
++              ret = -ENODEV;
++              goto error;
+       }
+       if (cold) {
+               info("found a '%s' in cold state, will try to load a firmware", desc->name);
+               ret = dvb_usb_download_firmware(udev, props);
+               if (!props->no_reconnect || ret != 0)
+-                      return ret;
++                      goto error;
+       }
+       info("found a '%s' in warm state.", desc->name);
+-      d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
+-      if (d == NULL) {
+-              err("no memory for 'struct dvb_usb_device'");
+-              return -ENOMEM;
+-      }
+-
+       d->udev = udev;
+-      memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
+       d->desc = desc;
+       d->owner = owner;
diff --git a/queue-5.12/media-dvbdev-fix-memory-leak-in-dvb_media_device_free.patch b/queue-5.12/media-dvbdev-fix-memory-leak-in-dvb_media_device_free.patch
new file mode 100644 (file)
index 0000000..01dc1dd
--- /dev/null
@@ -0,0 +1,37 @@
+From bf9a40ae8d722f281a2721779595d6df1c33a0bf Mon Sep 17 00:00:00 2001
+From: Peilin Ye <yepeilin.cs@gmail.com>
+Date: Fri, 11 Dec 2020 09:30:39 +0100
+Subject: media: dvbdev: Fix memory leak in dvb_media_device_free()
+
+From: Peilin Ye <yepeilin.cs@gmail.com>
+
+commit bf9a40ae8d722f281a2721779595d6df1c33a0bf upstream.
+
+dvb_media_device_free() is leaking memory. Free `dvbdev->adapter->conn`
+before setting it to NULL, as documented in include/media/media-device.h:
+"The media_entity instance itself must be freed explicitly by the driver
+if required."
+
+Link: https://syzkaller.appspot.com/bug?id=9bbe4b842c98f0ed05c5eed77a226e9de33bf298
+
+Link: https://lore.kernel.org/linux-media/20201211083039.521617-1-yepeilin.cs@gmail.com
+Cc: stable@vger.kernel.org
+Fixes: 0230d60e4661 ("[media] dvbdev: Add RF connector if needed")
+Reported-by: syzbot+7f09440acc069a0d38ac@syzkaller.appspotmail.com
+Signed-off-by: Peilin Ye <yepeilin.cs@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/dvb-core/dvbdev.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -241,6 +241,7 @@ static void dvb_media_device_free(struct
+       if (dvbdev->adapter->conn) {
+               media_device_unregister_entity(dvbdev->adapter->conn);
++              kfree(dvbdev->adapter->conn);
+               dvbdev->adapter->conn = NULL;
+               kfree(dvbdev->adapter->conn_pads);
+               dvbdev->adapter->conn_pads = NULL;
diff --git a/queue-5.12/media-staging-intel-ipu3-fix-memory-leak-in-imu_fmt.patch b/queue-5.12/media-staging-intel-ipu3-fix-memory-leak-in-imu_fmt.patch
new file mode 100644 (file)
index 0000000..1093fc4
--- /dev/null
@@ -0,0 +1,49 @@
+From 3630901933afba1d16c462b04d569b7576339223 Mon Sep 17 00:00:00 2001
+From: Ricardo Ribalda <ribalda@chromium.org>
+Date: Mon, 15 Mar 2021 13:34:05 +0100
+Subject: media: staging/intel-ipu3: Fix memory leak in imu_fmt
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit 3630901933afba1d16c462b04d569b7576339223 upstream.
+
+We are losing the reference to an allocated memory if try. Change the
+order of the check to avoid that.
+
+Cc: stable@vger.kernel.org
+Fixes: 6d5f26f2e045 ("media: staging/intel-ipu3-v4l: reduce kernel stack usage")
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/media/ipu3/ipu3-v4l2.c |   11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
+@@ -693,6 +693,13 @@ static int imgu_fmt(struct imgu_device *
+               if (inode == IMGU_NODE_STAT_3A || inode == IMGU_NODE_PARAMS)
+                       continue;
++              /* CSS expects some format on OUT queue */
++              if (i != IPU3_CSS_QUEUE_OUT &&
++                  !imgu_pipe->nodes[inode].enabled) {
++                      fmts[i] = NULL;
++                      continue;
++              }
++
+               if (try) {
+                       fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp,
+                                         sizeof(struct v4l2_pix_format_mplane),
+@@ -705,10 +712,6 @@ static int imgu_fmt(struct imgu_device *
+                       fmts[i] = &imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp;
+               }
+-              /* CSS expects some format on OUT queue */
+-              if (i != IPU3_CSS_QUEUE_OUT &&
+-                  !imgu_pipe->nodes[inode].enabled)
+-                      fmts[i] = NULL;
+       }
+       if (!try) {
diff --git a/queue-5.12/media-staging-intel-ipu3-fix-race-condition-during-set_fmt.patch b/queue-5.12/media-staging-intel-ipu3-fix-race-condition-during-set_fmt.patch
new file mode 100644 (file)
index 0000000..c366455
--- /dev/null
@@ -0,0 +1,105 @@
+From dccfe2548746ca9cca3a20401ece4cf255d1f171 Mon Sep 17 00:00:00 2001
+From: Ricardo Ribalda <ribalda@chromium.org>
+Date: Fri, 9 Apr 2021 10:41:35 +0200
+Subject: media: staging/intel-ipu3: Fix race condition during set_fmt
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit dccfe2548746ca9cca3a20401ece4cf255d1f171 upstream.
+
+Do not modify imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp, until the
+format has been correctly validated.
+
+Otherwise, even if we use a backup variable, there is a period of time
+where imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp might have an invalid
+value that can be used by other functions.
+
+Cc: stable@vger.kernel.org
+Fixes: ad91849996f9 ("media: staging/intel-ipu3: Fix set_fmt error handling")
+Reviewed-by: Tomasz Figa <tfiga@chromium.org>
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/media/ipu3/ipu3-v4l2.c |   30 ++++++++++++++----------------
+ 1 file changed, 14 insertions(+), 16 deletions(-)
+
+--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
+@@ -669,7 +669,6 @@ static int imgu_fmt(struct imgu_device *
+       struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe];
+       struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
+       struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd;
+-      struct v4l2_pix_format_mplane fmt_backup;
+       dev_dbg(dev, "set fmt node [%u][%u](try = %u)", pipe, node, try);
+@@ -687,6 +686,7 @@ static int imgu_fmt(struct imgu_device *
+       dev_dbg(dev, "IPU3 pipe %u pipe_id = %u", pipe, css_pipe->pipe_id);
++      css_q = imgu_node_to_queue(node);
+       for (i = 0; i < IPU3_CSS_QUEUES; i++) {
+               unsigned int inode = imgu_map_node(imgu, i);
+@@ -701,6 +701,11 @@ static int imgu_fmt(struct imgu_device *
+                       continue;
+               }
++              if (i == css_q) {
++                      fmts[i] = &f->fmt.pix_mp;
++                      continue;
++              }
++
+               if (try) {
+                       fmts[i] = kmemdup(&imgu_pipe->nodes[inode].vdev_fmt.fmt.pix_mp,
+                                         sizeof(struct v4l2_pix_format_mplane),
+@@ -729,39 +734,32 @@ static int imgu_fmt(struct imgu_device *
+               rects[IPU3_CSS_RECT_GDC]->height = pad_fmt.height;
+       }
+-      /*
+-       * imgu doesn't set the node to the value given by user
+-       * before we return success from this function, so set it here.
+-       */
+-      css_q = imgu_node_to_queue(node);
+       if (!fmts[css_q]) {
+               ret = -EINVAL;
+               goto out;
+       }
+-      fmt_backup = *fmts[css_q];
+-      *fmts[css_q] = f->fmt.pix_mp;
+       if (try)
+               ret = imgu_css_fmt_try(&imgu->css, fmts, rects, pipe);
+       else
+               ret = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe);
+-      if (try || ret < 0)
+-              *fmts[css_q] = fmt_backup;
+-
+       /* ret is the binary number in the firmware blob */
+       if (ret < 0)
+               goto out;
+-      if (try)
+-              f->fmt.pix_mp = *fmts[css_q];
+-      else
+-              f->fmt = imgu_pipe->nodes[node].vdev_fmt.fmt;
++      /*
++       * imgu doesn't set the node to the value given by user
++       * before we return success from this function, so set it here.
++       */
++      if (!try)
++              imgu_pipe->nodes[node].vdev_fmt.fmt.pix_mp = f->fmt.pix_mp;
+ out:
+       if (try) {
+               for (i = 0; i < IPU3_CSS_QUEUES; i++)
+-                      kfree(fmts[i]);
++                      if (i != css_q)
++                              kfree(fmts[i]);
+       }
+       return ret;
diff --git a/queue-5.12/media-staging-intel-ipu3-fix-set_fmt-error-handling.patch b/queue-5.12/media-staging-intel-ipu3-fix-set_fmt-error-handling.patch
new file mode 100644 (file)
index 0000000..572ae76
--- /dev/null
@@ -0,0 +1,57 @@
+From ad91849996f9dd79741a961fd03585a683b08356 Mon Sep 17 00:00:00 2001
+From: Ricardo Ribalda <ribalda@chromium.org>
+Date: Wed, 10 Mar 2021 01:16:46 +0100
+Subject: media: staging/intel-ipu3: Fix set_fmt error handling
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+commit ad91849996f9dd79741a961fd03585a683b08356 upstream.
+
+If there in an error during a set_fmt, do not overwrite the previous
+sizes with the invalid config.
+
+Without this patch, v4l2-compliance ends up allocating 4GiB of RAM and
+causing the following OOPs
+
+[   38.662975] ipu3-imgu 0000:00:05.0: swiotlb buffer is full (sz: 4096 bytes)
+[   38.662980] DMA: Out of SW-IOMMU space for 4096 bytes at device 0000:00:05.0
+[   38.663010] general protection fault: 0000 [#1] PREEMPT SMP
+
+Cc: stable@vger.kernel.org
+Fixes: 6d5f26f2e045 ("media: staging/intel-ipu3-v4l: reduce kernel stack usage")
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/staging/media/ipu3/ipu3-v4l2.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
+@@ -669,6 +669,7 @@ static int imgu_fmt(struct imgu_device *
+       struct imgu_css_pipe *css_pipe = &imgu->css.pipes[pipe];
+       struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
+       struct imgu_v4l2_subdev *imgu_sd = &imgu_pipe->imgu_sd;
++      struct v4l2_pix_format_mplane fmt_backup;
+       dev_dbg(dev, "set fmt node [%u][%u](try = %u)", pipe, node, try);
+@@ -737,6 +738,7 @@ static int imgu_fmt(struct imgu_device *
+               ret = -EINVAL;
+               goto out;
+       }
++      fmt_backup = *fmts[css_q];
+       *fmts[css_q] = f->fmt.pix_mp;
+       if (try)
+@@ -744,6 +746,9 @@ static int imgu_fmt(struct imgu_device *
+       else
+               ret = imgu_css_fmt_set(&imgu->css, fmts, rects, pipe);
++      if (try || ret < 0)
++              *fmts[css_q] = fmt_backup;
++
+       /* ret is the binary number in the firmware blob */
+       if (ret < 0)
+               goto out;
diff --git a/queue-5.12/media-v4l2-ctrls-fix-reference-to-freed-memory.patch b/queue-5.12/media-v4l2-ctrls-fix-reference-to-freed-memory.patch
new file mode 100644 (file)
index 0000000..3dde09d
--- /dev/null
@@ -0,0 +1,330 @@
+From ac34b79da14d67a9b494f6125186becbd067e225 Mon Sep 17 00:00:00 2001
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Date: Mon, 12 Apr 2021 13:51:23 +0200
+Subject: media: v4l2-ctrls: fix reference to freed memory
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+commit ac34b79da14d67a9b494f6125186becbd067e225 upstream.
+
+When controls are used together with the Request API, then for
+each request a v4l2_ctrl_handler struct is allocated. This contains
+the controls that can be set in a request. If a control is *not* set in
+the request, then the value used in the most recent previous request
+must be used, or the current value if it is not found in any outstanding
+requests.
+
+The framework tried to find such a previous request and it would set
+the 'req' pointer in struct v4l2_ctrl_ref to the v4l2_ctrl_ref of the
+control in such a previous request. So far, so good. However, when that
+previous request was applied to the hardware, returned to userspace, and
+then userspace would re-init or free that request, any 'ref' pointer in
+still-queued requests would suddenly point to freed memory.
+
+This was not noticed before since the drivers that use this expected
+that each request would always have the controls set, so there was
+never any need to find a control in older requests. This requirement
+was relaxed, and now this bug surfaced.
+
+It was also made worse by changeset
+2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req")
+which increased the chance of this happening.
+
+The use of the 'req' pointer in v4l2_ctrl_ref was very fragile, so
+drop this entirely. Instead add a valid_p_req bool to indicate that
+p_req contains a valid value for this control. And if it is false,
+then just use the current value of the control.
+
+Note that VIDIOC_G_EXT_CTRLS will always return -EACCES when attempting
+to get a control from a request until the request is completed. And in
+that case, all controls in the request will have the control value set
+(i.e. valid_p_req is true). This means that the whole 'find the most
+recent previous request containing a control' idea is pointless, and
+the code can be simplified considerably.
+
+The v4l2_g_ext_ctrls_common() function was refactored a bit to make
+it more understandable. It also avoids updating volatile controls
+in a completed request since that was already done when the request
+was completed.
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Fixes: 2fae4d6aabc8 ("media: v4l2-ctrls: v4l2_ctrl_request_complete() should always set ref->req")
+Fixes: 6fa6f831f095 ("media: v4l2-ctrls: add core request support")
+Cc: <stable@vger.kernel.org>      # for v5.9 and up
+Tested-by: Alexandre Courbot <acourbot@chromium.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/v4l2-core/v4l2-ctrls.c |  137 ++++++++++++++++-------------------
+ include/media/v4l2-ctrls.h           |   12 +--
+ 2 files changed, 70 insertions(+), 79 deletions(-)
+
+--- a/drivers/media/v4l2-core/v4l2-ctrls.c
++++ b/drivers/media/v4l2-core/v4l2-ctrls.c
+@@ -2397,7 +2397,16 @@ static void new_to_req(struct v4l2_ctrl_
+       if (!ref)
+               return;
+       ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
+-      ref->req = ref;
++      ref->valid_p_req = true;
++}
++
++/* Copy the current value to the request value */
++static void cur_to_req(struct v4l2_ctrl_ref *ref)
++{
++      if (!ref)
++              return;
++      ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->p_req);
++      ref->valid_p_req = true;
+ }
+ /* Copy the request value to the new value */
+@@ -2405,8 +2414,8 @@ static void req_to_new(struct v4l2_ctrl_
+ {
+       if (!ref)
+               return;
+-      if (ref->req)
+-              ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
++      if (ref->valid_p_req)
++              ptr_to_ptr(ref->ctrl, ref->p_req, ref->ctrl->p_new);
+       else
+               ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
+ }
+@@ -3573,39 +3582,8 @@ static void v4l2_ctrl_request_queue(stru
+       struct v4l2_ctrl_handler *hdl =
+               container_of(obj, struct v4l2_ctrl_handler, req_obj);
+       struct v4l2_ctrl_handler *main_hdl = obj->priv;
+-      struct v4l2_ctrl_handler *prev_hdl = NULL;
+-      struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
+       mutex_lock(main_hdl->lock);
+-      if (list_empty(&main_hdl->requests_queued))
+-              goto queue;
+-
+-      prev_hdl = list_last_entry(&main_hdl->requests_queued,
+-                                 struct v4l2_ctrl_handler, requests_queued);
+-      /*
+-       * Note: prev_hdl and hdl must contain the same list of control
+-       * references, so if any differences are detected then that is a
+-       * driver bug and the WARN_ON is triggered.
+-       */
+-      mutex_lock(prev_hdl->lock);
+-      ref_ctrl_prev = list_first_entry(&prev_hdl->ctrl_refs,
+-                                       struct v4l2_ctrl_ref, node);
+-      list_for_each_entry(ref_ctrl, &hdl->ctrl_refs, node) {
+-              if (ref_ctrl->req)
+-                      continue;
+-              while (ref_ctrl_prev->ctrl->id < ref_ctrl->ctrl->id) {
+-                      /* Should never happen, but just in case... */
+-                      if (list_is_last(&ref_ctrl_prev->node,
+-                                       &prev_hdl->ctrl_refs))
+-                              break;
+-                      ref_ctrl_prev = list_next_entry(ref_ctrl_prev, node);
+-              }
+-              if (WARN_ON(ref_ctrl_prev->ctrl->id != ref_ctrl->ctrl->id))
+-                      break;
+-              ref_ctrl->req = ref_ctrl_prev->req;
+-      }
+-      mutex_unlock(prev_hdl->lock);
+-queue:
+       list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
+       hdl->request_is_queued = true;
+       mutex_unlock(main_hdl->lock);
+@@ -3662,7 +3640,7 @@ v4l2_ctrl_request_hdl_ctrl_find(struct v
+ {
+       struct v4l2_ctrl_ref *ref = find_ref_lock(hdl, id);
+-      return (ref && ref->req == ref) ? ref->ctrl : NULL;
++      return (ref && ref->valid_p_req) ? ref->ctrl : NULL;
+ }
+ EXPORT_SYMBOL_GPL(v4l2_ctrl_request_hdl_ctrl_find);
+@@ -3848,7 +3826,13 @@ static int class_check(struct v4l2_ctrl_
+       return find_ref_lock(hdl, which | 1) ? 0 : -EINVAL;
+ }
+-/* Get extended controls. Allocates the helpers array if needed. */
++/*
++ * Get extended controls. Allocates the helpers array if needed.
++ *
++ * Note that v4l2_g_ext_ctrls_common() with 'which' set to
++ * V4L2_CTRL_WHICH_REQUEST_VAL is only called if the request was
++ * completed, and in that case valid_p_req is true for all controls.
++ */
+ static int v4l2_g_ext_ctrls_common(struct v4l2_ctrl_handler *hdl,
+                                  struct v4l2_ext_controls *cs,
+                                  struct video_device *vdev)
+@@ -3857,9 +3841,10 @@ static int v4l2_g_ext_ctrls_common(struc
+       struct v4l2_ctrl_helper *helpers = helper;
+       int ret;
+       int i, j;
+-      bool def_value;
++      bool is_default, is_request;
+-      def_value = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
++      is_default = (cs->which == V4L2_CTRL_WHICH_DEF_VAL);
++      is_request = (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL);
+       cs->error_idx = cs->count;
+       cs->which = V4L2_CTRL_ID2WHICH(cs->which);
+@@ -3885,11 +3870,9 @@ static int v4l2_g_ext_ctrls_common(struc
+                       ret = -EACCES;
+       for (i = 0; !ret && i < cs->count; i++) {
+-              int (*ctrl_to_user)(struct v4l2_ext_control *c,
+-                                  struct v4l2_ctrl *ctrl);
+               struct v4l2_ctrl *master;
+-
+-              ctrl_to_user = def_value ? def_to_user : cur_to_user;
++              bool is_volatile = false;
++              u32 idx = i;
+               if (helpers[i].mref == NULL)
+                       continue;
+@@ -3899,31 +3882,48 @@ static int v4l2_g_ext_ctrls_common(struc
+               v4l2_ctrl_lock(master);
+-              /* g_volatile_ctrl will update the new control values */
+-              if (!def_value &&
++              /*
++               * g_volatile_ctrl will update the new control values.
++               * This makes no sense for V4L2_CTRL_WHICH_DEF_VAL and
++               * V4L2_CTRL_WHICH_REQUEST_VAL. In the case of requests
++               * it is v4l2_ctrl_request_complete() that copies the
++               * volatile controls at the time of request completion
++               * to the request, so you don't want to do that again.
++               */
++              if (!is_default && !is_request &&
+                   ((master->flags & V4L2_CTRL_FLAG_VOLATILE) ||
+                   (master->has_volatiles && !is_cur_manual(master)))) {
+                       for (j = 0; j < master->ncontrols; j++)
+                               cur_to_new(master->cluster[j]);
+                       ret = call_op(master, g_volatile_ctrl);
+-                      ctrl_to_user = new_to_user;
++                      is_volatile = true;
+               }
+-              /* If OK, then copy the current (for non-volatile controls)
+-                 or the new (for volatile controls) control values to the
+-                 caller */
+-              if (!ret) {
+-                      u32 idx = i;
+-                      do {
+-                              if (helpers[idx].ref->req)
+-                                      ret = req_to_user(cs->controls + idx,
+-                                              helpers[idx].ref->req);
+-                              else
+-                                      ret = ctrl_to_user(cs->controls + idx,
+-                                              helpers[idx].ref->ctrl);
+-                              idx = helpers[idx].next;
+-                      } while (!ret && idx);
++              if (ret) {
++                      v4l2_ctrl_unlock(master);
++                      break;
+               }
++
++              /*
++               * Copy the default value (if is_default is true), the
++               * request value (if is_request is true and p_req is valid),
++               * the new volatile value (if is_volatile is true) or the
++               * current value.
++               */
++              do {
++                      struct v4l2_ctrl_ref *ref = helpers[idx].ref;
++
++                      if (is_default)
++                              ret = def_to_user(cs->controls + idx, ref->ctrl);
++                      else if (is_request && ref->valid_p_req)
++                              ret = req_to_user(cs->controls + idx, ref);
++                      else if (is_volatile)
++                              ret = new_to_user(cs->controls + idx, ref->ctrl);
++                      else
++                              ret = cur_to_user(cs->controls + idx, ref->ctrl);
++                      idx = helpers[idx].next;
++              } while (!ret && idx);
++
+               v4l2_ctrl_unlock(master);
+       }
+@@ -4566,8 +4566,6 @@ void v4l2_ctrl_request_complete(struct m
+               unsigned int i;
+               if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) {
+-                      ref->req = ref;
+-
+                       v4l2_ctrl_lock(master);
+                       /* g_volatile_ctrl will update the current control values */
+                       for (i = 0; i < master->ncontrols; i++)
+@@ -4577,21 +4575,12 @@ void v4l2_ctrl_request_complete(struct m
+                       v4l2_ctrl_unlock(master);
+                       continue;
+               }
+-              if (ref->req == ref)
++              if (ref->valid_p_req)
+                       continue;
++              /* Copy the current control value into the request */
+               v4l2_ctrl_lock(ctrl);
+-              if (ref->req) {
+-                      ptr_to_ptr(ctrl, ref->req->p_req, ref->p_req);
+-              } else {
+-                      ptr_to_ptr(ctrl, ctrl->p_cur, ref->p_req);
+-                      /*
+-                       * Set ref->req to ensure that when userspace wants to
+-                       * obtain the controls of this request it will take
+-                       * this value and not the current value of the control.
+-                       */
+-                      ref->req = ref;
+-              }
++              cur_to_req(ref);
+               v4l2_ctrl_unlock(ctrl);
+       }
+@@ -4655,7 +4644,7 @@ int v4l2_ctrl_request_setup(struct media
+                               struct v4l2_ctrl_ref *r =
+                                       find_ref(hdl, master->cluster[i]->id);
+-                              if (r->req && r == r->req) {
++                              if (r->valid_p_req) {
+                                       have_new_data = true;
+                                       break;
+                               }
+--- a/include/media/v4l2-ctrls.h
++++ b/include/media/v4l2-ctrls.h
+@@ -301,12 +301,14 @@ struct v4l2_ctrl {
+  *            the control has been applied. This prevents applying controls
+  *            from a cluster with multiple controls twice (when the first
+  *            control of a cluster is applied, they all are).
+- * @req:      If set, this refers to another request that sets this control.
++ * @valid_p_req: If set, then p_req contains the control value for the request.
+  * @p_req:    If the control handler containing this control reference
+  *            is bound to a media request, then this points to the
+- *            value of the control that should be applied when the request
++ *            value of the control that must be applied when the request
+  *            is executed, or to the value of the control at the time
+- *            that the request was completed.
++ *            that the request was completed. If @valid_p_req is false,
++ *            then this control was never set for this request and the
++ *            control will not be updated when this request is applied.
+  *
+  * Each control handler has a list of these refs. The list_head is used to
+  * keep a sorted-by-control-ID list of all controls, while the next pointer
+@@ -319,7 +321,7 @@ struct v4l2_ctrl_ref {
+       struct v4l2_ctrl_helper *helper;
+       bool from_other_dev;
+       bool req_done;
+-      struct v4l2_ctrl_ref *req;
++      bool valid_p_req;
+       union v4l2_ctrl_ptr p_req;
+ };
+@@ -346,7 +348,7 @@ struct v4l2_ctrl_ref {
+  * @error:    The error code of the first failed control addition.
+  * @request_is_queued: True if the request was queued.
+  * @requests: List to keep track of open control handler request objects.
+- *            For the parent control handler (@req_obj.req == NULL) this
++ *            For the parent control handler (@req_obj.ops == NULL) this
+  *            is the list header. When the parent control handler is
+  *            removed, it has to unbind and put all these requests since
+  *            they refer to the parent.
diff --git a/queue-5.12/media-venus-hfi_cmds-support-plane-actual-info-property-from-v1.patch b/queue-5.12/media-venus-hfi_cmds-support-plane-actual-info-property-from-v1.patch
new file mode 100644 (file)
index 0000000..9a14de3
--- /dev/null
@@ -0,0 +1,62 @@
+From 15447d18b1b877d9c6f979bd00088e470a4e0e9f Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Date: Sat, 6 Mar 2021 13:16:41 +0100
+Subject: media: venus: hfi_cmds: Support plane-actual-info property from v1
+
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+commit 15447d18b1b877d9c6f979bd00088e470a4e0e9f upstream.
+
+The property is supported from v1 and upwards. So move it to
+set_property_1x.
+
+Fixes: 01e869e78756 ("media: venus: venc: fix handlig of S_SELECTION and G_SELECTION")
+Cc: stable@vger.kernel.org # v5.12
+Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/qcom/venus/hfi_cmds.c |   24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/drivers/media/platform/qcom/venus/hfi_cmds.c
++++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
+@@ -1039,6 +1039,18 @@ static int pkt_session_set_property_1x(s
+               pkt->shdr.hdr.size += sizeof(u32) + sizeof(*hierp);
+               break;
+       }
++      case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: {
++              struct hfi_uncompressed_plane_actual_info *in = pdata;
++              struct hfi_uncompressed_plane_actual_info *info = prop_data;
++
++              info->buffer_type = in->buffer_type;
++              info->num_planes = in->num_planes;
++              info->plane_format[0] = in->plane_format[0];
++              if (in->num_planes > 1)
++                      info->plane_format[1] = in->plane_format[1];
++              pkt->shdr.hdr.size += sizeof(u32) + sizeof(*info);
++              break;
++      }
+       /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
+       case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS:
+@@ -1205,18 +1217,6 @@ pkt_session_set_property_4xx(struct hfi_
+               pkt->shdr.hdr.size += sizeof(u32) + sizeof(*cu);
+               break;
+       }
+-      case HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO: {
+-              struct hfi_uncompressed_plane_actual_info *in = pdata;
+-              struct hfi_uncompressed_plane_actual_info *info = prop_data;
+-
+-              info->buffer_type = in->buffer_type;
+-              info->num_planes = in->num_planes;
+-              info->plane_format[0] = in->plane_format[0];
+-              if (in->num_planes > 1)
+-                      info->plane_format[1] = in->plane_format[1];
+-              pkt->shdr.hdr.size += sizeof(u32) + sizeof(*info);
+-              break;
+-      }
+       case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
+       case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+       case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE:
diff --git a/queue-5.12/media-venus-hfi_parser-check-for-instance-after-hfi-platform-get.patch b/queue-5.12/media-venus-hfi_parser-check-for-instance-after-hfi-platform-get.patch
new file mode 100644 (file)
index 0000000..3abbf25
--- /dev/null
@@ -0,0 +1,43 @@
+From 9b5d8fd580caa898c6e1b8605c774f2517f786ab Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Date: Sun, 7 Mar 2021 12:17:27 +0100
+Subject: media: venus: hfi_parser: Check for instance after hfi platform get
+
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+commit 9b5d8fd580caa898c6e1b8605c774f2517f786ab upstream.
+
+The inst function argument is != NULL only for Venus v1 and
+we did not migrate v1 to a hfi_platform abstraction yet. So
+check for instance != NULL only after hfi_platform_get returns
+no error.
+
+Fixes: e29929266be1 ("media: venus: Get codecs and capabilities from hfi platform")
+Cc: stable@vger.kernel.org # v5.12
+Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/qcom/venus/hfi_parser.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/media/platform/qcom/venus/hfi_parser.c
++++ b/drivers/media/platform/qcom/venus/hfi_parser.c
+@@ -235,13 +235,13 @@ static int hfi_platform_parser(struct ve
+       u32 enc_codecs, dec_codecs, count = 0;
+       unsigned int entries;
+-      if (inst)
+-              return 0;
+-
+       plat = hfi_platform_get(core->res->hfi_version);
+       if (!plat)
+               return -EINVAL;
++      if (inst)
++              return 0;
++
+       if (plat->codecs)
+               plat->codecs(&enc_codecs, &dec_codecs, &count);
diff --git a/queue-5.12/media-venus-hfi_parser-don-t-initialize-parser-on-v1.patch b/queue-5.12/media-venus-hfi_parser-don-t-initialize-parser-on-v1.patch
new file mode 100644 (file)
index 0000000..c2cfd8f
--- /dev/null
@@ -0,0 +1,39 @@
+From 834124c596e2dddbbdba06620835710ccca32fd0 Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Date: Sun, 7 Mar 2021 12:16:03 +0100
+Subject: media: venus: hfi_parser: Don't initialize parser on v1
+
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+commit 834124c596e2dddbbdba06620835710ccca32fd0 upstream.
+
+The Venus v1 behaves differently comparing with the other Venus
+version in respect to capability parsing and when they are send
+to the driver. So we don't need to initialize hfi parser for
+multiple invocations like what we do for > v1 Venus versions.
+
+Fixes: 10865c98986b ("media: venus: parser: Prepare parser for multiple invocations")
+Cc: stable@vger.kernel.org # v5.10+
+Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/qcom/venus/hfi_parser.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/media/platform/qcom/venus/hfi_parser.c
++++ b/drivers/media/platform/qcom/venus/hfi_parser.c
+@@ -277,8 +277,10 @@ u32 hfi_parser(struct venus_core *core,
+       parser_init(inst, &codecs, &domain);
+-      core->codecs_count = 0;
+-      memset(core->caps, 0, sizeof(core->caps));
++      if (core->res->hfi_version > HFI_VERSION_1XX) {
++              core->codecs_count = 0;
++              memset(core->caps, 0, sizeof(core->caps));
++      }
+       while (words_count) {
+               data = word + 1;
diff --git a/queue-5.12/media-venus-pm_helpers-set-opp-clock-name-for-v1.patch b/queue-5.12/media-venus-pm_helpers-set-opp-clock-name-for-v1.patch
new file mode 100644 (file)
index 0000000..63dde04
--- /dev/null
@@ -0,0 +1,65 @@
+From 3215887167af7db9af9fa23d61321ebfbd6ed6d3 Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Date: Thu, 25 Feb 2021 15:28:57 +0100
+Subject: media: venus: pm_helpers: Set opp clock name for v1
+
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+commit 3215887167af7db9af9fa23d61321ebfbd6ed6d3 upstream.
+
+The rate of the core clock is set through devm_pm_opp_set_rate and
+to avoid errors from it we have to set the name of the clock via
+dev_pm_opp_set_clkname.
+
+Fixes: 9a538b83612c ("media: venus: core: Add support for opp tables/perf voting")
+Cc: stable@vger.kernel.org # v5.10+
+Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/qcom/venus/pm_helpers.c |   19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/platform/qcom/venus/pm_helpers.c
++++ b/drivers/media/platform/qcom/venus/pm_helpers.c
+@@ -279,7 +279,22 @@ set_freq:
+ static int core_get_v1(struct venus_core *core)
+ {
+-      return core_clks_get(core);
++      int ret;
++
++      ret = core_clks_get(core);
++      if (ret)
++              return ret;
++
++      core->opp_table = dev_pm_opp_set_clkname(core->dev, "core");
++      if (IS_ERR(core->opp_table))
++              return PTR_ERR(core->opp_table);
++
++      return 0;
++}
++
++static void core_put_v1(struct venus_core *core)
++{
++      dev_pm_opp_put_clkname(core->opp_table);
+ }
+ static int core_power_v1(struct venus_core *core, int on)
+@@ -296,6 +311,7 @@ static int core_power_v1(struct venus_co
+ static const struct venus_pm_ops pm_ops_v1 = {
+       .core_get = core_get_v1,
++      .core_put = core_put_v1,
+       .core_power = core_power_v1,
+       .load_scale = load_scale_v1,
+ };
+@@ -368,6 +384,7 @@ static int venc_power_v3(struct device *
+ static const struct venus_pm_ops pm_ops_v3 = {
+       .core_get = core_get_v1,
++      .core_put = core_put_v1,
+       .core_power = core_power_v1,
+       .vdec_get = vdec_get_v3,
+       .vdec_power = vdec_power_v3,
diff --git a/queue-5.12/media-venus-venc_ctrls-change-default-header-mode.patch b/queue-5.12/media-venus-venc_ctrls-change-default-header-mode.patch
new file mode 100644 (file)
index 0000000..5c6b351
--- /dev/null
@@ -0,0 +1,34 @@
+From 39a6b9185d305d236bff625509ee63801b50301b Mon Sep 17 00:00:00 2001
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Date: Sat, 6 Mar 2021 13:13:46 +0100
+Subject: media: venus: venc_ctrls: Change default header mode
+
+From: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+commit 39a6b9185d305d236bff625509ee63801b50301b upstream.
+
+It is observed that on Venus v1 the default header-mode is producing
+a bitstream which is not playble. Change the default header-mode to
+joined with 1st frame.
+
+Fixes: 002c22bd360e ("media: venus: venc: set inband mode property to FW.")
+Cc: stable@vger.kernel.org # v5.12
+Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/media/platform/qcom/venus/venc_ctrls.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/media/platform/qcom/venus/venc_ctrls.c
++++ b/drivers/media/platform/qcom/venus/venc_ctrls.c
+@@ -359,7 +359,7 @@ int venc_ctrl_init(struct venus_inst *in
+               V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+               ~((1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) |
+               (1 << V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME)),
+-              V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE);
++              V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
+       v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
diff --git a/queue-5.12/pci-dwc-move-iatu-detection-earlier.patch b/queue-5.12/pci-dwc-move-iatu-detection-earlier.patch
new file mode 100644 (file)
index 0000000..bd5b93d
--- /dev/null
@@ -0,0 +1,100 @@
+From 8bcca26585585ae4b44d25d30f351ad0afa4976b Mon Sep 17 00:00:00 2001
+From: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+Date: Tue, 13 Apr 2021 17:22:19 +0300
+Subject: PCI: dwc: Move iATU detection earlier
+
+From: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+
+commit 8bcca26585585ae4b44d25d30f351ad0afa4976b upstream.
+
+dw_pcie_ep_init() depends on the detected iATU region numbers to allocate
+the in/outbound window management bitmap.  It fails after 281f1f99cf3a
+("PCI: dwc: Detect number of iATU windows").
+
+Move the iATU region detection into a new function, move the detection to
+the very beginning of dw_pcie_host_init() and dw_pcie_ep_init().  Also
+remove it from the dw_pcie_setup(), since it's more like a software
+initialization step than hardware setup.
+
+Link: https://lore.kernel.org/r/20210125044803.4310-1-Zhiqiang.Hou@nxp.com
+Link: https://lore.kernel.org/linux-pci/20210407131255.702054-1-dmitry.baryshkov@linaro.org
+Link: https://lore.kernel.org/r/20210413142219.2301430-1-dmitry.baryshkov@linaro.org
+Fixes: 281f1f99cf3a ("PCI: dwc: Detect number of iATU windows")
+Tested-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
+[DB: moved dw_pcie_iatu_detect to happen after host_init callback]
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Cc: stable@vger.kernel.org     # v5.11+
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/dwc/pcie-designware-ep.c   |    2 ++
+ drivers/pci/controller/dwc/pcie-designware-host.c |    1 +
+ drivers/pci/controller/dwc/pcie-designware.c      |   11 ++++++++---
+ drivers/pci/controller/dwc/pcie-designware.h      |    1 +
+ 4 files changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
+@@ -705,6 +705,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *e
+               }
+       }
++      dw_pcie_iatu_detect(pci);
++
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
+       if (!res)
+               return -EINVAL;
+--- a/drivers/pci/controller/dwc/pcie-designware-host.c
++++ b/drivers/pci/controller/dwc/pcie-designware-host.c
+@@ -398,6 +398,7 @@ int dw_pcie_host_init(struct pcie_port *
+               if (ret)
+                       goto err_free_msi;
+       }
++      dw_pcie_iatu_detect(pci);
+       dw_pcie_setup_rc(pp);
+       dw_pcie_msi_init(pp);
+--- a/drivers/pci/controller/dwc/pcie-designware.c
++++ b/drivers/pci/controller/dwc/pcie-designware.c
+@@ -660,11 +660,9 @@ static void dw_pcie_iatu_detect_regions(
+       pci->num_ob_windows = ob;
+ }
+-void dw_pcie_setup(struct dw_pcie *pci)
++void dw_pcie_iatu_detect(struct dw_pcie *pci)
+ {
+-      u32 val;
+       struct device *dev = pci->dev;
+-      struct device_node *np = dev->of_node;
+       struct platform_device *pdev = to_platform_device(dev);
+       if (pci->version >= 0x480A || (!pci->version &&
+@@ -693,6 +691,13 @@ void dw_pcie_setup(struct dw_pcie *pci)
+       dev_info(pci->dev, "Detected iATU regions: %u outbound, %u inbound",
+                pci->num_ob_windows, pci->num_ib_windows);
++}
++
++void dw_pcie_setup(struct dw_pcie *pci)
++{
++      u32 val;
++      struct device *dev = pci->dev;
++      struct device_node *np = dev->of_node;
+       if (pci->link_gen > 0)
+               dw_pcie_link_set_max_speed(pci, pci->link_gen);
+--- a/drivers/pci/controller/dwc/pcie-designware.h
++++ b/drivers/pci/controller/dwc/pcie-designware.h
+@@ -306,6 +306,7 @@ int dw_pcie_prog_inbound_atu(struct dw_p
+ void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
+                        enum dw_pcie_region_type type);
+ void dw_pcie_setup(struct dw_pcie *pci);
++void dw_pcie_iatu_detect(struct dw_pcie *pci);
+ static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
+ {
diff --git a/queue-5.12/rsi-use-resume_noirq-for-sdio.patch b/queue-5.12/rsi-use-resume_noirq-for-sdio.patch
new file mode 100644 (file)
index 0000000..8d732eb
--- /dev/null
@@ -0,0 +1,46 @@
+From c434e5e48dc4e626364491455f97e2db0aa137b1 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Sun, 28 Mar 2021 00:59:32 +0100
+Subject: rsi: Use resume_noirq for SDIO
+
+From: Marek Vasut <marex@denx.de>
+
+commit c434e5e48dc4e626364491455f97e2db0aa137b1 upstream.
+
+The rsi_resume() does access the bus to enable interrupts on the RSI
+SDIO WiFi card, however when calling sdio_claim_host() in the resume
+path, it is possible the bus is already claimed and sdio_claim_host()
+spins indefinitelly. Enable the SDIO card interrupts in resume_noirq
+instead to prevent anything else from claiming the SDIO bus first.
+
+Fixes: 20db07332736 ("rsi: sdio suspend and resume support")
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Amitkumar Karwar <amit.karwar@redpinesignals.com>
+Cc: Angus Ainslie <angus@akkea.ca>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Kalle Valo <kvalo@codeaurora.org>
+Cc: Karun Eagalapati <karun256@gmail.com>
+Cc: Martin Kepplinger <martink@posteo.de>
+Cc: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
+Cc: Siva Rebbagondla <siva8118@gmail.com>
+Cc: netdev@vger.kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Link: https://lore.kernel.org/r/20210327235932.175896-1-marex@denx.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/rsi/rsi_91x_sdio.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
++++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
+@@ -1513,7 +1513,7 @@ static int rsi_restore(struct device *de
+ }
+ static const struct dev_pm_ops rsi_pm_ops = {
+       .suspend = rsi_suspend,
+-      .resume = rsi_resume,
++      .resume_noirq = rsi_resume,
+       .freeze = rsi_freeze,
+       .thaw = rsi_thaw,
+       .restore = rsi_restore,
index 2f6d3b4d7c3b51c822f7e186684a2e0818cdac0e..a583018d50db395577116b90733b532ecd341fd0 100644 (file)
@@ -332,3 +332,41 @@ smb3-do-not-attempt-multichannel-to-server-which-does-not-support-it.patch
 revert-337f13046ff0-futex-allow-futex_clock_realtime-with-futex_wait-op.patch
 futex-do-not-apply-time-namespace-adjustment-on-futex_lock_pi.patch
 x86-cpu-initialize-msr_tsc_aux-if-rdtscp-or-rdpid-is-supported.patch
+kbuild-update-config_data.gz-only-when-the-content-of-.config-is-changed.patch
+ext4-annotate-data-race-in-start_this_handle.patch
+ext4-annotate-data-race-in-jbd2_journal_dirty_metadata.patch
+ext4-fix-check-to-prevent-false-positive-report-of-incorrect-used-inodes.patch
+ext4-do-not-set-sb_active-in-ext4_orphan_cleanup.patch
+ext4-always-panic-when-errors-panic-is-specified.patch
+ext4-fix-error-code-in-ext4_commit_super.patch
+ext4-fix-ext4_error_err-save-negative-errno-into-superblock.patch
+ext4-fix-error-return-code-in-ext4_fc_perform_commit.patch
+ext4-allow-the-dax-flag-to-be-set-and-cleared-on-inline-directories.patch
+ext4-fix-occasional-generic-418-failure.patch
+media-dvbdev-fix-memory-leak-in-dvb_media_device_free.patch
+media-dvb-usb-fix-use-after-free-access.patch
+media-dvb-usb-fix-memory-leak-at-error-in-dvb_usb_device_init.patch
+media-staging-intel-ipu3-fix-memory-leak-in-imu_fmt.patch
+media-staging-intel-ipu3-fix-set_fmt-error-handling.patch
+media-staging-intel-ipu3-fix-race-condition-during-set_fmt.patch
+media-v4l2-ctrls-fix-reference-to-freed-memory.patch
+media-coda-fix-macroblocks-count-control-usage.patch
+media-venus-pm_helpers-set-opp-clock-name-for-v1.patch
+media-venus-venc_ctrls-change-default-header-mode.patch
+media-venus-hfi_cmds-support-plane-actual-info-property-from-v1.patch
+media-venus-hfi_parser-don-t-initialize-parser-on-v1.patch
+media-venus-hfi_parser-check-for-instance-after-hfi-platform-get.patch
+io_uring-remove-extra-sqpoll-submission-halting.patch
+io_uring-fix-shared-sqpoll-cancellation-hangs.patch
+io_uring-fix-work_exit-sqpoll-cancellations.patch
+io_uring-check-current-io_uring-in-io_uring_cancel_sqpoll.patch
+usb-gadget-dummy_hcd-fix-gpf-in-gadget_setup.patch
+usb-gadget-fix-double-free-of-device-descriptor-pointers.patch
+usb-gadget-function-f_fs-string-table-fix-for-multiple-languages.patch
+usb-dwc3-gadget-remove-fs-binterval_m1-limitation.patch
+usb-dwc3-gadget-fix-start_transfer-link-state-check.patch
+usb-dwc3-core-do-core-softreset-when-switch-mode.patch
+usb-dwc2-fix-session-request-interrupt-handler.patch
+pci-dwc-move-iatu-detection-earlier.patch
+tty-fix-memory-leak-in-vc_deallocate.patch
+rsi-use-resume_noirq-for-sdio.patch
diff --git a/queue-5.12/tty-fix-memory-leak-in-vc_deallocate.patch b/queue-5.12/tty-fix-memory-leak-in-vc_deallocate.patch
new file mode 100644 (file)
index 0000000..80a93c2
--- /dev/null
@@ -0,0 +1,34 @@
+From 211b4d42b70f1c1660feaa968dac0efc2a96ac4d Mon Sep 17 00:00:00 2001
+From: Pavel Skripkin <paskripkin@gmail.com>
+Date: Sun, 28 Mar 2021 00:44:43 +0300
+Subject: tty: fix memory leak in vc_deallocate
+
+From: Pavel Skripkin <paskripkin@gmail.com>
+
+commit 211b4d42b70f1c1660feaa968dac0efc2a96ac4d upstream.
+
+syzbot reported memory leak in tty/vt.
+The problem was in VT_DISALLOCATE ioctl cmd.
+After allocating unimap with PIO_UNIMAP it wasn't
+freed via VT_DISALLOCATE, but vc_cons[currcons].d was
+zeroed.
+
+Reported-by: syzbot+bcc922b19ccc64240b42@syzkaller.appspotmail.com
+Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210327214443.21548-1-paskripkin@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/vt/vt.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -1381,6 +1381,7 @@ struct vc_data *vc_deallocate(unsigned i
+               atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
+               vcs_remove_sysfs(currcons);
+               visual_deinit(vc);
++              con_free_unimap(vc);
+               put_pid(vc->vt_pid);
+               vc_uniscr_set(vc, NULL);
+               kfree(vc->vc_screenbuf);
diff --git a/queue-5.12/usb-dwc2-fix-session-request-interrupt-handler.patch b/queue-5.12/usb-dwc2-fix-session-request-interrupt-handler.patch
new file mode 100644 (file)
index 0000000..b9c1ac2
--- /dev/null
@@ -0,0 +1,47 @@
+From 42b32b164acecd850edef010915a02418345a033 Mon Sep 17 00:00:00 2001
+From: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
+Date: Thu, 8 Apr 2021 13:45:49 +0400
+Subject: usb: dwc2: Fix session request interrupt handler
+
+From: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
+
+commit 42b32b164acecd850edef010915a02418345a033 upstream.
+
+According to programming guide in host mode, port
+power must be turned on in session request
+interrupt handlers.
+
+Fixes: 21795c826a45 ("usb: dwc2: exit hibernation on session request")
+Cc: <stable@vger.kernel.org>
+Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
+Link: https://lore.kernel.org/r/20210408094550.75484A0094@mailhost.synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/core_intr.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/usb/dwc2/core_intr.c
++++ b/drivers/usb/dwc2/core_intr.c
+@@ -307,6 +307,7 @@ static void dwc2_handle_conn_id_status_c
+ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
+ {
+       int ret;
++      u32 hprt0;
+       /* Clear interrupt */
+       dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
+@@ -327,6 +328,13 @@ static void dwc2_handle_session_req_intr
+                * established
+                */
+               dwc2_hsotg_disconnect(hsotg);
++      } else {
++              /* Turn on the port power bit. */
++              hprt0 = dwc2_read_hprt0(hsotg);
++              hprt0 |= HPRT0_PWR;
++              dwc2_writel(hsotg, hprt0, HPRT0);
++              /* Connect hcd after port power is set. */
++              dwc2_hcd_connect(hsotg);
+       }
+ }
diff --git a/queue-5.12/usb-dwc3-core-do-core-softreset-when-switch-mode.patch b/queue-5.12/usb-dwc3-core-do-core-softreset-when-switch-mode.patch
new file mode 100644 (file)
index 0000000..9743944
--- /dev/null
@@ -0,0 +1,155 @@
+From f88359e1588b85cf0e8209ab7d6620085f3441d9 Mon Sep 17 00:00:00 2001
+From: Yu Chen <chenyu56@huawei.com>
+Date: Thu, 15 Apr 2021 15:20:30 -0700
+Subject: usb: dwc3: core: Do core softreset when switch mode
+
+From: Yu Chen <chenyu56@huawei.com>
+
+commit f88359e1588b85cf0e8209ab7d6620085f3441d9 upstream.
+
+From: John Stultz <john.stultz@linaro.org>
+
+According to the programming guide, to switch mode for DRD controller,
+the driver needs to do the following.
+
+To switch from device to host:
+1. Reset controller with GCTL.CoreSoftReset
+2. Set GCTL.PrtCapDir(host mode)
+3. Reset the host with USBCMD.HCRESET
+4. Then follow up with the initializing host registers sequence
+
+To switch from host to device:
+1. Reset controller with GCTL.CoreSoftReset
+2. Set GCTL.PrtCapDir(device mode)
+3. Reset the device with DCTL.CSftRst
+4. Then follow up with the initializing registers sequence
+
+Currently we're missing step 1) to do GCTL.CoreSoftReset and step 3) of
+switching from host to device. John Stult reported a lockup issue seen
+with HiKey960 platform without these steps[1]. Similar issue is observed
+with Ferry's testing platform[2].
+
+So, apply the required steps along with some fixes to Yu Chen's and John
+Stultz's version. The main fixes to their versions are the missing wait
+for clocks synchronization before clearing GCTL.CoreSoftReset and only
+apply DCTL.CSftRst when switching from host to device.
+
+[1] https://lore.kernel.org/linux-usb/20210108015115.27920-1-john.stultz@linaro.org/
+[2] https://lore.kernel.org/linux-usb/0ba7a6ba-e6a7-9cd4-0695-64fc927e01f1@gmail.com/
+
+Fixes: 41ce1456e1db ("usb: dwc3: core: make dwc3_set_mode() work properly")
+Cc: Andy Shevchenko <andy.shevchenko@gmail.com>
+Cc: Ferry Toth <fntoth@gmail.com>
+Cc: Wesley Cheng <wcheng@codeaurora.org>
+Cc: <stable@vger.kernel.org>
+Tested-by: John Stultz <john.stultz@linaro.org>
+Tested-by: Wesley Cheng <wcheng@codeaurora.org>
+Signed-off-by: Yu Chen <chenyu56@huawei.com>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/374440f8dcd4f06c02c2caf4b1efde86774e02d9.1618521663.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c |   27 +++++++++++++++++++++++++++
+ drivers/usb/dwc3/core.h |    5 +++++
+ 2 files changed, 32 insertions(+)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -114,6 +114,8 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u
+       dwc->current_dr_role = mode;
+ }
++static int dwc3_core_soft_reset(struct dwc3 *dwc);
++
+ static void __dwc3_set_mode(struct work_struct *work)
+ {
+       struct dwc3 *dwc = work_to_dwc(work);
+@@ -121,6 +123,8 @@ static void __dwc3_set_mode(struct work_
+       int ret;
+       u32 reg;
++      mutex_lock(&dwc->mutex);
++
+       pm_runtime_get_sync(dwc->dev);
+       if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG)
+@@ -154,6 +158,25 @@ static void __dwc3_set_mode(struct work_
+               break;
+       }
++      /* For DRD host or device mode only */
++      if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) {
++              reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++              reg |= DWC3_GCTL_CORESOFTRESET;
++              dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++
++              /*
++               * Wait for internal clocks to synchronized. DWC_usb31 and
++               * DWC_usb32 may need at least 50ms (less for DWC_usb3). To
++               * keep it consistent across different IPs, let's wait up to
++               * 100ms before clearing GCTL.CORESOFTRESET.
++               */
++              msleep(100);
++
++              reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++              reg &= ~DWC3_GCTL_CORESOFTRESET;
++              dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++      }
++
+       spin_lock_irqsave(&dwc->lock, flags);
+       dwc3_set_prtcap(dwc, dwc->desired_dr_role);
+@@ -178,6 +201,8 @@ static void __dwc3_set_mode(struct work_
+               }
+               break;
+       case DWC3_GCTL_PRTCAP_DEVICE:
++              dwc3_core_soft_reset(dwc);
++
+               dwc3_event_buffers_setup(dwc);
+               if (dwc->usb2_phy)
+@@ -200,6 +225,7 @@ static void __dwc3_set_mode(struct work_
+ out:
+       pm_runtime_mark_last_busy(dwc->dev);
+       pm_runtime_put_autosuspend(dwc->dev);
++      mutex_unlock(&dwc->mutex);
+ }
+ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
+@@ -1545,6 +1571,7 @@ static int dwc3_probe(struct platform_de
+       dwc3_cache_hwparams(dwc);
+       spin_lock_init(&dwc->lock);
++      mutex_init(&dwc->mutex);
+       pm_runtime_set_active(dev);
+       pm_runtime_use_autosuspend(dev);
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -13,6 +13,7 @@
+ #include <linux/device.h>
+ #include <linux/spinlock.h>
++#include <linux/mutex.h>
+ #include <linux/ioport.h>
+ #include <linux/list.h>
+ #include <linux/bitops.h>
+@@ -946,6 +947,7 @@ struct dwc3_scratchpad_array {
+  * @scratch_addr: dma address of scratchbuf
+  * @ep0_in_setup: one control transfer is completed and enter setup phase
+  * @lock: for synchronizing
++ * @mutex: for mode switching
+  * @dev: pointer to our struct device
+  * @sysdev: pointer to the DMA-capable device
+  * @xhci: pointer to our xHCI child
+@@ -1086,6 +1088,9 @@ struct dwc3 {
+       /* device lock */
+       spinlock_t              lock;
++      /* mode switching lock */
++      struct mutex            mutex;
++
+       struct device           *dev;
+       struct device           *sysdev;
diff --git a/queue-5.12/usb-dwc3-gadget-fix-start_transfer-link-state-check.patch b/queue-5.12/usb-dwc3-gadget-fix-start_transfer-link-state-check.patch
new file mode 100644 (file)
index 0000000..3a260e7
--- /dev/null
@@ -0,0 +1,63 @@
+From c560e76319a94a3b9285bc426c609903408e4826 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 19 Apr 2021 19:11:12 -0700
+Subject: usb: dwc3: gadget: Fix START_TRANSFER link state check
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit c560e76319a94a3b9285bc426c609903408e4826 upstream.
+
+The START_TRANSFER command needs to be executed while in ON/U0 link
+state (with an exception during register initialization). Don't use
+dwc->link_state to check this since the driver only tracks the link
+state when the link state change interrupt is enabled. Check the link
+state from DSTS register instead.
+
+Note that often the host already brings the device out of low power
+before it sends/requests the next transfer. So, the user won't see any
+issue when the device starts transfer then. This issue is more
+noticeable in cases when the device delays starting transfer, which can
+happen during delayed control status after the host put the device in
+low power.
+
+Fixes: 799e9dc82968 ("usb: dwc3: gadget: conditionally disable Link State change events")
+Cc: <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/bcefaa9ecbc3e1936858c0baa14de6612960e909.1618884221.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -308,13 +308,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+       }
+       if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
+-              int             needs_wakeup;
++              int link_state;
+-              needs_wakeup = (dwc->link_state == DWC3_LINK_STATE_U1 ||
+-                              dwc->link_state == DWC3_LINK_STATE_U2 ||
+-                              dwc->link_state == DWC3_LINK_STATE_U3);
+-
+-              if (unlikely(needs_wakeup)) {
++              link_state = dwc3_gadget_get_link_state(dwc);
++              if (link_state == DWC3_LINK_STATE_U1 ||
++                  link_state == DWC3_LINK_STATE_U2 ||
++                  link_state == DWC3_LINK_STATE_U3) {
+                       ret = __dwc3_gadget_wakeup(dwc);
+                       dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
+                                       ret);
+@@ -1975,6 +1974,8 @@ static int __dwc3_gadget_wakeup(struct d
+       case DWC3_LINK_STATE_RESET:
+       case DWC3_LINK_STATE_RX_DET:    /* in HS, means Early Suspend */
+       case DWC3_LINK_STATE_U3:        /* in HS, means SUSPEND */
++      case DWC3_LINK_STATE_U2:        /* in HS, means Sleep (L1) */
++      case DWC3_LINK_STATE_U1:
+       case DWC3_LINK_STATE_RESUME:
+               break;
+       default:
diff --git a/queue-5.12/usb-dwc3-gadget-remove-fs-binterval_m1-limitation.patch b/queue-5.12/usb-dwc3-gadget-remove-fs-binterval_m1-limitation.patch
new file mode 100644 (file)
index 0000000..3f1911f
--- /dev/null
@@ -0,0 +1,44 @@
+From 3232a3ce55edfc0d7f8904543b4088a5339c2b2b Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 15 Apr 2021 00:41:58 -0700
+Subject: usb: dwc3: gadget: Remove FS bInterval_m1 limitation
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 3232a3ce55edfc0d7f8904543b4088a5339c2b2b upstream.
+
+The programming guide incorrectly stated that the DCFG.bInterval_m1 must
+be set to 0 when operating in fullspeed. There's no such limitation for
+all IPs. See DWC_usb3x programming guide section 3.2.2.1.
+
+Fixes: a1679af85b2a ("usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1")
+Cc: <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/5d4139ae89d810eb0a2d8577fb096fc88e87bfab.1618472454.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/gadget.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -608,12 +608,14 @@ static int dwc3_gadget_set_ep_config(str
+               u8 bInterval_m1;
+               /*
+-               * Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it
+-               * must be set to 0 when the controller operates in full-speed.
++               * Valid range for DEPCFG.bInterval_m1 is from 0 to 13.
++               *
++               * NOTE: The programming guide incorrectly stated bInterval_m1
++               * must be set to 0 when operating in fullspeed. Internally the
++               * controller does not have this limitation. See DWC_usb3x
++               * programming guide section 3.2.2.1.
+                */
+               bInterval_m1 = min_t(u8, desc->bInterval - 1, 13);
+-              if (dwc->gadget->speed == USB_SPEED_FULL)
+-                      bInterval_m1 = 0;
+               if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT &&
+                   dwc->gadget->speed == USB_SPEED_FULL)
diff --git a/queue-5.12/usb-gadget-dummy_hcd-fix-gpf-in-gadget_setup.patch b/queue-5.12/usb-gadget-dummy_hcd-fix-gpf-in-gadget_setup.patch
new file mode 100644 (file)
index 0000000..613d391
--- /dev/null
@@ -0,0 +1,90 @@
+From 4a5d797a9f9c4f18585544237216d7812686a71f Mon Sep 17 00:00:00 2001
+From: Anirudh Rayabharam <mail@anirudhrb.com>
+Date: Mon, 19 Apr 2021 09:07:08 +0530
+Subject: usb: gadget: dummy_hcd: fix gpf in gadget_setup
+
+From: Anirudh Rayabharam <mail@anirudhrb.com>
+
+commit 4a5d797a9f9c4f18585544237216d7812686a71f upstream.
+
+Fix a general protection fault reported by syzbot due to a race between
+gadget_setup() and gadget_unbind() in raw_gadget.
+
+The gadget core is supposed to guarantee that there won't be any more
+callbacks to the gadget driver once the driver's unbind routine is
+called. That guarantee is enforced in usb_gadget_remove_driver as
+follows:
+
+        usb_gadget_disconnect(udc->gadget);
+        if (udc->gadget->irq)
+                synchronize_irq(udc->gadget->irq);
+        udc->driver->unbind(udc->gadget);
+        usb_gadget_udc_stop(udc);
+
+usb_gadget_disconnect turns off the pullup resistor, telling the host
+that the gadget is no longer connected and preventing the transmission
+of any more USB packets. Any packets that have already been received
+are sure to processed by the UDC driver's interrupt handler by the time
+synchronize_irq returns.
+
+But this doesn't work with dummy_hcd, because dummy_hcd doesn't use
+interrupts; it uses a timer instead. It does have code to emulate the
+effect of synchronize_irq, but that code doesn't get invoked at the
+right time -- it currently runs in usb_gadget_udc_stop, after the unbind
+callback instead of before. Indeed, there's no way for
+usb_gadget_remove_driver to invoke this code before the unbind callback.
+
+To fix this, move the synchronize_irq() emulation code to dummy_pullup
+so that it runs before unbind. Also, add a comment explaining why it is
+necessary to have it there.
+
+Reported-by: syzbot+eb4674092e6cc8d9e0bd@syzkaller.appspotmail.com
+Suggested-by: Alan Stern <stern@rowland.harvard.edu>
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Anirudh Rayabharam <mail@anirudhrb.com>
+Link: https://lore.kernel.org/r/20210419033713.3021-1-mail@anirudhrb.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/dummy_hcd.c |   23 +++++++++++++++--------
+ 1 file changed, 15 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -903,6 +903,21 @@ static int dummy_pullup(struct usb_gadge
+       spin_lock_irqsave(&dum->lock, flags);
+       dum->pullup = (value != 0);
+       set_link_state(dum_hcd);
++      if (value == 0) {
++              /*
++               * Emulate synchronize_irq(): wait for callbacks to finish.
++               * This seems to be the best place to emulate the call to
++               * synchronize_irq() that's in usb_gadget_remove_driver().
++               * Doing it in dummy_udc_stop() would be too late since it
++               * is called after the unbind callback and unbind shouldn't
++               * be invoked until all the other callbacks are finished.
++               */
++              while (dum->callback_usage > 0) {
++                      spin_unlock_irqrestore(&dum->lock, flags);
++                      usleep_range(1000, 2000);
++                      spin_lock_irqsave(&dum->lock, flags);
++              }
++      }
+       spin_unlock_irqrestore(&dum->lock, flags);
+       usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
+@@ -1004,14 +1019,6 @@ static int dummy_udc_stop(struct usb_gad
+       spin_lock_irq(&dum->lock);
+       dum->ints_enabled = 0;
+       stop_activity(dum);
+-
+-      /* emulate synchronize_irq(): wait for callbacks to finish */
+-      while (dum->callback_usage > 0) {
+-              spin_unlock_irq(&dum->lock);
+-              usleep_range(1000, 2000);
+-              spin_lock_irq(&dum->lock);
+-      }
+-
+       dum->driver = NULL;
+       spin_unlock_irq(&dum->lock);
diff --git a/queue-5.12/usb-gadget-fix-double-free-of-device-descriptor-pointers.patch b/queue-5.12/usb-gadget-fix-double-free-of-device-descriptor-pointers.patch
new file mode 100644 (file)
index 0000000..091cdd2
--- /dev/null
@@ -0,0 +1,44 @@
+From 43c4cab006f55b6ca549dd1214e22f5965a8675f Mon Sep 17 00:00:00 2001
+From: Hemant Kumar <hemantk@codeaurora.org>
+Date: Wed, 21 Apr 2021 12:47:32 -0700
+Subject: usb: gadget: Fix double free of device descriptor pointers
+
+From: Hemant Kumar <hemantk@codeaurora.org>
+
+commit 43c4cab006f55b6ca549dd1214e22f5965a8675f upstream.
+
+Upon driver unbind usb_free_all_descriptors() function frees all
+speed descriptor pointers without setting them to NULL. In case
+gadget speed changes (i.e from super speed plus to super speed)
+after driver unbind only upto super speed descriptor pointers get
+populated. Super speed plus desc still holds the stale (already
+freed) pointer. Fix this issue by setting all descriptor pointers
+to NULL after freeing them in usb_free_all_descriptors().
+
+Fixes: f5c61225cf29 ("usb: gadget: Update function for SuperSpeedPlus")
+cc: stable@vger.kernel.org
+Reviewed-by: Peter Chen <peter.chen@kernel.org>
+Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1619034452-17334-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/config.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/gadget/config.c
++++ b/drivers/usb/gadget/config.c
+@@ -194,9 +194,13 @@ EXPORT_SYMBOL_GPL(usb_assign_descriptors
+ void usb_free_all_descriptors(struct usb_function *f)
+ {
+       usb_free_descriptors(f->fs_descriptors);
++      f->fs_descriptors = NULL;
+       usb_free_descriptors(f->hs_descriptors);
++      f->hs_descriptors = NULL;
+       usb_free_descriptors(f->ss_descriptors);
++      f->ss_descriptors = NULL;
+       usb_free_descriptors(f->ssp_descriptors);
++      f->ssp_descriptors = NULL;
+ }
+ EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
diff --git a/queue-5.12/usb-gadget-function-f_fs-string-table-fix-for-multiple-languages.patch b/queue-5.12/usb-gadget-function-f_fs-string-table-fix-for-multiple-languages.patch
new file mode 100644 (file)
index 0000000..110487e
--- /dev/null
@@ -0,0 +1,44 @@
+From 55b74ce7d2ce0b0058f3e08cab185a0afacfe39e Mon Sep 17 00:00:00 2001
+From: Dean Anderson <dean@sensoray.com>
+Date: Wed, 17 Mar 2021 15:41:09 -0700
+Subject: usb: gadget/function/f_fs string table fix for multiple languages
+
+From: Dean Anderson <dean@sensoray.com>
+
+commit 55b74ce7d2ce0b0058f3e08cab185a0afacfe39e upstream.
+
+Fixes bug with the handling of more than one language in
+the string table in f_fs.c.
+str_count was not reset for subsequent language codes.
+str_count-- "rolls under" and processes u32 max strings on
+the processing of the second language entry.
+The existing bug can be reproduced by adding a second language table
+to the structure "strings" in tools/usb/ffs-test.c.
+
+Signed-off-by: Dean Anderson <dean@sensoray.com>
+Link: https://lore.kernel.org/r/20210317224109.21534-1-dean@sensoray.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/function/f_fs.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -2640,6 +2640,7 @@ static int __ffs_data_got_strings(struct
+       do { /* lang_count > 0 so we can use do-while */
+               unsigned needed = needed_count;
++              u32 str_per_lang = str_count;
+               if (len < 3)
+                       goto error_free;
+@@ -2675,7 +2676,7 @@ static int __ffs_data_got_strings(struct
+                       data += length + 1;
+                       len -= length + 1;
+-              } while (--str_count);
++              } while (--str_per_lang);
+               s->id = 0;   /* terminator */
+               s->s = NULL;