--- /dev/null
+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,
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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.
--- /dev/null
+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.
--- /dev/null
+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;
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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;
+ }
--- /dev/null
+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;
+ }
--- /dev/null
+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);
--- /dev/null
+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);
+ /*
--- /dev/null
+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;
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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) {
--- /dev/null
+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);
--- /dev/null
+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;
+
--- /dev/null
+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;
--- /dev/null
+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) {
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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.
--- /dev/null
+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:
--- /dev/null
+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);
+
--- /dev/null
+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;
--- /dev/null
+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,
--- /dev/null
+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,
--- /dev/null
+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)
+ {
--- /dev/null
+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,
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
--- /dev/null
+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, ¶m);
+ 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);
--- /dev/null
+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);
+ }
+ }
+
--- /dev/null
+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;
+
--- /dev/null
+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:
--- /dev/null
+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)
--- /dev/null
+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);
+
--- /dev/null
+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);
+
--- /dev/null
+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;