--- /dev/null
+From 58c724d501e7222c5966cc22cd4207b7400b910a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 11:47:33 +0100
+Subject: arm64: alternatives: mark patch_alternative() as `noinstr`
+
+From: Joey Gouly <joey.gouly@arm.com>
+
+[ Upstream commit a2c0b0fbe01419f8f5d1c0b9c581631f34ffce8b ]
+
+The alternatives code must be `noinstr` such that it does not patch itself,
+as the cache invalidation is only performed after all the alternatives have
+been applied.
+
+Mark patch_alternative() as `noinstr`. Mark branch_insn_requires_update()
+and get_alt_insn() with `__always_inline` since they are both only called
+through patch_alternative().
+
+Booting a kernel in QEMU TCG with KCSAN=y and ARM64_USE_LSE_ATOMICS=y caused
+a boot hang:
+[ 0.241121] CPU: All CPU(s) started at EL2
+
+The alternatives code was patching the atomics in __tsan_read4() from LL/SC
+atomics to LSE atomics.
+
+The following fragment is using LL/SC atomics in the .text section:
+ | <__tsan_unaligned_read4+304>: ldxr x6, [x2]
+ | <__tsan_unaligned_read4+308>: add x6, x6, x5
+ | <__tsan_unaligned_read4+312>: stxr w7, x6, [x2]
+ | <__tsan_unaligned_read4+316>: cbnz w7, <__tsan_unaligned_read4+304>
+
+This LL/SC atomic sequence was to be replaced with LSE atomics. However since
+the alternatives code was instrumentable, __tsan_read4() was being called after
+only the first instruction was replaced, which led to the following code in memory:
+ | <__tsan_unaligned_read4+304>: ldadd x5, x6, [x2]
+ | <__tsan_unaligned_read4+308>: add x6, x6, x5
+ | <__tsan_unaligned_read4+312>: stxr w7, x6, [x2]
+ | <__tsan_unaligned_read4+316>: cbnz w7, <__tsan_unaligned_read4+304>
+
+This caused an infinite loop as the `stxr` instruction never completed successfully,
+so `w7` was always 0.
+
+Signed-off-by: Joey Gouly <joey.gouly@arm.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20220405104733.11476-1-joey.gouly@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/kernel/alternative.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
+index 73039949b5ce..5f8e4c2df53c 100644
+--- a/arch/arm64/kernel/alternative.c
++++ b/arch/arm64/kernel/alternative.c
+@@ -41,7 +41,7 @@ bool alternative_is_applied(u16 cpufeature)
+ /*
+ * Check if the target PC is within an alternative block.
+ */
+-static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
++static __always_inline bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
+ {
+ unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
+ return !(pc >= replptr && pc <= (replptr + alt->alt_len));
+@@ -49,7 +49,7 @@ static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
+
+ #define align_down(x, a) ((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
+
+-static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
++static __always_inline u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
+ {
+ u32 insn;
+
+@@ -94,7 +94,7 @@ static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnp
+ return insn;
+ }
+
+-static void patch_alternative(struct alt_instr *alt,
++static noinstr void patch_alternative(struct alt_instr *alt,
+ __le32 *origptr, __le32 *updptr, int nr_inst)
+ {
+ __le32 *replptr;
+--
+2.35.1
+
--- /dev/null
+From 4d9941ddf259f01edb717f2a2aaa03901038bc48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 19 Mar 2022 21:11:03 +0100
+Subject: ata: libata-core: Disable READ LOG DMA EXT for Samsung 840 EVOs
+
+From: Christian Lamparter <chunkeey@gmail.com>
+
+[ Upstream commit 5399752299396a3c9df6617f4b3c907d7aa4ded8 ]
+
+Samsung' 840 EVO with the latest firmware (EXT0DB6Q) locks up with
+the a message: "READ LOG DMA EXT failed, trying PIO" during boot.
+
+Initially this was discovered because it caused a crash
+with the sata_dwc_460ex controller on a WD MyBook Live DUO.
+
+The reporter "Tice Rex" which has the unique opportunity that he
+has two Samsung 840 EVO SSD! One with the older firmware "EXT0BB0Q"
+which booted fine and didn't expose "READ LOG DMA EXT". But the
+newer/latest firmware "EXT0DB6Q" caused the headaches.
+
+BugLink: https://github.com/openwrt/openwrt/issues/9505
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-core.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index d2b544bdc7b5..f963a0a7da46 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -3974,6 +3974,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
++ { "Samsung SSD 840 EVO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
++ ATA_HORKAGE_NO_DMA_LOG |
++ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Samsung SSD 840*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "Samsung SSD 850*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+--
+2.35.1
+
--- /dev/null
+From 099d4d1113ecc973b99007b83dadaca9f42974c7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Mar 2022 11:30:36 -0400
+Subject: btrfs: do not warn for free space inode in cow_file_range
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit a7d16d9a07bbcb7dcd5214a1bea75c808830bc0d ]
+
+This is a long time leftover from when I originally added the free space
+inode, the point was to catch cases where we weren't honoring the NOCOW
+flag. However there exists a race with relocation, if we allocate our
+free space inode in a block group that is about to be relocated, we
+could trigger the COW path before the relocation has the opportunity to
+find the extents and delete the free space cache. In production where
+we have auto-relocation enabled we're seeing this WARN_ON_ONCE() around
+5k times in a 2 week period, so not super common but enough that it's at
+the top of our metrics.
+
+We're properly handling the error here, and with us phasing out v1 space
+cache anyway just drop the WARN_ON_ONCE.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index f7f4ac01589b..4a5248097d7a 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -995,7 +995,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+ int ret = 0;
+
+ if (btrfs_is_free_space_inode(inode)) {
+- WARN_ON_ONCE(1);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+--
+2.35.1
+
--- /dev/null
+From 41cc716f363af3bbf690767741051c71bf693dce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Mar 2022 10:55:32 -0700
+Subject: btrfs: fix fallocate to use file_modified to update permissions
+ consistently
+
+From: Darrick J. Wong <djwong@kernel.org>
+
+[ Upstream commit 05fd9564e9faf0f23b4676385e27d9405cef6637 ]
+
+Since the initial introduction of (posix) fallocate back at the turn of
+the century, it has been possible to use this syscall to change the
+user-visible contents of files. This can happen by extending the file
+size during a preallocation, or through any of the newer modes (punch,
+zero range). Because the call can be used to change file contents, we
+should treat it like we do any other modification to a file -- update
+the mtime, and drop set[ug]id privileges/capabilities.
+
+The VFS function file_modified() does all this for us if pass it a
+locked inode, so let's make fallocate drop permissions correctly.
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Darrick J. Wong <djwong@kernel.org>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/file.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index f59ec55e5feb..416a1b753ff6 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -2833,8 +2833,9 @@ int btrfs_replace_file_extents(struct inode *inode, struct btrfs_path *path,
+ return ret;
+ }
+
+-static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
++static int btrfs_punch_hole(struct file *file, loff_t offset, loff_t len)
+ {
++ struct inode *inode = file_inode(file);
+ struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct extent_state *cached_state = NULL;
+@@ -2866,6 +2867,10 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
+ goto out_only_mutex;
+ }
+
++ ret = file_modified(file);
++ if (ret)
++ goto out_only_mutex;
++
+ lockstart = round_up(offset, btrfs_inode_sectorsize(BTRFS_I(inode)));
+ lockend = round_down(offset + len,
+ btrfs_inode_sectorsize(BTRFS_I(inode))) - 1;
+@@ -3301,7 +3306,7 @@ static long btrfs_fallocate(struct file *file, int mode,
+ return -EOPNOTSUPP;
+
+ if (mode & FALLOC_FL_PUNCH_HOLE)
+- return btrfs_punch_hole(inode, offset, len);
++ return btrfs_punch_hole(file, offset, len);
+
+ /*
+ * Only trigger disk allocation, don't trigger qgroup reserve
+@@ -3323,6 +3328,10 @@ static long btrfs_fallocate(struct file *file, int mode,
+ goto out;
+ }
+
++ ret = file_modified(file);
++ if (ret)
++ goto out;
++
+ /*
+ * TODO: Move these two operations after we have checked
+ * accurate reserved space, or fallocate can still fail but
+--
+2.35.1
+
--- /dev/null
+From 3c5a524cadbd265d749c59f4c2fcdbb8a49c8b2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 14:37:51 +0530
+Subject: cfg80211: hold bss_lock while updating nontrans_list
+
+From: Rameshkumar Sundaram <quic_ramess@quicinc.com>
+
+[ Upstream commit a5199b5626cd6913cf8776a835bc63d40e0686ad ]
+
+Synchronize additions to nontrans_list of transmitting BSS with
+bss_lock to avoid races. Also when cfg80211_add_nontrans_list() fails
+__cfg80211_unlink_bss() needs bss_lock to be held (has lockdep assert
+on bss_lock). So protect the whole block with bss_lock to avoid
+races and warnings. Found during code review.
+
+Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning")
+Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
+Link: https://lore.kernel.org/r/1649668071-9370-1-git-send-email-quic_ramess@quicinc.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/wireless/scan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index c1b2655682a8..6dc9b7e22b71 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -1968,11 +1968,13 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
+ /* this is a nontransmitting bss, we need to add it to
+ * transmitting bss' list if it is not there
+ */
++ spin_lock_bh(&rdev->bss_lock);
+ if (cfg80211_add_nontrans_list(non_tx_data->tx_bss,
+ &res->pub)) {
+ if (__cfg80211_unlink_bss(rdev, res))
+ rdev->bss_generation++;
+ }
++ spin_unlock_bh(&rdev->bss_lock);
+ }
+
+ trace_cfg80211_return_bss(&res->pub);
+--
+2.35.1
+
--- /dev/null
+From 78fb7f87ed5934fe390f7a67875c17d07ec798fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Apr 2022 04:42:51 -0700
+Subject: cifs: potential buffer overflow in handling symlinks
+
+From: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+
+[ Upstream commit 64c4a37ac04eeb43c42d272f6e6c8c12bfcf4304 ]
+
+Smatch printed a warning:
+ arch/x86/crypto/poly1305_glue.c:198 poly1305_update_arch() error:
+ __memcpy() 'dctx->buf' too small (16 vs u32max)
+
+It's caused because Smatch marks 'link_len' as untrusted since it comes
+from sscanf(). Add a check to ensure that 'link_len' is not larger than
+the size of the 'link_str' buffer.
+
+Fixes: c69c1b6eaea1 ("cifs: implement CIFSParseMFSymlink()")
+Signed-off-by: Harshit Mogalapalli <harshit.m.mogalapalli@oracle.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/cifs/link.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/cifs/link.c b/fs/cifs/link.c
+index 94dab4309fbb..85d30fef98a2 100644
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -97,6 +97,9 @@ parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
+ if (rc != 1)
+ return -EINVAL;
+
++ if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
++ return -EINVAL;
++
+ rc = symlink_hash(link_len, link_str, md5_hash);
+ if (rc) {
+ cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
+--
+2.35.1
+
--- /dev/null
+From 0da48a9237a6094af4f97e44a3567d1f97437196 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 15:03:35 -0700
+Subject: dm mpath: only use ktime_get_ns() in historical selector
+
+From: Khazhismel Kumykov <khazhy@google.com>
+
+[ Upstream commit ce40426fdc3c92acdba6b5ca74bc7277ffaa6a3d ]
+
+Mixing sched_clock() and ktime_get_ns() usage will give bad results.
+
+Switch hst_select_path() from using sched_clock() to ktime_get_ns().
+Also rename path_service_time()'s 'sched_now' variable to 'now'.
+
+Fixes: 2613eab11996 ("dm mpath: add Historical Service Time Path Selector")
+Signed-off-by: Khazhismel Kumykov <khazhy@google.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-historical-service-time.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/md/dm-historical-service-time.c b/drivers/md/dm-historical-service-time.c
+index 186f91e2752c..06fe43c13ba3 100644
+--- a/drivers/md/dm-historical-service-time.c
++++ b/drivers/md/dm-historical-service-time.c
+@@ -429,7 +429,7 @@ static struct dm_path *hst_select_path(struct path_selector *ps,
+ {
+ struct selector *s = ps->context;
+ struct path_info *pi = NULL, *best = NULL;
+- u64 time_now = sched_clock();
++ u64 time_now = ktime_get_ns();
+ struct dm_path *ret = NULL;
+ unsigned long flags;
+
+@@ -470,7 +470,7 @@ static int hst_start_io(struct path_selector *ps, struct dm_path *path,
+
+ static u64 path_service_time(struct path_info *pi, u64 start_time)
+ {
+- u64 sched_now = ktime_get_ns();
++ u64 now = ktime_get_ns();
+
+ /* if a previous disk request has finished after this IO was
+ * sent to the hardware, pretend the submission happened
+@@ -479,11 +479,11 @@ static u64 path_service_time(struct path_info *pi, u64 start_time)
+ if (time_after64(pi->last_finish, start_time))
+ start_time = pi->last_finish;
+
+- pi->last_finish = sched_now;
+- if (time_before64(sched_now, start_time))
++ pi->last_finish = now;
++ if (time_before64(now, start_time))
+ return 0;
+
+- return sched_now - start_time;
++ return now - start_time;
+ }
+
+ static int hst_end_io(struct path_selector *ps, struct dm_path *path,
+--
+2.35.1
+
--- /dev/null
+From 29f2ab3ce3a330a5bc8e14e24b83ba1612946511 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Mar 2022 08:25:10 -0700
+Subject: Drivers: hv: vmbus: Prevent load re-ordering when reading ring buffer
+
+From: Michael Kelley <mikelley@microsoft.com>
+
+[ Upstream commit b6cae15b5710c8097aad26a2e5e752c323ee5348 ]
+
+When reading a packet from a host-to-guest ring buffer, there is no
+memory barrier between reading the write index (to see if there is
+a packet to read) and reading the contents of the packet. The Hyper-V
+host uses store-release when updating the write index to ensure that
+writes of the packet data are completed first. On the guest side,
+the processor can reorder and read the packet data before the write
+index, and sometimes get stale packet data. Getting such stale packet
+data has been observed in a reproducible case in a VM on ARM64.
+
+Fix this by using virt_load_acquire() to read the write index,
+ensuring that reads of the packet data cannot be reordered
+before it. Preventing such reordering is logically correct, and
+with this change, getting stale data can no longer be reproduced.
+
+Signed-off-by: Michael Kelley <mikelley@microsoft.com>
+Reviewed-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
+Link: https://lore.kernel.org/r/1648394710-33480-1-git-send-email-mikelley@microsoft.com
+Signed-off-by: Wei Liu <wei.liu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hv/ring_buffer.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
+index 356e22159e83..769851b6e74c 100644
+--- a/drivers/hv/ring_buffer.c
++++ b/drivers/hv/ring_buffer.c
+@@ -378,7 +378,16 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
+ static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
+ {
+ u32 priv_read_loc = rbi->priv_read_index;
+- u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
++ u32 write_loc;
++
++ /*
++ * The Hyper-V host writes the packet data, then uses
++ * store_release() to update the write_index. Use load_acquire()
++ * here to prevent loads of the packet data from being re-ordered
++ * before the read of the write_index and potentially getting
++ * stale data.
++ */
++ write_loc = virt_load_acquire(&rbi->ring_buffer->write_index);
+
+ if (write_loc >= priv_read_loc)
+ return write_loc - priv_read_loc;
+--
+2.35.1
+
--- /dev/null
+From 5ec9b7b6cc7a35e53f2430363b3918cf80d721a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 21:22:06 +0800
+Subject: drivers: net: slip: fix NPD bug in sl_tx_timeout()
+
+From: Duoming Zhou <duoming@zju.edu.cn>
+
+[ Upstream commit ec4eb8a86ade4d22633e1da2a7d85a846b7d1798 ]
+
+When a slip driver is detaching, the slip_close() will act to
+cleanup necessary resources and sl->tty is set to NULL in
+slip_close(). Meanwhile, the packet we transmit is blocked,
+sl_tx_timeout() will be called. Although slip_close() and
+sl_tx_timeout() use sl->lock to synchronize, we don`t judge
+whether sl->tty equals to NULL in sl_tx_timeout() and the
+null pointer dereference bug will happen.
+
+ (Thread 1) | (Thread 2)
+ | slip_close()
+ | spin_lock_bh(&sl->lock)
+ | ...
+... | sl->tty = NULL //(1)
+sl_tx_timeout() | spin_unlock_bh(&sl->lock)
+ spin_lock(&sl->lock); |
+ ... | ...
+ tty_chars_in_buffer(sl->tty)|
+ if (tty->ops->..) //(2) |
+ ... | synchronize_rcu()
+
+We set NULL to sl->tty in position (1) and dereference sl->tty
+in position (2).
+
+This patch adds check in sl_tx_timeout(). If sl->tty equals to
+NULL, sl_tx_timeout() will goto out.
+
+Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20220405132206.55291-1-duoming@zju.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/slip/slip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
+index f81fb0b13a94..369bd30fed35 100644
+--- a/drivers/net/slip/slip.c
++++ b/drivers/net/slip/slip.c
+@@ -468,7 +468,7 @@ static void sl_tx_timeout(struct net_device *dev, unsigned int txqueue)
+ spin_lock(&sl->lock);
+
+ if (netif_queue_stopped(dev)) {
+- if (!netif_running(dev))
++ if (!netif_running(dev) || !sl->tty)
+ goto out;
+
+ /* May be we must check transmitter timeout here ?
+--
+2.35.1
+
--- /dev/null
+From 5ba3fb4cc8ecf0565a95bc40a9061c71292780ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Mar 2022 14:53:24 -0400
+Subject: drm/amd: Add USBC connector ID
+
+From: Aurabindo Pillai <aurabindo.pillai@amd.com>
+
+[ Upstream commit c5c948aa894a831f96fccd025e47186b1ee41615 ]
+
+[Why&How] Add a dedicated AMDGPU specific ID for use with
+newer ASICs that support USB-C output
+
+Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/ObjectID.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/ObjectID.h b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+index 5b393622f592..a0f0a17e224f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/ObjectID.h
++++ b/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+@@ -119,6 +119,7 @@
+ #define CONNECTOR_OBJECT_ID_eDP 0x14
+ #define CONNECTOR_OBJECT_ID_MXM 0x15
+ #define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16
++#define CONNECTOR_OBJECT_ID_USBC 0x17
+
+ /* deleted */
+
+--
+2.35.1
+
--- /dev/null
+From 7de966e99f05a44e951a49d218154fc1ea358f0b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Mar 2022 00:07:59 +0800
+Subject: drm/amd/display: FEC check in timing validation
+
+From: Chiawen Huang <chiawen.huang@amd.com>
+
+[ Upstream commit 7d56a154e22ffb3613fdebf83ec34d5225a22993 ]
+
+[Why]
+disable/enable leads FEC mismatch between hw/sw FEC state.
+
+[How]
+check FEC status to fastboot on/off.
+
+Reviewed-by: Anthony Koo <Anthony.Koo@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Chiawen Huang <chiawen.huang@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 93f5229c303e..ac5323596c65 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -1173,6 +1173,10 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ return false;
+
++ /* Check for FEC status*/
++ if (link->link_enc->funcs->fec_is_active(link->link_enc))
++ return false;
++
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
+
+ if (enc_inst == ENGINE_ID_UNKNOWN)
+--
+2.35.1
+
--- /dev/null
+From abdfba2c3476fce6fe85eb16dfc0cf1944158f50 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Mar 2022 19:55:05 -0400
+Subject: drm/amd/display: Fix allocate_mst_payload assert on resume
+
+From: Roman Li <Roman.Li@amd.com>
+
+[ Upstream commit f4346fb3edf7720db3f7f5e1cab1f667cd024280 ]
+
+[Why]
+On resume we do link detection for all non-MST connectors.
+MST is handled separately. However the condition for telling
+if connector is on mst branch is not enough for mst hub case.
+Link detection for mst branch link leads to mst topology reset.
+That causes assert in dc_link_allocate_mst_payload()
+
+[How]
+Use link type as indicator for mst link.
+
+Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Roman Li <Roman.Li@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index e828f9414ba2..7bb151283f44 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2022,7 +2022,8 @@ static int dm_resume(void *handle)
+ * this is the case when traversing through already created
+ * MST connectors, should be skipped
+ */
+- if (aconnector->mst_port)
++ if (aconnector->dc_link &&
++ aconnector->dc_link->type == dc_connection_mst_branch)
+ continue;
+
+ mutex_lock(&aconnector->hpd_lock);
+--
+2.35.1
+
--- /dev/null
+From f1e278145b40b62f5f413526e89e76aea00de25b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Mar 2022 18:31:29 -0500
+Subject: drm/amd/display: fix audio format not updated after edid updated
+
+From: Charlene Liu <Charlene.Liu@amd.com>
+
+[ Upstream commit 5e8a71cf13bc9184fee915b2220be71b4c6cac74 ]
+
+[why]
+for the case edid change only changed audio format.
+driver still need to update stream.
+
+Reviewed-by: Alvin Lee <Alvin.Lee2@amd.com>
+Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+index 5c5ccbad9658..1e47afc4ccc1 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1701,8 +1701,8 @@ bool dc_is_stream_unchanged(
+ if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
+ return false;
+
+- // Only Have Audio left to check whether it is same or not. This is a corner case for Tiled sinks
+- if (old_stream->audio_info.mode_count != stream->audio_info.mode_count)
++ /*compare audio info*/
++ if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0)
+ return false;
+
+ return true;
+--
+2.35.1
+
--- /dev/null
+From a1aa5686c44e484d4441fc7dafc7207a0c9f644b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Mar 2022 11:12:36 -0400
+Subject: drm/amd/display: Revert FEC check in validation
+
+From: Martin Leung <Martin.Leung@amd.com>
+
+[ Upstream commit b2075fce104b88b789c15ef1ed2b91dc94198e26 ]
+
+why and how:
+causes failure on install on certain machines
+
+Reviewed-by: George Shen <George.Shen@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Martin Leung <Martin.Leung@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index ac5323596c65..93f5229c303e 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -1173,10 +1173,6 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
+ if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ return false;
+
+- /* Check for FEC status*/
+- if (link->link_enc->funcs->fec_is_active(link->link_enc))
+- return false;
+-
+ enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);
+
+ if (enc_inst == ENGINE_ID_UNKNOWN)
+--
+2.35.1
+
--- /dev/null
+From 6ecd479a634b390d1b8a9d4b4a8dc609f10af528 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Mar 2022 11:35:29 -0500
+Subject: drm/amd/display: Update VTEM Infopacket definition
+
+From: Leo (Hanghong) Ma <hanghong.ma@amd.com>
+
+[ Upstream commit c9fbf6435162ed5fb7201d1d4adf6585c6a8c327 ]
+
+[Why & How]
+The latest HDMI SPEC has updated the VTEM packet structure,
+so change the VTEM Infopacket defined in the driver side to align
+with the SPEC.
+
+Reviewed-by: Chris Park <Chris.Park@amd.com>
+Acked-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Leo (Hanghong) Ma <hanghong.ma@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/modules/info_packet/info_packet.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+index 0fdf7a3e96de..96e18050a617 100644
+--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+@@ -100,7 +100,8 @@ enum vsc_packet_revision {
+ //PB7 = MD0
+ #define MASK_VTEM_MD0__VRR_EN 0x01
+ #define MASK_VTEM_MD0__M_CONST 0x02
+-#define MASK_VTEM_MD0__RESERVED2 0x0C
++#define MASK_VTEM_MD0__QMS_EN 0x04
++#define MASK_VTEM_MD0__RESERVED2 0x08
+ #define MASK_VTEM_MD0__FVA_FACTOR_M1 0xF0
+
+ //MD1
+@@ -109,7 +110,7 @@ enum vsc_packet_revision {
+ //MD2
+ #define MASK_VTEM_MD2__BASE_REFRESH_RATE_98 0x03
+ #define MASK_VTEM_MD2__RB 0x04
+-#define MASK_VTEM_MD2__RESERVED3 0xF8
++#define MASK_VTEM_MD2__NEXT_TFR 0xF8
+
+ //MD3
+ #define MASK_VTEM_MD3__BASE_REFRESH_RATE_07 0xFF
+--
+2.35.1
+
--- /dev/null
+From 10ab073f2cd34554922275ab34193ea4a898f087 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Mar 2022 23:54:58 +0800
+Subject: drm/amdgpu/vcn: improve vcn dpg stop procedure
+
+From: Tianci Yin <tianci.yin@amd.com>
+
+[ Upstream commit 6ea239adc2a712eb318f04f5c29b018ba65ea38a ]
+
+Prior to disabling dpg, VCN need unpausing dpg mode, or VCN will hang in
+S3 resuming.
+
+Reviewed-by: James Zhu <James.Zhu@amd.com>
+Signed-off-by: Tianci Yin <tianci.yin@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+index 2099f6ebd833..bdb8e596bda6 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+@@ -1429,8 +1429,11 @@ static int vcn_v3_0_start_sriov(struct amdgpu_device *adev)
+
+ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
+ {
++ struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE};
+ uint32_t tmp;
+
++ vcn_v3_0_pause_dpg_mode(adev, 0, &state);
++
+ /* Wait for power status to be 1 */
+ SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
+--
+2.35.1
+
--- /dev/null
+From 8706d6d91091b99da560efd27b9cf71dbfe71fc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Mar 2022 16:26:23 +0800
+Subject: drm/amdkfd: Check for potential null return of kmalloc_array()
+
+From: QintaoShen <unSimple1993@163.com>
+
+[ Upstream commit ebbb7bb9e80305820dc2328a371c1b35679f2667 ]
+
+As the kmalloc_array() may return null, the 'event_waiters[i].wait' would lead to null-pointer dereference.
+Therefore, it is better to check the return value of kmalloc_array() to avoid this confusion.
+
+Signed-off-by: QintaoShen <unSimple1993@163.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+index ba2c2ce0c55a..159be13ef20b 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+@@ -531,6 +531,8 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
+ event_waiters = kmalloc_array(num_events,
+ sizeof(struct kfd_event_waiter),
+ GFP_KERNEL);
++ if (!event_waiters)
++ return NULL;
+
+ for (i = 0; (event_waiters) && (i < num_events) ; i++) {
+ init_wait(&event_waiters[i].wait);
+--
+2.35.1
+
--- /dev/null
+From dfcd30616dc1ff05a09a9df48c4b3ca1a9c95e58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Mar 2022 15:31:22 -0400
+Subject: drm/amdkfd: Fix Incorrect VMIDs passed to HWS
+
+From: Tushar Patel <tushar.patel@amd.com>
+
+[ Upstream commit b7dfbd2e601f3fee545bc158feceba4f340fe7cf ]
+
+Compute-only GPUs have more than 8 VMIDs allocated to KFD. Fix
+this by passing correct number of VMIDs to HWS
+
+v2: squash in warning fix (Alex)
+
+Signed-off-by: Tushar Patel <tushar.patel@amd.com>
+Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 11 +++--------
+ 2 files changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index ed13a2f76884..30659c1776e8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -632,7 +632,7 @@ MODULE_PARM_DESC(sched_policy,
+ * Maximum number of processes that HWS can schedule concurrently. The maximum is the
+ * number of VMIDs assigned to the HWS, which is also the default.
+ */
+-int hws_max_conc_proc = 8;
++int hws_max_conc_proc = -1;
+ module_param(hws_max_conc_proc, int, 0444);
+ MODULE_PARM_DESC(hws_max_conc_proc,
+ "Max # processes HWS can execute concurrently when sched_policy=0 (0 = no concurrency, #VMIDs for KFD = Maximum(default))");
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+index 84313135c2ea..148e43dee657 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+@@ -664,15 +664,10 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
+ - kfd->vm_info.first_vmid_kfd + 1;
+
+ /* Verify module parameters regarding mapped process number*/
+- if ((hws_max_conc_proc < 0)
+- || (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) {
+- dev_err(kfd_device,
+- "hws_max_conc_proc %d must be between 0 and %d, use %d instead\n",
+- hws_max_conc_proc, kfd->vm_info.vmid_num_kfd,
+- kfd->vm_info.vmid_num_kfd);
++ if (hws_max_conc_proc >= 0)
++ kfd->max_proc_per_quantum = min((u32)hws_max_conc_proc, kfd->vm_info.vmid_num_kfd);
++ else
+ kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
+- } else
+- kfd->max_proc_per_quantum = hws_max_conc_proc;
+
+ /* calculate max size of mqds needed for queues */
+ size = max_num_of_queues_per_device *
+--
+2.35.1
+
--- /dev/null
+From b1e7034c58af552abc97cef5bdc7b48be51297d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Mar 2022 11:45:49 -0700
+Subject: drm/msm: Add missing put_task_struct() in debugfs path
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit ac3e4f42d5ec459f701743debd9c1ad2f2247402 ]
+
+Fixes: 25faf2f2e065 ("drm/msm: Show process names in gem_describe")
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Link: https://lore.kernel.org/r/20220317184550.227991-1-robdclark@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/msm_gem.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
+index 819567e40565..9c05bf6c4551 100644
+--- a/drivers/gpu/drm/msm/msm_gem.c
++++ b/drivers/gpu/drm/msm/msm_gem.c
+@@ -849,6 +849,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
+ get_pid_task(aspace->pid, PIDTYPE_PID);
+ if (task) {
+ comm = kstrdup(task->comm, GFP_KERNEL);
++ put_task_struct(task);
+ } else {
+ comm = NULL;
+ }
+--
+2.35.1
+
--- /dev/null
+From 37dfe680171cb75a0b5102a47487815334901540 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Mar 2022 17:07:31 -0700
+Subject: drm/msm/dsi: Use connector directly in
+ msm_dsi_manager_connector_init()
+
+From: Stephen Boyd <swboyd@chromium.org>
+
+[ Upstream commit 47b7de6b88b962ef339a2427a023d2a23d161654 ]
+
+The member 'msm_dsi->connector' isn't assigned until
+msm_dsi_manager_connector_init() returns (see msm_dsi_modeset_init() and
+how it assigns the return value). Therefore this pointer is going to be
+NULL here. Let's use 'connector' which is what was intended.
+
+Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Cc: Sean Paul <seanpaul@chromium.org>
+Fixes: 6d5e78406991 ("drm/msm/dsi: Move dsi panel init into modeset init path")
+Signed-off-by: Stephen Boyd <swboyd@chromium.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Patchwork: https://patchwork.freedesktop.org/patch/478693/
+Link: https://lore.kernel.org/r/20220318000731.2823718-1-swboyd@chromium.org
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/dsi/dsi_manager.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
+index 1d28dfba2c9b..fb421ca56b3d 100644
+--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
++++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
+@@ -644,7 +644,7 @@ struct drm_connector *msm_dsi_manager_connector_init(u8 id)
+ return connector;
+
+ fail:
+- connector->funcs->destroy(msm_dsi->connector);
++ connector->funcs->destroy(connector);
+ return ERR_PTR(ret);
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 6ce36b7ffa8065fef809797a9ee0d2e27c2b636e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 13:28:33 -0700
+Subject: drm/msm: Fix range size vs end confusion
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit 537fef808be5ea56f6fc06932162550819a3b3c3 ]
+
+The fourth param is size, rather than range_end.
+
+Note that we could increase the address space size if we had a way to
+prevent buffers from spanning a 4G split, mostly just to avoid fw bugs
+with 64b math.
+
+Fixes: 84c31ee16f90 ("drm/msm/a6xx: Add support for per-instance pagetables")
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Link: https://lore.kernel.org/r/20220407202836.1211268-1-robdclark@gmail.com
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index 9e09805575db..39563daff4a0 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -1222,7 +1222,7 @@ a6xx_create_private_address_space(struct msm_gpu *gpu)
+ return ERR_CAST(mmu);
+
+ return msm_gem_address_space_create(mmu,
+- "gpu", 0x100000000ULL, 0x1ffffffffULL);
++ "gpu", 0x100000000ULL, SZ_4G);
+ }
+
+ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+--
+2.35.1
+
--- /dev/null
+From 76a53b3725e0c85abaff2607f4e1680de97d1903 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Mar 2022 09:28:13 +0000
+Subject: firmware: arm_scmi: Fix sorting of retrieved clock rates
+
+From: Cristian Marussi <cristian.marussi@arm.com>
+
+[ Upstream commit 23274739a5b6166f74d8d9cb5243d7bf6b46aab9 ]
+
+During SCMI Clock protocol initialization, after having retrieved from the
+SCMI platform all the available discrete rates for a specific clock, the
+clock rates array is sorted, unfortunately using a pointer to its end as
+a base instead of its start, so that sorting does not work.
+
+Fix invocation of sort() passing as base a pointer to the start of the
+retrieved clock rates array.
+
+Link: https://lore.kernel.org/r/20220318092813.49283-1-cristian.marussi@arm.com
+Fixes: dccec73de91d ("firmware: arm_scmi: Keep the discrete clock rates sorted")
+Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_scmi/clock.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
+index 4645677d86f1..a45678cd9b74 100644
+--- a/drivers/firmware/arm_scmi/clock.c
++++ b/drivers/firmware/arm_scmi/clock.c
+@@ -202,7 +202,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
+
+ if (rate_discrete && rate) {
+ clk->list.num_rates = tot_rate_cnt;
+- sort(rate, tot_rate_cnt, sizeof(*rate), rate_cmp_func, NULL);
++ sort(clk->list.rates, tot_rate_cnt, sizeof(*rate),
++ rate_cmp_func, NULL);
+ }
+
+ clk->rate_discrete = rate_discrete;
+--
+2.35.1
+
--- /dev/null
+From 3ef2ed0217cba2969672078a88806c47cdca60ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 19 Mar 2022 16:21:09 -0700
+Subject: gpiolib: acpi: use correct format characters
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+[ Upstream commit 213d266ebfb1621aab79cfe63388facc520a1381 ]
+
+When compiling with -Wformat, clang emits the following warning:
+
+ gpiolib-acpi.c:393:4: warning: format specifies type 'unsigned char' but the argument has type 'int' [-Wformat]
+ pin);
+ ^~~
+
+So warning that '%hhX' is paired with an 'int' is all just completely
+mindless and wrong. Sadly, I can see a different bogus warning reason
+why people would want to use '%02hhX'.
+
+Again, the *sane* thing from a human perspective is to use '%02X. But
+if the compiler doesn't do any range analysis at all, it could decide
+that "Oh, that print format could need up to 8 bytes of space in the
+result". Using '%02hhX' would cut that down to two.
+
+And since we use
+
+ char ev_name[5];
+
+and currently use "_%c%02hhX" as the format string, even a compiler
+that doesn't notice that "pin <= 255" test that guards this all will
+go "OK, that's at most 4 bytes and the final NUL termination, so it's
+fine".
+
+While a compiler - like gcc - that only sees that the original source
+of the 'pin' value is a 'unsigned short' array, and then doesn't take
+the "pin <= 255" into account, will warn like this:
+
+ gpiolib-acpi.c: In function 'acpi_gpiochip_request_interrupt':
+ gpiolib-acpi.c:206:24: warning: '%02X' directive writing between 2 and 4 bytes into a region of size 3 [-Wformat-overflow=]
+ sprintf(ev_name, "_%c%02X",
+ ^~~~
+ gpiolib-acpi.c:206:20: note: directive argument in the range [0, 65535]
+
+because gcc isn't being very good at that argument range analysis either.
+
+In other words, the original use of 'hhx' was bogus to begin with, and
+due to *another* compiler warning being bad, and we had that bad code
+being written back in 2016 to work around _that_ compiler warning
+(commit e40a3ae1f794: "gpio: acpi: work around false-positive
+-Wstring-overflow warning").
+
+Sadly, two different bad compiler warnings together does not make for
+one good one.
+
+It just makes for even more pain.
+
+End result: I think the simplest and cleanest option is simply the
+proposed change which undoes that '%hhX' change for gcc, and replaces
+it with just using a slightly bigger stack allocation. It's not like
+a 5-byte allocation is in any way likely to have saved any actual stack,
+since all the other variables in that function are 'int' or bigger.
+
+False-positive compiler warnings really do make people write worse
+code, and that's a problem. But on a scale of bad code, I feel that
+extending the buffer trivially is better than adding a pointless cast
+that literally makes no sense.
+
+At least in this case the end result isn't unreadable or buggy. We've
+had several cases of bad compiler warnings that caused changes that
+were actually horrendously wrong.
+
+Fixes: e40a3ae1f794 ("gpio: acpi: work around false-positive -Wstring-overflow warning")
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib-acpi.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 55e4f402ec8b..44ee319da1b3 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -276,8 +276,8 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
+ pin = agpio->pin_table[0];
+
+ if (pin <= 255) {
+- char ev_name[5];
+- sprintf(ev_name, "_%c%02hhX",
++ char ev_name[8];
++ sprintf(ev_name, "_%c%02X",
+ agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
+ pin);
+ if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
+--
+2.35.1
+
--- /dev/null
+From 21eb7387de1f68096b3d173ac7961f9e847d6d68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Feb 2022 16:14:11 +0100
+Subject: gpu: ipu-v3: Fix dev_dbg frequency output
+
+From: Leo Ruan <tingquan.ruan@cn.bosch.com>
+
+[ Upstream commit 070a88fd4a03f921b73a2059e97d55faaa447dab ]
+
+This commit corrects the printing of the IPU clock error percentage if
+it is between -0.1% to -0.9%. For example, if the pixel clock requested
+is 27.2 MHz but only 27.0 MHz can be achieved the deviation is -0.8%.
+But the fixed point math had a flaw and calculated error of 0.2%.
+
+Before:
+ Clocks: IPU 270000000Hz DI 24716667Hz Needed 27200000Hz
+ IPU clock can give 27000000 with divider 10, error 0.2%
+ Want 27200000Hz IPU 270000000Hz DI 24716667Hz using IPU, 27000000Hz
+
+After:
+ Clocks: IPU 270000000Hz DI 24716667Hz Needed 27200000Hz
+ IPU clock can give 27000000 with divider 10, error -0.8%
+ Want 27200000Hz IPU 270000000Hz DI 24716667Hz using IPU, 27000000Hz
+
+Signed-off-by: Leo Ruan <tingquan.ruan@cn.bosch.com>
+Signed-off-by: Mark Jonas <mark.jonas@de.bosch.com>
+Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
+Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
+Link: https://lore.kernel.org/r/20220207151411.5009-1-mark.jonas@de.bosch.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/ipu-v3/ipu-di.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/ipu-v3/ipu-di.c b/drivers/gpu/ipu-v3/ipu-di.c
+index b4a31d506fcc..74eca68891ad 100644
+--- a/drivers/gpu/ipu-v3/ipu-di.c
++++ b/drivers/gpu/ipu-v3/ipu-di.c
+@@ -451,8 +451,9 @@ static void ipu_di_config_clock(struct ipu_di *di,
+
+ error = rate / (sig->mode.pixelclock / 1000);
+
+- dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %d.%u%%\n",
+- rate, div, (signed)(error - 1000) / 10, error % 10);
++ dev_dbg(di->ipu->dev, " IPU clock can give %lu with divider %u, error %c%d.%d%%\n",
++ rate, div, error < 1000 ? '-' : '+',
++ abs(error - 1000) / 10, abs(error - 1000) % 10);
+
+ /* Allow a 1% error */
+ if (error < 1010 && error >= 990) {
+--
+2.35.1
+
--- /dev/null
+From 6e5bf5f4556d598e2a6df4e530b9453983b16352 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Nov 2021 13:23:02 +0100
+Subject: media: rockchip/rga: do proper error checking in probe
+
+From: Kyle Copperfield <kmcopper@danwin1210.me>
+
+[ Upstream commit 6150f276073a1480030242a7e006a89e161d6cd6 ]
+
+The latest fix for probe error handling contained a typo that causes
+probing to fail with the following message:
+
+ rockchip-rga: probe of ff680000.rga failed with error -12
+
+This patch fixes the typo.
+
+Fixes: e58430e1d4fd (media: rockchip/rga: fix error handling in probe)
+Reviewed-by: Dragan Simic <dragan.simic@gmail.com>
+Signed-off-by: Kyle Copperfield <kmcopper@danwin1210.me>
+Reviewed-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
+Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/rockchip/rga/rga.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/platform/rockchip/rga/rga.c b/drivers/media/platform/rockchip/rga/rga.c
+index 6759091b15e0..d99ea8973b67 100644
+--- a/drivers/media/platform/rockchip/rga/rga.c
++++ b/drivers/media/platform/rockchip/rga/rga.c
+@@ -895,7 +895,7 @@ static int rga_probe(struct platform_device *pdev)
+ }
+ rga->dst_mmu_pages =
+ (unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
+- if (rga->dst_mmu_pages) {
++ if (!rga->dst_mmu_pages) {
+ ret = -ENOMEM;
+ goto free_src_pages;
+ }
+--
+2.35.1
+
--- /dev/null
+From 13ea56c87dd98ca1cece1727c1b4e04bca342986 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Mar 2022 11:01:43 +0000
+Subject: memory: atmel-ebi: Fix missing of_node_put in atmel_ebi_probe
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 6f296a9665ba5ac68937bf11f96214eb9de81baa ]
+
+The device_node pointer is returned by of_parse_phandle() with refcount
+incremented. We should use of_node_put() on it when done.
+
+Fixes: 87108dc78eb8 ("memory: atmel-ebi: Enable the SMC clock if specified")
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com>
+Link: https://lore.kernel.org/r/20220309110144.22412-1-linmq006@gmail.com
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/memory/atmel-ebi.c | 23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
+index c267283b01fd..e749dcb3ddea 100644
+--- a/drivers/memory/atmel-ebi.c
++++ b/drivers/memory/atmel-ebi.c
+@@ -544,20 +544,27 @@ static int atmel_ebi_probe(struct platform_device *pdev)
+ smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
+
+ ebi->smc.regmap = syscon_node_to_regmap(smc_np);
+- if (IS_ERR(ebi->smc.regmap))
+- return PTR_ERR(ebi->smc.regmap);
++ if (IS_ERR(ebi->smc.regmap)) {
++ ret = PTR_ERR(ebi->smc.regmap);
++ goto put_node;
++ }
+
+ ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np);
+- if (IS_ERR(ebi->smc.layout))
+- return PTR_ERR(ebi->smc.layout);
++ if (IS_ERR(ebi->smc.layout)) {
++ ret = PTR_ERR(ebi->smc.layout);
++ goto put_node;
++ }
+
+ ebi->smc.clk = of_clk_get(smc_np, 0);
+ if (IS_ERR(ebi->smc.clk)) {
+- if (PTR_ERR(ebi->smc.clk) != -ENOENT)
+- return PTR_ERR(ebi->smc.clk);
++ if (PTR_ERR(ebi->smc.clk) != -ENOENT) {
++ ret = PTR_ERR(ebi->smc.clk);
++ goto put_node;
++ }
+
+ ebi->smc.clk = NULL;
+ }
++ of_node_put(smc_np);
+ ret = clk_prepare_enable(ebi->smc.clk);
+ if (ret)
+ return ret;
+@@ -608,6 +615,10 @@ static int atmel_ebi_probe(struct platform_device *pdev)
+ }
+
+ return of_platform_populate(np, NULL, NULL, dev);
++
++put_node:
++ of_node_put(smc_np);
++ return ret;
+ }
+
+ static __maybe_unused int atmel_ebi_resume(struct device *dev)
+--
+2.35.1
+
--- /dev/null
+From 06f8c0537362f855acab70e80611e0d725220f03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 10:07:03 +0300
+Subject: mlxsw: i2c: Fix initialization error flow
+
+From: Vadim Pasternak <vadimp@nvidia.com>
+
+[ Upstream commit d452088cdfd5a4ad9d96d847d2273fe958d6339b ]
+
+Add mutex_destroy() call in driver initialization error flow.
+
+Fixes: 6882b0aee180f ("mlxsw: Introduce support for I2C bus")
+Signed-off-by: Vadim Pasternak <vadimp@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://lore.kernel.org/r/20220407070703.2421076-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/i2c.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+index 939b692ffc33..ce843ea91464 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+@@ -650,6 +650,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
+ return 0;
+
+ errout:
++ mutex_destroy(&mlxsw_i2c->cmd.lock);
+ i2c_set_clientdata(client, NULL);
+
+ return err;
+--
+2.35.1
+
--- /dev/null
+From 3c3d498cfa6817808e53a48699956c9f1b4185e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 11:55:56 +0800
+Subject: myri10ge: fix an incorrect free for skb in myri10ge_sw_tso
+
+From: Xiaomeng Tong <xiam0nd.tong@gmail.com>
+
+[ Upstream commit b423e54ba965b4469b48e46fd16941f1e1701697 ]
+
+All remaining skbs should be released when myri10ge_xmit fails to
+transmit a packet. Fix it within another skb_list_walk_safe.
+
+Signed-off-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+index fc99ad8e4a38..1664e9184c9c 100644
+--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+@@ -2895,11 +2895,9 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+ status = myri10ge_xmit(curr, dev);
+ if (status != 0) {
+ dev_kfree_skb_any(curr);
+- if (segs != NULL) {
+- curr = segs;
+- segs = next;
++ skb_list_walk_safe(next, curr, next) {
+ curr->next = NULL;
+- dev_kfree_skb_any(segs);
++ dev_kfree_skb_any(curr);
+ }
+ goto drop;
+ }
+--
+2.35.1
+
--- /dev/null
+From 06d75492d7167275570ad41fba93218492c46efa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 17:19:26 +0800
+Subject: net: axienet: setup mdio unconditionally
+
+From: Andy Chiu <andy.chiu@sifive.com>
+
+[ Upstream commit d1c4f93e3f0a023024a6f022a61528c06cf1daa9 ]
+
+The call to axienet_mdio_setup should not depend on whether "phy-node"
+pressents on the DT. Besides, since `lp->phy_node` is used if PHY is in
+SGMII or 100Base-X modes, move it into the if statement. And the next patch
+will remove `lp->phy_node` from driver's private structure and do an
+of_node_put on it right away after use since it is not used elsewhere.
+
+Signed-off-by: Andy Chiu <andy.chiu@sifive.com>
+Reviewed-by: Greentime Hu <greentime.hu@sifive.com>
+Reviewed-by: Robert Hancock <robert.hancock@calian.com>
+Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+index bbdcba88c021..3d91baf2e55a 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -2060,15 +2060,14 @@ static int axienet_probe(struct platform_device *pdev)
+ if (ret)
+ goto cleanup_clk;
+
+- lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+- if (lp->phy_node) {
+- ret = axienet_mdio_setup(lp);
+- if (ret)
+- dev_warn(&pdev->dev,
+- "error registering MDIO bus: %d\n", ret);
+- }
++ ret = axienet_mdio_setup(lp);
++ if (ret)
++ dev_warn(&pdev->dev,
++ "error registering MDIO bus: %d\n", ret);
++
+ if (lp->phy_mode == PHY_INTERFACE_MODE_SGMII ||
+ lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX) {
++ lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
+ if (!lp->phy_node) {
+ dev_err(&pdev->dev, "phy-handle required for 1000BaseX/SGMII\n");
+ ret = -EINVAL;
+--
+2.35.1
+
--- /dev/null
+From b213e233dccfa53e33e2ac10087a9bc9bdd200dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Apr 2022 16:04:20 -0500
+Subject: net: bcmgenet: Revert "Use stronger register read/writes to assure
+ ordering"
+
+From: Jeremy Linton <jeremy.linton@arm.com>
+
+[ Upstream commit 2df3fc4a84e917a422935cc5bae18f43f9955d31 ]
+
+It turns out after digging deeper into this bug, that it was being
+triggered by GCC12 failing to call the bcmgenet_enable_dma()
+routine. Given that a gcc12 fix has been merged [1] and the genet
+driver now works properly when built with gcc12, this commit should
+be reverted.
+
+[1]
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105160
+https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=aabb9a261ef060cf24fd626713f1d7d9df81aa57
+
+Fixes: 8d3ea3d402db ("net: bcmgenet: Use stronger register read/writes to assure ordering")
+Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Link: https://lore.kernel.org/r/20220412210420.1129430-1-jeremy.linton@arm.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+index 7dcd5613ee56..a2062144d7ca 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -76,7 +76,7 @@ static inline void bcmgenet_writel(u32 value, void __iomem *offset)
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ __raw_writel(value, offset);
+ else
+- writel(value, offset);
++ writel_relaxed(value, offset);
+ }
+
+ static inline u32 bcmgenet_readl(void __iomem *offset)
+@@ -84,7 +84,7 @@ static inline u32 bcmgenet_readl(void __iomem *offset)
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ return __raw_readl(offset);
+ else
+- return readl(offset);
++ return readl_relaxed(offset);
+ }
+
+ static inline void dmadesc_set_length_status(struct bcmgenet_priv *priv,
+--
+2.35.1
+
--- /dev/null
+From ccdd5953a0999a69ca6024d8d14f9db63c875d21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Apr 2022 12:15:21 +0200
+Subject: net: dsa: felix: suppress -EPROBE_DEFER errors
+
+From: Michael Walle <michael@walle.cc>
+
+[ Upstream commit e6934e4048c91502efcb21da92b7ae37cd8fa741 ]
+
+The DSA master might not have been probed yet in which case the probe of
+the felix switch fails with -EPROBE_DEFER:
+[ 4.435305] mscc_felix 0000:00:00.5: Failed to register DSA switch: -517
+
+It is not an error. Use dev_err_probe() to demote this particular error
+to a debug message.
+
+Fixes: 56051948773e ("net: dsa: ocelot: add driver for Felix switch family")
+Signed-off-by: Michael Walle <michael@walle.cc>
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://lore.kernel.org/r/20220408101521.281886-1-michael@walle.cc
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/ocelot/felix_vsc9959.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
+index cd8d9b0e0edb..c96dfc11aa6f 100644
+--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
+@@ -1466,7 +1466,7 @@ static int felix_pci_probe(struct pci_dev *pdev,
+
+ err = dsa_register_switch(ds);
+ if (err) {
+- dev_err(&pdev->dev, "Failed to register DSA switch: %d\n", err);
++ dev_err_probe(&pdev->dev, err, "Failed to register DSA switch\n");
+ goto err_register_ds;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 8fc68b012f94fd109d5f6ceeae5076acc11ca312 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 08:25:21 -0500
+Subject: net: ethernet: stmmac: fix altr_tse_pcs function when using a
+ fixed-link
+
+From: Dinh Nguyen <dinguyen@kernel.org>
+
+[ Upstream commit a6aaa00324240967272b451bfa772547bd576ee6 ]
+
+When using a fixed-link, the altr_tse_pcs driver crashes
+due to null-pointer dereference as no phy_device is provided to
+tse_pcs_fix_mac_speed function. Fix this by adding a check for
+phy_dev before calling the tse_pcs_fix_mac_speed() function.
+
+Also clean up the tse_pcs_fix_mac_speed function a bit. There is
+no need to check for splitter_base and sgmii_adapter_base
+because the driver will fail if these 2 variables are not
+derived from the device tree.
+
+Fixes: fb3bbdb85989 ("net: ethernet: Add TSE PCS support to dwmac-socfpga")
+Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c | 8 --------
+ drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h | 4 ++++
+ drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 13 +++++--------
+ 3 files changed, 9 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+index cd478d2cd871..00f6d347eaf7 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
++++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+@@ -57,10 +57,6 @@
+ #define TSE_PCS_USE_SGMII_ENA BIT(0)
+ #define TSE_PCS_IF_USE_SGMII 0x03
+
+-#define SGMII_ADAPTER_CTRL_REG 0x00
+-#define SGMII_ADAPTER_DISABLE 0x0001
+-#define SGMII_ADAPTER_ENABLE 0x0000
+-
+ #define AUTONEGO_LINK_TIMER 20
+
+ static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs)
+@@ -202,12 +198,8 @@ void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev,
+ unsigned int speed)
+ {
+ void __iomem *tse_pcs_base = pcs->tse_pcs_base;
+- void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
+ u32 val;
+
+- writew(SGMII_ADAPTER_ENABLE,
+- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+-
+ pcs->autoneg = phy_dev->autoneg;
+
+ if (phy_dev->autoneg == AUTONEG_ENABLE) {
+diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+index 442812c0a4bd..694ac25ef426 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
++++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+@@ -10,6 +10,10 @@
+ #include <linux/phy.h>
+ #include <linux/timer.h>
+
++#define SGMII_ADAPTER_CTRL_REG 0x00
++#define SGMII_ADAPTER_ENABLE 0x0000
++#define SGMII_ADAPTER_DISABLE 0x0001
++
+ struct tse_pcs {
+ struct device *dev;
+ void __iomem *tse_pcs_base;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+index f37b6d57b2fe..8bb0106cb7ea 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+@@ -18,9 +18,6 @@
+
+ #include "altr_tse_pcs.h"
+
+-#define SGMII_ADAPTER_CTRL_REG 0x00
+-#define SGMII_ADAPTER_DISABLE 0x0001
+-
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+ #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+@@ -62,16 +59,14 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
+ {
+ struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
+ void __iomem *splitter_base = dwmac->splitter_base;
+- void __iomem *tse_pcs_base = dwmac->pcs.tse_pcs_base;
+ void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
+ struct device *dev = dwmac->dev;
+ struct net_device *ndev = dev_get_drvdata(dev);
+ struct phy_device *phy_dev = ndev->phydev;
+ u32 val;
+
+- if ((tse_pcs_base) && (sgmii_adapter_base))
+- writew(SGMII_ADAPTER_DISABLE,
+- sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
++ writew(SGMII_ADAPTER_DISABLE,
++ sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
+
+ if (splitter_base) {
+ val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG);
+@@ -93,7 +88,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed)
+ writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
+ }
+
+- if (tse_pcs_base && sgmii_adapter_base)
++ writew(SGMII_ADAPTER_ENABLE,
++ sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
++ if (phy_dev)
+ tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 93afc67680963dbea5fef1e39fac4fd5580a97e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Mar 2021 16:19:05 +0530
+Subject: net: mdio: Alphabetically sort header inclusion
+
+From: Calvin Johnson <calvin.johnson@oss.nxp.com>
+
+[ Upstream commit 1bf343665057312167750509b0c48e8299293ac5 ]
+
+Alphabetically sort header inclusion
+
+Signed-off-by: Calvin Johnson <calvin.johnson@oss.nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/mdio/mdio-bcm-unimac.c | 16 +++++++---------
+ drivers/net/mdio/mdio-bitbang.c | 4 ++--
+ drivers/net/mdio/mdio-cavium.c | 2 +-
+ drivers/net/mdio/mdio-gpio.c | 10 +++++-----
+ drivers/net/mdio/mdio-ipq4019.c | 4 ++--
+ drivers/net/mdio/mdio-ipq8064.c | 4 ++--
+ drivers/net/mdio/mdio-mscc-miim.c | 8 ++++----
+ drivers/net/mdio/mdio-mux-bcm-iproc.c | 10 +++++-----
+ drivers/net/mdio/mdio-mux-gpio.c | 8 ++++----
+ drivers/net/mdio/mdio-mux-mmioreg.c | 6 +++---
+ drivers/net/mdio/mdio-mux-multiplexer.c | 2 +-
+ drivers/net/mdio/mdio-mux.c | 6 +++---
+ drivers/net/mdio/mdio-octeon.c | 8 ++++----
+ drivers/net/mdio/mdio-thunder.c | 10 +++++-----
+ drivers/net/mdio/mdio-xgene.c | 6 +++---
+ drivers/net/mdio/of_mdio.c | 10 +++++-----
+ 16 files changed, 56 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/net/mdio/mdio-bcm-unimac.c b/drivers/net/mdio/mdio-bcm-unimac.c
+index fbd36891ee64..5d171e7f118d 100644
+--- a/drivers/net/mdio/mdio-bcm-unimac.c
++++ b/drivers/net/mdio/mdio-bcm-unimac.c
+@@ -5,20 +5,18 @@
+ * Copyright (C) 2014-2017 Broadcom
+ */
+
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/io.h>
+ #include <linux/kernel.h>
+-#include <linux/phy.h>
+-#include <linux/platform_device.h>
+-#include <linux/sched.h>
+ #include <linux/module.h>
+-#include <linux/io.h>
+-#include <linux/delay.h>
+-#include <linux/clk.h>
+-
+ #include <linux/of.h>
+-#include <linux/of_platform.h>
+ #include <linux/of_mdio.h>
+-
++#include <linux/of_platform.h>
++#include <linux/phy.h>
+ #include <linux/platform_data/mdio-bcm-unimac.h>
++#include <linux/platform_device.h>
++#include <linux/sched.h>
+
+ #define MDIO_CMD 0x00
+ #define MDIO_START_BUSY (1 << 29)
+diff --git a/drivers/net/mdio/mdio-bitbang.c b/drivers/net/mdio/mdio-bitbang.c
+index 5136275c8e73..99588192cc78 100644
+--- a/drivers/net/mdio/mdio-bitbang.c
++++ b/drivers/net/mdio/mdio-bitbang.c
+@@ -14,10 +14,10 @@
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ */
+
+-#include <linux/module.h>
++#include <linux/delay.h>
+ #include <linux/mdio-bitbang.h>
++#include <linux/module.h>
+ #include <linux/types.h>
+-#include <linux/delay.h>
+
+ #define MDIO_READ 2
+ #define MDIO_WRITE 1
+diff --git a/drivers/net/mdio/mdio-cavium.c b/drivers/net/mdio/mdio-cavium.c
+index 1afd6fc1a351..95ce274c1be1 100644
+--- a/drivers/net/mdio/mdio-cavium.c
++++ b/drivers/net/mdio/mdio-cavium.c
+@@ -4,9 +4,9 @@
+ */
+
+ #include <linux/delay.h>
++#include <linux/io.h>
+ #include <linux/module.h>
+ #include <linux/phy.h>
+-#include <linux/io.h>
+
+ #include "mdio-cavium.h"
+
+diff --git a/drivers/net/mdio/mdio-gpio.c b/drivers/net/mdio/mdio-gpio.c
+index 1b00235d7dc5..56c8f914f893 100644
+--- a/drivers/net/mdio/mdio-gpio.c
++++ b/drivers/net/mdio/mdio-gpio.c
+@@ -17,15 +17,15 @@
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ */
+
+-#include <linux/module.h>
+-#include <linux/slab.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/interrupt.h>
+-#include <linux/platform_device.h>
+-#include <linux/platform_data/mdio-gpio.h>
+ #include <linux/mdio-bitbang.h>
+ #include <linux/mdio-gpio.h>
+-#include <linux/gpio/consumer.h>
++#include <linux/module.h>
+ #include <linux/of_mdio.h>
++#include <linux/platform_data/mdio-gpio.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
+
+ struct mdio_gpio_info {
+ struct mdiobb_ctrl ctrl;
+diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c
+index 25c25ea6da66..9cd71d896963 100644
+--- a/drivers/net/mdio/mdio-ipq4019.c
++++ b/drivers/net/mdio/mdio-ipq4019.c
+@@ -3,10 +3,10 @@
+ /* Copyright (c) 2020 Sartura Ltd. */
+
+ #include <linux/delay.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_mdio.h>
+ #include <linux/phy.h>
+diff --git a/drivers/net/mdio/mdio-ipq8064.c b/drivers/net/mdio/mdio-ipq8064.c
+index f0a6bfa61645..49d4e9aa30bb 100644
+--- a/drivers/net/mdio/mdio-ipq8064.c
++++ b/drivers/net/mdio/mdio-ipq8064.c
+@@ -7,12 +7,12 @@
+
+ #include <linux/delay.h>
+ #include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+-#include <linux/regmap.h>
+ #include <linux/of_mdio.h>
+ #include <linux/of_address.h>
+ #include <linux/platform_device.h>
+-#include <linux/mfd/syscon.h>
++#include <linux/regmap.h>
+
+ /* MII address register definitions */
+ #define MII_ADDR_REG_ADDR 0x10
+diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c
+index 1c9232fca1e2..037649bef92e 100644
+--- a/drivers/net/mdio/mdio-mscc-miim.c
++++ b/drivers/net/mdio/mdio-mscc-miim.c
+@@ -6,14 +6,14 @@
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/phy.h>
+-#include <linux/platform_device.h>
+ #include <linux/bitops.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+ #include <linux/of_mdio.h>
++#include <linux/phy.h>
++#include <linux/platform_device.h>
+
+ #define MSCC_MIIM_REG_STATUS 0x0
+ #define MSCC_MIIM_STATUS_STAT_PENDING BIT(2)
+diff --git a/drivers/net/mdio/mdio-mux-bcm-iproc.c b/drivers/net/mdio/mdio-mux-bcm-iproc.c
+index 42fb5f166136..641cfa41f492 100644
+--- a/drivers/net/mdio/mdio-mux-bcm-iproc.c
++++ b/drivers/net/mdio/mdio-mux-bcm-iproc.c
+@@ -3,14 +3,14 @@
+ * Copyright 2016 Broadcom
+ */
+ #include <linux/clk.h>
+-#include <linux/platform_device.h>
++#include <linux/delay.h>
+ #include <linux/device.h>
+-#include <linux/of_mdio.h>
++#include <linux/iopoll.h>
++#include <linux/mdio-mux.h>
+ #include <linux/module.h>
++#include <linux/of_mdio.h>
+ #include <linux/phy.h>
+-#include <linux/mdio-mux.h>
+-#include <linux/delay.h>
+-#include <linux/iopoll.h>
++#include <linux/platform_device.h>
+
+ #define MDIO_RATE_ADJ_EXT_OFFSET 0x000
+ #define MDIO_RATE_ADJ_INT_OFFSET 0x004
+diff --git a/drivers/net/mdio/mdio-mux-gpio.c b/drivers/net/mdio/mdio-mux-gpio.c
+index 10a758fdc9e6..3c7f16f06b45 100644
+--- a/drivers/net/mdio/mdio-mux-gpio.c
++++ b/drivers/net/mdio/mdio-mux-gpio.c
+@@ -3,13 +3,13 @@
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+-#include <linux/platform_device.h>
+ #include <linux/device.h>
+-#include <linux/of_mdio.h>
++#include <linux/gpio/consumer.h>
++#include <linux/mdio-mux.h>
+ #include <linux/module.h>
++#include <linux/of_mdio.h>
+ #include <linux/phy.h>
+-#include <linux/mdio-mux.h>
+-#include <linux/gpio/consumer.h>
++#include <linux/platform_device.h>
+
+ #define DRV_VERSION "1.1"
+ #define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
+diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c
+index d1a8780e24d8..c02fb2a067ee 100644
+--- a/drivers/net/mdio/mdio-mux-mmioreg.c
++++ b/drivers/net/mdio/mdio-mux-mmioreg.c
+@@ -7,13 +7,13 @@
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ */
+
+-#include <linux/platform_device.h>
+ #include <linux/device.h>
++#include <linux/mdio-mux.h>
++#include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_mdio.h>
+-#include <linux/module.h>
+ #include <linux/phy.h>
+-#include <linux/mdio-mux.h>
++#include <linux/platform_device.h>
+
+ struct mdio_mux_mmioreg_state {
+ void *mux_handle;
+diff --git a/drivers/net/mdio/mdio-mux-multiplexer.c b/drivers/net/mdio/mdio-mux-multiplexer.c
+index d6564381aa3e..527acfc3c045 100644
+--- a/drivers/net/mdio/mdio-mux-multiplexer.c
++++ b/drivers/net/mdio/mdio-mux-multiplexer.c
+@@ -4,10 +4,10 @@
+ * Copyright 2019 NXP
+ */
+
+-#include <linux/platform_device.h>
+ #include <linux/mdio-mux.h>
+ #include <linux/module.h>
+ #include <linux/mux/consumer.h>
++#include <linux/platform_device.h>
+
+ struct mdio_mux_multiplexer_state {
+ struct mux_control *muxc;
+diff --git a/drivers/net/mdio/mdio-mux.c b/drivers/net/mdio/mdio-mux.c
+index ccb3ee704eb1..3dde0c2b3e09 100644
+--- a/drivers/net/mdio/mdio-mux.c
++++ b/drivers/net/mdio/mdio-mux.c
+@@ -3,12 +3,12 @@
+ * Copyright (C) 2011, 2012 Cavium, Inc.
+ */
+
+-#include <linux/platform_device.h>
+-#include <linux/mdio-mux.h>
+-#include <linux/of_mdio.h>
+ #include <linux/device.h>
++#include <linux/mdio-mux.h>
+ #include <linux/module.h>
++#include <linux/of_mdio.h>
+ #include <linux/phy.h>
++#include <linux/platform_device.h>
+
+ #define DRV_DESCRIPTION "MDIO bus multiplexer driver"
+
+diff --git a/drivers/net/mdio/mdio-octeon.c b/drivers/net/mdio/mdio-octeon.c
+index 6faf39314ac9..e096e68ac667 100644
+--- a/drivers/net/mdio/mdio-octeon.c
++++ b/drivers/net/mdio/mdio-octeon.c
+@@ -3,13 +3,13 @@
+ * Copyright (C) 2009-2015 Cavium, Inc.
+ */
+
+-#include <linux/platform_device.h>
++#include <linux/gfp.h>
++#include <linux/io.h>
++#include <linux/module.h>
+ #include <linux/of_address.h>
+ #include <linux/of_mdio.h>
+-#include <linux/module.h>
+-#include <linux/gfp.h>
+ #include <linux/phy.h>
+-#include <linux/io.h>
++#include <linux/platform_device.h>
+
+ #include "mdio-cavium.h"
+
+diff --git a/drivers/net/mdio/mdio-thunder.c b/drivers/net/mdio/mdio-thunder.c
+index dd7430c998a2..822d2cdd2f35 100644
+--- a/drivers/net/mdio/mdio-thunder.c
++++ b/drivers/net/mdio/mdio-thunder.c
+@@ -3,14 +3,14 @@
+ * Copyright (C) 2009-2016 Cavium, Inc.
+ */
+
+-#include <linux/of_address.h>
+-#include <linux/of_mdio.h>
+-#include <linux/module.h>
++#include <linux/acpi.h>
+ #include <linux/gfp.h>
+-#include <linux/phy.h>
+ #include <linux/io.h>
+-#include <linux/acpi.h>
++#include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_mdio.h>
+ #include <linux/pci.h>
++#include <linux/phy.h>
+
+ #include "mdio-cavium.h"
+
+diff --git a/drivers/net/mdio/mdio-xgene.c b/drivers/net/mdio/mdio-xgene.c
+index 461207cdf5d6..7ab4e26db08c 100644
+--- a/drivers/net/mdio/mdio-xgene.c
++++ b/drivers/net/mdio/mdio-xgene.c
+@@ -13,11 +13,11 @@
+ #include <linux/io.h>
+ #include <linux/mdio/mdio-xgene.h>
+ #include <linux/module.h>
+-#include <linux/of_platform.h>
+-#include <linux/of_net.h>
+ #include <linux/of_mdio.h>
+-#include <linux/prefetch.h>
++#include <linux/of_net.h>
++#include <linux/of_platform.h>
+ #include <linux/phy.h>
++#include <linux/prefetch.h>
+ #include <net/ip.h>
+
+ static bool xgene_mdio_status;
+diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
+index 4daf94bb56a5..ea0bf13e8ac3 100644
+--- a/drivers/net/mdio/of_mdio.c
++++ b/drivers/net/mdio/of_mdio.c
+@@ -8,17 +8,17 @@
+ * out of the OpenFirmware device tree and using it to populate an mii_bus.
+ */
+
+-#include <linux/kernel.h>
+ #include <linux/device.h>
+-#include <linux/netdevice.h>
+ #include <linux/err.h>
+-#include <linux/phy.h>
+-#include <linux/phy_fixed.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/netdevice.h>
+ #include <linux/of.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_mdio.h>
+ #include <linux/of_net.h>
+-#include <linux/module.h>
++#include <linux/phy.h>
++#include <linux/phy_fixed.h>
+
+ #define DEFAULT_GPIO_RESET_DELAY 10 /* in microseconds */
+
+--
+2.35.1
+
--- /dev/null
+From bed07730c64ea1cae21c77b1ead4602ced0c24cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Mar 2022 22:42:44 -0700
+Subject: net: micrel: fix KS8851_MLL Kconfig
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit c3efcedd272aa6dd5929e20cf902a52ddaa1197a ]
+
+KS8851_MLL selects MICREL_PHY, which depends on PTP_1588_CLOCK_OPTIONAL,
+so make KS8851_MLL also depend on PTP_1588_CLOCK_OPTIONAL since
+'select' does not follow any dependency chains.
+
+Fixes kconfig warning and build errors:
+
+WARNING: unmet direct dependencies detected for MICREL_PHY
+ Depends on [m]: NETDEVICES [=y] && PHYLIB [=y] && PTP_1588_CLOCK_OPTIONAL [=m]
+ Selected by [y]:
+ - KS8851_MLL [=y] && NETDEVICES [=y] && ETHERNET [=y] && NET_VENDOR_MICREL [=y] && HAS_IOMEM [=y]
+
+ld: drivers/net/phy/micrel.o: in function `lan8814_ts_info':
+micrel.c:(.text+0xb35): undefined reference to `ptp_clock_index'
+ld: drivers/net/phy/micrel.o: in function `lan8814_probe':
+micrel.c:(.text+0x2586): undefined reference to `ptp_clock_register'
+
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/micrel/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/micrel/Kconfig b/drivers/net/ethernet/micrel/Kconfig
+index 42bc014136fe..9ceb7e1fb169 100644
+--- a/drivers/net/ethernet/micrel/Kconfig
++++ b/drivers/net/ethernet/micrel/Kconfig
+@@ -37,6 +37,7 @@ config KS8851
+ config KS8851_MLL
+ tristate "Micrel KS8851 MLL"
+ depends on HAS_IOMEM
++ depends on PTP_1588_CLOCK_OPTIONAL
+ select MII
+ select CRC32
+ select EEPROM_93CX6
+--
+2.35.1
+
--- /dev/null
+From 215bed702d6aff9372e509bd280aeb0313ef1a48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 11:29:23 -0300
+Subject: net/sched: fix initialization order when updating chain 0 head
+
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+
+[ Upstream commit e65812fd22eba32f11abe28cb377cbd64cfb1ba0 ]
+
+Currently, when inserting a new filter that needs to sit at the head
+of chain 0, it will first update the heads pointer on all devices using
+the (shared) block, and only then complete the initialization of the new
+element so that it has a "next" element.
+
+This can lead to a situation that the chain 0 head is propagated to
+another CPU before the "next" initialization is done. When this race
+condition is triggered, packets being matched on that CPU will simply
+miss all other filters, and will flow through the stack as if there were
+no other filters installed. If the system is using OVS + TC, such
+packets will get handled by vswitchd via upcall, which results in much
+higher latency and reordering. For other applications it may result in
+packet drops.
+
+This is reproducible with a tc only setup, but it varies from system to
+system. It could be reproduced with a shared block amongst 10 veth
+tunnels, and an ingress filter mirroring packets to another veth.
+That's because using the last added veth tunnel to the shared block to
+do the actual traffic, it makes the race window bigger and easier to
+trigger.
+
+The fix is rather simple, to just initialize the next pointer of the new
+filter instance (tp) before propagating the head change.
+
+The fixes tag is pointing to the original code though this issue should
+only be observed when using it unlocked.
+
+Fixes: 2190d1d0944f ("net: sched: introduce helpers to work with filter chains")
+Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
+Reviewed-by: Davide Caratti <dcaratti@redhat.com>
+Link: https://lore.kernel.org/r/b97d5f4eaffeeb9d058155bcab63347527261abf.1649341369.git.marcelo.leitner@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/cls_api.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index 9a789a057a74..b8ffb7e4f696 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -1656,10 +1656,10 @@ static int tcf_chain_tp_insert(struct tcf_chain *chain,
+ if (chain->flushing)
+ return -EAGAIN;
+
++ RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info));
+ if (*chain_info->pprev == chain->filter_chain)
+ tcf_chain0_head_change(chain, tp);
+ tcf_proto_get(tp);
+- RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info));
+ rcu_assign_pointer(*chain_info->pprev, tp);
+
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From d84c20e49cafa084a87c45d7a85d3bb093bfba3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 14:22:41 +0300
+Subject: net/sched: flower: fix parsing of ethertype following VLAN header
+
+From: Vlad Buslov <vladbu@nvidia.com>
+
+[ Upstream commit 2105f700b53c24aa48b65c15652acc386044d26a ]
+
+A tc flower filter matching TCA_FLOWER_KEY_VLAN_ETH_TYPE is expected to
+match the L2 ethertype following the first VLAN header, as confirmed by
+linked discussion with the maintainer. However, such rule also matches
+packets that have additional second VLAN header, even though filter has
+both eth_type and vlan_ethtype set to "ipv4". Looking at the code this
+seems to be mostly an artifact of the way flower uses flow dissector.
+First, even though looking at the uAPI eth_type and vlan_ethtype appear
+like a distinct fields, in flower they are all mapped to the same
+key->basic.n_proto. Second, flow dissector skips following VLAN header as
+no keys for FLOW_DISSECTOR_KEY_CVLAN are set and eventually assigns the
+value of n_proto to last parsed header. With these, such filters ignore any
+headers present between first VLAN header and first "non magic"
+header (ipv4 in this case) that doesn't result
+FLOW_DISSECT_RET_PROTO_AGAIN.
+
+Fix the issue by extending flow dissector VLAN key structure with new
+'vlan_eth_type' field that matches first ethertype following previously
+parsed VLAN header. Modify flower classifier to set the new
+flow_dissector_key_vlan->vlan_eth_type with value obtained from
+TCA_FLOWER_KEY_VLAN_ETH_TYPE/TCA_FLOWER_KEY_CVLAN_ETH_TYPE uAPIs.
+
+Link: https://lore.kernel.org/all/Yjhgi48BpTGh6dig@nanopsycho/
+Fixes: 9399ae9a6cb2 ("net_sched: flower: Add vlan support")
+Fixes: d64efd0926ba ("net/sched: flower: Add supprt for matching on QinQ vlan headers")
+Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/flow_dissector.h | 2 ++
+ net/core/flow_dissector.c | 1 +
+ net/sched/cls_flower.c | 18 +++++++++++++-----
+ 3 files changed, 16 insertions(+), 5 deletions(-)
+
+diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
+index cc10b10dc3a1..5eecf4436965 100644
+--- a/include/net/flow_dissector.h
++++ b/include/net/flow_dissector.h
+@@ -59,6 +59,8 @@ struct flow_dissector_key_vlan {
+ __be16 vlan_tci;
+ };
+ __be16 vlan_tpid;
++ __be16 vlan_eth_type;
++ u16 padding;
+ };
+
+ struct flow_dissector_mpls_lse {
+diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
+index 813c709c61cf..f9baa9b1c77f 100644
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -1171,6 +1171,7 @@ bool __skb_flow_dissect(const struct net *net,
+ VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ }
+ key_vlan->vlan_tpid = saved_vlan_tpid;
++ key_vlan->vlan_eth_type = proto;
+ }
+
+ fdret = FLOW_DISSECT_RET_PROTO_AGAIN;
+diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
+index 8ff6945b9f8f..35ee6d8226e6 100644
+--- a/net/sched/cls_flower.c
++++ b/net/sched/cls_flower.c
+@@ -998,6 +998,7 @@ static int fl_set_key_mpls(struct nlattr **tb,
+ static void fl_set_key_vlan(struct nlattr **tb,
+ __be16 ethertype,
+ int vlan_id_key, int vlan_prio_key,
++ int vlan_next_eth_type_key,
+ struct flow_dissector_key_vlan *key_val,
+ struct flow_dissector_key_vlan *key_mask)
+ {
+@@ -1016,6 +1017,11 @@ static void fl_set_key_vlan(struct nlattr **tb,
+ }
+ key_val->vlan_tpid = ethertype;
+ key_mask->vlan_tpid = cpu_to_be16(~0);
++ if (tb[vlan_next_eth_type_key]) {
++ key_val->vlan_eth_type =
++ nla_get_be16(tb[vlan_next_eth_type_key]);
++ key_mask->vlan_eth_type = cpu_to_be16(~0);
++ }
+ }
+
+ static void fl_set_key_flag(u32 flower_key, u32 flower_mask,
+@@ -1497,8 +1503,9 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
+
+ if (eth_type_vlan(ethertype)) {
+ fl_set_key_vlan(tb, ethertype, TCA_FLOWER_KEY_VLAN_ID,
+- TCA_FLOWER_KEY_VLAN_PRIO, &key->vlan,
+- &mask->vlan);
++ TCA_FLOWER_KEY_VLAN_PRIO,
++ TCA_FLOWER_KEY_VLAN_ETH_TYPE,
++ &key->vlan, &mask->vlan);
+
+ if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
+ ethertype = nla_get_be16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
+@@ -1506,6 +1513,7 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
+ fl_set_key_vlan(tb, ethertype,
+ TCA_FLOWER_KEY_CVLAN_ID,
+ TCA_FLOWER_KEY_CVLAN_PRIO,
++ TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+ &key->cvlan, &mask->cvlan);
+ fl_set_key_val(tb, &key->basic.n_proto,
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+@@ -2861,13 +2869,13 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
+ goto nla_put_failure;
+
+ if (mask->basic.n_proto) {
+- if (mask->cvlan.vlan_tpid) {
++ if (mask->cvlan.vlan_eth_type) {
+ if (nla_put_be16(skb, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+ key->basic.n_proto))
+ goto nla_put_failure;
+- } else if (mask->vlan.vlan_tpid) {
++ } else if (mask->vlan.vlan_eth_type) {
+ if (nla_put_be16(skb, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
+- key->basic.n_proto))
++ key->vlan.vlan_eth_type))
+ goto nla_put_failure;
+ }
+ }
+--
+2.35.1
+
--- /dev/null
+From 356b35c11017168301dec7340002b5228c8c58bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Apr 2022 11:47:45 +0200
+Subject: net/sched: taprio: Check if socket flags are valid
+
+From: Benedikt Spranger <b.spranger@linutronix.de>
+
+[ Upstream commit e8a64bbaaad1f6548cec5508297bc6d45e8ab69e ]
+
+A user may set the SO_TXTIME socket option to ensure a packet is send
+at a given time. The taprio scheduler has to confirm, that it is allowed
+to send a packet at that given time, by a check against the packet time
+schedule. The scheduler drop the packet, if the gates are closed at the
+given send time.
+
+The check, if SO_TXTIME is set, may fail since sk_flags are part of an
+union and the union is used otherwise. This happen, if a socket is not
+a full socket, like a request socket for example.
+
+Add a check to verify, if the union is used for sk_flags.
+
+Fixes: 4cfd5779bd6e ("taprio: Add support for txtime-assist mode")
+Signed-off-by: Benedikt Spranger <b.spranger@linutronix.de>
+Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de>
+Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_taprio.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
+index 806babdd838d..eca525791013 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -427,7 +427,8 @@ static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ if (unlikely(!child))
+ return qdisc_drop(skb, sch, to_free);
+
+- if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
++ /* sk_flags are only safe to use on full sockets. */
++ if (skb->sk && sk_fullsock(skb->sk) && sock_flag(skb->sk, SOCK_TXTIME)) {
+ if (!is_valid_interval(skb, sch))
+ return qdisc_drop(skb, sch, to_free);
+ } else if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
+--
+2.35.1
+
--- /dev/null
+From 31aa101b67807f16adc2dd14ce454da2050ee7d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Apr 2022 17:10:34 +0200
+Subject: net/smc: Fix NULL pointer dereference in smc_pnet_find_ib()
+
+From: Karsten Graul <kgraul@linux.ibm.com>
+
+[ Upstream commit d22f4f977236f97e01255a80bca2ea93a8094fc8 ]
+
+dev_name() was called with dev.parent as argument but without to
+NULL-check it before.
+Solve this by checking the pointer before the call to dev_name().
+
+Fixes: af5f60c7e3d5 ("net/smc: allow PCI IDs as ib device names in the pnet table")
+Reported-by: syzbot+03e3e228510223dabd34@syzkaller.appspotmail.com
+Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_pnet.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
+index 9007c7e3bae4..30bae60d626c 100644
+--- a/net/smc/smc_pnet.c
++++ b/net/smc/smc_pnet.c
+@@ -310,8 +310,9 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
+ list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
+ if (!strncmp(ibdev->ibdev->name, ib_name,
+ sizeof(ibdev->ibdev->name)) ||
+- !strncmp(dev_name(ibdev->ibdev->dev.parent), ib_name,
+- IB_DEVICE_NAME_MAX - 1)) {
++ (ibdev->ibdev->dev.parent &&
++ !strncmp(dev_name(ibdev->ibdev->dev.parent), ib_name,
++ IB_DEVICE_NAME_MAX - 1))) {
+ goto out;
+ }
+ }
+--
+2.35.1
+
--- /dev/null
+From 9ebfb7683814aebda14cc70d067bd2691054887a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 10:05:37 +0200
+Subject: net: usb: aqc111: Fix out-of-bounds accesses in RX fixup
+
+From: Marcin Kozlowski <marcinguy@gmail.com>
+
+[ Upstream commit afb8e246527536848b9b4025b40e613edf776a9d ]
+
+aqc111_rx_fixup() contains several out-of-bounds accesses that can be
+triggered by a malicious (or defective) USB device, in particular:
+
+ - The metadata array (desc_offset..desc_offset+2*pkt_count) can be out of bounds,
+ causing OOB reads and (on big-endian systems) OOB endianness flips.
+ - A packet can overlap the metadata array, causing a later OOB
+ endianness flip to corrupt data used by a cloned SKB that has already
+ been handed off into the network stack.
+ - A packet SKB can be constructed whose tail is far beyond its end,
+ causing out-of-bounds heap data to be considered part of the SKB's
+ data.
+
+Found doing variant analysis. Tested it with another driver (ax88179_178a), since
+I don't have a aqc111 device to test it, but the code looks very similar.
+
+Signed-off-by: Marcin Kozlowski <marcinguy@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/aqc111.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
+index 0717c18015c9..c9c409518174 100644
+--- a/drivers/net/usb/aqc111.c
++++ b/drivers/net/usb/aqc111.c
+@@ -1102,10 +1102,15 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ if (start_of_descs != desc_offset)
+ goto err;
+
+- /* self check desc_offset from header*/
+- if (desc_offset >= skb_len)
++ /* self check desc_offset from header and make sure that the
++ * bounds of the metadata array are inside the SKB
++ */
++ if (pkt_count * 2 + desc_offset >= skb_len)
+ goto err;
+
++ /* Packets must not overlap the metadata array */
++ skb_trim(skb, desc_offset);
++
+ if (pkt_count == 0)
+ goto err;
+
+--
+2.35.1
+
--- /dev/null
+From cd7238de8779b4c8d8933d0524e7e30c650b68c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Apr 2022 00:04:30 +0800
+Subject: nfc: nci: add flush_workqueue to prevent uaf
+
+From: Lin Ma <linma@zju.edu.cn>
+
+[ Upstream commit ef27324e2cb7bb24542d6cb2571740eefe6b00dc ]
+
+Our detector found a concurrent use-after-free bug when detaching an
+NCI device. The main reason for this bug is the unexpected scheduling
+between the used delayed mechanism (timer and workqueue).
+
+The race can be demonstrated below:
+
+Thread-1 Thread-2
+ | nci_dev_up()
+ | nci_open_device()
+ | __nci_request(nci_reset_req)
+ | nci_send_cmd
+ | queue_work(cmd_work)
+nci_unregister_device() |
+ nci_close_device() | ...
+ del_timer_sync(cmd_timer)[1] |
+... | Worker
+nci_free_device() | nci_cmd_work()
+ kfree(ndev)[3] | mod_timer(cmd_timer)[2]
+
+In short, the cleanup routine thought that the cmd_timer has already
+been detached by [1] but the mod_timer can re-attach the timer [2], even
+it is already released [3], resulting in UAF.
+
+This UAF is easy to trigger, crash trace by POC is like below
+
+[ 66.703713] ==================================================================
+[ 66.703974] BUG: KASAN: use-after-free in enqueue_timer+0x448/0x490
+[ 66.703974] Write of size 8 at addr ffff888009fb7058 by task kworker/u4:1/33
+[ 66.703974]
+[ 66.703974] CPU: 1 PID: 33 Comm: kworker/u4:1 Not tainted 5.18.0-rc2 #5
+[ 66.703974] Workqueue: nfc2_nci_cmd_wq nci_cmd_work
+[ 66.703974] Call Trace:
+[ 66.703974] <TASK>
+[ 66.703974] dump_stack_lvl+0x57/0x7d
+[ 66.703974] print_report.cold+0x5e/0x5db
+[ 66.703974] ? enqueue_timer+0x448/0x490
+[ 66.703974] kasan_report+0xbe/0x1c0
+[ 66.703974] ? enqueue_timer+0x448/0x490
+[ 66.703974] enqueue_timer+0x448/0x490
+[ 66.703974] __mod_timer+0x5e6/0xb80
+[ 66.703974] ? mark_held_locks+0x9e/0xe0
+[ 66.703974] ? try_to_del_timer_sync+0xf0/0xf0
+[ 66.703974] ? lockdep_hardirqs_on_prepare+0x17b/0x410
+[ 66.703974] ? queue_work_on+0x61/0x80
+[ 66.703974] ? lockdep_hardirqs_on+0xbf/0x130
+[ 66.703974] process_one_work+0x8bb/0x1510
+[ 66.703974] ? lockdep_hardirqs_on_prepare+0x410/0x410
+[ 66.703974] ? pwq_dec_nr_in_flight+0x230/0x230
+[ 66.703974] ? rwlock_bug.part.0+0x90/0x90
+[ 66.703974] ? _raw_spin_lock_irq+0x41/0x50
+[ 66.703974] worker_thread+0x575/0x1190
+[ 66.703974] ? process_one_work+0x1510/0x1510
+[ 66.703974] kthread+0x2a0/0x340
+[ 66.703974] ? kthread_complete_and_exit+0x20/0x20
+[ 66.703974] ret_from_fork+0x22/0x30
+[ 66.703974] </TASK>
+[ 66.703974]
+[ 66.703974] Allocated by task 267:
+[ 66.703974] kasan_save_stack+0x1e/0x40
+[ 66.703974] __kasan_kmalloc+0x81/0xa0
+[ 66.703974] nci_allocate_device+0xd3/0x390
+[ 66.703974] nfcmrvl_nci_register_dev+0x183/0x2c0
+[ 66.703974] nfcmrvl_nci_uart_open+0xf2/0x1dd
+[ 66.703974] nci_uart_tty_ioctl+0x2c3/0x4a0
+[ 66.703974] tty_ioctl+0x764/0x1310
+[ 66.703974] __x64_sys_ioctl+0x122/0x190
+[ 66.703974] do_syscall_64+0x3b/0x90
+[ 66.703974] entry_SYSCALL_64_after_hwframe+0x44/0xae
+[ 66.703974]
+[ 66.703974] Freed by task 406:
+[ 66.703974] kasan_save_stack+0x1e/0x40
+[ 66.703974] kasan_set_track+0x21/0x30
+[ 66.703974] kasan_set_free_info+0x20/0x30
+[ 66.703974] __kasan_slab_free+0x108/0x170
+[ 66.703974] kfree+0xb0/0x330
+[ 66.703974] nfcmrvl_nci_unregister_dev+0x90/0xd0
+[ 66.703974] nci_uart_tty_close+0xdf/0x180
+[ 66.703974] tty_ldisc_kill+0x73/0x110
+[ 66.703974] tty_ldisc_hangup+0x281/0x5b0
+[ 66.703974] __tty_hangup.part.0+0x431/0x890
+[ 66.703974] tty_release+0x3a8/0xc80
+[ 66.703974] __fput+0x1f0/0x8c0
+[ 66.703974] task_work_run+0xc9/0x170
+[ 66.703974] exit_to_user_mode_prepare+0x194/0x1a0
+[ 66.703974] syscall_exit_to_user_mode+0x19/0x50
+[ 66.703974] do_syscall_64+0x48/0x90
+[ 66.703974] entry_SYSCALL_64_after_hwframe+0x44/0xae
+
+To fix the UAF, this patch adds flush_workqueue() to ensure the
+nci_cmd_work is finished before the following del_timer_sync.
+This combination will promise the timer is actually detached.
+
+Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
+Signed-off-by: Lin Ma <linma@zju.edu.cn>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/nci/core.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index e38719e2ee58..2cfff70f70e0 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -548,6 +548,10 @@ static int nci_close_device(struct nci_dev *ndev)
+ mutex_lock(&ndev->req_lock);
+
+ if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
++ /* Need to flush the cmd wq in case
++ * there is a queued/running cmd_work
++ */
++ flush_workqueue(ndev->cmd_wq);
+ del_timer_sync(&ndev->cmd_timer);
+ del_timer_sync(&ndev->data_timer);
+ mutex_unlock(&ndev->req_lock);
+--
+2.35.1
+
--- /dev/null
+From 4cb69b7c054cd830ff440e611bebadee21ba55c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Apr 2022 17:15:15 +0200
+Subject: perf/imx_ddr: Fix undefined behavior due to shift overflowing the
+ constant
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Borislav Petkov <bp@suse.de>
+
+[ Upstream commit d02b4dd84e1a90f7f1444d027c0289bf355b0d5a ]
+
+Fix:
+
+ In file included from <command-line>:0:0:
+ In function ‘ddr_perf_counter_enable’,
+ inlined from ‘ddr_perf_irq_handler’ at drivers/perf/fsl_imx8_ddr_perf.c:651:2:
+ ././include/linux/compiler_types.h:352:38: error: call to ‘__compiletime_assert_729’ \
+ declared with attribute error: FIELD_PREP: mask is not constant
+ _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
+...
+
+See https://lore.kernel.org/r/YkwQ6%2BtIH8GQpuct@zn.tnic for the gory
+details as to why it triggers with older gccs only.
+
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Cc: Frank Li <Frank.li@nxp.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Shawn Guo <shawnguo@kernel.org>
+Cc: Sascha Hauer <s.hauer@pengutronix.de>
+Cc: Pengutronix Kernel Team <kernel@pengutronix.de>
+Cc: Fabio Estevam <festevam@gmail.com>
+Cc: NXP Linux Team <linux-imx@nxp.com>
+Cc: linux-arm-kernel@lists.infradead.org
+Acked-by: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20220405151517.29753-10-bp@alien8.de
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/fsl_imx8_ddr_perf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
+index 7f7bc0993670..e09bbf3890c4 100644
+--- a/drivers/perf/fsl_imx8_ddr_perf.c
++++ b/drivers/perf/fsl_imx8_ddr_perf.c
+@@ -29,7 +29,7 @@
+ #define CNTL_OVER_MASK 0xFFFFFFFE
+
+ #define CNTL_CSV_SHIFT 24
+-#define CNTL_CSV_MASK (0xFF << CNTL_CSV_SHIFT)
++#define CNTL_CSV_MASK (0xFFU << CNTL_CSV_SHIFT)
+
+ #define EVENT_CYCLES_ID 0
+ #define EVENT_CYCLES_COUNTER 0
+--
+2.35.1
+
--- /dev/null
+From 256b124427c0230feac1dda4e7578624994dd893 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 09:17:58 +0300
+Subject: perf tools: Fix misleading add event PMU debug message
+
+From: Adrian Hunter <adrian.hunter@intel.com>
+
+[ Upstream commit f034fc50d3c7d9385c20d505ab4cf56b8fd18ac7 ]
+
+Fix incorrect debug message:
+
+ Attempting to add event pmu 'intel_pt' with '' that may result in
+ non-fatal errors
+
+which always appears with perf record -vv and intel_pt e.g.
+
+ perf record -vv -e intel_pt//u uname
+
+The message is incorrect because there will never be non-fatal errors.
+
+Suppress the message if the PMU is 'selectable' i.e. meant to be
+selected directly as an event.
+
+Fixes: 4ac22b484d4c79e8 ("perf parse-events: Make add PMU verbose output clearer")
+Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Link: http://lore.kernel.org/lkml/20220411061758.2458417-1-adrian.hunter@intel.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/util/parse-events.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
+index 3b273580fb84..3a0a7930cd10 100644
+--- a/tools/perf/util/parse-events.c
++++ b/tools/perf/util/parse-events.c
+@@ -1442,7 +1442,9 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
+ bool use_uncore_alias;
+ LIST_HEAD(config_terms);
+
+- if (verbose > 1) {
++ pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
++
++ if (verbose > 1 && !(pmu && pmu->selectable)) {
+ fprintf(stderr, "Attempting to add event pmu '%s' with '",
+ name);
+ if (head_config) {
+@@ -1455,7 +1457,6 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
+ fprintf(stderr, "' that may result in non-fatal errors\n");
+ }
+
+- pmu = parse_state->fake_pmu ?: perf_pmu__find(name);
+ if (!pmu) {
+ char *err_str;
+
+--
+2.35.1
+
--- /dev/null
+From 05a56857996d360935d17d68241b80f07bb9594e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Mar 2022 18:01:54 -0700
+Subject: regulator: wm8994: Add an off-on delay for WM8994 variant
+
+From: Jonathan Bakker <xc-racer2@live.ca>
+
+[ Upstream commit 92d96b603738ec4f35cde7198c303ae264dd47cb ]
+
+As per Table 130 of the wm8994 datasheet at [1], there is an off-on
+delay for LDO1 and LDO2. In the wm8958 datasheet [2], I could not
+find any reference to it. I could not find a wm1811 datasheet to
+double-check there, but as no one has complained presumably it works
+without it.
+
+This solves the issue on Samsung Aries boards with a wm8994 where
+register writes fail when the device is powered off and back-on
+quickly.
+
+[1] https://statics.cirrus.com/pubs/proDatasheet/WM8994_Rev4.6.pdf
+[2] https://statics.cirrus.com/pubs/proDatasheet/WM8958_v3.5.pdf
+
+Signed-off-by: Jonathan Bakker <xc-racer2@live.ca>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/CY4PR04MB056771CFB80DC447C30D5A31CB1D9@CY4PR04MB0567.namprd04.prod.outlook.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/wm8994-regulator.c | 42 ++++++++++++++++++++++++++--
+ 1 file changed, 39 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c
+index cadea0344486..40befdd9dfa9 100644
+--- a/drivers/regulator/wm8994-regulator.c
++++ b/drivers/regulator/wm8994-regulator.c
+@@ -71,6 +71,35 @@ static const struct regulator_ops wm8994_ldo2_ops = {
+ };
+
+ static const struct regulator_desc wm8994_ldo_desc[] = {
++ {
++ .name = "LDO1",
++ .id = 1,
++ .type = REGULATOR_VOLTAGE,
++ .n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
++ .vsel_reg = WM8994_LDO_1,
++ .vsel_mask = WM8994_LDO1_VSEL_MASK,
++ .ops = &wm8994_ldo1_ops,
++ .min_uV = 2400000,
++ .uV_step = 100000,
++ .enable_time = 3000,
++ .off_on_delay = 36000,
++ .owner = THIS_MODULE,
++ },
++ {
++ .name = "LDO2",
++ .id = 2,
++ .type = REGULATOR_VOLTAGE,
++ .n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
++ .vsel_reg = WM8994_LDO_2,
++ .vsel_mask = WM8994_LDO2_VSEL_MASK,
++ .ops = &wm8994_ldo2_ops,
++ .enable_time = 3000,
++ .off_on_delay = 36000,
++ .owner = THIS_MODULE,
++ },
++};
++
++static const struct regulator_desc wm8958_ldo_desc[] = {
+ {
+ .name = "LDO1",
+ .id = 1,
+@@ -172,9 +201,16 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
+ * regulator core and we need not worry about it on the
+ * error path.
+ */
+- ldo->regulator = devm_regulator_register(&pdev->dev,
+- &wm8994_ldo_desc[id],
+- &config);
++ if (ldo->wm8994->type == WM8994) {
++ ldo->regulator = devm_regulator_register(&pdev->dev,
++ &wm8994_ldo_desc[id],
++ &config);
++ } else {
++ ldo->regulator = devm_regulator_register(&pdev->dev,
++ &wm8958_ldo_desc[id],
++ &config);
++ }
++
+ if (IS_ERR(ldo->regulator)) {
+ ret = PTR_ERR(ldo->regulator);
+ dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
+--
+2.35.1
+
--- /dev/null
+From 44e3e3c8f067cd8dbc18525b1512aa9b211ae605 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Mar 2022 12:44:43 -0700
+Subject: scsi: ibmvscsis: Increase INITIAL_SRP_LIMIT to 1024
+
+From: Tyrel Datwyler <tyreld@linux.ibm.com>
+
+[ Upstream commit 0bade8e53279157c7cc9dd95d573b7e82223d78a ]
+
+The adapter request_limit is hardcoded to be INITIAL_SRP_LIMIT which is
+currently an arbitrary value of 800. Increase this value to 1024 which
+better matches the characteristics of the typical IBMi Initiator that
+supports 32 LUNs and a queue depth of 32.
+
+This change also has the secondary benefit of being a power of two as
+required by the kfifo API. Since, Commit ab9bb6318b09 ("Partially revert
+"kfifo: fix kfifo_alloc() and kfifo_init()"") the size of IU pool for each
+target has been rounded down to 512 when attempting to kfifo_init() those
+pools with the current request_limit size of 800.
+
+Link: https://lore.kernel.org/r/20220322194443.678433-1-tyreld@linux.ibm.com
+Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+index cc3908c2d2f9..a3431485def8 100644
+--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
++++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+@@ -35,7 +35,7 @@
+
+ #define IBMVSCSIS_VERSION "v0.2"
+
+-#define INITIAL_SRP_LIMIT 800
++#define INITIAL_SRP_LIMIT 1024
+ #define DEFAULT_MAX_SECTORS 256
+ #define MAX_TXU 1024 * 1024
+
+--
+2.35.1
+
--- /dev/null
+From 92ab0651a77fc668ad6830fcf06e58f3e5a8d1c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 19:13:09 -0500
+Subject: scsi: iscsi: Fix conn cleanup and stop race during iscsid restart
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 7c6e99c18167ed89729bf167ccb4a7e3ab3115ba ]
+
+If iscsid is doing a stop_conn at the same time the kernel is starting
+error recovery we can hit a race that allows the cleanup work to run on a
+valid connection. In the race, iscsi_if_stop_conn sees the cleanup bit set,
+but it calls flush_work on the clean_work before iscsi_conn_error_event has
+queued it. The flush then returns before the queueing and so the
+cleanup_work can run later and disconnect/stop a conn while it's in a
+connected state.
+
+The patch:
+
+Commit 0ab710458da1 ("scsi: iscsi: Perform connection failure entirely in
+kernel space")
+
+added the late stop_conn call bug originally, and the patch:
+
+Commit 23d6fefbb3f6 ("scsi: iscsi: Fix in-kernel conn failure handling")
+
+attempted to fix it but only fixed the normal EH case and left the above
+race for the iscsid restart case. For the normal EH case we don't hit the
+race because we only signal userspace to start recovery after we have done
+the queueing, so the flush will always catch the queued work or see it
+completed.
+
+For iscsid restart cases like boot, we can hit the race because iscsid will
+call down to the kernel before the kernel has signaled any error, so both
+code paths can be running at the same time. This adds a lock around the
+setting of the cleanup bit and queueing so they happen together.
+
+Link: https://lore.kernel.org/r/20220408001314.5014-6-michael.christie@oracle.com
+Fixes: 0ab710458da1 ("scsi: iscsi: Perform connection failure entirely in kernel space")
+Tested-by: Manish Rangankar <mrangankar@marvell.com>
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Reviewed-by: Chris Leech <cleech@redhat.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 17 +++++++++++++++++
+ include/scsi/scsi_transport_iscsi.h | 2 ++
+ 2 files changed, 19 insertions(+)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 38abc3a15692..21cc306a0f11 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2263,9 +2263,12 @@ static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
+ bool is_active)
+ {
+ /* Check if this was a conn error and the kernel took ownership */
++ spin_lock_irq(&conn->lock);
+ if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
+ iscsi_ep_disconnect(conn, is_active);
+ } else {
++ spin_unlock_irq(&conn->lock);
+ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
+ mutex_unlock(&conn->ep_mutex);
+
+@@ -2308,9 +2311,12 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ /*
+ * Figure out if it was the kernel or userspace initiating this.
+ */
++ spin_lock_irq(&conn->lock);
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
+ iscsi_stop_conn(conn, flag);
+ } else {
++ spin_unlock_irq(&conn->lock);
+ ISCSI_DBG_TRANS_CONN(conn,
+ "flush kernel conn cleanup.\n");
+ flush_work(&conn->cleanup_work);
+@@ -2319,7 +2325,9 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ * Only clear for recovery to avoid extra cleanup runs during
+ * termination.
+ */
++ spin_lock_irq(&conn->lock);
+ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
++ spin_unlock_irq(&conn->lock);
+ }
+ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
+ return 0;
+@@ -2340,7 +2348,9 @@ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
+ */
+ if (conn->state != ISCSI_CONN_BOUND && conn->state != ISCSI_CONN_UP) {
+ ISCSI_DBG_TRANS_CONN(conn, "Got error while conn is already failed. Ignoring.\n");
++ spin_lock_irq(&conn->lock);
+ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
++ spin_unlock_irq(&conn->lock);
+ mutex_unlock(&conn->ep_mutex);
+ return;
+ }
+@@ -2400,6 +2410,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+ conn->dd_data = &conn[1];
+
+ mutex_init(&conn->ep_mutex);
++ spin_lock_init(&conn->lock);
+ INIT_LIST_HEAD(&conn->conn_list);
+ INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
+ conn->transport = transport;
+@@ -2591,9 +2602,12 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ struct iscsi_uevent *ev;
+ struct iscsi_internal *priv;
+ int len = nlmsg_total_size(sizeof(*ev));
++ unsigned long flags;
+
++ spin_lock_irqsave(&conn->lock, flags);
+ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags))
+ queue_work(iscsi_conn_cleanup_workq, &conn->cleanup_work);
++ spin_unlock_irqrestore(&conn->lock, flags);
+
+ priv = iscsi_if_transport_lookup(conn->transport);
+ if (!priv)
+@@ -3736,11 +3750,14 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+ return -EINVAL;
+
+ mutex_lock(&conn->ep_mutex);
++ spin_lock_irq(&conn->lock);
+ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ spin_unlock_irq(&conn->lock);
+ mutex_unlock(&conn->ep_mutex);
+ ev->r.retcode = -ENOTCONN;
+ return 0;
+ }
++ spin_unlock_irq(&conn->lock);
+
+ switch (nlh->nlmsg_type) {
+ case ISCSI_UEVENT_BIND_CONN:
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index c5d7810fd792..037c77fb5dc5 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -211,6 +211,8 @@ struct iscsi_cls_conn {
+ struct mutex ep_mutex;
+ struct iscsi_endpoint *ep;
+
++ /* Used when accessing flags and queueing work. */
++ spinlock_t lock;
+ unsigned long flags;
+ struct work_struct cleanup_work;
+
+--
+2.35.1
+
--- /dev/null
+From 79a713447a8f803b1a148149390262bd60c9d17d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 May 2021 13:18:00 -0500
+Subject: scsi: iscsi: Fix in-kernel conn failure handling
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 23d6fefbb3f6b1cc29794427588b470ed06ff64e ]
+
+Commit 0ab710458da1 ("scsi: iscsi: Perform connection failure entirely in
+kernel space") has the following regressions/bugs that this patch fixes:
+
+1. It can return cmds to upper layers like dm-multipath where that can
+retry them. After they are successful the fs/app can send new I/O to the
+same sectors, but we've left the cmds running in FW or in the net layer.
+We need to be calling ep_disconnect if userspace is not up.
+
+This patch only fixes the issue for offload drivers. iscsi_tcp will be
+fixed in separate commit because it doesn't have a ep_disconnect call.
+
+2. The drivers that implement ep_disconnect expect that it's called before
+conn_stop. Besides crashes, if the cleanup_task callout is called before
+ep_disconnect it might free up driver/card resources for session1 then they
+could be allocated for session2. But because the driver's ep_disconnect is
+not called it has not cleaned up the firmware so the card is still using
+the resources for the original cmd.
+
+3. The stop_conn_work_fn can run after userspace has done its recovery and
+we are happily using the session. We will then end up with various bugs
+depending on what is going on at the time.
+
+We may also run stop_conn_work_fn late after userspace has called stop_conn
+and ep_disconnect and is now going to call start/bind conn. If
+stop_conn_work_fn runs after bind but before start, we would leave the conn
+in a unbound but sort of started state where IO might be allowed even
+though the drivers have been set in a state where they no longer expect
+I/O.
+
+4. Returning -EAGAIN in iscsi_if_destroy_conn if we haven't yet run the in
+kernel stop_conn function is breaking userspace. We should have been doing
+this for the caller.
+
+Link: https://lore.kernel.org/r/20210525181821.7617-8-michael.christie@oracle.com
+Fixes: 0ab710458da1 ("scsi: iscsi: Perform connection failure entirely in kernel space")
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 471 ++++++++++++++++------------
+ include/scsi/scsi_transport_iscsi.h | 10 +-
+ 2 files changed, 283 insertions(+), 198 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index dea0944ebbfa..7246f7b2ff03 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -86,15 +86,11 @@ struct iscsi_internal {
+ struct transport_container session_cont;
+ };
+
+-/* Worker to perform connection failure on unresponsive connections
+- * completely in kernel space.
+- */
+-static void stop_conn_work_fn(struct work_struct *work);
+-static DECLARE_WORK(stop_conn_work, stop_conn_work_fn);
+-
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+ static struct workqueue_struct *iscsi_eh_timer_workq;
+
++static struct workqueue_struct *iscsi_conn_cleanup_workq;
++
+ static DEFINE_IDA(iscsi_sess_ida);
+ /*
+ * list of registered transports and lock that must
+@@ -1601,12 +1597,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
+ static struct sock *nls;
+ static DEFINE_MUTEX(rx_queue_mutex);
+
+-/*
+- * conn_mutex protects the {start,bind,stop,destroy}_conn from racing
+- * against the kernel stop_connection recovery mechanism
+- */
+-static DEFINE_MUTEX(conn_mutex);
+-
+ static LIST_HEAD(sesslist);
+ static DEFINE_SPINLOCK(sesslock);
+ static LIST_HEAD(connlist);
+@@ -2228,6 +2218,123 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_remove_session);
+
++static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
++{
++ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn.\n");
++
++ switch (flag) {
++ case STOP_CONN_RECOVER:
++ conn->state = ISCSI_CONN_FAILED;
++ break;
++ case STOP_CONN_TERM:
++ conn->state = ISCSI_CONN_DOWN;
++ break;
++ default:
++ iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
++ flag);
++ return;
++ }
++
++ conn->transport->stop_conn(conn, flag);
++ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
++}
++
++static int iscsi_if_stop_conn(struct iscsi_transport *transport,
++ struct iscsi_uevent *ev)
++{
++ int flag = ev->u.stop_conn.flag;
++ struct iscsi_cls_conn *conn;
++
++ conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
++ if (!conn)
++ return -EINVAL;
++
++ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n");
++ /*
++ * If this is a termination we have to call stop_conn with that flag
++ * so the correct states get set. If we haven't run the work yet try to
++ * avoid the extra run.
++ */
++ if (flag == STOP_CONN_TERM) {
++ cancel_work_sync(&conn->cleanup_work);
++ iscsi_stop_conn(conn, flag);
++ } else {
++ /*
++ * Figure out if it was the kernel or userspace initiating this.
++ */
++ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ iscsi_stop_conn(conn, flag);
++ } else {
++ ISCSI_DBG_TRANS_CONN(conn,
++ "flush kernel conn cleanup.\n");
++ flush_work(&conn->cleanup_work);
++ }
++ /*
++ * Only clear for recovery to avoid extra cleanup runs during
++ * termination.
++ */
++ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
++ }
++ ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
++ return 0;
++}
++
++static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
++{
++ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
++ struct iscsi_endpoint *ep;
++
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
++ conn->state = ISCSI_CONN_FAILED;
++
++ if (!conn->ep || !session->transport->ep_disconnect)
++ return;
++
++ ep = conn->ep;
++ conn->ep = NULL;
++
++ session->transport->unbind_conn(conn, is_active);
++ session->transport->ep_disconnect(ep);
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
++}
++
++static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
++{
++ struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
++ cleanup_work);
++ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
++
++ mutex_lock(&conn->ep_mutex);
++ /*
++ * If we are not at least bound there is nothing for us to do. Userspace
++ * will do a ep_disconnect call if offload is used, but will not be
++ * doing a stop since there is nothing to clean up, so we have to clear
++ * the cleanup bit here.
++ */
++ if (conn->state != ISCSI_CONN_BOUND && conn->state != ISCSI_CONN_UP) {
++ ISCSI_DBG_TRANS_CONN(conn, "Got error while conn is already failed. Ignoring.\n");
++ clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
++ mutex_unlock(&conn->ep_mutex);
++ return;
++ }
++
++ iscsi_ep_disconnect(conn, false);
++
++ if (system_state != SYSTEM_RUNNING) {
++ /*
++ * If the user has set up for the session to never timeout
++ * then hang like they wanted. For all other cases fail right
++ * away since userspace is not going to relogin.
++ */
++ if (session->recovery_tmo > 0)
++ session->recovery_tmo = 0;
++ }
++
++ iscsi_stop_conn(conn, STOP_CONN_RECOVER);
++ mutex_unlock(&conn->ep_mutex);
++ ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
++}
++
+ void iscsi_free_session(struct iscsi_cls_session *session)
+ {
+ ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
+@@ -2267,7 +2374,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
+
+ mutex_init(&conn->ep_mutex);
+ INIT_LIST_HEAD(&conn->conn_list);
+- INIT_LIST_HEAD(&conn->conn_list_err);
++ INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
+ conn->transport = transport;
+ conn->cid = cid;
+ conn->state = ISCSI_CONN_DOWN;
+@@ -2324,7 +2431,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
+
+ spin_lock_irqsave(&connlock, flags);
+ list_del(&conn->conn_list);
+- list_del(&conn->conn_list_err);
+ spin_unlock_irqrestore(&connlock, flags);
+
+ transport_unregister_device(&conn->dev);
+@@ -2451,83 +2557,6 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
+
+-/*
+- * This can be called without the rx_queue_mutex, if invoked by the kernel
+- * stop work. But, in that case, it is guaranteed not to race with
+- * iscsi_destroy by conn_mutex.
+- */
+-static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
+-{
+- /*
+- * It is important that this path doesn't rely on
+- * rx_queue_mutex, otherwise, a thread doing allocation on a
+- * start_session/start_connection could sleep waiting on a
+- * writeback to a failed iscsi device, that cannot be recovered
+- * because the lock is held. If we don't hold it here, the
+- * kernel stop_conn_work_fn has a chance to stop the broken
+- * session and resolve the allocation.
+- *
+- * Still, the user invoked .stop_conn() needs to be serialized
+- * with stop_conn_work_fn by a private mutex. Not pretty, but
+- * it works.
+- */
+- mutex_lock(&conn_mutex);
+- switch (flag) {
+- case STOP_CONN_RECOVER:
+- conn->state = ISCSI_CONN_FAILED;
+- break;
+- case STOP_CONN_TERM:
+- conn->state = ISCSI_CONN_DOWN;
+- break;
+- default:
+- iscsi_cls_conn_printk(KERN_ERR, conn,
+- "invalid stop flag %d\n", flag);
+- goto unlock;
+- }
+-
+- conn->transport->stop_conn(conn, flag);
+-unlock:
+- mutex_unlock(&conn_mutex);
+-}
+-
+-static void stop_conn_work_fn(struct work_struct *work)
+-{
+- struct iscsi_cls_conn *conn, *tmp;
+- unsigned long flags;
+- LIST_HEAD(recovery_list);
+-
+- spin_lock_irqsave(&connlock, flags);
+- if (list_empty(&connlist_err)) {
+- spin_unlock_irqrestore(&connlock, flags);
+- return;
+- }
+- list_splice_init(&connlist_err, &recovery_list);
+- spin_unlock_irqrestore(&connlock, flags);
+-
+- list_for_each_entry_safe(conn, tmp, &recovery_list, conn_list_err) {
+- uint32_t sid = iscsi_conn_get_sid(conn);
+- struct iscsi_cls_session *session;
+-
+- session = iscsi_session_lookup(sid);
+- if (session) {
+- if (system_state != SYSTEM_RUNNING) {
+- /*
+- * If the user has set up for the session to
+- * never timeout then hang like they wanted.
+- * For all other cases fail right away since
+- * userspace is not going to relogin.
+- */
+- if (session->recovery_tmo > 0)
+- session->recovery_tmo = 0;
+- }
+-
+- iscsi_if_stop_conn(conn, STOP_CONN_RECOVER);
+- }
+-
+- list_del_init(&conn->conn_list_err);
+- }
+-}
+-
+ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ {
+ struct nlmsghdr *nlh;
+@@ -2535,12 +2564,9 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
+ struct iscsi_uevent *ev;
+ struct iscsi_internal *priv;
+ int len = nlmsg_total_size(sizeof(*ev));
+- unsigned long flags;
+
+- spin_lock_irqsave(&connlock, flags);
+- list_add(&conn->conn_list_err, &connlist_err);
+- spin_unlock_irqrestore(&connlock, flags);
+- queue_work(system_unbound_wq, &stop_conn_work);
++ if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags))
++ queue_work(iscsi_conn_cleanup_workq, &conn->cleanup_work);
+
+ priv = iscsi_if_transport_lookup(conn->transport);
+ if (!priv)
+@@ -2870,26 +2896,17 @@ static int
+ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+ {
+ struct iscsi_cls_conn *conn;
+- unsigned long flags;
+
+ conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
+ if (!conn)
+ return -EINVAL;
+
+- spin_lock_irqsave(&connlock, flags);
+- if (!list_empty(&conn->conn_list_err)) {
+- spin_unlock_irqrestore(&connlock, flags);
+- return -EAGAIN;
+- }
+- spin_unlock_irqrestore(&connlock, flags);
+-
++ ISCSI_DBG_TRANS_CONN(conn, "Flushing cleanup during destruction\n");
++ flush_work(&conn->cleanup_work);
+ ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
+
+- mutex_lock(&conn_mutex);
+ if (transport->destroy_conn)
+ transport->destroy_conn(conn);
+- mutex_unlock(&conn_mutex);
+-
+ return 0;
+ }
+
+@@ -2966,7 +2983,7 @@ static int iscsi_if_ep_connect(struct iscsi_transport *transport,
+ }
+
+ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+- u64 ep_handle, bool is_active)
++ u64 ep_handle)
+ {
+ struct iscsi_cls_conn *conn;
+ struct iscsi_endpoint *ep;
+@@ -2977,17 +2994,30 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ ep = iscsi_lookup_endpoint(ep_handle);
+ if (!ep)
+ return -EINVAL;
++
+ conn = ep->conn;
+- if (conn) {
+- mutex_lock(&conn->ep_mutex);
+- conn->ep = NULL;
++ if (!conn) {
++ /*
++ * conn was not even bound yet, so we can't get iscsi conn
++ * failures yet.
++ */
++ transport->ep_disconnect(ep);
++ goto put_ep;
++ }
++
++ mutex_lock(&conn->ep_mutex);
++ /* Check if this was a conn error and the kernel took ownership */
++ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
+ mutex_unlock(&conn->ep_mutex);
+- conn->state = ISCSI_CONN_FAILED;
+
+- transport->unbind_conn(conn, is_active);
++ flush_work(&conn->cleanup_work);
++ goto put_ep;
+ }
+
+- transport->ep_disconnect(ep);
++ iscsi_ep_disconnect(conn, false);
++ mutex_unlock(&conn->ep_mutex);
++put_ep:
+ iscsi_put_endpoint(ep);
+ return 0;
+ }
+@@ -3018,8 +3048,7 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ break;
+ case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ rc = iscsi_if_ep_disconnect(transport,
+- ev->u.ep_disconnect.ep_handle,
+- false);
++ ev->u.ep_disconnect.ep_handle);
+ break;
+ }
+ return rc;
+@@ -3646,18 +3675,129 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
+ return err;
+ }
+
++static int iscsi_if_transport_conn(struct iscsi_transport *transport,
++ struct nlmsghdr *nlh)
++{
++ struct iscsi_uevent *ev = nlmsg_data(nlh);
++ struct iscsi_cls_session *session;
++ struct iscsi_cls_conn *conn = NULL;
++ struct iscsi_endpoint *ep;
++ uint32_t pdu_len;
++ int err = 0;
++
++ switch (nlh->nlmsg_type) {
++ case ISCSI_UEVENT_CREATE_CONN:
++ return iscsi_if_create_conn(transport, ev);
++ case ISCSI_UEVENT_DESTROY_CONN:
++ return iscsi_if_destroy_conn(transport, ev);
++ case ISCSI_UEVENT_STOP_CONN:
++ return iscsi_if_stop_conn(transport, ev);
++ }
++
++ /*
++ * The following cmds need to be run under the ep_mutex so in kernel
++ * conn cleanup (ep_disconnect + unbind and conn) is not done while
++ * these are running. They also must not run if we have just run a conn
++ * cleanup because they would set the state in a way that might allow
++ * IO or send IO themselves.
++ */
++ switch (nlh->nlmsg_type) {
++ case ISCSI_UEVENT_START_CONN:
++ conn = iscsi_conn_lookup(ev->u.start_conn.sid,
++ ev->u.start_conn.cid);
++ break;
++ case ISCSI_UEVENT_BIND_CONN:
++ conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
++ break;
++ case ISCSI_UEVENT_SEND_PDU:
++ conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
++ break;
++ }
++
++ if (!conn)
++ return -EINVAL;
++
++ mutex_lock(&conn->ep_mutex);
++ if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ mutex_unlock(&conn->ep_mutex);
++ ev->r.retcode = -ENOTCONN;
++ return 0;
++ }
++
++ switch (nlh->nlmsg_type) {
++ case ISCSI_UEVENT_BIND_CONN:
++ if (conn->ep) {
++ /*
++ * For offload boot support where iscsid is restarted
++ * during the pivot root stage, the ep will be intact
++ * here when the new iscsid instance starts up and
++ * reconnects.
++ */
++ iscsi_ep_disconnect(conn, true);
++ }
++
++ session = iscsi_session_lookup(ev->u.b_conn.sid);
++ if (!session) {
++ err = -EINVAL;
++ break;
++ }
++
++ ev->r.retcode = transport->bind_conn(session, conn,
++ ev->u.b_conn.transport_eph,
++ ev->u.b_conn.is_leading);
++ if (!ev->r.retcode)
++ conn->state = ISCSI_CONN_BOUND;
++
++ if (ev->r.retcode || !transport->ep_connect)
++ break;
++
++ ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
++ if (ep) {
++ ep->conn = conn;
++ conn->ep = ep;
++ iscsi_put_endpoint(ep);
++ } else {
++ err = -ENOTCONN;
++ iscsi_cls_conn_printk(KERN_ERR, conn,
++ "Could not set ep conn binding\n");
++ }
++ break;
++ case ISCSI_UEVENT_START_CONN:
++ ev->r.retcode = transport->start_conn(conn);
++ if (!ev->r.retcode)
++ conn->state = ISCSI_CONN_UP;
++ break;
++ case ISCSI_UEVENT_SEND_PDU:
++ pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
++
++ if ((ev->u.send_pdu.hdr_size > pdu_len) ||
++ (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
++ err = -EINVAL;
++ break;
++ }
++
++ ev->r.retcode = transport->send_pdu(conn,
++ (struct iscsi_hdr *)((char *)ev + sizeof(*ev)),
++ (char *)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
++ ev->u.send_pdu.data_size);
++ break;
++ default:
++ err = -ENOSYS;
++ }
++
++ mutex_unlock(&conn->ep_mutex);
++ return err;
++}
+
+ static int
+ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ {
+ int err = 0;
+ u32 portid;
+- u32 pdu_len;
+ struct iscsi_uevent *ev = nlmsg_data(nlh);
+ struct iscsi_transport *transport = NULL;
+ struct iscsi_internal *priv;
+ struct iscsi_cls_session *session;
+- struct iscsi_cls_conn *conn;
+ struct iscsi_endpoint *ep = NULL;
+
+ if (!netlink_capable(skb, CAP_SYS_ADMIN))
+@@ -3734,90 +3874,16 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ else
+ err = -EINVAL;
+ break;
+- case ISCSI_UEVENT_CREATE_CONN:
+- err = iscsi_if_create_conn(transport, ev);
+- break;
+- case ISCSI_UEVENT_DESTROY_CONN:
+- err = iscsi_if_destroy_conn(transport, ev);
+- break;
+- case ISCSI_UEVENT_BIND_CONN:
+- session = iscsi_session_lookup(ev->u.b_conn.sid);
+- conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
+-
+- if (conn && conn->ep)
+- iscsi_if_ep_disconnect(transport, conn->ep->id, true);
+-
+- if (!session || !conn) {
+- err = -EINVAL;
+- break;
+- }
+-
+- mutex_lock(&conn_mutex);
+- ev->r.retcode = transport->bind_conn(session, conn,
+- ev->u.b_conn.transport_eph,
+- ev->u.b_conn.is_leading);
+- if (!ev->r.retcode)
+- conn->state = ISCSI_CONN_BOUND;
+- mutex_unlock(&conn_mutex);
+-
+- if (ev->r.retcode || !transport->ep_connect)
+- break;
+-
+- ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
+- if (ep) {
+- ep->conn = conn;
+-
+- mutex_lock(&conn->ep_mutex);
+- conn->ep = ep;
+- mutex_unlock(&conn->ep_mutex);
+- iscsi_put_endpoint(ep);
+- } else
+- iscsi_cls_conn_printk(KERN_ERR, conn,
+- "Could not set ep conn "
+- "binding\n");
+- break;
+ case ISCSI_UEVENT_SET_PARAM:
+ err = iscsi_set_param(transport, ev);
+ break;
+- case ISCSI_UEVENT_START_CONN:
+- conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
+- if (conn) {
+- mutex_lock(&conn_mutex);
+- ev->r.retcode = transport->start_conn(conn);
+- if (!ev->r.retcode)
+- conn->state = ISCSI_CONN_UP;
+- mutex_unlock(&conn_mutex);
+- }
+- else
+- err = -EINVAL;
+- break;
++ case ISCSI_UEVENT_CREATE_CONN:
++ case ISCSI_UEVENT_DESTROY_CONN:
+ case ISCSI_UEVENT_STOP_CONN:
+- conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
+- if (conn)
+- iscsi_if_stop_conn(conn, ev->u.stop_conn.flag);
+- else
+- err = -EINVAL;
+- break;
++ case ISCSI_UEVENT_START_CONN:
++ case ISCSI_UEVENT_BIND_CONN:
+ case ISCSI_UEVENT_SEND_PDU:
+- pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev);
+-
+- if ((ev->u.send_pdu.hdr_size > pdu_len) ||
+- (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
+- err = -EINVAL;
+- break;
+- }
+-
+- conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
+- if (conn) {
+- mutex_lock(&conn_mutex);
+- ev->r.retcode = transport->send_pdu(conn,
+- (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
+- (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
+- ev->u.send_pdu.data_size);
+- mutex_unlock(&conn_mutex);
+- }
+- else
+- err = -EINVAL;
++ err = iscsi_if_transport_conn(transport, nlh);
+ break;
+ case ISCSI_UEVENT_GET_STATS:
+ err = iscsi_if_get_stats(transport, nlh);
+@@ -4820,8 +4886,18 @@ static __init int iscsi_transport_init(void)
+ goto release_nls;
+ }
+
++ iscsi_conn_cleanup_workq = alloc_workqueue("%s",
++ WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
++ "iscsi_conn_cleanup");
++ if (!iscsi_conn_cleanup_workq) {
++ err = -ENOMEM;
++ goto destroy_wq;
++ }
++
+ return 0;
+
++destroy_wq:
++ destroy_workqueue(iscsi_eh_timer_workq);
+ release_nls:
+ netlink_kernel_release(nls);
+ unregister_flashnode_bus:
+@@ -4843,6 +4919,7 @@ static __init int iscsi_transport_init(void)
+
+ static void __exit iscsi_transport_exit(void)
+ {
++ destroy_workqueue(iscsi_conn_cleanup_workq);
+ destroy_workqueue(iscsi_eh_timer_workq);
+ netlink_kernel_release(nls);
+ bus_unregister(&iscsi_flashnode_bus);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index 09992f019dc9..c5d7810fd792 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -197,15 +197,23 @@ enum iscsi_connection_state {
+ ISCSI_CONN_BOUND,
+ };
+
++#define ISCSI_CLS_CONN_BIT_CLEANUP 1
++
+ struct iscsi_cls_conn {
+ struct list_head conn_list; /* item in connlist */
+- struct list_head conn_list_err; /* item in connlist_err */
+ void *dd_data; /* LLD private data */
+ struct iscsi_transport *transport;
+ uint32_t cid; /* connection id */
++ /*
++ * This protects the conn startup and binding/unbinding of the ep to
++ * the conn. Unbinding includes ep_disconnect and stop_conn.
++ */
+ struct mutex ep_mutex;
+ struct iscsi_endpoint *ep;
+
++ unsigned long flags;
++ struct work_struct cleanup_work;
++
+ struct device dev; /* sysfs transport/container device */
+ enum iscsi_connection_state state;
+ };
+--
+2.35.1
+
--- /dev/null
+From 07ec8ac2135313fdf5a99141dcedd3b5a9b8147b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 19:13:06 -0500
+Subject: scsi: iscsi: Fix offload conn cleanup when iscsid restarts
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit cbd2283aaf47fef4ded4b29124b1ef3beb515f3a ]
+
+When userspace restarts during boot or upgrades it won't know about the
+offload driver's endpoint and connection mappings. iscsid will start by
+cleaning up the old session by doing a stop_conn call. Later, if we are
+able to create a new connection, we clean up the old endpoint during the
+binding stage. The problem is that if we do stop_conn before doing the
+ep_disconnect call offload, drivers can still be executing I/O. We then
+might free tasks from the under the card/driver.
+
+This moves the ep_disconnect call to before we do the stop_conn call for
+this case. It will then work and look like a normal recovery/cleanup
+procedure from the driver's point of view.
+
+Link: https://lore.kernel.org/r/20220408001314.5014-3-michael.christie@oracle.com
+Tested-by: Manish Rangankar <mrangankar@marvell.com>
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Reviewed-by: Chris Leech <cleech@redhat.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 48 +++++++++++++++++------------
+ 1 file changed, 28 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 8f6dc391356d..38abc3a15692 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2258,6 +2258,23 @@ static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
+ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
+ }
+
++static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
++ struct iscsi_endpoint *ep,
++ bool is_active)
++{
++ /* Check if this was a conn error and the kernel took ownership */
++ if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
++ iscsi_ep_disconnect(conn, is_active);
++ } else {
++ ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
++ mutex_unlock(&conn->ep_mutex);
++
++ flush_work(&conn->cleanup_work);
++
++ mutex_lock(&conn->ep_mutex);
++ }
++}
++
+ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+ {
+@@ -2278,6 +2295,16 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ cancel_work_sync(&conn->cleanup_work);
+ iscsi_stop_conn(conn, flag);
+ } else {
++ /*
++ * For offload, when iscsid is restarted it won't know about
++ * existing endpoints so it can't do a ep_disconnect. We clean
++ * it up here for userspace.
++ */
++ mutex_lock(&conn->ep_mutex);
++ if (conn->ep)
++ iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
++ mutex_unlock(&conn->ep_mutex);
++
+ /*
+ * Figure out if it was the kernel or userspace initiating this.
+ */
+@@ -3006,16 +3033,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ }
+
+ mutex_lock(&conn->ep_mutex);
+- /* Check if this was a conn error and the kernel took ownership */
+- if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
+- ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
+- mutex_unlock(&conn->ep_mutex);
+-
+- flush_work(&conn->cleanup_work);
+- goto put_ep;
+- }
+-
+- iscsi_ep_disconnect(conn, false);
++ iscsi_if_disconnect_bound_ep(conn, ep, false);
+ mutex_unlock(&conn->ep_mutex);
+ put_ep:
+ iscsi_put_endpoint(ep);
+@@ -3726,16 +3744,6 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport,
+
+ switch (nlh->nlmsg_type) {
+ case ISCSI_UEVENT_BIND_CONN:
+- if (conn->ep) {
+- /*
+- * For offload boot support where iscsid is restarted
+- * during the pivot root stage, the ep will be intact
+- * here when the new iscsid instance starts up and
+- * reconnects.
+- */
+- iscsi_ep_disconnect(conn, true);
+- }
+-
+ session = iscsi_session_lookup(ev->u.b_conn.sid);
+ if (!session) {
+ err = -EINVAL;
+--
+2.35.1
+
--- /dev/null
+From 7fff6f554a3c23afb20f0cc19c12ae8a2e6f9f87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 May 2021 13:17:57 -0500
+Subject: scsi: iscsi: Force immediate failure during shutdown
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 06c203a5566beecebb1f8838d026de8a61c8df71 ]
+
+If the system is not up, we can just fail immediately since iscsid is not
+going to ever answer our netlink events. We are already setting the
+recovery_tmo to 0, but by passing stop_conn STOP_CONN_TERM we never will
+block the session and start the recovery timer, because for that flag
+userspace will do the unbind and destroy events which would remove the
+devices and wake up and kill the eh.
+
+Since the conn is dead and the system is going dowm this just has us use
+STOP_CONN_RECOVER with recovery_tmo=0 so we fail immediately. However, if
+the user has set the recovery_tmo=-1 we let the system hang like they
+requested since they might have used that setting for specific reasons
+(one known reason is for buggy cluster software).
+
+Link: https://lore.kernel.org/r/20210525181821.7617-5-michael.christie@oracle.com
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 6490211b55d2..f93660142e35 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2508,11 +2508,17 @@ static void stop_conn_work_fn(struct work_struct *work)
+ session = iscsi_session_lookup(sid);
+ if (session) {
+ if (system_state != SYSTEM_RUNNING) {
+- session->recovery_tmo = 0;
+- iscsi_if_stop_conn(conn, STOP_CONN_TERM);
+- } else {
+- iscsi_if_stop_conn(conn, STOP_CONN_RECOVER);
++ /*
++ * If the user has set up for the session to
++ * never timeout then hang like they wanted.
++ * For all other cases fail right away since
++ * userspace is not going to relogin.
++ */
++ if (session->recovery_tmo > 0)
++ session->recovery_tmo = 0;
+ }
++
++ iscsi_if_stop_conn(conn, STOP_CONN_RECOVER);
+ }
+
+ list_del_init(&conn->conn_list_err);
+--
+2.35.1
+
--- /dev/null
+From a75b7f44aebfc5a21689c70ed5d22719aa59c79f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Apr 2022 19:13:05 -0500
+Subject: scsi: iscsi: Move iscsi_ep_disconnect()
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit c34f95e98d8fb750eefd4f3fe58b4f8b5e89253b ]
+
+This patch moves iscsi_ep_disconnect() so it can be called earlier in the
+next patch.
+
+Link: https://lore.kernel.org/r/20220408001314.5014-2-michael.christie@oracle.com
+Tested-by: Manish Rangankar <mrangankar@marvell.com>
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Reviewed-by: Chris Leech <cleech@redhat.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 38 ++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index 7246f7b2ff03..8f6dc391356d 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2239,6 +2239,25 @@ static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
+ ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
+ }
+
++static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
++{
++ struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
++ struct iscsi_endpoint *ep;
++
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
++ conn->state = ISCSI_CONN_FAILED;
++
++ if (!conn->ep || !session->transport->ep_disconnect)
++ return;
++
++ ep = conn->ep;
++ conn->ep = NULL;
++
++ session->transport->unbind_conn(conn, is_active);
++ session->transport->ep_disconnect(ep);
++ ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
++}
++
+ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ struct iscsi_uevent *ev)
+ {
+@@ -2279,25 +2298,6 @@ static int iscsi_if_stop_conn(struct iscsi_transport *transport,
+ return 0;
+ }
+
+-static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
+-{
+- struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
+- struct iscsi_endpoint *ep;
+-
+- ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
+- conn->state = ISCSI_CONN_FAILED;
+-
+- if (!conn->ep || !session->transport->ep_disconnect)
+- return;
+-
+- ep = conn->ep;
+- conn->ep = NULL;
+-
+- session->transport->unbind_conn(conn, is_active);
+- session->transport->ep_disconnect(ep);
+- ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
+-}
+-
+ static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
+ {
+ struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
+--
+2.35.1
+
--- /dev/null
+From db19ec244a5c52a4c1734da3d1e12147e65e28de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 May 2021 13:17:59 -0500
+Subject: scsi: iscsi: Rel ref after iscsi_lookup_endpoint()
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 9e5fe1700896c85040943fdc0d3fee0dd3e0d36f ]
+
+Subsequent commits allow the kernel to do ep_disconnect. In that case we
+will have to get a proper refcount on the ep so one thread does not delete
+it from under another.
+
+Link: https://lore.kernel.org/r/20210525181821.7617-7-michael.christie@oracle.com
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/ulp/iser/iscsi_iser.c | 1 +
+ drivers/scsi/be2iscsi/be_iscsi.c | 19 ++++++++++++------
+ drivers/scsi/bnx2i/bnx2i_iscsi.c | 23 +++++++++++++++-------
+ drivers/scsi/cxgbi/libcxgbi.c | 12 ++++++++----
+ drivers/scsi/qedi/qedi_iscsi.c | 25 +++++++++++++++++-------
+ drivers/scsi/qla4xxx/ql4_os.c | 1 +
+ drivers/scsi/scsi_transport_iscsi.c | 25 ++++++++++++++++--------
+ include/scsi/scsi_transport_iscsi.h | 1 +
+ 8 files changed, 75 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 8857d8322710..a16e066989fa 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -499,6 +499,7 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+ iser_conn->iscsi_conn = conn;
+
+ out:
++ iscsi_put_endpoint(ep);
+ mutex_unlock(&iser_conn->state_mutex);
+ return error;
+ }
+diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
+index a13c203ef7a9..c4881657a807 100644
+--- a/drivers/scsi/be2iscsi/be_iscsi.c
++++ b/drivers/scsi/be2iscsi/be_iscsi.c
+@@ -182,6 +182,7 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ struct beiscsi_endpoint *beiscsi_ep;
+ struct iscsi_endpoint *ep;
+ uint16_t cri_index;
++ int rc = 0;
+
+ ep = iscsi_lookup_endpoint(transport_fd);
+ if (!ep)
+@@ -189,15 +190,17 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+
+ beiscsi_ep = ep->dd_data;
+
+- if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+- return -EINVAL;
++ if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
++ rc = -EINVAL;
++ goto put_ep;
++ }
+
+ if (beiscsi_ep->phba != phba) {
+ beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
+ "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
+ beiscsi_ep->phba, phba);
+-
+- return -EEXIST;
++ rc = -EEXIST;
++ goto put_ep;
+ }
+ cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
+ if (phba->conn_table[cri_index]) {
+@@ -209,7 +212,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ beiscsi_ep->ep_cid,
+ beiscsi_conn,
+ phba->conn_table[cri_index]);
+- return -EINVAL;
++ rc = -EINVAL;
++ goto put_ep;
+ }
+ }
+
+@@ -226,7 +230,10 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
+ "BS_%d : cid %d phba->conn_table[%u]=%p\n",
+ beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
+ phba->conn_table[cri_index] = beiscsi_conn;
+- return 0;
++
++put_ep:
++ iscsi_put_endpoint(ep);
++ return rc;
+ }
+
+ static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 173d8c6a8cbf..649664dc6da4 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -1422,17 +1422,23 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
+ * Forcefully terminate all in progress connection recovery at the
+ * earliest, either in bind(), send_pdu(LOGIN), or conn_start()
+ */
+- if (bnx2i_adapter_ready(hba))
+- return -EIO;
++ if (bnx2i_adapter_ready(hba)) {
++ ret_code = -EIO;
++ goto put_ep;
++ }
+
+ bnx2i_ep = ep->dd_data;
+ if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
+- (bnx2i_ep->state == EP_STATE_TCP_RST_RCVD))
++ (bnx2i_ep->state == EP_STATE_TCP_RST_RCVD)) {
+ /* Peer disconnect via' FIN or RST */
+- return -EINVAL;
++ ret_code = -EINVAL;
++ goto put_ep;
++ }
+
+- if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+- return -EINVAL;
++ if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
++ ret_code = -EINVAL;
++ goto put_ep;
++ }
+
+ if (bnx2i_ep->hba != hba) {
+ /* Error - TCP connection does not belong to this device
+@@ -1443,7 +1449,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
+ iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data,
+ "belong to hba (%s)\n",
+ hba->netdev->name);
+- return -EEXIST;
++ ret_code = -EEXIST;
++ goto put_ep;
+ }
+ bnx2i_ep->conn = bnx2i_conn;
+ bnx2i_conn->ep = bnx2i_ep;
+@@ -1460,6 +1467,8 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
+ bnx2i_put_rq_buf(bnx2i_conn, 0);
+
+ bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE);
++put_ep:
++ iscsi_put_endpoint(ep);
+ return ret_code;
+ }
+
+diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
+index ecb134b4699f..506b561670af 100644
+--- a/drivers/scsi/cxgbi/libcxgbi.c
++++ b/drivers/scsi/cxgbi/libcxgbi.c
+@@ -2690,11 +2690,13 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+ err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
+ ppm->tformat.pgsz_idx_dflt);
+ if (err < 0)
+- return err;
++ goto put_ep;
+
+ err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+- if (err)
+- return -EINVAL;
++ if (err) {
++ err = -EINVAL;
++ goto put_ep;
++ }
+
+ /* calculate the tag idx bits needed for this conn based on cmds_max */
+ cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1;
+@@ -2715,7 +2717,9 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
+ /* init recv engine */
+ iscsi_tcp_hdr_recv_prep(tcp_conn);
+
+- return 0;
++put_ep:
++ iscsi_put_endpoint(ep);
++ return err;
+ }
+ EXPORT_SYMBOL_GPL(cxgbi_bind_conn);
+
+diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
+index 8f8036ae9a56..5f7e62f19d83 100644
+--- a/drivers/scsi/qedi/qedi_iscsi.c
++++ b/drivers/scsi/qedi/qedi_iscsi.c
+@@ -387,6 +387,7 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
+ struct qedi_ctx *qedi = iscsi_host_priv(shost);
+ struct qedi_endpoint *qedi_ep;
+ struct iscsi_endpoint *ep;
++ int rc = 0;
+
+ ep = iscsi_lookup_endpoint(transport_fd);
+ if (!ep)
+@@ -394,11 +395,16 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
+
+ qedi_ep = ep->dd_data;
+ if ((qedi_ep->state == EP_STATE_TCP_FIN_RCVD) ||
+- (qedi_ep->state == EP_STATE_TCP_RST_RCVD))
+- return -EINVAL;
++ (qedi_ep->state == EP_STATE_TCP_RST_RCVD)) {
++ rc = -EINVAL;
++ goto put_ep;
++ }
++
++ if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
++ rc = -EINVAL;
++ goto put_ep;
++ }
+
+- if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
+- return -EINVAL;
+
+ qedi_ep->conn = qedi_conn;
+ qedi_conn->ep = qedi_ep;
+@@ -408,13 +414,18 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
+ qedi_conn->cmd_cleanup_req = 0;
+ qedi_conn->cmd_cleanup_cmpl = 0;
+
+- if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn))
+- return -EINVAL;
++ if (qedi_bind_conn_to_iscsi_cid(qedi, qedi_conn)) {
++ rc = -EINVAL;
++ goto put_ep;
++ }
++
+
+ spin_lock_init(&qedi_conn->tmf_work_lock);
+ INIT_LIST_HEAD(&qedi_conn->tmf_work_list);
+ init_waitqueue_head(&qedi_conn->wait_queue);
+- return 0;
++put_ep:
++ iscsi_put_endpoint(ep);
++ return rc;
+ }
+
+ static int qedi_iscsi_update_conn(struct qedi_ctx *qedi,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index a8b8bf118c76..8d82d2a83059 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -3238,6 +3238,7 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
+ conn = cls_conn->dd_data;
+ qla_conn = conn->dd_data;
+ qla_conn->qla_ep = ep->dd_data;
++ iscsi_put_endpoint(ep);
+ return 0;
+ }
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index ed0c7e812445..dea0944ebbfa 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -266,9 +266,20 @@ void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
+ }
+ EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
+
++void iscsi_put_endpoint(struct iscsi_endpoint *ep)
++{
++ put_device(&ep->dev);
++}
++EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
++
++/**
++ * iscsi_lookup_endpoint - get ep from handle
++ * @handle: endpoint handle
++ *
++ * Caller must do a iscsi_put_endpoint.
++ */
+ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ {
+- struct iscsi_endpoint *ep;
+ struct device *dev;
+
+ dev = class_find_device(&iscsi_endpoint_class, NULL, &handle,
+@@ -276,13 +287,7 @@ struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
+ if (!dev)
+ return NULL;
+
+- ep = iscsi_dev_to_endpoint(dev);
+- /*
+- * we can drop this now because the interface will prevent
+- * removals and lookups from racing.
+- */
+- put_device(dev);
+- return ep;
++ return iscsi_dev_to_endpoint(dev);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
+
+@@ -2983,6 +2988,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ }
+
+ transport->ep_disconnect(ep);
++ iscsi_put_endpoint(ep);
+ return 0;
+ }
+
+@@ -3008,6 +3014,7 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+
+ ev->r.retcode = transport->ep_poll(ep,
+ ev->u.ep_poll.timeout_ms);
++ iscsi_put_endpoint(ep);
+ break;
+ case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ rc = iscsi_if_ep_disconnect(transport,
+@@ -3691,6 +3698,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ ev->u.c_bound_session.initial_cmdsn,
+ ev->u.c_bound_session.cmds_max,
+ ev->u.c_bound_session.queue_depth);
++ iscsi_put_endpoint(ep);
+ break;
+ case ISCSI_UEVENT_DESTROY_SESSION:
+ session = iscsi_session_lookup(ev->u.d_session.sid);
+@@ -3762,6 +3770,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ mutex_lock(&conn->ep_mutex);
+ conn->ep = ep;
+ mutex_unlock(&conn->ep_mutex);
++ iscsi_put_endpoint(ep);
+ } else
+ iscsi_cls_conn_printk(KERN_ERR, conn,
+ "Could not set ep conn "
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index eb6ed499324d..09992f019dc9 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -444,6 +444,7 @@ extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
+ extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
+ extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
+ extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
++extern void iscsi_put_endpoint(struct iscsi_endpoint *ep);
+ extern int iscsi_block_scsi_eh(struct scsi_cmnd *cmd);
+ extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost,
+ struct iscsi_transport *t,
+--
+2.35.1
+
--- /dev/null
+From d07eeb43533d97d256b4337f1d9eb5e99a51c6f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 May 2021 13:17:55 -0500
+Subject: scsi: iscsi: Stop queueing during ep_disconnect
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit 891e2639deae721dc43764a44fa255890dc34313 ]
+
+During ep_disconnect we have been doing iscsi_suspend_tx/queue to block new
+I/O but every driver except cxgbi and iscsi_tcp can still get I/O from
+__iscsi_conn_send_pdu() if we haven't called iscsi_conn_failure() before
+ep_disconnect. This could happen if we were terminating the session, and
+the logout timed out before it was even sent to libiscsi.
+
+Fix the issue by adding a helper which reverses the bind_conn call that
+allows new I/O to be queued. Drivers implementing ep_disconnect can use this
+to make sure new I/O is not queued to them when handling the disconnect.
+
+Link: https://lore.kernel.org/r/20210525181821.7617-3-michael.christie@oracle.com
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/ulp/iser/iscsi_iser.c | 1 +
+ drivers/scsi/be2iscsi/be_main.c | 1 +
+ drivers/scsi/bnx2i/bnx2i_iscsi.c | 1 +
+ drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 1 +
+ drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 1 +
+ drivers/scsi/libiscsi.c | 70 +++++++++++++++++++++---
+ drivers/scsi/qedi/qedi_iscsi.c | 1 +
+ drivers/scsi/qla4xxx/ql4_os.c | 1 +
+ drivers/scsi/scsi_transport_iscsi.c | 10 +++-
+ include/scsi/libiscsi.h | 1 +
+ include/scsi/scsi_transport_iscsi.h | 1 +
+ 11 files changed, 78 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
+index 3690e28cc7ea..8857d8322710 100644
+--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
++++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
+@@ -988,6 +988,7 @@ static struct iscsi_transport iscsi_iser_transport = {
+ /* connection management */
+ .create_conn = iscsi_iser_conn_create,
+ .bind_conn = iscsi_iser_conn_bind,
++ .unbind_conn = iscsi_conn_unbind,
+ .destroy_conn = iscsi_conn_teardown,
+ .attr_is_visible = iser_attr_is_visible,
+ .set_param = iscsi_iser_set_param,
+diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
+index 987dc8135a9b..b977e039bb78 100644
+--- a/drivers/scsi/be2iscsi/be_main.c
++++ b/drivers/scsi/be2iscsi/be_main.c
+@@ -5810,6 +5810,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
+ .destroy_session = beiscsi_session_destroy,
+ .create_conn = beiscsi_conn_create,
+ .bind_conn = beiscsi_conn_bind,
++ .unbind_conn = iscsi_conn_unbind,
+ .destroy_conn = iscsi_conn_teardown,
+ .attr_is_visible = beiscsi_attr_is_visible,
+ .set_iface_param = beiscsi_iface_set_param,
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 21efc73b87be..173d8c6a8cbf 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -2278,6 +2278,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
+ .destroy_session = bnx2i_session_destroy,
+ .create_conn = bnx2i_conn_create,
+ .bind_conn = bnx2i_conn_bind,
++ .unbind_conn = iscsi_conn_unbind,
+ .destroy_conn = bnx2i_conn_destroy,
+ .attr_is_visible = bnx2i_attr_is_visible,
+ .set_param = iscsi_set_param,
+diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+index 37d99357120f..edcd3fab6973 100644
+--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
++++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+@@ -117,6 +117,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
+ /* connection management */
+ .create_conn = cxgbi_create_conn,
+ .bind_conn = cxgbi_bind_conn,
++ .unbind_conn = iscsi_conn_unbind,
+ .destroy_conn = iscsi_tcp_conn_teardown,
+ .start_conn = iscsi_conn_start,
+ .stop_conn = iscsi_conn_stop,
+diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+index 2c3491528d42..efb3e2b3398e 100644
+--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
++++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+@@ -134,6 +134,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
+ /* connection management */
+ .create_conn = cxgbi_create_conn,
+ .bind_conn = cxgbi_bind_conn,
++ .unbind_conn = iscsi_conn_unbind,
+ .destroy_conn = iscsi_tcp_conn_teardown,
+ .start_conn = iscsi_conn_start,
+ .stop_conn = iscsi_conn_stop,
+diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
+index d4e66c595eb8..05799b41974d 100644
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -1367,23 +1367,32 @@ void iscsi_session_failure(struct iscsi_session *session,
+ }
+ EXPORT_SYMBOL_GPL(iscsi_session_failure);
+
+-void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
++static bool iscsi_set_conn_failed(struct iscsi_conn *conn)
+ {
+ struct iscsi_session *session = conn->session;
+
+- spin_lock_bh(&session->frwd_lock);
+- if (session->state == ISCSI_STATE_FAILED) {
+- spin_unlock_bh(&session->frwd_lock);
+- return;
+- }
++ if (session->state == ISCSI_STATE_FAILED)
++ return false;
+
+ if (conn->stop_stage == 0)
+ session->state = ISCSI_STATE_FAILED;
+- spin_unlock_bh(&session->frwd_lock);
+
+ set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+ set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+- iscsi_conn_error_event(conn->cls_conn, err);
++ return true;
++}
++
++void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
++{
++ struct iscsi_session *session = conn->session;
++ bool needs_evt;
++
++ spin_lock_bh(&session->frwd_lock);
++ needs_evt = iscsi_set_conn_failed(conn);
++ spin_unlock_bh(&session->frwd_lock);
++
++ if (needs_evt)
++ iscsi_conn_error_event(conn->cls_conn, err);
+ }
+ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+
+@@ -2117,6 +2126,51 @@ static void iscsi_check_transport_timeouts(struct timer_list *t)
+ spin_unlock(&session->frwd_lock);
+ }
+
++/**
++ * iscsi_conn_unbind - prevent queueing to conn.
++ * @cls_conn: iscsi conn ep is bound to.
++ * @is_active: is the conn in use for boot or is this for EH/termination
++ *
++ * This must be called by drivers implementing the ep_disconnect callout.
++ * It disables queueing to the connection from libiscsi in preparation for
++ * an ep_disconnect call.
++ */
++void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active)
++{
++ struct iscsi_session *session;
++ struct iscsi_conn *conn;
++
++ if (!cls_conn)
++ return;
++
++ conn = cls_conn->dd_data;
++ session = conn->session;
++ /*
++ * Wait for iscsi_eh calls to exit. We don't wait for the tmf to
++ * complete or timeout. The caller just wants to know what's running
++ * is everything that needs to be cleaned up, and no cmds will be
++ * queued.
++ */
++ mutex_lock(&session->eh_mutex);
++
++ iscsi_suspend_queue(conn);
++ iscsi_suspend_tx(conn);
++
++ spin_lock_bh(&session->frwd_lock);
++ if (!is_active) {
++ /*
++ * if logout timed out before userspace could even send a PDU
++ * the state might still be in ISCSI_STATE_LOGGED_IN and
++ * allowing new cmds and TMFs.
++ */
++ if (session->state == ISCSI_STATE_LOGGED_IN)
++ iscsi_set_conn_failed(conn);
++ }
++ spin_unlock_bh(&session->frwd_lock);
++ mutex_unlock(&session->eh_mutex);
++}
++EXPORT_SYMBOL_GPL(iscsi_conn_unbind);
++
+ static void iscsi_prep_abort_task_pdu(struct iscsi_task *task,
+ struct iscsi_tm *hdr)
+ {
+diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c
+index f51723e2d522..8f8036ae9a56 100644
+--- a/drivers/scsi/qedi/qedi_iscsi.c
++++ b/drivers/scsi/qedi/qedi_iscsi.c
+@@ -1428,6 +1428,7 @@ struct iscsi_transport qedi_iscsi_transport = {
+ .destroy_session = qedi_session_destroy,
+ .create_conn = qedi_conn_create,
+ .bind_conn = qedi_conn_bind,
++ .unbind_conn = iscsi_conn_unbind,
+ .start_conn = qedi_conn_start,
+ .stop_conn = iscsi_conn_stop,
+ .destroy_conn = qedi_conn_destroy,
+diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
+index 2c23b692e318..a8b8bf118c76 100644
+--- a/drivers/scsi/qla4xxx/ql4_os.c
++++ b/drivers/scsi/qla4xxx/ql4_os.c
+@@ -259,6 +259,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
+ .start_conn = qla4xxx_conn_start,
+ .create_conn = qla4xxx_conn_create,
+ .bind_conn = qla4xxx_conn_bind,
++ .unbind_conn = iscsi_conn_unbind,
+ .stop_conn = iscsi_conn_stop,
+ .destroy_conn = qla4xxx_conn_destroy,
+ .set_param = iscsi_set_param,
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index a5759d0e388a..6490211b55d2 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -2957,7 +2957,7 @@ static int iscsi_if_ep_connect(struct iscsi_transport *transport,
+ }
+
+ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+- u64 ep_handle)
++ u64 ep_handle, bool is_active)
+ {
+ struct iscsi_cls_conn *conn;
+ struct iscsi_endpoint *ep;
+@@ -2974,6 +2974,8 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+ conn->ep = NULL;
+ mutex_unlock(&conn->ep_mutex);
+ conn->state = ISCSI_CONN_FAILED;
++
++ transport->unbind_conn(conn, is_active);
+ }
+
+ transport->ep_disconnect(ep);
+@@ -3005,7 +3007,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
+ break;
+ case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+ rc = iscsi_if_ep_disconnect(transport,
+- ev->u.ep_disconnect.ep_handle);
++ ev->u.ep_disconnect.ep_handle,
++ false);
+ break;
+ }
+ return rc;
+@@ -3730,7 +3733,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
+
+ if (conn && conn->ep)
+- iscsi_if_ep_disconnect(transport, conn->ep->id);
++ iscsi_if_ep_disconnect(transport, conn->ep->id, true);
+
+ if (!session || !conn) {
+ err = -EINVAL;
+@@ -4649,6 +4652,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
+ int err;
+
+ BUG_ON(!tt);
++ WARN_ON(tt->ep_disconnect && !tt->unbind_conn);
+
+ priv = iscsi_if_transport_lookup(tt);
+ if (priv)
+diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
+index 2b5f97224f69..fa00e2543ad6 100644
+--- a/include/scsi/libiscsi.h
++++ b/include/scsi/libiscsi.h
+@@ -421,6 +421,7 @@ extern int iscsi_conn_start(struct iscsi_cls_conn *);
+ extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+ extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+ int);
++extern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active);
+ extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
+ extern void iscsi_session_failure(struct iscsi_session *session,
+ enum iscsi_err err);
+diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
+index f28bb20d6271..eb6ed499324d 100644
+--- a/include/scsi/scsi_transport_iscsi.h
++++ b/include/scsi/scsi_transport_iscsi.h
+@@ -82,6 +82,7 @@ struct iscsi_transport {
+ void (*destroy_session) (struct iscsi_cls_session *session);
+ struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
+ uint32_t cid);
++ void (*unbind_conn) (struct iscsi_cls_conn *conn, bool is_active);
+ int (*bind_conn) (struct iscsi_cls_session *session,
+ struct iscsi_cls_conn *cls_conn,
+ uint64_t transport_eph, int is_leading);
+--
+2.35.1
+
--- /dev/null
+From a1c30878445db8520f5eaa2ce089816b48f1fdcd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 May 2021 13:17:58 -0500
+Subject: scsi: iscsi: Use system_unbound_wq for destroy_work
+
+From: Mike Christie <michael.christie@oracle.com>
+
+[ Upstream commit b25b957d2db1585602c2c70fdf4261a5641fe6b7 ]
+
+Use the system_unbound_wq for async session destruction. We don't need a
+dedicated workqueue for async session destruction because:
+
+ 1. perf does not seem to be an issue since we only allow 1 active work.
+
+ 2. it does not have deps with other system works and we can run them in
+ parallel with each other.
+
+Link: https://lore.kernel.org/r/20210525181821.7617-6-michael.christie@oracle.com
+Reviewed-by: Lee Duncan <lduncan@suse.com>
+Signed-off-by: Mike Christie <michael.christie@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_transport_iscsi.c | 15 +--------------
+ 1 file changed, 1 insertion(+), 14 deletions(-)
+
+diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
+index f93660142e35..ed0c7e812445 100644
+--- a/drivers/scsi/scsi_transport_iscsi.c
++++ b/drivers/scsi/scsi_transport_iscsi.c
+@@ -95,8 +95,6 @@ static DECLARE_WORK(stop_conn_work, stop_conn_work_fn);
+ static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
+ static struct workqueue_struct *iscsi_eh_timer_workq;
+
+-static struct workqueue_struct *iscsi_destroy_workq;
+-
+ static DEFINE_IDA(iscsi_sess_ida);
+ /*
+ * list of registered transports and lock that must
+@@ -3717,7 +3715,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
+ list_del_init(&session->sess_list);
+ spin_unlock_irqrestore(&sesslock, flags);
+
+- queue_work(iscsi_destroy_workq, &session->destroy_work);
++ queue_work(system_unbound_wq, &session->destroy_work);
+ }
+ break;
+ case ISCSI_UEVENT_UNBIND_SESSION:
+@@ -4813,18 +4811,8 @@ static __init int iscsi_transport_init(void)
+ goto release_nls;
+ }
+
+- iscsi_destroy_workq = alloc_workqueue("%s",
+- WQ_SYSFS | __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_UNBOUND,
+- 1, "iscsi_destroy");
+- if (!iscsi_destroy_workq) {
+- err = -ENOMEM;
+- goto destroy_wq;
+- }
+-
+ return 0;
+
+-destroy_wq:
+- destroy_workqueue(iscsi_eh_timer_workq);
+ release_nls:
+ netlink_kernel_release(nls);
+ unregister_flashnode_bus:
+@@ -4846,7 +4834,6 @@ static __init int iscsi_transport_init(void)
+
+ static void __exit iscsi_transport_exit(void)
+ {
+- destroy_workqueue(iscsi_destroy_workq);
+ destroy_workqueue(iscsi_eh_timer_workq);
+ netlink_kernel_release(nls);
+ bus_unregister(&iscsi_flashnode_bus);
+--
+2.35.1
+
--- /dev/null
+From bc82b456a60e370377ea2faf3faa359c16df10be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Mar 2022 20:27:36 -0700
+Subject: scsi: lpfc: Fix queue failures when recovering from PCI parity error
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit df0101197c4d9596682901631f3ee193ed354873 ]
+
+When recovering from a pci-parity error the driver is failing to re-create
+queues, causing recovery to fail. Looking deeper, it was found that the
+interrupt vector count allocated on the recovery was fewer than the vectors
+originally allocated. This disparity resulted in CPU map entries with stale
+information. When the driver tries to re-create the queues, it attempts to
+use the stale information which indicates an eq/interrupt vector that was
+no longer created.
+
+Fix by clearng the cpup map array before enabling and requesting the IRQs
+in the lpfc_sli_reset_slot_s4 routine().
+
+Link: https://lore.kernel.org/r/20220317032737.45308-4-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 1149bfc42fe6..134e4ee5dc48 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -13614,6 +13614,8 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
+ psli->sli_flag &= ~LPFC_SLI_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
++ /* Init cpu_map array */
++ lpfc_cpu_map_array_init(phba);
+ /* Configure and enable interrupt */
+ intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
+ if (intr_mode == LPFC_INTR_ERROR) {
+--
+2.35.1
+
--- /dev/null
+From 2f567beda3c9f64de683d8d33a490ebc543dc603 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Mar 2022 02:47:11 -0700
+Subject: scsi: megaraid_sas: Target with invalid LUN ID is deleted during scan
+
+From: Chandrakanth patil <chandrakanth.patil@broadcom.com>
+
+[ Upstream commit 56495f295d8e021f77d065b890fc0100e3f9f6d8 ]
+
+The megaraid_sas driver supports single LUN for RAID devices. That is LUN
+0. All other LUNs are unsupported. When a device scan on a logical target
+with invalid LUN number is invoked through sysfs, that target ends up
+getting removed.
+
+Add LUN ID validation in the slave destroy function to avoid the target
+deletion.
+
+Link: https://lore.kernel.org/r/20220324094711.48833-1-chandrakanth.patil@broadcom.com
+Signed-off-by: Chandrakanth patil <chandrakanth.patil@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/megaraid/megaraid_sas.h | 3 +++
+ drivers/scsi/megaraid/megaraid_sas_base.c | 7 +++++++
+ 2 files changed, 10 insertions(+)
+
+diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
+index 6b8ec57e8bdf..c088a848776e 100644
+--- a/drivers/scsi/megaraid/megaraid_sas.h
++++ b/drivers/scsi/megaraid/megaraid_sas.h
+@@ -2554,6 +2554,9 @@ struct megasas_instance_template {
+ #define MEGASAS_IS_LOGICAL(sdev) \
+ ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1)
+
++#define MEGASAS_IS_LUN_VALID(sdev) \
++ (((sdev)->lun == 0) ? 1 : 0)
++
+ #define MEGASAS_DEV_INDEX(scp) \
+ (((scp->device->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + \
+ scp->device->id)
+diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
+index 1a70cc995c28..84a2e9292fd0 100644
+--- a/drivers/scsi/megaraid/megaraid_sas_base.c
++++ b/drivers/scsi/megaraid/megaraid_sas_base.c
+@@ -2111,6 +2111,9 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
+ goto scan_target;
+ }
+ return -ENXIO;
++ } else if (!MEGASAS_IS_LUN_VALID(sdev)) {
++ sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
++ return -ENXIO;
+ }
+
+ scan_target:
+@@ -2141,6 +2144,10 @@ static void megasas_slave_destroy(struct scsi_device *sdev)
+ instance = megasas_lookup_instance(sdev->host->host_no);
+
+ if (MEGASAS_IS_LOGICAL(sdev)) {
++ if (!MEGASAS_IS_LUN_VALID(sdev)) {
++ sdev_printk(KERN_INFO, sdev, "%s: invalid LUN\n", __func__);
++ return;
++ }
+ ld_tgt_id = MEGASAS_TARGET_ID(sdev);
+ instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_DELETED;
+ if (megasas_dbg_lvl & LD_PD_DEBUG)
+--
+2.35.1
+
--- /dev/null
+From 5c972d1c93e043640ea9d2f27f9399885e3d9959 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Mar 2022 22:25:35 +0100
+Subject: scsi: mvsas: Add PCI ID of RocketRaid 2640
+
+From: Alexey Galakhov <agalakhov@gmail.com>
+
+[ Upstream commit 5f2bce1e222028dc1c15f130109a17aa654ae6e8 ]
+
+The HighPoint RocketRaid 2640 is a low-cost SAS controller based on Marvell
+chip. The chip in question was already supported by the kernel, just the
+PCI ID of this particular board was missing.
+
+Link: https://lore.kernel.org/r/20220309212535.402987-1-agalakhov@gmail.com
+Signed-off-by: Alexey Galakhov <agalakhov@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mvsas/mv_init.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
+index 0cfea7b2ab13..85ca8421fb86 100644
+--- a/drivers/scsi/mvsas/mv_init.c
++++ b/drivers/scsi/mvsas/mv_init.c
+@@ -646,6 +646,7 @@ static struct pci_device_id mvs_pci_table[] = {
+ { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
+ { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
+ { PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
++ { PCI_VDEVICE(TTI, 0x2640), chip_6440 },
+ { PCI_VDEVICE(TTI, 0x2710), chip_9480 },
+ { PCI_VDEVICE(TTI, 0x2720), chip_9480 },
+ { PCI_VDEVICE(TTI, 0x2721), chip_9480 },
+--
+2.35.1
+
--- /dev/null
+From 4dd4e7afb5467fefe73f7b8cda6dc0ae3fe4e1e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 12:16:03 +0530
+Subject: scsi: pm80xx: Enable upper inbound, outbound queues
+
+From: Ajish Koshy <Ajish.Koshy@microchip.com>
+
+[ Upstream commit bcd8a45223470e00b5f254018174d64a75db4bbe ]
+
+Executing driver on servers with more than 32 CPUs were faced with command
+timeouts. This is because we were not geting completions for commands
+submitted on IQ32 - IQ63.
+
+Set E64Q bit to enable upper inbound and outbound queues 32 to 63 in the
+MPI main configuration table.
+
+Added 500ms delay after successful MPI initialization as mentioned in
+controller datasheet.
+
+Link: https://lore.kernel.org/r/20220411064603.668448-3-Ajish.Koshy@microchip.com
+Fixes: 05c6c029a44d ("scsi: pm80xx: Increase number of supported queues")
+Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
+Acked-by: Jack Wang <jinpu.wang@ionos.com>
+Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>
+Signed-off-by: Viswas G <Viswas.G@microchip.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/pm8001/pm80xx_hwi.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
+index 0543ff3ff1ba..0305c8999ba5 100644
+--- a/drivers/scsi/pm8001/pm80xx_hwi.c
++++ b/drivers/scsi/pm8001/pm80xx_hwi.c
+@@ -765,6 +765,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;
+
++ /* Enable higher IQs and OQs, 32 to 63, bit 16 */
++ if (pm8001_ha->max_q_num > 32)
++ pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
++ 1 << 16;
+ /* Disable end to end CRC checking */
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16);
+
+@@ -1024,6 +1028,13 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha)
+ if (0x0000 != gst_len_mpistate)
+ return -EBUSY;
+
++ /*
++ * As per controller datasheet, after successful MPI
++ * initialization minimum 500ms delay is required before
++ * issuing commands.
++ */
++ msleep(500);
++
+ return 0;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 2b3c6f208edd328423d11f448f685a2f31d2229e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 12:16:02 +0530
+Subject: scsi: pm80xx: Mask and unmask upper interrupt vectors 32-63
+
+From: Ajish Koshy <Ajish.Koshy@microchip.com>
+
+[ Upstream commit 294080eacf92a0781e6d43663448a55001ec8c64 ]
+
+When upper inbound and outbound queues 32-63 are enabled, we see upper
+vectors 32-63 in interrupt service routine. We need corresponding registers
+to handle masking and unmasking of these upper interrupts.
+
+To achieve this, we use registers MSGU_ODMR_U(0x34) to mask and
+MSGU_ODMR_CLR_U(0x3C) to unmask the interrupts. In these registers bit 0-31
+represents interrupt vectors 32-63.
+
+Link: https://lore.kernel.org/r/20220411064603.668448-2-Ajish.Koshy@microchip.com
+Fixes: 05c6c029a44d ("scsi: pm80xx: Increase number of supported queues")
+Reviewed-by: John Garry <john.garry@huawei.com>
+Acked-by: Jack Wang <jinpu.wang@ionos.com>
+Signed-off-by: Ajish Koshy <Ajish.Koshy@microchip.com>
+Signed-off-by: Viswas G <Viswas.G@microchip.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/pm8001/pm80xx_hwi.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
+index 4c03bf08b543..0543ff3ff1ba 100644
+--- a/drivers/scsi/pm8001/pm80xx_hwi.c
++++ b/drivers/scsi/pm8001/pm80xx_hwi.c
+@@ -1682,10 +1682,11 @@ static void
+ pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+ {
+ #ifdef PM8001_USE_MSIX
+- u32 mask;
+- mask = (u32)(1 << vec);
+-
+- pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF));
++ if (vec < 32)
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, 1U << vec);
++ else
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR_U,
++ 1U << (vec - 32));
+ return;
+ #endif
+ pm80xx_chip_intx_interrupt_enable(pm8001_ha);
+@@ -1701,12 +1702,15 @@ static void
+ pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec)
+ {
+ #ifdef PM8001_USE_MSIX
+- u32 mask;
+- if (vec == 0xFF)
+- mask = 0xFFFFFFFF;
++ if (vec == 0xFF) {
++ /* disable all vectors 0-31, 32-63 */
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 0xFFFFFFFF);
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U, 0xFFFFFFFF);
++ } else if (vec < 32)
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, 1U << vec);
+ else
+- mask = (u32)(1 << vec);
+- pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF));
++ pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_U,
++ 1U << (vec - 32));
+ return;
+ #endif
+ pm80xx_chip_intx_interrupt_disable(pm8001_ha);
+--
+2.35.1
+
--- /dev/null
+From 9d66caa131336a96f1c8321ec4d65b79057ef86b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Mar 2022 21:22:05 +0800
+Subject: scsi: target: tcmu: Fix possible page UAF
+
+From: Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
+
+[ Upstream commit a6968f7a367f128d120447360734344d5a3d5336 ]
+
+tcmu_try_get_data_page() looks up pages under cmdr_lock, but it does not
+take refcount properly and just returns page pointer. When
+tcmu_try_get_data_page() returns, the returned page may have been freed by
+tcmu_blocks_release().
+
+We need to get_page() under cmdr_lock to avoid concurrent
+tcmu_blocks_release().
+
+Link: https://lore.kernel.org/r/20220311132206.24515-1-xiaoguang.wang@linux.alibaba.com
+Reviewed-by: Bodo Stroesser <bostroesser@gmail.com>
+Signed-off-by: Xiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/target_core_user.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
+index c6950f157b99..c283e45ac300 100644
+--- a/drivers/target/target_core_user.c
++++ b/drivers/target/target_core_user.c
+@@ -1676,6 +1676,7 @@ static struct page *tcmu_try_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
+ mutex_lock(&udev->cmdr_lock);
+ page = tcmu_get_block_page(udev, dbi);
+ if (likely(page)) {
++ get_page(page);
+ mutex_unlock(&udev->cmdr_lock);
+ return page;
+ }
+@@ -1714,6 +1715,7 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
+ /* For the vmalloc()ed cmd area pages */
+ addr = (void *)(unsigned long)info->mem[mi].addr + offset;
+ page = vmalloc_to_page(addr);
++ get_page(page);
+ } else {
+ uint32_t dbi;
+
+@@ -1724,7 +1726,6 @@ static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
+ return VM_FAULT_SIGBUS;
+ }
+
+- get_page(page);
+ vmf->page = page;
+ return 0;
+ }
+--
+2.35.1
+
--- /dev/null
+From c00d21d417449c82d8691ba86c29c249289f308f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 9 Apr 2022 08:36:11 +0200
+Subject: sctp: Initialize daddr on peeled off socket
+
+From: Petr Malat <oss@malat.biz>
+
+[ Upstream commit 8467dda0c26583547731e7f3ea73fc3856bae3bf ]
+
+Function sctp_do_peeloff() wrongly initializes daddr of the original
+socket instead of the peeled off socket, which makes getpeername()
+return zeroes instead of the primary address. Initialize the new socket
+instead.
+
+Fixes: d570ee490fb1 ("[SCTP]: Correctly set daddr for IPv6 sockets during peeloff")
+Signed-off-by: Petr Malat <oss@malat.biz>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Link: https://lore.kernel.org/r/20220409063611.673193-1-oss@malat.biz
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 0a9e2c7d8e5f..e9b4ea3d934f 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -5518,7 +5518,7 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
+ * Set the daddr and initialize id to something more random and also
+ * copy over any ip options.
+ */
+- sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
++ sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sock->sk);
+ sp->pf->copy_ip_options(sk, sock->sk);
+
+ /* Populate the fields of the newsk from the oldsk and migrate the
+--
+2.35.1
+
cpuidle-psci-move-the-has_lpi-check-to-the-beginning-of-the-function.patch
acpi-processor-idle-check-for-architectural-support-for-lpi.patch
btrfs-remove-unused-variable-in-btrfs_-start-write-_dirty_block_groups.patch
+drm-msm-add-missing-put_task_struct-in-debugfs-path.patch
+memory-atmel-ebi-fix-missing-of_node_put-in-atmel_eb.patch
+firmware-arm_scmi-fix-sorting-of-retrieved-clock-rat.patch
+media-rockchip-rga-do-proper-error-checking-in-probe.patch
+sunrpc-fix-the-svc_deferred_event-trace-class.patch
+net-sched-flower-fix-parsing-of-ethertype-following-.patch
+veth-ensure-eth-header-is-in-skb-s-linear-part.patch
+gpiolib-acpi-use-correct-format-characters.patch
+net-mdio-alphabetically-sort-header-inclusion.patch
+mlxsw-i2c-fix-initialization-error-flow.patch
+net-sched-fix-initialization-order-when-updating-cha.patch
+net-dsa-felix-suppress-eprobe_defer-errors.patch
+net-ethernet-stmmac-fix-altr_tse_pcs-function-when-u.patch
+net-sched-taprio-check-if-socket-flags-are-valid.patch
+cfg80211-hold-bss_lock-while-updating-nontrans_list.patch
+drm-msm-fix-range-size-vs-end-confusion.patch
+drm-msm-dsi-use-connector-directly-in-msm_dsi_manage.patch
+net-smc-fix-null-pointer-dereference-in-smc_pnet_fin.patch
+scsi-pm80xx-mask-and-unmask-upper-interrupt-vectors-.patch
+scsi-pm80xx-enable-upper-inbound-outbound-queues.patch
+scsi-iscsi-stop-queueing-during-ep_disconnect.patch
+scsi-iscsi-force-immediate-failure-during-shutdown.patch
+scsi-iscsi-use-system_unbound_wq-for-destroy_work.patch
+scsi-iscsi-rel-ref-after-iscsi_lookup_endpoint.patch
+scsi-iscsi-fix-in-kernel-conn-failure-handling.patch
+scsi-iscsi-move-iscsi_ep_disconnect.patch
+scsi-iscsi-fix-offload-conn-cleanup-when-iscsid-rest.patch
+scsi-iscsi-fix-conn-cleanup-and-stop-race-during-isc.patch
+sctp-initialize-daddr-on-peeled-off-socket.patch
+testing-selftests-mqueue-fix-mq_perf_tests-to-free-t.patch
+perf-tools-fix-misleading-add-event-pmu-debug-messag.patch
+nfc-nci-add-flush_workqueue-to-prevent-uaf.patch
+cifs-potential-buffer-overflow-in-handling-symlinks.patch
+dm-mpath-only-use-ktime_get_ns-in-historical-selecto.patch
+net-bcmgenet-revert-use-stronger-register-read-write.patch
+drm-amd-add-usbc-connector-id.patch
+btrfs-fix-fallocate-to-use-file_modified-to-update-p.patch
+btrfs-do-not-warn-for-free-space-inode-in-cow_file_r.patch
+drm-amd-display-fix-audio-format-not-updated-after-e.patch
+drm-amd-display-fec-check-in-timing-validation.patch
+drm-amd-display-update-vtem-infopacket-definition.patch
+drm-amdkfd-fix-incorrect-vmids-passed-to-hws.patch
+drm-amdgpu-vcn-improve-vcn-dpg-stop-procedure.patch
+drm-amdkfd-check-for-potential-null-return-of-kmallo.patch
+drivers-hv-vmbus-prevent-load-re-ordering-when-readi.patch
+scsi-target-tcmu-fix-possible-page-uaf.patch
+scsi-lpfc-fix-queue-failures-when-recovering-from-pc.patch
+scsi-ibmvscsis-increase-initial_srp_limit-to-1024.patch
+net-micrel-fix-ks8851_mll-kconfig.patch
+ata-libata-core-disable-read-log-dma-ext-for-samsung.patch
+gpu-ipu-v3-fix-dev_dbg-frequency-output.patch
+regulator-wm8994-add-an-off-on-delay-for-wm8994-vari.patch
+arm64-alternatives-mark-patch_alternative-as-noinstr.patch
+tlb-hugetlb-add-more-sizes-to-tlb_remove_huge_tlb_en.patch
+net-axienet-setup-mdio-unconditionally.patch
+net-usb-aqc111-fix-out-of-bounds-accesses-in-rx-fixu.patch
+myri10ge-fix-an-incorrect-free-for-skb-in-myri10ge_s.patch
+drm-amd-display-revert-fec-check-in-validation.patch
+drm-amd-display-fix-allocate_mst_payload-assert-on-r.patch
+scsi-mvsas-add-pci-id-of-rocketraid-2640.patch
+scsi-megaraid_sas-target-with-invalid-lun-id-is-dele.patch
+drivers-net-slip-fix-npd-bug-in-sl_tx_timeout.patch
+perf-imx_ddr-fix-undefined-behavior-due-to-shift-ove.patch
--- /dev/null
+From 8c899986c21ddb43ea99a32a7807892dea8bc470 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 13:51:32 -0400
+Subject: SUNRPC: Fix the svc_deferred_event trace class
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 4d5004451ab2218eab94a30e1841462c9316ba19 ]
+
+Fix a NULL deref crash that occurs when an svc_rqst is deferred
+while the sunrpc tracing subsystem is enabled. svc_revisit() sets
+dr->xprt to NULL, so it can't be relied upon in the tracepoint to
+provide the remote's address.
+
+Unfortunately we can't revert the "svc_deferred_class" hunk in
+commit ece200ddd54b ("sunrpc: Save remote presentation address in
+svc_xprt for trace events") because there is now a specific check
+of event format specifiers for unsafe dereferences. The warning
+that check emits is:
+
+ event svc_defer_recv has unsafe dereference of argument 1
+
+A "%pISpc" format specifier with a "struct sockaddr *" is indeed
+flagged by this check.
+
+Instead, take the brute-force approach used by the svcrdma_qp_error
+tracepoint. Convert the dr::addr field into a presentation address
+in the TP_fast_assign() arm of the trace event, and store that as
+a string. This fix can be backported to -stable kernels.
+
+In the meantime, commit c6ced22997ad ("tracing: Update print fmt
+check to handle new __get_sockaddr() macro") is now in v5.18, so
+this wonky fix can be replaced with __sockaddr() and friends
+properly during the v5.19 merge window.
+
+Fixes: ece200ddd54b ("sunrpc: Save remote presentation address in svc_xprt for trace events")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/sunrpc.h | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
+index 23db248a7fdb..ed1bbac004d5 100644
+--- a/include/trace/events/sunrpc.h
++++ b/include/trace/events/sunrpc.h
+@@ -1874,17 +1874,18 @@ DECLARE_EVENT_CLASS(svc_deferred_event,
+ TP_STRUCT__entry(
+ __field(const void *, dr)
+ __field(u32, xid)
+- __string(addr, dr->xprt->xpt_remotebuf)
++ __array(__u8, addr, INET6_ADDRSTRLEN + 10)
+ ),
+
+ TP_fast_assign(
+ __entry->dr = dr;
+ __entry->xid = be32_to_cpu(*(__be32 *)(dr->args +
+ (dr->xprt_hlen>>2)));
+- __assign_str(addr, dr->xprt->xpt_remotebuf);
++ snprintf(__entry->addr, sizeof(__entry->addr) - 1,
++ "%pISpc", (struct sockaddr *)&dr->addr);
+ ),
+
+- TP_printk("addr=%s dr=%p xid=0x%08x", __get_str(addr), __entry->dr,
++ TP_printk("addr=%s dr=%p xid=0x%08x", __entry->addr, __entry->dr,
+ __entry->xid)
+ );
+
+--
+2.35.1
+
--- /dev/null
+From 039ad91fbf2d050333f8381794c81b7d668e1e62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Apr 2022 12:54:31 +0530
+Subject: testing/selftests/mqueue: Fix mq_perf_tests to free the allocated cpu
+ set
+
+From: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+
+[ Upstream commit ce64763c63854b4079f2e036638aa881a1fb3fbc ]
+
+The selftest "mqueue/mq_perf_tests.c" use CPU_ALLOC to allocate
+CPU set. This cpu set is used further in pthread_attr_setaffinity_np
+and by pthread_create in the code. But in current code, allocated
+cpu set is not freed.
+
+Fix this issue by adding CPU_FREE in the "shutdown" function which
+is called in most of the error/exit path for the cleanup. There are
+few error paths which exit without using shutdown. Add a common goto
+error path with CPU_FREE for these cases.
+
+Fixes: 7820b0715b6f ("tools/selftests: add mq_perf_tests")
+Signed-off-by: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../testing/selftests/mqueue/mq_perf_tests.c | 25 +++++++++++++------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+diff --git a/tools/testing/selftests/mqueue/mq_perf_tests.c b/tools/testing/selftests/mqueue/mq_perf_tests.c
+index b019e0b8221c..84fda3b49073 100644
+--- a/tools/testing/selftests/mqueue/mq_perf_tests.c
++++ b/tools/testing/selftests/mqueue/mq_perf_tests.c
+@@ -180,6 +180,9 @@ void shutdown(int exit_val, char *err_cause, int line_no)
+ if (in_shutdown++)
+ return;
+
++ /* Free the cpu_set allocated using CPU_ALLOC in main function */
++ CPU_FREE(cpu_set);
++
+ for (i = 0; i < num_cpus_to_pin; i++)
+ if (cpu_threads[i]) {
+ pthread_kill(cpu_threads[i], SIGUSR1);
+@@ -551,6 +554,12 @@ int main(int argc, char *argv[])
+ perror("sysconf(_SC_NPROCESSORS_ONLN)");
+ exit(1);
+ }
++
++ if (getuid() != 0)
++ ksft_exit_skip("Not running as root, but almost all tests "
++ "require root in order to modify\nsystem settings. "
++ "Exiting.\n");
++
+ cpus_online = min(MAX_CPUS, sysconf(_SC_NPROCESSORS_ONLN));
+ cpu_set = CPU_ALLOC(cpus_online);
+ if (cpu_set == NULL) {
+@@ -589,7 +598,7 @@ int main(int argc, char *argv[])
+ cpu_set)) {
+ fprintf(stderr, "Any given CPU may "
+ "only be given once.\n");
+- exit(1);
++ goto err_code;
+ } else
+ CPU_SET_S(cpus_to_pin[cpu],
+ cpu_set_size, cpu_set);
+@@ -607,7 +616,7 @@ int main(int argc, char *argv[])
+ queue_path = malloc(strlen(option) + 2);
+ if (!queue_path) {
+ perror("malloc()");
+- exit(1);
++ goto err_code;
+ }
+ queue_path[0] = '/';
+ queue_path[1] = 0;
+@@ -622,17 +631,12 @@ int main(int argc, char *argv[])
+ fprintf(stderr, "Must pass at least one CPU to continuous "
+ "mode.\n");
+ poptPrintUsage(popt_context, stderr, 0);
+- exit(1);
++ goto err_code;
+ } else if (!continuous_mode) {
+ num_cpus_to_pin = 1;
+ cpus_to_pin[0] = cpus_online - 1;
+ }
+
+- if (getuid() != 0)
+- ksft_exit_skip("Not running as root, but almost all tests "
+- "require root in order to modify\nsystem settings. "
+- "Exiting.\n");
+-
+ max_msgs = fopen(MAX_MSGS, "r+");
+ max_msgsize = fopen(MAX_MSGSIZE, "r+");
+ if (!max_msgs)
+@@ -740,4 +744,9 @@ int main(int argc, char *argv[])
+ sleep(1);
+ }
+ shutdown(0, "", 0);
++
++err_code:
++ CPU_FREE(cpu_set);
++ exit(1);
++
+ }
+--
+2.35.1
+
--- /dev/null
+From 7dd60fbc47a924e7a4375afaeddc86ec8abe73bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Mar 2022 12:25:43 +0100
+Subject: tlb: hugetlb: Add more sizes to tlb_remove_huge_tlb_entry
+
+From: Steve Capper <steve.capper@arm.com>
+
+[ Upstream commit 697a1d44af8ba0477ee729e632f4ade37999249a ]
+
+tlb_remove_huge_tlb_entry only considers PMD_SIZE and PUD_SIZE when
+updating the mmu_gather structure.
+
+Unfortunately on arm64 there are two additional huge page sizes that
+need to be covered: CONT_PTE_SIZE and CONT_PMD_SIZE. Where an end-user
+attempts to employ contiguous huge pages, a VM_BUG_ON can be experienced
+due to the fact that the tlb structure hasn't been correctly updated by
+the relevant tlb_flush_p.._range() call from tlb_remove_huge_tlb_entry.
+
+This patch adds inequality logic to the generic implementation of
+tlb_remove_huge_tlb_entry s.t. CONT_PTE_SIZE and CONT_PMD_SIZE are
+effectively covered on arm64. Also, as well as ptes, pmds and puds;
+p4ds are now considered too.
+
+Reported-by: David Hildenbrand <david@redhat.com>
+Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: Anshuman Khandual <anshuman.khandual@arm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/linux-mm/811c5c8e-b3a2-85d2-049c-717f17c3a03a@redhat.com/
+Signed-off-by: Steve Capper <steve.capper@arm.com>
+Acked-by: David Hildenbrand <david@redhat.com>
+Reviewed-by: Anshuman Khandual <anshuman.khandual@arm.com>
+Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220330112543.863-1-steve.capper@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/asm-generic/tlb.h | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
+index 6661ee1cff47..a0c4b99d2899 100644
+--- a/include/asm-generic/tlb.h
++++ b/include/asm-generic/tlb.h
+@@ -563,10 +563,14 @@ static inline void tlb_flush_p4d_range(struct mmu_gather *tlb,
+ #define tlb_remove_huge_tlb_entry(h, tlb, ptep, address) \
+ do { \
+ unsigned long _sz = huge_page_size(h); \
+- if (_sz == PMD_SIZE) \
+- tlb_flush_pmd_range(tlb, address, _sz); \
+- else if (_sz == PUD_SIZE) \
++ if (_sz >= P4D_SIZE) \
++ tlb_flush_p4d_range(tlb, address, _sz); \
++ else if (_sz >= PUD_SIZE) \
+ tlb_flush_pud_range(tlb, address, _sz); \
++ else if (_sz >= PMD_SIZE) \
++ tlb_flush_pmd_range(tlb, address, _sz); \
++ else \
++ tlb_flush_pte_range(tlb, address, _sz); \
+ __tlb_remove_tlb_entry(tlb, ptep, address); \
+ } while (0)
+
+--
+2.35.1
+
--- /dev/null
+From 8d0074ed6ecd6c903fc1fc8ddb7b2ed6811d2d81 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Apr 2022 16:18:54 +0200
+Subject: veth: Ensure eth header is in skb's linear part
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ Upstream commit 726e2c5929de841fdcef4e2bf995680688ae1b87 ]
+
+After feeding a decapsulated packet to a veth device with act_mirred,
+skb_headlen() may be 0. But veth_xmit() calls __dev_forward_skb(),
+which expects at least ETH_HLEN byte of linear data (as
+__dev_forward_skb2() calls eth_type_trans(), which pulls ETH_HLEN bytes
+unconditionally).
+
+Use pskb_may_pull() to ensure veth_xmit() respects this constraint.
+
+kernel BUG at include/linux/skbuff.h:2328!
+RIP: 0010:eth_type_trans+0xcf/0x140
+Call Trace:
+ <IRQ>
+ __dev_forward_skb2+0xe3/0x160
+ veth_xmit+0x6e/0x250 [veth]
+ dev_hard_start_xmit+0xc7/0x200
+ __dev_queue_xmit+0x47f/0x520
+ ? skb_ensure_writable+0x85/0xa0
+ ? skb_mpls_pop+0x98/0x1c0
+ tcf_mirred_act+0x442/0x47e [act_mirred]
+ tcf_action_exec+0x86/0x140
+ fl_classify+0x1d8/0x1e0 [cls_flower]
+ ? dma_pte_clear_level+0x129/0x1a0
+ ? dma_pte_clear_level+0x129/0x1a0
+ ? prb_fill_curr_block+0x2f/0xc0
+ ? skb_copy_bits+0x11a/0x220
+ __tcf_classify+0x58/0x110
+ tcf_classify_ingress+0x6b/0x140
+ __netif_receive_skb_core.constprop.0+0x47d/0xfd0
+ ? __iommu_dma_unmap_swiotlb+0x44/0x90
+ __netif_receive_skb_one_core+0x3d/0xa0
+ netif_receive_skb+0x116/0x170
+ be_process_rx+0x22f/0x330 [be2net]
+ be_poll+0x13c/0x370 [be2net]
+ __napi_poll+0x2a/0x170
+ net_rx_action+0x22f/0x2f0
+ __do_softirq+0xca/0x2a8
+ __irq_exit_rcu+0xc1/0xe0
+ common_interrupt+0x83/0xa0
+
+Fixes: e314dbdc1c0d ("[NET]: Virtual ethernet device driver.")
+Signed-off-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/veth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index f7e3eb309a26..5be8ed910553 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -292,7 +292,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ rcu_read_lock();
+ rcv = rcu_dereference(priv->peer);
+- if (unlikely(!rcv)) {
++ if (unlikely(!rcv) || !pskb_may_pull(skb, ETH_HLEN)) {
+ kfree_skb(skb);
+ goto drop;
+ }
+--
+2.35.1
+