--- /dev/null
+From 5fb67c8bf3ff9d0dd160763e420c7b0eb612ac87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Sep 2021 00:01:52 +0100
+Subject: afs: Fix corruption in reads at fpos 2G-4G from an OpenAFS server
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit b537a3c21775075395af475dcc6ef212fcf29db8 ]
+
+AFS-3 has two data fetch RPC variants, FS.FetchData and FS.FetchData64, and
+Linux's afs client switches between them when talking to a non-YFS server
+if the read size, the file position or the sum of the two have the upper 32
+bits set of the 64-bit value.
+
+This is a problem, however, since the file position and length fields of
+FS.FetchData are *signed* 32-bit values.
+
+Fix this by capturing the capability bits obtained from the fileserver when
+it's sent an FS.GetCapabilities RPC, rather than just discarding them, and
+then picking out the VICED_CAPABILITY_64BITFILES flag. This can then be
+used to decide whether to use FS.FetchData or FS.FetchData64 - and also
+FS.StoreData or FS.StoreData64 - rather than using upper_32_bits() to
+switch on the parameter values.
+
+This capabilities flag could also be used to limit the maximum size of the
+file, but all servers must be checked for that.
+
+Note that the issue does not exist with FS.StoreData - that uses *unsigned*
+32-bit values. It's also not a problem with Auristor servers as its
+YFS.FetchData64 op uses unsigned 64-bit values.
+
+This can be tested by cloning a git repo through an OpenAFS client to an
+OpenAFS server and then doing "git status" on it from a Linux afs
+client[1]. Provided the clone has a pack file that's in the 2G-4G range,
+the git status will show errors like:
+
+ error: packfile .git/objects/pack/pack-5e813c51d12b6847bbc0fcd97c2bca66da50079c.pack does not match index
+ error: packfile .git/objects/pack/pack-5e813c51d12b6847bbc0fcd97c2bca66da50079c.pack does not match index
+
+This can be observed in the server's FileLog with something like the
+following appearing:
+
+Sun Aug 29 19:31:39 2021 SRXAFS_FetchData, Fid = 2303380852.491776.3263114, Host 192.168.11.201:7001, Id 1001
+Sun Aug 29 19:31:39 2021 CheckRights: len=0, for host=192.168.11.201:7001
+Sun Aug 29 19:31:39 2021 FetchData_RXStyle: Pos 18446744071815340032, Len 3154
+Sun Aug 29 19:31:39 2021 FetchData_RXStyle: file size 2400758866
+...
+Sun Aug 29 19:31:40 2021 SRXAFS_FetchData returns 5
+
+Note the file position of 18446744071815340032. This is the requested file
+position sign-extended.
+
+Fixes: b9b1f8d5930a ("AFS: write support fixes")
+Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Marc Dionne <marc.dionne@auristor.com>
+Tested-by: Markus Suvanto <markus.suvanto@gmail.com>
+cc: linux-afs@lists.infradead.org
+cc: openafs-devel@openafs.org
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=214217#c9 [1]
+Link: https://lore.kernel.org/r/951332.1631308745@warthog.procyon.org.uk/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/fs_probe.c | 8 +++++++-
+ fs/afs/fsclient.c | 31 ++++++++++++++++++++-----------
+ fs/afs/internal.h | 1 +
+ fs/afs/protocol_afs.h | 15 +++++++++++++++
+ fs/afs/protocol_yfs.h | 6 ++++++
+ 5 files changed, 49 insertions(+), 12 deletions(-)
+ create mode 100644 fs/afs/protocol_afs.h
+
+diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c
+index e7e98ad63a91..c0031a3ab42f 100644
+--- a/fs/afs/fs_probe.c
++++ b/fs/afs/fs_probe.c
+@@ -9,6 +9,7 @@
+ #include <linux/slab.h>
+ #include "afs_fs.h"
+ #include "internal.h"
++#include "protocol_afs.h"
+ #include "protocol_yfs.h"
+
+ static unsigned int afs_fs_probe_fast_poll_interval = 30 * HZ;
+@@ -102,7 +103,7 @@ void afs_fileserver_probe_result(struct afs_call *call)
+ struct afs_addr_list *alist = call->alist;
+ struct afs_server *server = call->server;
+ unsigned int index = call->addr_ix;
+- unsigned int rtt_us = 0;
++ unsigned int rtt_us = 0, cap0;
+ int ret = call->error;
+
+ _enter("%pU,%u", &server->uuid, index);
+@@ -159,6 +160,11 @@ void afs_fileserver_probe_result(struct afs_call *call)
+ clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
+ alist->addrs[index].srx_service = call->service_id;
+ }
++ cap0 = ntohl(call->tmp);
++ if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES)
++ set_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
++ else
++ clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
+ }
+
+ if (rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us) &&
+diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
+index dd3f45d906d2..4943413d9c5f 100644
+--- a/fs/afs/fsclient.c
++++ b/fs/afs/fsclient.c
+@@ -456,9 +456,7 @@ void afs_fs_fetch_data(struct afs_operation *op)
+ struct afs_read *req = op->fetch.req;
+ __be32 *bp;
+
+- if (upper_32_bits(req->pos) ||
+- upper_32_bits(req->len) ||
+- upper_32_bits(req->pos + req->len))
++ if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
+ return afs_fs_fetch_data64(op);
+
+ _enter("");
+@@ -1113,9 +1111,7 @@ void afs_fs_store_data(struct afs_operation *op)
+ (unsigned long long)op->store.pos,
+ (unsigned long long)op->store.i_size);
+
+- if (upper_32_bits(op->store.pos) ||
+- upper_32_bits(op->store.size) ||
+- upper_32_bits(op->store.i_size))
++ if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
+ return afs_fs_store_data64(op);
+
+ call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData,
+@@ -1229,7 +1225,7 @@ static void afs_fs_setattr_size(struct afs_operation *op)
+ key_serial(op->key), vp->fid.vid, vp->fid.vnode);
+
+ ASSERT(attr->ia_valid & ATTR_SIZE);
+- if (upper_32_bits(attr->ia_size))
++ if (test_bit(AFS_SERVER_FL_HAS_FS64, &op->server->flags))
+ return afs_fs_setattr_size64(op);
+
+ call = afs_alloc_flat_call(op->net, &afs_RXFSStoreData_as_Status,
+@@ -1657,20 +1653,33 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
+ return ret;
+
+ count = ntohl(call->tmp);
+-
+ call->count = count;
+ call->count2 = count;
+- afs_extract_discard(call, count * sizeof(__be32));
++ if (count == 0) {
++ call->unmarshall = 4;
++ call->tmp = 0;
++ break;
++ }
++
++ /* Extract the first word of the capabilities to call->tmp */
++ afs_extract_to_tmp(call);
+ call->unmarshall++;
+ fallthrough;
+
+- /* Extract capabilities words */
+ case 2:
+ ret = afs_extract_data(call, false);
+ if (ret < 0)
+ return ret;
+
+- /* TODO: Examine capabilities */
++ afs_extract_discard(call, (count - 1) * sizeof(__be32));
++ call->unmarshall++;
++ fallthrough;
++
++ /* Extract remaining capabilities words */
++ case 3:
++ ret = afs_extract_data(call, false);
++ if (ret < 0)
++ return ret;
+
+ call->unmarshall++;
+ break;
+diff --git a/fs/afs/internal.h b/fs/afs/internal.h
+index 5ed416f4ff33..928408888054 100644
+--- a/fs/afs/internal.h
++++ b/fs/afs/internal.h
+@@ -516,6 +516,7 @@ struct afs_server {
+ #define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */
+ #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */
+ #define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */
++#define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */
+ atomic_t ref; /* Object refcount */
+ atomic_t active; /* Active user count */
+ u32 addr_version; /* Address list version */
+diff --git a/fs/afs/protocol_afs.h b/fs/afs/protocol_afs.h
+new file mode 100644
+index 000000000000..0c39358c8b70
+--- /dev/null
++++ b/fs/afs/protocol_afs.h
+@@ -0,0 +1,15 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/* AFS protocol bits
++ *
++ * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
++ * Written by David Howells (dhowells@redhat.com)
++ */
++
++
++#define AFSCAPABILITIESMAX 196 /* Maximum number of words in a capability set */
++
++/* AFS3 Fileserver capabilities word 0 */
++#define AFS3_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Uses UAE errors */
++#define AFS3_VICED_CAPABILITY_64BITFILES 0x0002 /* FetchData64 & StoreData64 supported */
++#define AFS3_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */
++#define AFS3_VICED_CAPABILITY_SANEACLS 0x0008 /* ACLs reviewed for sanity - don't use */
+diff --git a/fs/afs/protocol_yfs.h b/fs/afs/protocol_yfs.h
+index b5bd03b1d3c7..e4cd89c44c46 100644
+--- a/fs/afs/protocol_yfs.h
++++ b/fs/afs/protocol_yfs.h
+@@ -168,3 +168,9 @@ enum yfs_lock_type {
+ yfs_LockMandatoryWrite = 0x101,
+ yfs_LockMandatoryExtend = 0x102,
+ };
++
++/* RXYFS Viced Capability Flags */
++#define YFS_VICED_CAPABILITY_ERRORTRANS 0x0001 /* Deprecated v0.195 */
++#define YFS_VICED_CAPABILITY_64BITFILES 0x0002 /* Deprecated v0.195 */
++#define YFS_VICED_CAPABILITY_WRITELOCKACL 0x0004 /* Can lock a file even without lock perm */
++#define YFS_VICED_CAPABILITY_SANEACLS 0x0008 /* Deprecated v0.195 */
+--
+2.33.0
+
--- /dev/null
+From 91a80e76db4e4b1b7f72cd06d014eadbb8a254d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Sep 2021 18:11:33 +0100
+Subject: afs: Fix incorrect triggering of sillyrename on 3rd-party
+ invalidation
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 63d49d843ef5fffeea069e0ffdfbd2bf40ba01c6 ]
+
+The AFS filesystem is currently triggering the silly-rename cleanup from
+afs_d_revalidate() when it sees that a dentry has been changed by a third
+party[1]. It should not be doing this as the cleanup includes deleting the
+silly-rename target file on iput.
+
+Fix this by removing the places in the d_revalidate handling that validate
+anything other than the directory and the dirent. It probably should not
+be looking to validate the target inode of the dentry also.
+
+This includes removing the point in afs_d_revalidate() where the inode that
+a dentry used to point to was marked as being deleted (AFS_VNODE_DELETED).
+We don't know it got deleted. It could have been renamed or it could have
+hard links remaining.
+
+This was reproduced by cloning a git repo onto an afs volume on one
+machine, switching to another machine and doing "git status", then
+switching back to the first and doing "git status". The second status
+would show weird output due to ".git/index" getting deleted by the above
+mentioned mechanism.
+
+A simpler way to do it is to do:
+
+ machine 1: touch a
+ machine 2: touch b; mv -f b a
+ machine 1: stat a
+
+on an afs volume. The bug shows up as the stat failing with ENOENT and the
+file server log showing that machine 1 deleted "a".
+
+Fixes: 79ddbfa500b3 ("afs: Implement sillyrename for unlink and rename")
+Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Tested-by: Markus Suvanto <markus.suvanto@gmail.com>
+cc: linux-afs@lists.infradead.org
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=214217#c4 [1]
+Link: https://lore.kernel.org/r/163111668100.283156.3851669884664475428.stgit@warthog.procyon.org.uk/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/dir.c | 46 +++++++---------------------------------------
+ 1 file changed, 7 insertions(+), 39 deletions(-)
+
+diff --git a/fs/afs/dir.c b/fs/afs/dir.c
+index ac829e63c570..54ee54ae36bc 100644
+--- a/fs/afs/dir.c
++++ b/fs/afs/dir.c
+@@ -1077,9 +1077,9 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
+ */
+ static int afs_d_revalidate_rcu(struct dentry *dentry)
+ {
+- struct afs_vnode *dvnode, *vnode;
++ struct afs_vnode *dvnode;
+ struct dentry *parent;
+- struct inode *dir, *inode;
++ struct inode *dir;
+ long dir_version, de_version;
+
+ _enter("%p", dentry);
+@@ -1109,18 +1109,6 @@ static int afs_d_revalidate_rcu(struct dentry *dentry)
+ return -ECHILD;
+ }
+
+- /* Check to see if the vnode referred to by the dentry still
+- * has a callback.
+- */
+- if (d_really_is_positive(dentry)) {
+- inode = d_inode_rcu(dentry);
+- if (inode) {
+- vnode = AFS_FS_I(inode);
+- if (!afs_check_validity(vnode))
+- return -ECHILD;
+- }
+- }
+-
+ return 1; /* Still valid */
+ }
+
+@@ -1156,17 +1144,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ if (IS_ERR(key))
+ key = NULL;
+
+- if (d_really_is_positive(dentry)) {
+- inode = d_inode(dentry);
+- if (inode) {
+- vnode = AFS_FS_I(inode);
+- afs_validate(vnode, key);
+- if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
+- goto out_bad;
+- }
+- }
+-
+- /* lock down the parent dentry so we can peer at it */
++ /* Hold the parent dentry so we can peer at it */
+ parent = dget_parent(dentry);
+ dir = AFS_FS_I(d_inode(parent));
+
+@@ -1175,7 +1153,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+
+ if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
+ _debug("%pd: parent dir deleted", dentry);
+- goto out_bad_parent;
++ goto not_found;
+ }
+
+ /* We only need to invalidate a dentry if the server's copy changed
+@@ -1201,12 +1179,12 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ case 0:
+ /* the filename maps to something */
+ if (d_really_is_negative(dentry))
+- goto out_bad_parent;
++ goto not_found;
+ inode = d_inode(dentry);
+ if (is_bad_inode(inode)) {
+ printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
+ dentry);
+- goto out_bad_parent;
++ goto not_found;
+ }
+
+ vnode = AFS_FS_I(inode);
+@@ -1228,9 +1206,6 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ dentry, fid.unique,
+ vnode->fid.unique,
+ vnode->vfs_inode.i_generation);
+- write_seqlock(&vnode->cb_lock);
+- set_bit(AFS_VNODE_DELETED, &vnode->flags);
+- write_sequnlock(&vnode->cb_lock);
+ goto not_found;
+ }
+ goto out_valid;
+@@ -1245,7 +1220,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ default:
+ _debug("failed to iterate dir %pd: %d",
+ parent, ret);
+- goto out_bad_parent;
++ goto not_found;
+ }
+
+ out_valid:
+@@ -1256,16 +1231,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ _leave(" = 1 [valid]");
+ return 1;
+
+- /* the dirent, if it exists, now points to a different vnode */
+ not_found:
+- spin_lock(&dentry->d_lock);
+- dentry->d_flags |= DCACHE_NFSFS_RENAMED;
+- spin_unlock(&dentry->d_lock);
+-
+-out_bad_parent:
+ _debug("dropping dentry %pd2", dentry);
+ dput(parent);
+-out_bad:
+ key_put(key);
+
+ _leave(" = 0 [bad]");
+--
+2.33.0
+
--- /dev/null
+From d7185ea92614526b1882e73a7d19465cff5fb1c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Sep 2021 09:15:21 +0100
+Subject: afs: Fix page leak
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 581b2027af0018944ba301d68e7af45c6d1128b5 ]
+
+There's a loop in afs_extend_writeback() that adds extra pages to a write
+we want to make to improve the efficiency of the writeback by making it
+larger. This loop stops, however, if we hit a page we can't write back
+from immediately, but it doesn't get rid of the page ref we speculatively
+acquired.
+
+This was caused by the removal of the cleanup loop when the code switched
+from using find_get_pages_contig() to xarray scanning as the latter only
+gets a single page at a time, not a batch.
+
+Fix this by putting the page on a ref on an early break from the loop.
+Unfortunately, we can't just add that page to the pagevec we're employing
+as we'll go through that and add those pages to the RPC call.
+
+This was found by the generic/074 test. It leaks ~4GiB of RAM each time it
+is run - which can be observed with "top".
+
+Fixes: e87b03f5830e ("afs: Prepare for use of THPs")
+Reported-by: Marc Dionne <marc.dionne@auristor.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-and-tested-by: Marc Dionne <marc.dionne@auristor.com>
+cc: linux-afs@lists.infradead.org
+Link: https://lore.kernel.org/r/163111666635.283156.177701903478910460.stgit@warthog.procyon.org.uk/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/write.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/fs/afs/write.c b/fs/afs/write.c
+index c0534697268e..66b235266893 100644
+--- a/fs/afs/write.c
++++ b/fs/afs/write.c
+@@ -471,13 +471,18 @@ static void afs_extend_writeback(struct address_space *mapping,
+ }
+
+ /* Has the page moved or been split? */
+- if (unlikely(page != xas_reload(&xas)))
++ if (unlikely(page != xas_reload(&xas))) {
++ put_page(page);
+ break;
++ }
+
+- if (!trylock_page(page))
++ if (!trylock_page(page)) {
++ put_page(page);
+ break;
++ }
+ if (!PageDirty(page) || PageWriteback(page)) {
+ unlock_page(page);
++ put_page(page);
+ break;
+ }
+
+@@ -487,6 +492,7 @@ static void afs_extend_writeback(struct address_space *mapping,
+ t = afs_page_dirty_to(page, priv);
+ if (f != 0 && !new_content) {
+ unlock_page(page);
++ put_page(page);
+ break;
+ }
+
+--
+2.33.0
+
--- /dev/null
+From 156ba2d7137e093c21ca9f824caf71e8fe1d8b8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Sep 2021 21:55:19 +0100
+Subject: afs: Fix updating of i_blocks on file/dir extension
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 9d37e1cab2a9d2cee2737973fa455e6f89eee46a ]
+
+When an afs file or directory is modified locally such that the total file
+size is extended, i_blocks needs to be recalculated too.
+
+Fix this by making afs_write_end() and afs_edit_dir_add() call
+afs_set_i_size() rather than setting inode->i_size directly as that also
+recalculates inode->i_blocks.
+
+This can be tested by creating and writing into directories and files and
+then examining them with du. Without this change, directories show a 4
+blocks (they start out at 2048 bytes) and files show 0 blocks; with this
+change, they should show a number of blocks proportional to the file size
+rounded up to 1024.
+
+Fixes: 31143d5d515e ("AFS: implement basic file write support")
+Fixes: 63a4681ff39c ("afs: Locally edit directory data for mkdir/create/unlink/...")
+Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Reviewed-by: Marc Dionne <marc.dionne@auristor.com>
+Tested-by: Markus Suvanto <markus.suvanto@gmail.com>
+cc: linux-afs@lists.infradead.org
+Link: https://lore.kernel.org/r/163113612442.352844.11162345591911691150.stgit@warthog.procyon.org.uk/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/dir_edit.c | 4 ++--
+ fs/afs/inode.c | 10 ----------
+ fs/afs/internal.h | 10 ++++++++++
+ fs/afs/write.c | 2 +-
+ 4 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c
+index f4600c1353ad..540b9fc96824 100644
+--- a/fs/afs/dir_edit.c
++++ b/fs/afs/dir_edit.c
+@@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
+ if (b == nr_blocks) {
+ _debug("init %u", b);
+ afs_edit_init_block(meta, block, b);
+- i_size_write(&vnode->vfs_inode, (b + 1) * AFS_DIR_BLOCK_SIZE);
++ afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE);
+ }
+
+ /* Only lower dir pages have a counter in the header. */
+@@ -296,7 +296,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
+ new_directory:
+ afs_edit_init_block(meta, meta, 0);
+ i_size = AFS_DIR_BLOCK_SIZE;
+- i_size_write(&vnode->vfs_inode, i_size);
++ afs_set_i_size(vnode, i_size);
+ slot = AFS_DIR_RESV_BLOCKS0;
+ page = page0;
+ block = meta;
+diff --git a/fs/afs/inode.c b/fs/afs/inode.c
+index 80b6c8d967d5..c18cbc69fa58 100644
+--- a/fs/afs/inode.c
++++ b/fs/afs/inode.c
+@@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
+ dump_stack();
+ }
+
+-/*
+- * Set the file size and block count. Estimate the number of 512 bytes blocks
+- * used, rounded up to nearest 1K for consistency with other AFS clients.
+- */
+-static void afs_set_i_size(struct afs_vnode *vnode, u64 size)
+-{
+- i_size_write(&vnode->vfs_inode, size);
+- vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
+-}
+-
+ /*
+ * Initialise an inode from the vnode status.
+ */
+diff --git a/fs/afs/internal.h b/fs/afs/internal.h
+index 928408888054..345494881f65 100644
+--- a/fs/afs/internal.h
++++ b/fs/afs/internal.h
+@@ -1586,6 +1586,16 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
+ (void *)(unsigned long)dir_vp->scb.status.data_version;
+ }
+
++/*
++ * Set the file size and block count. Estimate the number of 512 bytes blocks
++ * used, rounded up to nearest 1K for consistency with other AFS clients.
++ */
++static inline void afs_set_i_size(struct afs_vnode *vnode, u64 size)
++{
++ i_size_write(&vnode->vfs_inode, size);
++ vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
++}
++
+ /*
+ * Check for a conflicting operation on a directory that we just unlinked from.
+ * If someone managed to sneak a link or an unlink in on the file we just
+diff --git a/fs/afs/write.c b/fs/afs/write.c
+index 66b235266893..e86f5a245514 100644
+--- a/fs/afs/write.c
++++ b/fs/afs/write.c
+@@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
+ write_seqlock(&vnode->cb_lock);
+ i_size = i_size_read(&vnode->vfs_inode);
+ if (maybe_i_size > i_size)
+- i_size_write(&vnode->vfs_inode, maybe_i_size);
++ afs_set_i_size(vnode, maybe_i_size);
+ write_sequnlock(&vnode->cb_lock);
+ }
+
+--
+2.33.0
+
--- /dev/null
+From 639f62086b5f30c9928cb016aa44d239edbcdb97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Sep 2021 03:16:05 -0700
+Subject: atlantic: Fix issue in the pm resume flow.
+
+From: Sudarsana Reddy Kalluru <skalluru@marvell.com>
+
+[ Upstream commit 4d88c339c423eefe2fd48215016cb0c75fcb4c4d ]
+
+After fixing hibernation resume flow, another usecase was found which
+should be explicitly handled - resume when device is in "down" state.
+Invoke aq_nic_init jointly with aq_nic_start only if ndev was already
+up during suspend/hibernate. We still need to perform nic_deinit() if
+caller requests for it, to handle the freeze/resume scenarios.
+
+Fixes: 57f780f1c433 ("atlantic: Fix driver resume flow.")
+Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
+Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+index f26d03735619..5b996330f228 100644
+--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
++++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+@@ -419,13 +419,13 @@ static int atl_resume_common(struct device *dev, bool deep)
+ if (deep) {
+ /* Reinitialize Nic/Vecs objects */
+ aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol);
++ }
+
++ if (netif_running(nic->ndev)) {
+ ret = aq_nic_init(nic);
+ if (ret)
+ goto err_exit;
+- }
+
+- if (netif_running(nic->ndev)) {
+ ret = aq_nic_start(nic);
+ if (ret)
+ goto err_exit;
+--
+2.33.0
+
--- /dev/null
+From c5193ea352b9a256ce4c490e65cdd3f28039c040 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Sep 2021 02:51:52 -0400
+Subject: bnxt_en: Fix TX timeout when TX ring size is set to the smallest
+
+From: Michael Chan <michael.chan@broadcom.com>
+
+[ Upstream commit 5bed8b0704c9ecccc8f4a2c377d7c8e21090a82e ]
+
+The smallest TX ring size we support must fit a TX SKB with MAX_SKB_FRAGS
++ 1. Because the first TX BD for a packet is always a long TX BD, we
+need an extra TX BD to fit this packet. Define BNXT_MIN_TX_DESC_CNT with
+this value to make this more clear. The current code uses a minimum
+that is off by 1. Fix it using this constant.
+
+The tx_wake_thresh to determine when to wake up the TX queue is half the
+ring size but we must have at least BNXT_MIN_TX_DESC_CNT for the next
+packet which may have maximum fragments. So the comparison of the
+available TX BDs with tx_wake_thresh should be >= instead of > in the
+current code. Otherwise, at the smallest ring size, we will never wake
+up the TX queue and will cause TX timeout.
+
+Fixes: c0c050c58d84 ("bnxt_en: New Broadcom ethernet driver.")
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Signed-off-by: Michael Chan <michael.chan@broadocm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++----
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 5 +++++
+ drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +-
+ 3 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index fdbf47446a99..f20b57b8cd70 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -385,7 +385,7 @@ static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp,
+ * netif_tx_queue_stopped().
+ */
+ smp_mb();
+- if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) {
++ if (bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh) {
+ netif_tx_wake_queue(txq);
+ return false;
+ }
+@@ -758,7 +758,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+ smp_mb();
+
+ if (unlikely(netif_tx_queue_stopped(txq)) &&
+- bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
++ bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh &&
+ READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING)
+ netif_tx_wake_queue(txq);
+ }
+@@ -2375,7 +2375,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
+ tx_pkts++;
+ /* return full budget so NAPI will complete. */
+- if (unlikely(tx_pkts > bp->tx_wake_thresh)) {
++ if (unlikely(tx_pkts >= bp->tx_wake_thresh)) {
+ rx_pkts = budget;
+ raw_cons = NEXT_RAW_CMP(raw_cons);
+ if (budget)
+@@ -3531,7 +3531,7 @@ static int bnxt_init_tx_rings(struct bnxt *bp)
+ u16 i;
+
+ bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2,
+- MAX_SKB_FRAGS + 1);
++ BNXT_MIN_TX_DESC_CNT);
+
+ for (i = 0; i < bp->tx_nr_rings; i++) {
+ struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index ba4e0fc38520..d4dca4508d26 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -615,6 +615,11 @@ struct nqe_cn {
+ #define BNXT_MAX_RX_JUM_DESC_CNT (RX_DESC_CNT * MAX_RX_AGG_PAGES - 1)
+ #define BNXT_MAX_TX_DESC_CNT (TX_DESC_CNT * MAX_TX_PAGES - 1)
+
++/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1. We need one extra
++ * BD because the first TX BD is always a long BD.
++ */
++#define BNXT_MIN_TX_DESC_CNT (MAX_SKB_FRAGS + 2)
++
+ #define RX_RING(x) (((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
+ #define RX_IDX(x) ((x) & (RX_DESC_CNT - 1))
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+index 786ca51e669b..3a8c28463592 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+@@ -784,7 +784,7 @@ static int bnxt_set_ringparam(struct net_device *dev,
+
+ if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) ||
+ (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) ||
+- (ering->tx_pending <= MAX_SKB_FRAGS))
++ (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
+ return -EINVAL;
+
+ if (netif_running(dev))
+--
+2.33.0
+
--- /dev/null
+From 0f9a3e1ae8c30341caea807fb637c3052c984a55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Sep 2021 16:33:40 -0400
+Subject: drm/amdkfd: fix dma mapping leaking warning
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit f63251184a81039ebc805306505838c2a073e51a ]
+
+For xnack off, restore work dma unmap previous system memory page, and
+dma map the updated system memory page to update GPU mapping, this is
+not dma mapping leaking, remove the WARN_ONCE for dma mapping leaking.
+
+prange->dma_addr store the VRAM page pfn after the range migrated to
+VRAM, should not dma unmap VRAM page when updating GPU mapping or
+remove prange. Add helper svm_is_valid_dma_mapping_addr to check VRAM
+page and error cases.
+
+Mask out SVM_RANGE_VRAM_DOMAIN flag in dma_addr before calling amdgpu vm
+update to avoid BUG_ON(*addr & 0xFFFF00000000003FULL), and set it again
+immediately after. This flag is used to know the type of page later to
+dma unmapping system memory page.
+
+Fixes: 1d5dbfe6c06a ("drm/amdkfd: classify and map mixed svm range pages in GPU")
+Signed-off-by: Philip Yang <Philip.Yang@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/amdkfd/kfd_svm.c | 18 ++++++++++++++----
+ 1 file changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index ddac10b5bd3a..e85035fd1ccb 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -118,6 +118,13 @@ static void svm_range_remove_notifier(struct svm_range *prange)
+ mmu_interval_notifier_remove(&prange->notifier);
+ }
+
++static bool
++svm_is_valid_dma_mapping_addr(struct device *dev, dma_addr_t dma_addr)
++{
++ return dma_addr && !dma_mapping_error(dev, dma_addr) &&
++ !(dma_addr & SVM_RANGE_VRAM_DOMAIN);
++}
++
+ static int
+ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
+ unsigned long offset, unsigned long npages,
+@@ -139,8 +146,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
+
+ addr += offset;
+ for (i = 0; i < npages; i++) {
+- if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
+- "leaking dma mapping\n"))
++ if (svm_is_valid_dma_mapping_addr(dev, addr[i]))
+ dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
+
+ page = hmm_pfn_to_page(hmm_pfns[i]);
+@@ -209,7 +215,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr,
+ return;
+
+ for (i = offset; i < offset + npages; i++) {
+- if (!dma_addr[i] || dma_mapping_error(dev, dma_addr[i]))
++ if (!svm_is_valid_dma_mapping_addr(dev, dma_addr[i]))
+ continue;
+ pr_debug("dma unmapping 0x%llx\n", dma_addr[i] >> PAGE_SHIFT);
+ dma_unmap_page(dev, dma_addr[i], PAGE_SIZE, dir);
+@@ -1165,7 +1171,7 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ unsigned long last_start;
+ int last_domain;
+ int r = 0;
+- int64_t i;
++ int64_t i, j;
+
+ last_start = prange->start + offset;
+
+@@ -1201,6 +1207,10 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ NULL, dma_addr,
+ &vm->last_update,
+ &table_freed);
++
++ for (j = last_start - prange->start; j <= i; j++)
++ dma_addr[j] |= last_domain;
++
+ if (r) {
+ pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start);
+ goto out;
+--
+2.33.0
+
--- /dev/null
+From e59ed433e8f04fc3300c0a349f2913470b60083b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Aug 2021 09:34:53 -0400
+Subject: drm/amdkfd: map SVM range with correct access permission
+
+From: Philip Yang <Philip.Yang@amd.com>
+
+[ Upstream commit 2f617f4df8dfef68f175160d533f5820a368023e ]
+
+Restore retry fault or prefetch range, or restore svm range after
+eviction to map range to GPU with correct read or write access
+permission.
+
+Range may includes multiple VMAs, update GPU page table with offset of
+prange, number of pages for each VMA according VMA access permission.
+
+Signed-off-by: Philip Yang <Philip.Yang@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/amdkfd/kfd_svm.c | 134 +++++++++++++++++----------
+ 1 file changed, 86 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index 0f7f1e5621ea..ddac10b5bd3a 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -120,6 +120,7 @@ static void svm_range_remove_notifier(struct svm_range *prange)
+
+ static int
+ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
++ unsigned long offset, unsigned long npages,
+ unsigned long *hmm_pfns, uint32_t gpuidx)
+ {
+ enum dma_data_direction dir = DMA_BIDIRECTIONAL;
+@@ -136,7 +137,8 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
+ prange->dma_addr[gpuidx] = addr;
+ }
+
+- for (i = 0; i < prange->npages; i++) {
++ addr += offset;
++ for (i = 0; i < npages; i++) {
+ if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]),
+ "leaking dma mapping\n"))
+ dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
+@@ -167,6 +169,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
+
+ static int
+ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
++ unsigned long offset, unsigned long npages,
+ unsigned long *hmm_pfns)
+ {
+ struct kfd_process *p;
+@@ -187,7 +190,8 @@ svm_range_dma_map(struct svm_range *prange, unsigned long *bitmap,
+ }
+ adev = (struct amdgpu_device *)pdd->dev->kgd;
+
+- r = svm_range_dma_map_dev(adev, prange, hmm_pfns, gpuidx);
++ r = svm_range_dma_map_dev(adev, prange, offset, npages,
++ hmm_pfns, gpuidx);
+ if (r)
+ break;
+ }
+@@ -1088,11 +1092,6 @@ svm_range_get_pte_flags(struct amdgpu_device *adev, struct svm_range *prange,
+ pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
+
+ pte_flags |= amdgpu_gem_va_map_flags(adev, mapping_flags);
+-
+- pr_debug("svms 0x%p [0x%lx 0x%lx] vram %d PTE 0x%llx mapping 0x%x\n",
+- prange->svms, prange->start, prange->last,
+- (domain == SVM_RANGE_VRAM_DOMAIN) ? 1:0, pte_flags, mapping_flags);
+-
+ return pte_flags;
+ }
+
+@@ -1156,7 +1155,8 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start,
+
+ static int
+ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+- struct svm_range *prange, dma_addr_t *dma_addr,
++ struct svm_range *prange, unsigned long offset,
++ unsigned long npages, bool readonly, dma_addr_t *dma_addr,
+ struct amdgpu_device *bo_adev, struct dma_fence **fence)
+ {
+ struct amdgpu_bo_va bo_va;
+@@ -1167,14 +1167,15 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ int r = 0;
+ int64_t i;
+
+- pr_debug("svms 0x%p [0x%lx 0x%lx]\n", prange->svms, prange->start,
+- prange->last);
++ last_start = prange->start + offset;
++
++ pr_debug("svms 0x%p [0x%lx 0x%lx] readonly %d\n", prange->svms,
++ last_start, last_start + npages - 1, readonly);
+
+ if (prange->svm_bo && prange->ttm_res)
+ bo_va.is_xgmi = amdgpu_xgmi_same_hive(adev, bo_adev);
+
+- last_start = prange->start;
+- for (i = 0; i < prange->npages; i++) {
++ for (i = offset; i < offset + npages; i++) {
+ last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN;
+ dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN;
+ if ((prange->start + i) < prange->last &&
+@@ -1183,13 +1184,21 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+
+ pr_debug("Mapping range [0x%lx 0x%llx] on domain: %s\n",
+ last_start, prange->start + i, last_domain ? "GPU" : "CPU");
++
+ pte_flags = svm_range_get_pte_flags(adev, prange, last_domain);
+- r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false, NULL,
+- last_start,
++ if (readonly)
++ pte_flags &= ~AMDGPU_PTE_WRITEABLE;
++
++ pr_debug("svms 0x%p map [0x%lx 0x%llx] vram %d PTE 0x%llx\n",
++ prange->svms, last_start, prange->start + i,
++ (last_domain == SVM_RANGE_VRAM_DOMAIN) ? 1 : 0,
++ pte_flags);
++
++ r = amdgpu_vm_bo_update_mapping(adev, bo_adev, vm, false, false,
++ NULL, last_start,
+ prange->start + i, pte_flags,
+ last_start - prange->start,
+- NULL,
+- dma_addr,
++ NULL, dma_addr,
+ &vm->last_update,
+ &table_freed);
+ if (r) {
+@@ -1220,8 +1229,10 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ return r;
+ }
+
+-static int svm_range_map_to_gpus(struct svm_range *prange,
+- unsigned long *bitmap, bool wait)
++static int
++svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset,
++ unsigned long npages, bool readonly,
++ unsigned long *bitmap, bool wait)
+ {
+ struct kfd_process_device *pdd;
+ struct amdgpu_device *bo_adev;
+@@ -1257,7 +1268,8 @@ static int svm_range_map_to_gpus(struct svm_range *prange,
+ }
+
+ r = svm_range_map_to_gpu(adev, drm_priv_to_vm(pdd->drm_priv),
+- prange, prange->dma_addr[gpuidx],
++ prange, offset, npages, readonly,
++ prange->dma_addr[gpuidx],
+ bo_adev, wait ? &fence : NULL);
+ if (r)
+ break;
+@@ -1390,7 +1402,7 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+ int32_t gpuidx, bool intr, bool wait)
+ {
+ struct svm_validate_context ctx;
+- struct hmm_range *hmm_range;
++ unsigned long start, end, addr;
+ struct kfd_process *p;
+ void *owner;
+ int32_t idx;
+@@ -1448,40 +1460,66 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
+ break;
+ }
+ }
+- r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
+- prange->start << PAGE_SHIFT,
+- prange->npages, &hmm_range,
+- false, true, owner);
+- if (r) {
+- pr_debug("failed %d to get svm range pages\n", r);
+- goto unreserve_out;
+- }
+
+- r = svm_range_dma_map(prange, ctx.bitmap,
+- hmm_range->hmm_pfns);
+- if (r) {
+- pr_debug("failed %d to dma map range\n", r);
+- goto unreserve_out;
+- }
++ start = prange->start << PAGE_SHIFT;
++ end = (prange->last + 1) << PAGE_SHIFT;
++ for (addr = start; addr < end && !r; ) {
++ struct hmm_range *hmm_range;
++ struct vm_area_struct *vma;
++ unsigned long next;
++ unsigned long offset;
++ unsigned long npages;
++ bool readonly;
+
+- prange->validated_once = true;
++ vma = find_vma(mm, addr);
++ if (!vma || addr < vma->vm_start) {
++ r = -EFAULT;
++ goto unreserve_out;
++ }
++ readonly = !(vma->vm_flags & VM_WRITE);
+
+- svm_range_lock(prange);
+- if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
+- pr_debug("hmm update the range, need validate again\n");
+- r = -EAGAIN;
+- goto unlock_out;
+- }
+- if (!list_empty(&prange->child_list)) {
+- pr_debug("range split by unmap in parallel, validate again\n");
+- r = -EAGAIN;
+- goto unlock_out;
+- }
++ next = min(vma->vm_end, end);
++ npages = (next - addr) >> PAGE_SHIFT;
++ r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
++ addr, npages, &hmm_range,
++ readonly, true, owner);
++ if (r) {
++ pr_debug("failed %d to get svm range pages\n", r);
++ goto unreserve_out;
++ }
+
+- r = svm_range_map_to_gpus(prange, ctx.bitmap, wait);
++ offset = (addr - start) >> PAGE_SHIFT;
++ r = svm_range_dma_map(prange, ctx.bitmap, offset, npages,
++ hmm_range->hmm_pfns);
++ if (r) {
++ pr_debug("failed %d to dma map range\n", r);
++ goto unreserve_out;
++ }
++
++ svm_range_lock(prange);
++ if (amdgpu_hmm_range_get_pages_done(hmm_range)) {
++ pr_debug("hmm update the range, need validate again\n");
++ r = -EAGAIN;
++ goto unlock_out;
++ }
++ if (!list_empty(&prange->child_list)) {
++ pr_debug("range split by unmap in parallel, validate again\n");
++ r = -EAGAIN;
++ goto unlock_out;
++ }
++
++ r = svm_range_map_to_gpus(prange, offset, npages, readonly,
++ ctx.bitmap, wait);
+
+ unlock_out:
+- svm_range_unlock(prange);
++ svm_range_unlock(prange);
++
++ addr = next;
++ }
++
++ if (addr == end)
++ prange->validated_once = true;
++
+ unreserve_out:
+ svm_range_unreserve_bos(&ctx);
+
+--
+2.33.0
+
--- /dev/null
+From 660f756a6358ea6c7aa75a240b0ca081b89f140c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 13:22:05 +0300
+Subject: enetc: Fix illegal access when reading affinity_hint
+
+From: Claudiu Manoil <claudiu.manoil@nxp.com>
+
+[ Upstream commit 7237a494decfa17d0b9d0076e6cee3235719de90 ]
+
+irq_set_affinity_hit() stores a reference to the cpumask_t
+parameter in the irq descriptor, and that reference can be
+accessed later from irq_affinity_hint_proc_show(). Since
+the cpu_mask parameter passed to irq_set_affinity_hit() has
+only temporary storage (it's on the stack memory), later
+accesses to it are illegal. Thus reads from the corresponding
+procfs affinity_hint file can result in paging request oops.
+
+The issue is fixed by the get_cpu_mask() helper, which provides
+a permanent storage for the cpumask_t parameter.
+
+Fixes: d4fd0404c1c9 ("enetc: Introduce basic PF and VF ENETC ethernet drivers")
+Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/enetc/enetc.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
+index 3ca93adb9662..7f90c27c0e79 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc.c
+@@ -1879,7 +1879,6 @@ static void enetc_clear_bdrs(struct enetc_ndev_priv *priv)
+ static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
+ {
+ struct pci_dev *pdev = priv->si->pdev;
+- cpumask_t cpu_mask;
+ int i, j, err;
+
+ for (i = 0; i < priv->bdr_int_num; i++) {
+@@ -1908,9 +1907,7 @@ static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
+
+ enetc_wr(hw, ENETC_SIMSITRV(idx), entry);
+ }
+- cpumask_clear(&cpu_mask);
+- cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
+- irq_set_affinity_hint(irq, &cpu_mask);
++ irq_set_affinity_hint(irq, get_cpu_mask(i % num_online_cpus()));
+ }
+
+ return 0;
+--
+2.33.0
+
--- /dev/null
+From e5f82d256992b7f85706f6310223fcc2dbdeb2ac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 13:22:06 +0300
+Subject: enetc: Fix uninitialized struct dim_sample field usage
+
+From: Claudiu Manoil <claudiu.manoil@nxp.com>
+
+[ Upstream commit 9f7afa05c9522b086327929ae622facab0f0f72b ]
+
+The only struct dim_sample member that does not get
+initialized by dim_update_sample() is comp_ctr. (There
+is special API to initialize comp_ctr:
+dim_update_sample_with_comps(), and it is currently used
+only for RDMA.) comp_ctr is used to compute curr_stats->cmps
+and curr_stats->cpe_ratio (see dim_calc_stats()) which in
+turn are consumed by the rdma_dim_*() API. Therefore,
+functionally, the net_dim*() API consumers are not affected.
+Nevertheless, fix the computation of statistics based
+on an uninitialized variable, even if the mentioned statistics
+are not used at the moment.
+
+Fixes: ae0e6a5d1627 ("enetc: Add adaptive interrupt coalescing")
+Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/enetc/enetc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
+index 7f90c27c0e79..042327b9981f 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc.c
+@@ -419,7 +419,7 @@ static void enetc_rx_dim_work(struct work_struct *w)
+
+ static void enetc_rx_net_dim(struct enetc_int_vector *v)
+ {
+- struct dim_sample dim_sample;
++ struct dim_sample dim_sample = {};
+
+ v->comp_cnt++;
+
+--
+2.33.0
+
--- /dev/null
+From 73b2756a7b24d59169de31ec4a1987e6a4b0b770 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Sep 2021 20:19:35 +0900
+Subject: gpio: uniphier: Fix void functions to remove return value
+
+From: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+[ Upstream commit 2dd824cca3407bc9a2bd11b00f6e117b66fcfcf1 ]
+
+The return type of irq_chip.irq_mask() and irq_chip.irq_unmask() should
+be void.
+
+Fixes: dbe776c2ca54 ("gpio: uniphier: add UniPhier GPIO controller driver")
+Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-uniphier.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
+index f99f3c10bed0..39dca147d587 100644
+--- a/drivers/gpio/gpio-uniphier.c
++++ b/drivers/gpio/gpio-uniphier.c
+@@ -184,7 +184,7 @@ static void uniphier_gpio_irq_mask(struct irq_data *data)
+
+ uniphier_gpio_reg_update(priv, UNIPHIER_GPIO_IRQ_EN, mask, 0);
+
+- return irq_chip_mask_parent(data);
++ irq_chip_mask_parent(data);
+ }
+
+ static void uniphier_gpio_irq_unmask(struct irq_data *data)
+@@ -194,7 +194,7 @@ static void uniphier_gpio_irq_unmask(struct irq_data *data)
+
+ uniphier_gpio_reg_update(priv, UNIPHIER_GPIO_IRQ_EN, mask, mask);
+
+- return irq_chip_unmask_parent(data);
++ irq_chip_unmask_parent(data);
+ }
+
+ static int uniphier_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+--
+2.33.0
+
--- /dev/null
+From 89c5f75daa3cce1e1606458f30182b4aeca7b9fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Aug 2021 12:41:19 +0200
+Subject: gpiolib: acpi: Make set-debounce-timeout failures non fatal
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit cef0d022f55364d69017daeb9443bd31510ad6a2 ]
+
+Commit 8dcb7a15a585 ("gpiolib: acpi: Take into account debounce settings")
+made the gpiolib-acpi code call gpio_set_debounce_timeout() when requesting
+GPIOs.
+
+This in itself is fine, but it also made gpio_set_debounce_timeout()
+errors fatal, causing the requesting of the GPIO to fail. This is causing
+regressions. E.g. on a HP ElitePad 1000 G2 various _AEI specified GPIO
+ACPI event sources specify a debouncy timeout of 20 ms, but the
+pinctrl-baytrail.c only supports certain fixed values, the closest
+ones being 12 or 24 ms and pinctrl-baytrail.c responds with -EINVAL
+when specified a value which is not one of the fixed values.
+
+This is causing the acpi_request_own_gpiod() call to fail for 3
+ACPI event sources on the HP ElitePad 1000 G2, which in turn is causing
+e.g. the battery charging vs discharging status to never get updated,
+even though a charger has been plugged-in or unplugged.
+
+Make gpio_set_debounce_timeout() errors non fatal, warning about the
+failure instead, to fix this regression.
+
+Note we should probably also fix various pinctrl drivers to just
+pick the first bigger discrete value rather then returning -EINVAL but
+this will need to be done on a per driver basis, where as this fix
+at least gets us back to where things were before and thus restores
+functionality on devices where this was lost due to
+gpio_set_debounce_timeout() errors.
+
+Fixes: 8dcb7a15a585 ("gpiolib: acpi: Take into account debounce settings")
+Depends-on: 2e2b496cebef ("gpiolib: acpi: Extract acpi_request_own_gpiod() helper")
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpiolib-acpi.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 411525ac4cc4..47712b6903b5 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -313,9 +313,11 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
+
+ ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout);
+ if (ret)
+- gpiochip_free_own_desc(desc);
++ dev_warn(chip->parent,
++ "Failed to set debounce-timeout for pin 0x%04X, err %d\n",
++ pin, ret);
+
+- return ret ? ERR_PTR(ret) : desc;
++ return desc;
+ }
+
+ static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
+--
+2.33.0
+
--- /dev/null
+From b0109b74618c35b48f2aed1d456a3141bba02ea3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 14:05:47 -0700
+Subject: igc: fix build errors for PTP
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 87758511075ec961486fe78d7548dd709b524433 ]
+
+When IGC=y and PTP_1588_CLOCK=m, the ptp_*() interface family is
+not available to the igc driver. Make this driver depend on
+PTP_1588_CLOCK_OPTIONAL so that it will build without errors.
+
+Various igc commits have used ptp_*() functions without checking
+that PTP_1588_CLOCK is enabled. Fix all of these here.
+
+Fixes these build errors:
+
+ld: drivers/net/ethernet/intel/igc/igc_main.o: in function `igc_msix_other':
+igc_main.c:(.text+0x6494): undefined reference to `ptp_clock_event'
+ld: igc_main.c:(.text+0x64ef): undefined reference to `ptp_clock_event'
+ld: igc_main.c:(.text+0x6559): undefined reference to `ptp_clock_event'
+ld: drivers/net/ethernet/intel/igc/igc_ethtool.o: in function `igc_ethtool_get_ts_info':
+igc_ethtool.c:(.text+0xc7a): undefined reference to `ptp_clock_index'
+ld: drivers/net/ethernet/intel/igc/igc_ptp.o: in function `igc_ptp_feature_enable_i225':
+igc_ptp.c:(.text+0x330): undefined reference to `ptp_find_pin'
+ld: igc_ptp.c:(.text+0x36f): undefined reference to `ptp_find_pin'
+ld: drivers/net/ethernet/intel/igc/igc_ptp.o: in function `igc_ptp_init':
+igc_ptp.c:(.text+0x11cd): undefined reference to `ptp_clock_register'
+ld: drivers/net/ethernet/intel/igc/igc_ptp.o: in function `igc_ptp_stop':
+igc_ptp.c:(.text+0x12dd): undefined reference to `ptp_clock_unregister'
+ld: drivers/platform/x86/dell/dell-wmi-privacy.o: in function `dell_privacy_wmi_probe':
+
+Fixes: 64433e5bf40ab ("igc: Enable internal i225 PPS")
+Fixes: 60dbede0c4f3d ("igc: Add support for ethtool GET_TS_INFO command")
+Fixes: 87938851b6efb ("igc: enable auxiliary PHC functions for the i225")
+Fixes: 5f2958052c582 ("igc: Add basic skeleton for PTP")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Ederson de Souza <ederson.desouza@intel.com>
+Cc: Tony Nguyen <anthony.l.nguyen@intel.com>
+Cc: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Cc: intel-wired-lan@lists.osuosl.org
+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>
+---
+ drivers/net/ethernet/intel/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
+index 82744a7501c7..c11d974a62d8 100644
+--- a/drivers/net/ethernet/intel/Kconfig
++++ b/drivers/net/ethernet/intel/Kconfig
+@@ -335,6 +335,7 @@ config IGC
+ tristate "Intel(R) Ethernet Controller I225-LM/I225-V support"
+ default n
+ depends on PCI
++ depends on PTP_1588_CLOCK_OPTIONAL
+ help
+ This driver supports Intel(R) Ethernet Controller I225-LM/I225-V
+ family of adapters.
+--
+2.33.0
+
--- /dev/null
+From fa72d24606bffc558979c61627352e16d3d95028 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Aug 2021 14:42:40 +0100
+Subject: kselftest/arm64: signal: Add SVE to the set of features we can check
+ for
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit d4e4dc4fab686c5f3f185272a19b83930664bef5 ]
+
+Allow testcases for SVE signal handling to flag the dependency and be
+skipped on systems without SVE support.
+
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20210819134245.13935-2-broonie@kernel.org
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/arm64/signal/test_signals.h | 2 ++
+ tools/testing/selftests/arm64/signal/test_signals_utils.c | 3 +++
+ 2 files changed, 5 insertions(+)
+
+diff --git a/tools/testing/selftests/arm64/signal/test_signals.h b/tools/testing/selftests/arm64/signal/test_signals.h
+index f96baf1cef1a..ebe8694dbef0 100644
+--- a/tools/testing/selftests/arm64/signal/test_signals.h
++++ b/tools/testing/selftests/arm64/signal/test_signals.h
+@@ -33,10 +33,12 @@
+ */
+ enum {
+ FSSBS_BIT,
++ FSVE_BIT,
+ FMAX_END
+ };
+
+ #define FEAT_SSBS (1UL << FSSBS_BIT)
++#define FEAT_SVE (1UL << FSVE_BIT)
+
+ /*
+ * A descriptor used to describe and configure a test case.
+diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c
+index 2de6e5ed5e25..6836510a522f 100644
+--- a/tools/testing/selftests/arm64/signal/test_signals_utils.c
++++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c
+@@ -26,6 +26,7 @@ static int sig_copyctx = SIGTRAP;
+
+ static char const *const feats_names[FMAX_END] = {
+ " SSBS ",
++ " SVE ",
+ };
+
+ #define MAX_FEATS_SZ 128
+@@ -263,6 +264,8 @@ int test_init(struct tdescr *td)
+ */
+ if (getauxval(AT_HWCAP) & HWCAP_SSBS)
+ td->feats_supported |= FEAT_SSBS;
++ if (getauxval(AT_HWCAP) & HWCAP_SVE)
++ td->feats_supported |= FEAT_SVE;
+ if (feats_ok(td))
+ fprintf(stderr,
+ "Required Features: [%s] supported\n",
+--
+2.33.0
+
--- /dev/null
+From d07d4e71c57304f12a160b5fca0f2885dddbb0a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Sep 2021 13:12:28 +0100
+Subject: kselftest/arm64: signal: Skip tests if required features are missing
+
+From: Cristian Marussi <cristian.marussi@arm.com>
+
+[ Upstream commit 0e3dbf765fe22060acbcb8eb8c4d256e655a1247 ]
+
+During initialization of a signal testcase, features declared as required
+are properly checked against the running system but no action is then taken
+to effectively skip such a testcase.
+
+Fix core signals test logic to abort initialization and report such a
+testcase as skipped to the KSelfTest framework.
+
+Fixes: f96bf4340316 ("kselftest: arm64: mangle_pstate_invalid_compat_toggle and common utils")
+Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20210920121228.35368-1-cristian.marussi@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/arm64/signal/test_signals_utils.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c
+index 6836510a522f..22722abc9dfa 100644
+--- a/tools/testing/selftests/arm64/signal/test_signals_utils.c
++++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c
+@@ -266,16 +266,19 @@ int test_init(struct tdescr *td)
+ td->feats_supported |= FEAT_SSBS;
+ if (getauxval(AT_HWCAP) & HWCAP_SVE)
+ td->feats_supported |= FEAT_SVE;
+- if (feats_ok(td))
++ if (feats_ok(td)) {
+ fprintf(stderr,
+ "Required Features: [%s] supported\n",
+ feats_to_string(td->feats_required &
+ td->feats_supported));
+- else
++ } else {
+ fprintf(stderr,
+ "Required Features: [%s] NOT supported\n",
+ feats_to_string(td->feats_required &
+ ~td->feats_supported));
++ td->result = KSFT_SKIP;
++ return 0;
++ }
+ }
+
+ /* Perform test specific additional initialization */
+--
+2.33.0
+
--- /dev/null
+From b887dc24abdb1f0c5c8503ecdc73472bb79bd3f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 13:12:17 +0200
+Subject: mptcp: ensure tx skbs always have the MPTCP ext
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit 977d293e23b48a1129830d7968605f61c4af71a0 ]
+
+Due to signed/unsigned comparison, the expression:
+
+ info->size_goal - skb->len > 0
+
+evaluates to true when the size goal is smaller than the
+skb size. That results in lack of tx cache refill, so that
+the skb allocated by the core TCP code lacks the required
+MPTCP skb extensions.
+
+Due to the above, syzbot is able to trigger the following WARN_ON():
+
+WARNING: CPU: 1 PID: 810 at net/mptcp/protocol.c:1366 mptcp_sendmsg_frag+0x1362/0x1bc0 net/mptcp/protocol.c:1366
+Modules linked in:
+CPU: 1 PID: 810 Comm: syz-executor.4 Not tainted 5.14.0-syzkaller #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
+RIP: 0010:mptcp_sendmsg_frag+0x1362/0x1bc0 net/mptcp/protocol.c:1366
+Code: ff 4c 8b 74 24 50 48 8b 5c 24 58 e9 0f fb ff ff e8 13 44 8b f8 4c 89 e7 45 31 ed e8 98 57 2e fe e9 81 f4 ff ff e8 fe 43 8b f8 <0f> 0b 41 bd ea ff ff ff e9 6f f4 ff ff 4c 89 e7 e8 b9 8e d2 f8 e9
+RSP: 0018:ffffc9000531f6a0 EFLAGS: 00010216
+RAX: 000000000000697f RBX: 0000000000000000 RCX: ffffc90012107000
+RDX: 0000000000040000 RSI: ffffffff88eac9e2 RDI: 0000000000000003
+RBP: ffff888078b15780 R08: 0000000000000000 R09: 0000000000000000
+R10: ffffffff88eac017 R11: 0000000000000000 R12: ffff88801de0a280
+R13: 0000000000006b58 R14: ffff888066278280 R15: ffff88803c2fe9c0
+FS: 00007fd9f866e700(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007faebcb2f718 CR3: 00000000267cb000 CR4: 00000000001506e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ __mptcp_push_pending+0x1fb/0x6b0 net/mptcp/protocol.c:1547
+ mptcp_release_cb+0xfe/0x210 net/mptcp/protocol.c:3003
+ release_sock+0xb4/0x1b0 net/core/sock.c:3206
+ sk_stream_wait_memory+0x604/0xed0 net/core/stream.c:145
+ mptcp_sendmsg+0xc39/0x1bc0 net/mptcp/protocol.c:1749
+ inet6_sendmsg+0x99/0xe0 net/ipv6/af_inet6.c:643
+ sock_sendmsg_nosec net/socket.c:704 [inline]
+ sock_sendmsg+0xcf/0x120 net/socket.c:724
+ sock_write_iter+0x2a0/0x3e0 net/socket.c:1057
+ call_write_iter include/linux/fs.h:2163 [inline]
+ new_sync_write+0x40b/0x640 fs/read_write.c:507
+ vfs_write+0x7cf/0xae0 fs/read_write.c:594
+ ksys_write+0x1ee/0x250 fs/read_write.c:647
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x44/0xae
+RIP: 0033:0x4665f9
+Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007fd9f866e188 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
+RAX: ffffffffffffffda RBX: 000000000056c038 RCX: 00000000004665f9
+RDX: 00000000000e7b78 RSI: 0000000020000000 RDI: 0000000000000003
+RBP: 00000000004bfcc4 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 000000000056c038
+R13: 0000000000a9fb1f R14: 00007fd9f866e300 R15: 0000000000022000
+
+Fix the issue rewriting the relevant expression to avoid
+sign-related problems - note: size_goal is always >= 0.
+
+Additionally, ensure that the skb in the tx cache always carries
+the relevant extension.
+
+Reported-and-tested-by: syzbot+263a248eec3e875baa7b@syzkaller.appspotmail.com
+Fixes: 1094c6fe7280 ("mptcp: fix possible divide by zero")
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/protocol.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index acbead7cf50f..4d2abdd3cd3b 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -1291,7 +1291,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
+ goto alloc_skb;
+ }
+
+- must_collapse = (info->size_goal - skb->len > 0) &&
++ must_collapse = (info->size_goal > skb->len) &&
+ (skb_shinfo(skb)->nr_frags < sysctl_max_skb_frags);
+ if (must_collapse) {
+ size_bias = skb->len;
+@@ -1300,7 +1300,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
+ }
+
+ alloc_skb:
+- if (!must_collapse && !ssk->sk_tx_skb_cache &&
++ if (!must_collapse &&
+ !mptcp_alloc_tx_skb(sk, ssk, info->data_lock_held))
+ return 0;
+
+--
+2.33.0
+
--- /dev/null
+From e66cad414e6f11dd5921096760711ca2a37ed8c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Sep 2021 16:52:32 +0800
+Subject: napi: fix race inside napi_enable
+
+From: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+
+[ Upstream commit 3765996e4f0b8a755cab215a08df744490c76052 ]
+
+The process will cause napi.state to contain NAPI_STATE_SCHED and
+not in the poll_list, which will cause napi_disable() to get stuck.
+
+The prefix "NAPI_STATE_" is removed in the figure below, and
+NAPI_STATE_HASHED is ignored in napi.state.
+
+ CPU0 | CPU1 | napi.state
+===============================================================================
+napi_disable() | | SCHED | NPSVC
+napi_enable() | |
+{ | |
+ smp_mb__before_atomic(); | |
+ clear_bit(SCHED, &n->state); | | NPSVC
+ | napi_schedule_prep() | SCHED | NPSVC
+ | napi_poll() |
+ | napi_complete_done() |
+ | { |
+ | if (n->state & (NPSVC | | (1)
+ | _BUSY_POLL))) |
+ | return false; |
+ | ................ |
+ | } | SCHED | NPSVC
+ | |
+ clear_bit(NPSVC, &n->state); | | SCHED
+} | |
+ | |
+napi_schedule_prep() | | SCHED | MISSED (2)
+
+(1) Here return direct. Because of NAPI_STATE_NPSVC exists.
+(2) NAPI_STATE_SCHED exists. So not add napi.poll_list to sd->poll_list
+
+Since NAPI_STATE_SCHED already exists and napi is not in the
+sd->poll_list queue, NAPI_STATE_SCHED cannot be cleared and will always
+exist.
+
+1. This will cause this queue to no longer receive packets.
+2. If you encounter napi_disable under the protection of rtnl_lock, it
+ will cause the entire rtnl_lock to be locked, affecting the overall
+ system.
+
+This patch uses cmpxchg to implement napi_enable(), which ensures that
+there will be no race due to the separation of clear two bits.
+
+Fixes: 2d8bff12699abc ("netpoll: Close race condition between poll_one_napi and napi_disable")
+Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/dev.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 8f1a47ad6781..693f15a05630 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6988,12 +6988,16 @@ EXPORT_SYMBOL(napi_disable);
+ */
+ void napi_enable(struct napi_struct *n)
+ {
+- BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
+- smp_mb__before_atomic();
+- clear_bit(NAPI_STATE_SCHED, &n->state);
+- clear_bit(NAPI_STATE_NPSVC, &n->state);
+- if (n->dev->threaded && n->thread)
+- set_bit(NAPI_STATE_THREADED, &n->state);
++ unsigned long val, new;
++
++ do {
++ val = READ_ONCE(n->state);
++ BUG_ON(!test_bit(NAPI_STATE_SCHED, &val));
++
++ new = val & ~(NAPIF_STATE_SCHED | NAPIF_STATE_NPSVC);
++ if (n->dev->threaded && n->thread)
++ new |= NAPIF_STATE_THREADED;
++ } while (cmpxchg(&n->state, val, new) != val);
+ }
+ EXPORT_SYMBOL(napi_enable);
+
+--
+2.33.0
+
--- /dev/null
+From 234407902c72d0dbd894047ec73459057f0f2933 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Sep 2021 13:57:25 +0200
+Subject: net: bgmac-bcma: handle deferred probe error due to mac-address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christian Lamparter <chunkeey@gmail.com>
+
+[ Upstream commit 029497e66bdc762e001880e4c85a91f35a54b1e2 ]
+
+Due to the inclusion of nvmem handling into the mac-address getter
+function of_get_mac_address() by
+commit d01f449c008a ("of_net: add NVMEM support to of_get_mac_address")
+it is now possible to get a -EPROBE_DEFER return code. Which did cause
+bgmac to assign a random ethernet address.
+
+This exact issue happened on my Meraki MR32. The nvmem provider is
+an EEPROM (at24c64) which gets instantiated once the module
+driver is loaded... This happens once the filesystem becomes available.
+
+With this patch, bgmac_probe() will propagate the -EPROBE_DEFER error.
+Then the driver subsystem will reschedule the probe at a later time.
+
+Cc: Petr Å tetiar <ynezz@true.cz>
+Cc: Michael Walle <michael@walle.cc>
+Fixes: d01f449c008a ("of_net: add NVMEM support to of_get_mac_address")
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c
+index 85fa0ab7201c..9513cfb5ba58 100644
+--- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
++++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
+@@ -129,6 +129,8 @@ static int bgmac_probe(struct bcma_device *core)
+ bcma_set_drvdata(core, bgmac);
+
+ err = of_get_mac_address(bgmac->dev->of_node, bgmac->net_dev->dev_addr);
++ if (err == -EPROBE_DEFER)
++ return err;
+
+ /* If no MAC address assigned via device tree, check SPROM */
+ if (err) {
+--
+2.33.0
+
--- /dev/null
+From 8dc2ef7557160c7d0c98e378c7ac9c2de6185f42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 00:42:08 +0300
+Subject: net: dsa: don't allocate the slave_mii_bus using devres
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 5135e96a3dd2f4555ae6981c3155a62bcf3227f6 ]
+
+The Linux device model permits both the ->shutdown and ->remove driver
+methods to get called during a shutdown procedure. Example: a DSA switch
+which sits on an SPI bus, and the SPI bus driver calls this on its
+->shutdown method:
+
+spi_unregister_controller
+-> device_for_each_child(&ctlr->dev, NULL, __unregister);
+ -> spi_unregister_device(to_spi_device(dev));
+ -> device_del(&spi->dev);
+
+So this is a simple pattern which can theoretically appear on any bus,
+although the only other buses on which I've been able to find it are
+I2C:
+
+i2c_del_adapter
+-> device_for_each_child(&adap->dev, NULL, __unregister_client);
+ -> i2c_unregister_device(client);
+ -> device_unregister(&client->dev);
+
+The implication of this pattern is that devices on these buses can be
+unregistered after having been shut down. The drivers for these devices
+might choose to return early either from ->remove or ->shutdown if the
+other callback has already run once, and they might choose that the
+->shutdown method should only perform a subset of the teardown done by
+->remove (to avoid unnecessary delays when rebooting).
+
+So in other words, the device driver may choose on ->remove to not
+do anything (therefore to not unregister an MDIO bus it has registered
+on ->probe), because this ->remove is actually triggered by the
+device_shutdown path, and its ->shutdown method has already run and done
+the minimally required cleanup.
+
+This used to be fine until the blamed commit, but now, the following
+BUG_ON triggers:
+
+void mdiobus_free(struct mii_bus *bus)
+{
+ /* For compatibility with error handling in drivers. */
+ if (bus->state == MDIOBUS_ALLOCATED) {
+ kfree(bus);
+ return;
+ }
+
+ BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
+ bus->state = MDIOBUS_RELEASED;
+
+ put_device(&bus->dev);
+}
+
+In other words, there is an attempt to free an MDIO bus which was not
+unregistered. The attempt to free it comes from the devres release
+callbacks of the SPI device, which are executed after the device is
+unregistered.
+
+I'm not saying that the fact that MDIO buses allocated using devres
+would automatically get unregistered wasn't strange. I'm just saying
+that the commit didn't care about auditing existing call paths in the
+kernel, and now, the following code sequences are potentially buggy:
+
+(a) devm_mdiobus_alloc followed by plain mdiobus_register, for a device
+ located on a bus that unregisters its children on shutdown. After
+ the blamed patch, either both the alloc and the register should use
+ devres, or none should.
+
+(b) devm_mdiobus_alloc followed by plain mdiobus_register, and then no
+ mdiobus_unregister at all in the remove path. After the blamed
+ patch, nobody unregisters the MDIO bus anymore, so this is even more
+ buggy than the previous case which needs a specific bus
+ configuration to be seen, this one is an unconditional bug.
+
+In this case, DSA falls into category (a), it tries to be helpful and
+registers an MDIO bus on behalf of the switch, which might be on such a
+bus. I've no idea why it does it under devres.
+
+It does this on probe:
+
+ if (!ds->slave_mii_bus && ds->ops->phy_read)
+ alloc and register mdio bus
+
+and this on remove:
+
+ if (ds->slave_mii_bus && ds->ops->phy_read)
+ unregister mdio bus
+
+I _could_ imagine using devres because the condition used on remove is
+different than the condition used on probe. So strictly speaking, DSA
+cannot determine whether the ds->slave_mii_bus it sees on remove is the
+ds->slave_mii_bus that _it_ has allocated on probe. Using devres would
+have solved that problem. But nonetheless, the existing code already
+proceeds to unregister the MDIO bus, even though it might be
+unregistering an MDIO bus it has never registered. So I can only guess
+that no driver that implements ds->ops->phy_read also allocates and
+registers ds->slave_mii_bus itself.
+
+So in that case, if unregistering is fine, freeing must be fine too.
+
+Stop using devres and free the MDIO bus manually. This will make devres
+stop attempting to free a still registered MDIO bus on ->shutdown.
+
+Fixes: ac3a68d56651 ("net: phy: don't abuse devres in devm_mdiobus_register()")
+Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Tested-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dsa/dsa2.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index 383fdc0565c7..76ed5ef0e36a 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -792,7 +792,7 @@ static int dsa_switch_setup(struct dsa_switch *ds)
+ devlink_params_publish(ds->devlink);
+
+ if (!ds->slave_mii_bus && ds->ops->phy_read) {
+- ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
++ ds->slave_mii_bus = mdiobus_alloc();
+ if (!ds->slave_mii_bus) {
+ err = -ENOMEM;
+ goto teardown;
+@@ -802,13 +802,16 @@ static int dsa_switch_setup(struct dsa_switch *ds)
+
+ err = mdiobus_register(ds->slave_mii_bus);
+ if (err < 0)
+- goto teardown;
++ goto free_slave_mii_bus;
+ }
+
+ ds->setup = true;
+
+ return 0;
+
++free_slave_mii_bus:
++ if (ds->slave_mii_bus && ds->ops->phy_read)
++ mdiobus_free(ds->slave_mii_bus);
+ teardown:
+ if (ds->ops->teardown)
+ ds->ops->teardown(ds);
+@@ -833,8 +836,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds)
+ if (!ds->setup)
+ return;
+
+- if (ds->slave_mii_bus && ds->ops->phy_read)
++ if (ds->slave_mii_bus && ds->ops->phy_read) {
+ mdiobus_unregister(ds->slave_mii_bus);
++ mdiobus_free(ds->slave_mii_bus);
++ ds->slave_mii_bus = NULL;
++ }
+
+ dsa_switch_unregister_notifier(ds);
+
+--
+2.33.0
+
--- /dev/null
+From 15517d2a4733450b46d8aa9e231a054ec409da14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 01:49:18 +0300
+Subject: net: dsa: fix dsa_tree_setup error path
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit e5845aa0eadda3d8a950eb8845c1396827131f30 ]
+
+Since the blamed commit, dsa_tree_teardown_switches() was split into two
+smaller functions, dsa_tree_teardown_switches and dsa_tree_teardown_ports.
+
+However, the error path of dsa_tree_setup stopped calling dsa_tree_teardown_ports.
+
+Fixes: a57d8c217aad ("net: dsa: flush switchdev workqueue before tearing down CPU/DSA ports")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/dsa/dsa2.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index 3a8136d5915d..383fdc0565c7 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1001,6 +1001,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
+ teardown_master:
+ dsa_tree_teardown_master(dst);
+ teardown_switches:
++ dsa_tree_teardown_ports(dst);
+ dsa_tree_teardown_switches(dst);
+ teardown_default_cpu:
+ dsa_tree_teardown_default_cpu(dst);
+--
+2.33.0
+
--- /dev/null
+From 5a8fa1511bcf9d6bcf04245ccdb61b4d788c0212 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 16:34:34 +0300
+Subject: net: dsa: hellcreek: be compatible with masters which unregister on
+ shutdown
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 46baae56e1001a771a5d132aa883cb5605013ae2 ]
+
+Since commit 2f1e8ea726e9 ("net: dsa: link interfaces with the DSA
+master to get rid of lockdep warnings"), DSA gained a requirement which
+it did not fulfill, which is to unlink itself from the DSA master at
+shutdown time.
+
+Since the hellcreek driver was introduced after the bad commit, it has
+never worked with DSA masters which decide to unregister their
+net_device on shutdown, effectively hanging the reboot process.
+
+Hellcreek is a platform device driver, so we probably cannot have the
+oddities of ->shutdown and ->remove getting both called for the exact
+same struct device. But to be in line with the pattern from the other
+device drivers which are on slow buses, implement the same "if this then
+not that" pattern of either running the ->shutdown or the ->remove hook.
+The driver's current ->remove implementation makes that very easy
+because it already zeroes out its device_drvdata on ->remove.
+
+Fixes: e4b27ebc780f ("net: dsa: Add DSA driver for Hirschmann Hellcreek switches")
+Link: https://lore.kernel.org/netdev/20210909095324.12978-1-LinoSanfilippo@gmx.de/
+Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Acked-by: Kurt Kanzenbach <kurt@linutronix.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/hirschmann/hellcreek.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
+index 7062db6a083c..a0f5ec4f4e58 100644
+--- a/drivers/net/dsa/hirschmann/hellcreek.c
++++ b/drivers/net/dsa/hirschmann/hellcreek.c
+@@ -1915,6 +1915,9 @@ static int hellcreek_remove(struct platform_device *pdev)
+ {
+ struct hellcreek *hellcreek = platform_get_drvdata(pdev);
+
++ if (!hellcreek)
++ return 0;
++
+ hellcreek_hwtstamp_free(hellcreek);
+ hellcreek_ptp_free(hellcreek);
+ dsa_unregister_switch(hellcreek->ds);
+@@ -1923,6 +1926,18 @@ static int hellcreek_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++static void hellcreek_shutdown(struct platform_device *pdev)
++{
++ struct hellcreek *hellcreek = platform_get_drvdata(pdev);
++
++ if (!hellcreek)
++ return;
++
++ dsa_switch_shutdown(hellcreek->ds);
++
++ platform_set_drvdata(pdev, NULL);
++}
++
+ static const struct hellcreek_platform_data de1soc_r1_pdata = {
+ .name = "r4c30",
+ .num_ports = 4,
+@@ -1945,6 +1960,7 @@ MODULE_DEVICE_TABLE(of, hellcreek_of_match);
+ static struct platform_driver hellcreek_driver = {
+ .probe = hellcreek_probe,
+ .remove = hellcreek_remove,
++ .shutdown = hellcreek_shutdown,
+ .driver = {
+ .name = "hellcreek",
+ .of_match_table = hellcreek_of_match,
+--
+2.33.0
+
--- /dev/null
+From 0294db7d706b7950efb7b6c1cac14101d136710e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 16:34:35 +0300
+Subject: net: dsa: microchip: ksz8863: be compatible with masters which
+ unregister on shutdown
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit fe4053078cd0f02a3fa140c43660f327702a9f10 ]
+
+Since commit 2f1e8ea726e9 ("net: dsa: link interfaces with the DSA
+master to get rid of lockdep warnings"), DSA gained a requirement which
+it did not fulfill, which is to unlink itself from the DSA master at
+shutdown time.
+
+Since the Microchip sub-driver for KSZ8863 was introduced after the bad
+commit, it has never worked with DSA masters which decide to unregister
+their net_device on shutdown, effectively hanging the reboot process.
+To fix that, we need to call dsa_switch_shutdown.
+
+Since this driver expects the MDIO bus to be backed by mdio_bitbang, I
+don't think there is currently any MDIO bus driver which implements its
+->shutdown by redirecting it to ->remove, but in any case, to be
+compatible with that pattern, it is necessary to implement an "if this
+then not that" scheme, to avoid ->remove and ->shutdown from being
+called both for the same struct device.
+
+Fixes: 60a364760002 ("net: dsa: microchip: Add Microchip KSZ8863 SMI based driver support")
+Link: https://lore.kernel.org/netdev/20210909095324.12978-1-LinoSanfilippo@gmx.de/
+Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/microchip/ksz8863_smi.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c
+index 11293485138c..5883fa7edda2 100644
+--- a/drivers/net/dsa/microchip/ksz8863_smi.c
++++ b/drivers/net/dsa/microchip/ksz8863_smi.c
+@@ -191,6 +191,18 @@ static void ksz8863_smi_remove(struct mdio_device *mdiodev)
+
+ if (dev)
+ ksz_switch_remove(dev);
++
++ dev_set_drvdata(&mdiodev->dev, NULL);
++}
++
++static void ksz8863_smi_shutdown(struct mdio_device *mdiodev)
++{
++ struct ksz_device *dev = dev_get_drvdata(&mdiodev->dev);
++
++ if (dev)
++ dsa_switch_shutdown(dev->ds);
++
++ dev_set_drvdata(&mdiodev->dev, NULL);
+ }
+
+ static const struct of_device_id ksz8863_dt_ids[] = {
+@@ -203,6 +215,7 @@ MODULE_DEVICE_TABLE(of, ksz8863_dt_ids);
+ static struct mdio_driver ksz8863_driver = {
+ .probe = ksz8863_smi_probe,
+ .remove = ksz8863_smi_remove,
++ .shutdown = ksz8863_smi_shutdown,
+ .mdiodrv.driver = {
+ .name = "ksz8863-switch",
+ .of_match_table = ksz8863_dt_ids,
+--
+2.33.0
+
--- /dev/null
+From c11fb6081fa1b7e18811c46f8cdeb8d6028c0236 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 00:42:09 +0300
+Subject: net: dsa: realtek: register the MDIO bus under devres
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 74b6d7d13307b016f4b5bba8198297824c0ee6df ]
+
+The Linux device model permits both the ->shutdown and ->remove driver
+methods to get called during a shutdown procedure. Example: a DSA switch
+which sits on an SPI bus, and the SPI bus driver calls this on its
+->shutdown method:
+
+spi_unregister_controller
+-> device_for_each_child(&ctlr->dev, NULL, __unregister);
+ -> spi_unregister_device(to_spi_device(dev));
+ -> device_del(&spi->dev);
+
+So this is a simple pattern which can theoretically appear on any bus,
+although the only other buses on which I've been able to find it are
+I2C:
+
+i2c_del_adapter
+-> device_for_each_child(&adap->dev, NULL, __unregister_client);
+ -> i2c_unregister_device(client);
+ -> device_unregister(&client->dev);
+
+The implication of this pattern is that devices on these buses can be
+unregistered after having been shut down. The drivers for these devices
+might choose to return early either from ->remove or ->shutdown if the
+other callback has already run once, and they might choose that the
+->shutdown method should only perform a subset of the teardown done by
+->remove (to avoid unnecessary delays when rebooting).
+
+So in other words, the device driver may choose on ->remove to not
+do anything (therefore to not unregister an MDIO bus it has registered
+on ->probe), because this ->remove is actually triggered by the
+device_shutdown path, and its ->shutdown method has already run and done
+the minimally required cleanup.
+
+This used to be fine until the blamed commit, but now, the following
+BUG_ON triggers:
+
+void mdiobus_free(struct mii_bus *bus)
+{
+ /* For compatibility with error handling in drivers. */
+ if (bus->state == MDIOBUS_ALLOCATED) {
+ kfree(bus);
+ return;
+ }
+
+ BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
+ bus->state = MDIOBUS_RELEASED;
+
+ put_device(&bus->dev);
+}
+
+In other words, there is an attempt to free an MDIO bus which was not
+unregistered. The attempt to free it comes from the devres release
+callbacks of the SPI device, which are executed after the device is
+unregistered.
+
+I'm not saying that the fact that MDIO buses allocated using devres
+would automatically get unregistered wasn't strange. I'm just saying
+that the commit didn't care about auditing existing call paths in the
+kernel, and now, the following code sequences are potentially buggy:
+
+(a) devm_mdiobus_alloc followed by plain mdiobus_register, for a device
+ located on a bus that unregisters its children on shutdown. After
+ the blamed patch, either both the alloc and the register should use
+ devres, or none should.
+
+(b) devm_mdiobus_alloc followed by plain mdiobus_register, and then no
+ mdiobus_unregister at all in the remove path. After the blamed
+ patch, nobody unregisters the MDIO bus anymore, so this is even more
+ buggy than the previous case which needs a specific bus
+ configuration to be seen, this one is an unconditional bug.
+
+In this case, the Realtek drivers fall under category (b). To solve it,
+we can register the MDIO bus under devres too, which restores the
+previous behavior.
+
+Fixes: ac3a68d56651 ("net: phy: don't abuse devres in devm_mdiobus_register()")
+Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Reported-by: Alvin Å ipraga <alsi@bang-olufsen.dk>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.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/dsa/realtek-smi-core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/realtek-smi-core.c b/drivers/net/dsa/realtek-smi-core.c
+index 8e49d4f85d48..6bf46d76c028 100644
+--- a/drivers/net/dsa/realtek-smi-core.c
++++ b/drivers/net/dsa/realtek-smi-core.c
+@@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
+ smi->slave_mii_bus->parent = smi->dev;
+ smi->ds->slave_mii_bus = smi->slave_mii_bus;
+
+- ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np);
++ ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np);
+ if (ret) {
+ dev_err(smi->dev, "unable to register MDIO bus %s\n",
+ smi->slave_mii_bus->id);
+--
+2.33.0
+
--- /dev/null
+From dd7065123e80821cc872e0d816743672e97fb8e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 17:29:16 +0300
+Subject: net: dsa: tear down devlink port regions when tearing down the
+ devlink port on error
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit fd292c189a979838622d5e03e15fa688c81dd50b ]
+
+Commit 86f8b1c01a0a ("net: dsa: Do not make user port errors fatal")
+decided it was fine to ignore errors on certain ports that fail to
+probe, and go on with the ports that do probe fine.
+
+Commit fb6ec87f7229 ("net: dsa: Fix type was not set for devlink port")
+noticed that devlink_port_type_eth_set(dlp, dp->slave); does not get
+called, and devlink notices after a timeout of 3600 seconds and prints a
+WARN_ON. So it went ahead to unregister the devlink port. And because
+there exists an UNUSED port flavour, we actually re-register the devlink
+port as UNUSED.
+
+Commit 08156ba430b4 ("net: dsa: Add devlink port regions support to
+DSA") added devlink port regions, which are set up by the driver and not
+by DSA.
+
+When we trigger the devlink port deregistration and reregistration as
+unused, devlink now prints another WARN_ON, from here:
+
+devlink_port_unregister:
+ WARN_ON(!list_empty(&devlink_port->region_list));
+
+So the port still has regions, which makes sense, because they were set
+up by the driver, and the driver doesn't know we're unregistering the
+devlink port.
+
+Somebody needs to tear them down, and optionally (actually it would be
+nice, to be consistent) set them up again for the new devlink port.
+
+But DSA's layering stays in our way quite badly here.
+
+The options I've considered are:
+
+1. Introduce a function in devlink to just change a port's type and
+ flavour. No dice, devlink keeps a lot of state, it really wants the
+ port to not be registered when you set its parameters, so changing
+ anything can only be done by destroying what we currently have and
+ recreating it.
+
+2. Make DSA cache the parameters passed to dsa_devlink_port_region_create,
+ and the region returned, keep those in a list, then when the devlink
+ port unregister needs to take place, the existing devlink regions are
+ destroyed by DSA, and we replay the creation of new regions using the
+ cached parameters. Problem: mv88e6xxx keeps the region pointers in
+ chip->ports[port].region, and these will remain stale after DSA frees
+ them. There are many things DSA can do, but updating mv88e6xxx's
+ private pointers is not one of them.
+
+3. Just let the driver do it (i.e. introduce a very specific method
+ called ds->ops->port_reinit_as_unused, which unregisters its devlink
+ port devlink regions, then the old devlink port, then registers the
+ new one, then the devlink port regions for it). While it does work,
+ as opposed to the others, it's pretty horrible from an API
+ perspective and we can do better.
+
+4. Introduce a new pair of methods, ->port_setup and ->port_teardown,
+ which in the case of mv88e6xxx must register and unregister the
+ devlink port regions. Call these 2 methods when the port must be
+ reinitialized as unused.
+
+Naturally, I went for the 4th approach.
+
+Fixes: 08156ba430b4 ("net: dsa: Add devlink port regions support to DSA")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 16 ++++++-
+ drivers/net/dsa/mv88e6xxx/devlink.c | 73 ++++-------------------------
+ drivers/net/dsa/mv88e6xxx/devlink.h | 6 ++-
+ include/net/dsa.h | 8 ++++
+ net/dsa/dsa2.c | 51 ++++++++++++++++++--
+ 5 files changed, 81 insertions(+), 73 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 111a6d5985da..1c122a1f2f97 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -3012,7 +3012,7 @@ static void mv88e6xxx_teardown(struct dsa_switch *ds)
+ {
+ mv88e6xxx_teardown_devlink_params(ds);
+ dsa_devlink_resources_unregister(ds);
+- mv88e6xxx_teardown_devlink_regions(ds);
++ mv88e6xxx_teardown_devlink_regions_global(ds);
+ }
+
+ static int mv88e6xxx_setup(struct dsa_switch *ds)
+@@ -3147,7 +3147,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
+ if (err)
+ goto out_resources;
+
+- err = mv88e6xxx_setup_devlink_regions(ds);
++ err = mv88e6xxx_setup_devlink_regions_global(ds);
+ if (err)
+ goto out_params;
+
+@@ -3161,6 +3161,16 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
+ return err;
+ }
+
++static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port)
++{
++ return mv88e6xxx_setup_devlink_regions_port(ds, port);
++}
++
++static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port)
++{
++ mv88e6xxx_teardown_devlink_regions_port(ds, port);
++}
++
+ /* prod_id for switch families which do not have a PHY model number */
+ static const u16 family_prod_id_table[] = {
+ [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
+@@ -6055,6 +6065,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
+ .change_tag_protocol = mv88e6xxx_change_tag_protocol,
+ .setup = mv88e6xxx_setup,
+ .teardown = mv88e6xxx_teardown,
++ .port_setup = mv88e6xxx_port_setup,
++ .port_teardown = mv88e6xxx_port_teardown,
+ .phylink_validate = mv88e6xxx_validate,
+ .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
+ .phylink_mac_config = mv88e6xxx_mac_config,
+diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xxx/devlink.c
+index 0c0f5ea6680c..381068395c63 100644
+--- a/drivers/net/dsa/mv88e6xxx/devlink.c
++++ b/drivers/net/dsa/mv88e6xxx/devlink.c
+@@ -647,26 +647,25 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] = {
+ },
+ };
+
+-static void
+-mv88e6xxx_teardown_devlink_regions_global(struct mv88e6xxx_chip *chip)
++void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds)
+ {
++ struct mv88e6xxx_chip *chip = ds->priv;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++)
+ dsa_devlink_region_destroy(chip->regions[i]);
+ }
+
+-static void
+-mv88e6xxx_teardown_devlink_regions_port(struct mv88e6xxx_chip *chip,
+- int port)
++void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port)
+ {
++ struct mv88e6xxx_chip *chip = ds->priv;
++
+ dsa_devlink_region_destroy(chip->ports[port].region);
+ }
+
+-static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,
+- struct mv88e6xxx_chip *chip,
+- int port)
++int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port)
+ {
++ struct mv88e6xxx_chip *chip = ds->priv;
+ struct devlink_region *region;
+
+ region = dsa_devlink_port_region_create(ds,
+@@ -681,40 +680,10 @@ static int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds,
+ return 0;
+ }
+
+-static void
+-mv88e6xxx_teardown_devlink_regions_ports(struct mv88e6xxx_chip *chip)
+-{
+- int port;
+-
+- for (port = 0; port < mv88e6xxx_num_ports(chip); port++)
+- mv88e6xxx_teardown_devlink_regions_port(chip, port);
+-}
+-
+-static int mv88e6xxx_setup_devlink_regions_ports(struct dsa_switch *ds,
+- struct mv88e6xxx_chip *chip)
+-{
+- int port;
+- int err;
+-
+- for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+- err = mv88e6xxx_setup_devlink_regions_port(ds, chip, port);
+- if (err)
+- goto out;
+- }
+-
+- return 0;
+-
+-out:
+- while (port-- > 0)
+- mv88e6xxx_teardown_devlink_regions_port(chip, port);
+-
+- return err;
+-}
+-
+-static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds,
+- struct mv88e6xxx_chip *chip)
++int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds)
+ {
+ bool (*cond)(struct mv88e6xxx_chip *chip);
++ struct mv88e6xxx_chip *chip = ds->priv;
+ struct devlink_region_ops *ops;
+ struct devlink_region *region;
+ u64 size;
+@@ -753,30 +722,6 @@ static int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds,
+ return PTR_ERR(region);
+ }
+
+-int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds)
+-{
+- struct mv88e6xxx_chip *chip = ds->priv;
+- int err;
+-
+- err = mv88e6xxx_setup_devlink_regions_global(ds, chip);
+- if (err)
+- return err;
+-
+- err = mv88e6xxx_setup_devlink_regions_ports(ds, chip);
+- if (err)
+- mv88e6xxx_teardown_devlink_regions_global(chip);
+-
+- return err;
+-}
+-
+-void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds)
+-{
+- struct mv88e6xxx_chip *chip = ds->priv;
+-
+- mv88e6xxx_teardown_devlink_regions_ports(chip);
+- mv88e6xxx_teardown_devlink_regions_global(chip);
+-}
+-
+ int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,
+ struct devlink_info_req *req,
+ struct netlink_ext_ack *extack)
+diff --git a/drivers/net/dsa/mv88e6xxx/devlink.h b/drivers/net/dsa/mv88e6xxx/devlink.h
+index 3d72db3dcf95..65ce6a6858b9 100644
+--- a/drivers/net/dsa/mv88e6xxx/devlink.h
++++ b/drivers/net/dsa/mv88e6xxx/devlink.h
+@@ -12,8 +12,10 @@ int mv88e6xxx_devlink_param_get(struct dsa_switch *ds, u32 id,
+ struct devlink_param_gset_ctx *ctx);
+ int mv88e6xxx_devlink_param_set(struct dsa_switch *ds, u32 id,
+ struct devlink_param_gset_ctx *ctx);
+-int mv88e6xxx_setup_devlink_regions(struct dsa_switch *ds);
+-void mv88e6xxx_teardown_devlink_regions(struct dsa_switch *ds);
++int mv88e6xxx_setup_devlink_regions_global(struct dsa_switch *ds);
++void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds);
++int mv88e6xxx_setup_devlink_regions_port(struct dsa_switch *ds, int port);
++void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port);
+
+ int mv88e6xxx_devlink_info_get(struct dsa_switch *ds,
+ struct devlink_info_req *req,
+diff --git a/include/net/dsa.h b/include/net/dsa.h
+index d833f717e802..004514a21e30 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -575,8 +575,16 @@ struct dsa_switch_ops {
+ int (*change_tag_protocol)(struct dsa_switch *ds, int port,
+ enum dsa_tag_protocol proto);
+
++ /* Optional switch-wide initialization and destruction methods */
+ int (*setup)(struct dsa_switch *ds);
+ void (*teardown)(struct dsa_switch *ds);
++
++ /* Per-port initialization and destruction methods. Mandatory if the
++ * driver registers devlink port regions, optional otherwise.
++ */
++ int (*port_setup)(struct dsa_switch *ds, int port);
++ void (*port_teardown)(struct dsa_switch *ds, int port);
++
+ u32 (*get_phy_flags)(struct dsa_switch *ds, int port);
+
+ /*
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index 79267b00af68..3a8136d5915d 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -342,6 +342,7 @@ static int dsa_port_setup(struct dsa_port *dp)
+ {
+ struct devlink_port *dlp = &dp->devlink_port;
+ bool dsa_port_link_registered = false;
++ struct dsa_switch *ds = dp->ds;
+ bool dsa_port_enabled = false;
+ int err = 0;
+
+@@ -351,6 +352,12 @@ static int dsa_port_setup(struct dsa_port *dp)
+ INIT_LIST_HEAD(&dp->fdbs);
+ INIT_LIST_HEAD(&dp->mdbs);
+
++ if (ds->ops->port_setup) {
++ err = ds->ops->port_setup(ds, dp->index);
++ if (err)
++ return err;
++ }
++
+ switch (dp->type) {
+ case DSA_PORT_TYPE_UNUSED:
+ dsa_port_disable(dp);
+@@ -393,8 +400,11 @@ static int dsa_port_setup(struct dsa_port *dp)
+ dsa_port_disable(dp);
+ if (err && dsa_port_link_registered)
+ dsa_port_link_unregister_of(dp);
+- if (err)
++ if (err) {
++ if (ds->ops->port_teardown)
++ ds->ops->port_teardown(ds, dp->index);
+ return err;
++ }
+
+ dp->setup = true;
+
+@@ -446,11 +456,15 @@ static int dsa_port_devlink_setup(struct dsa_port *dp)
+ static void dsa_port_teardown(struct dsa_port *dp)
+ {
+ struct devlink_port *dlp = &dp->devlink_port;
++ struct dsa_switch *ds = dp->ds;
+ struct dsa_mac_addr *a, *tmp;
+
+ if (!dp->setup)
+ return;
+
++ if (ds->ops->port_teardown)
++ ds->ops->port_teardown(ds, dp->index);
++
+ devlink_port_type_clear(dlp);
+
+ switch (dp->type) {
+@@ -494,6 +508,36 @@ static void dsa_port_devlink_teardown(struct dsa_port *dp)
+ dp->devlink_port_setup = false;
+ }
+
++/* Destroy the current devlink port, and create a new one which has the UNUSED
++ * flavour. At this point, any call to ds->ops->port_setup has been already
++ * balanced out by a call to ds->ops->port_teardown, so we know that any
++ * devlink port regions the driver had are now unregistered. We then call its
++ * ds->ops->port_setup again, in order for the driver to re-create them on the
++ * new devlink port.
++ */
++static int dsa_port_reinit_as_unused(struct dsa_port *dp)
++{
++ struct dsa_switch *ds = dp->ds;
++ int err;
++
++ dsa_port_devlink_teardown(dp);
++ dp->type = DSA_PORT_TYPE_UNUSED;
++ err = dsa_port_devlink_setup(dp);
++ if (err)
++ return err;
++
++ if (ds->ops->port_setup) {
++ /* On error, leave the devlink port registered,
++ * dsa_switch_teardown will clean it up later.
++ */
++ err = ds->ops->port_setup(ds, dp->index);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
+ static int dsa_devlink_info_get(struct devlink *dl,
+ struct devlink_info_req *req,
+ struct netlink_ext_ack *extack)
+@@ -850,12 +894,9 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
+ list_for_each_entry(dp, &dst->ports, list) {
+ err = dsa_port_setup(dp);
+ if (err) {
+- dsa_port_devlink_teardown(dp);
+- dp->type = DSA_PORT_TYPE_UNUSED;
+- err = dsa_port_devlink_setup(dp);
++ err = dsa_port_reinit_as_unused(dp);
+ if (err)
+ goto teardown;
+- continue;
+ }
+ }
+
+--
+2.33.0
+
--- /dev/null
+From 3b03f95218d1b0ccc14ca23a3093196e712fa91d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 16:34:36 +0300
+Subject: net: dsa: xrs700x: be compatible with masters which unregister on
+ shutdown
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit a68e9da48568a0adf5dc817ef81971c0d1aa0672 ]
+
+Since commit 2f1e8ea726e9 ("net: dsa: link interfaces with the DSA
+master to get rid of lockdep warnings"), DSA gained a requirement which
+it did not fulfill, which is to unlink itself from the DSA master at
+shutdown time.
+
+Since the Arrow SpeedChips XRS700x driver was introduced after the bad
+commit, it has never worked with DSA masters which decide to unregister
+their net_device on shutdown, effectively hanging the reboot process.
+To fix that, we need to call dsa_switch_shutdown.
+
+These devices can be connected by I2C or by MDIO, and if I search for
+I2C or MDIO bus drivers that implement their ->shutdown by redirecting
+it to ->remove I don't see any, however this does not mean it would not
+be possible. To be compatible with that pattern, it is necessary to
+implement an "if this then not that" scheme, to avoid ->remove and
+->shutdown from being called both for the same struct device.
+
+Fixes: ee00b24f32eb ("net: dsa: add Arrow SpeedChips XRS700x driver")
+Link: https://lore.kernel.org/netdev/20210909095324.12978-1-LinoSanfilippo@gmx.de/
+Reported-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: George McCollister <george.mccollister@gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/xrs700x/xrs700x.c | 6 ++++++
+ drivers/net/dsa/xrs700x/xrs700x.h | 1 +
+ drivers/net/dsa/xrs700x/xrs700x_i2c.c | 18 ++++++++++++++++++
+ drivers/net/dsa/xrs700x/xrs700x_mdio.c | 18 ++++++++++++++++++
+ 4 files changed, 43 insertions(+)
+
+diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c
+index 130abb0f1438..469420941054 100644
+--- a/drivers/net/dsa/xrs700x/xrs700x.c
++++ b/drivers/net/dsa/xrs700x/xrs700x.c
+@@ -822,6 +822,12 @@ void xrs700x_switch_remove(struct xrs700x *priv)
+ }
+ EXPORT_SYMBOL(xrs700x_switch_remove);
+
++void xrs700x_switch_shutdown(struct xrs700x *priv)
++{
++ dsa_switch_shutdown(priv->ds);
++}
++EXPORT_SYMBOL(xrs700x_switch_shutdown);
++
+ MODULE_AUTHOR("George McCollister <george.mccollister@gmail.com>");
+ MODULE_DESCRIPTION("Arrow SpeedChips XRS700x DSA driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/net/dsa/xrs700x/xrs700x.h b/drivers/net/dsa/xrs700x/xrs700x.h
+index ff62cf61b091..4d58257471d2 100644
+--- a/drivers/net/dsa/xrs700x/xrs700x.h
++++ b/drivers/net/dsa/xrs700x/xrs700x.h
+@@ -40,3 +40,4 @@ struct xrs700x {
+ struct xrs700x *xrs700x_switch_alloc(struct device *base, void *devpriv);
+ int xrs700x_switch_register(struct xrs700x *priv);
+ void xrs700x_switch_remove(struct xrs700x *priv);
++void xrs700x_switch_shutdown(struct xrs700x *priv);
+diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
+index 489d9385b4f0..6deae388a0d6 100644
+--- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c
++++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c
+@@ -109,11 +109,28 @@ static int xrs700x_i2c_remove(struct i2c_client *i2c)
+ {
+ struct xrs700x *priv = i2c_get_clientdata(i2c);
+
++ if (!priv)
++ return 0;
++
+ xrs700x_switch_remove(priv);
+
++ i2c_set_clientdata(i2c, NULL);
++
+ return 0;
+ }
+
++static void xrs700x_i2c_shutdown(struct i2c_client *i2c)
++{
++ struct xrs700x *priv = i2c_get_clientdata(i2c);
++
++ if (!priv)
++ return;
++
++ xrs700x_switch_shutdown(priv);
++
++ i2c_set_clientdata(i2c, NULL);
++}
++
+ static const struct i2c_device_id xrs700x_i2c_id[] = {
+ { "xrs700x-switch", 0 },
+ {},
+@@ -137,6 +154,7 @@ static struct i2c_driver xrs700x_i2c_driver = {
+ },
+ .probe = xrs700x_i2c_probe,
+ .remove = xrs700x_i2c_remove,
++ .shutdown = xrs700x_i2c_shutdown,
+ .id_table = xrs700x_i2c_id,
+ };
+
+diff --git a/drivers/net/dsa/xrs700x/xrs700x_mdio.c b/drivers/net/dsa/xrs700x/xrs700x_mdio.c
+index 44f58bee04a4..d01cf1073d49 100644
+--- a/drivers/net/dsa/xrs700x/xrs700x_mdio.c
++++ b/drivers/net/dsa/xrs700x/xrs700x_mdio.c
+@@ -136,7 +136,24 @@ static void xrs700x_mdio_remove(struct mdio_device *mdiodev)
+ {
+ struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
+
++ if (!priv)
++ return;
++
+ xrs700x_switch_remove(priv);
++
++ dev_set_drvdata(&mdiodev->dev, NULL);
++}
++
++static void xrs700x_mdio_shutdown(struct mdio_device *mdiodev)
++{
++ struct xrs700x *priv = dev_get_drvdata(&mdiodev->dev);
++
++ if (!priv)
++ return;
++
++ xrs700x_switch_shutdown(priv);
++
++ dev_set_drvdata(&mdiodev->dev, NULL);
+ }
+
+ static const struct of_device_id __maybe_unused xrs700x_mdio_dt_ids[] = {
+@@ -155,6 +172,7 @@ static struct mdio_driver xrs700x_mdio_driver = {
+ },
+ .probe = xrs700x_mdio_probe,
+ .remove = xrs700x_mdio_remove,
++ .shutdown = xrs700x_mdio_shutdown,
+ };
+
+ mdio_module_driver(xrs700x_mdio_driver);
+--
+2.33.0
+
--- /dev/null
+From bef8eaa6c23d53872ae76a333d7ac4d869ac9bbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 16:55:48 -0700
+Subject: net: ethernet: mtk_eth_soc: avoid creating duplicate offload entries
+
+From: Felix Fietkau <nbd@nbd.name>
+
+[ Upstream commit e68daf61ed13832aef8892200a874139700ca754 ]
+
+Sometimes multiple CLS_REPLACE calls are issued for the same connection.
+rhashtable_insert_fast does not check for these duplicates, so multiple
+hardware flow entries can be created.
+Fix this by checking for an existing entry early
+
+Fixes: 502e84e2382d ("net: ethernet: mtk_eth_soc: add flow offloading support")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index b5f68f66d42a..7bb1f20002b5 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -186,6 +186,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ int hash;
+ int i;
+
++ if (rhashtable_lookup(ð->flow_table, &f->cookie, mtk_flow_ht_params))
++ return -EEXIST;
++
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
+ struct flow_match_meta match;
+
+--
+2.33.0
+
--- /dev/null
+From 25a6211d4eaa481dbd7db76ddd2175150d05227f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:09 +0800
+Subject: net: hns3: check queue id range before using
+
+From: Yufeng Mo <moyufeng@huawei.com>
+
+[ Upstream commit 63b1279d9905100a14da9e043de7b28e99dba3f8 ]
+
+The input parameters may not be reliable. Before using the
+queue id, we should check this parameter. Otherwise, memory
+overwriting may occur.
+
+Fixes: d34100184685 ("net: hns3: refactor the mailbox message between PF and VF")
+Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+index 91c32f99b644..c1a4b79a7050 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+@@ -588,9 +588,17 @@ static void hclge_get_queue_id_in_pf(struct hclge_vport *vport,
+ struct hclge_mbx_vf_to_pf_cmd *mbx_req,
+ struct hclge_respond_to_vf_msg *resp_msg)
+ {
++ struct hnae3_handle *handle = &vport->nic;
++ struct hclge_dev *hdev = vport->back;
+ u16 queue_id, qid_in_pf;
+
+ memcpy(&queue_id, mbx_req->msg.data, sizeof(queue_id));
++ if (queue_id >= handle->kinfo.num_tqps) {
++ dev_err(&hdev->pdev->dev, "Invalid queue id(%u) from VF %u\n",
++ queue_id, mbx_req->mbx_src_vfid);
++ return;
++ }
++
+ qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id);
+ memcpy(resp_msg->data, &qid_in_pf, sizeof(qid_in_pf));
+ resp_msg->len = sizeof(qid_in_pf);
+--
+2.33.0
+
--- /dev/null
+From 4e35c958f4a595b20943b5c91ac6f4e38cec0821 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:10 +0800
+Subject: net: hns3: check vlan id before using it
+
+From: liaoguojia <liaoguojia@huawei.com>
+
+[ Upstream commit ef39d632608e66f428c1246836fd060cf4818d67 ]
+
+The input parameters may not be reliable, so check the vlan id before
+using it, otherwise may set wrong vlan id into hardware.
+
+Fixes: dc8131d846d4 ("net: hns3: Fix for packet loss due wrong filter config in VLAN tbls")
+Signed-off-by: liaoguojia <liaoguojia@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 3f8d56ccc057..556dfc854763 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -9810,6 +9810,9 @@ static int hclge_set_vlan_filter_hw(struct hclge_dev *hdev, __be16 proto,
+ if (is_kill && !vlan_id)
+ return 0;
+
++ if (vlan_id >= VLAN_N_VID)
++ return -EINVAL;
++
+ ret = hclge_set_vf_vlan_common(hdev, vport_id, is_kill, vlan_id);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+--
+2.33.0
+
--- /dev/null
+From cf5a0e4a2133675e944d0bc5a78a0c7a040a636d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:11 +0800
+Subject: net: hns3: fix a return value error in hclge_get_reset_status()
+
+From: Yufeng Mo <moyufeng@huawei.com>
+
+[ Upstream commit 5126b9d3d4acdebc12b9d436282f88d8a1b5146c ]
+
+hclge_get_reset_status() should return the tqp reset status.
+However, if the CMDQ fails, the caller will take it as tqp reset
+success status by mistake. Therefore, uses a parameters to get
+the tqp reset status instead.
+
+Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support")
+Signed-off-by: Yufeng Mo <moyufeng@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 556dfc854763..90a72c79fec9 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -10719,7 +10719,8 @@ static int hclge_reset_tqp_cmd_send(struct hclge_dev *hdev, u16 queue_id,
+ return 0;
+ }
+
+-static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
++static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id,
++ u8 *reset_status)
+ {
+ struct hclge_reset_tqp_queue_cmd *req;
+ struct hclge_desc desc;
+@@ -10737,7 +10738,9 @@ static int hclge_get_reset_status(struct hclge_dev *hdev, u16 queue_id)
+ return ret;
+ }
+
+- return hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B);
++ *reset_status = hnae3_get_bit(req->ready_to_reset, HCLGE_TQP_RESET_B);
++
++ return 0;
+ }
+
+ u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id)
+@@ -10756,7 +10759,7 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle)
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ u16 reset_try_times = 0;
+- int reset_status;
++ u8 reset_status;
+ u16 queue_gid;
+ int ret;
+ u16 i;
+@@ -10772,7 +10775,11 @@ static int hclge_reset_tqp_cmd(struct hnae3_handle *handle)
+ }
+
+ while (reset_try_times++ < HCLGE_TQP_RESET_TRY_TIMES) {
+- reset_status = hclge_get_reset_status(hdev, queue_gid);
++ ret = hclge_get_reset_status(hdev, queue_gid,
++ &reset_status);
++ if (ret)
++ return ret;
++
+ if (reset_status)
+ break;
+
+--
+2.33.0
+
--- /dev/null
+From 2b5f201a21f75fdc152651e60d6cb977a0a2a704 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:06 +0800
+Subject: net: hns3: fix change RSS 'hfunc' ineffective issue
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ Upstream commit e184cec5e29d8eb3c3435b12a9074b75e2d69e4a ]
+
+When user change rss 'hfunc' without set rss 'hkey' by ethtool
+-X command, the driver will ignore the 'hfunc' for the hkey is
+NULL. It's unreasonable. So fix it.
+
+Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support")
+Fixes: 374ad291762a ("net: hns3: Add RSS general configuration support for VF")
+Signed-off-by: Jian Shen <shenjian15@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../hisilicon/hns3/hns3pf/hclge_main.c | 45 ++++++++++------
+ .../hisilicon/hns3/hns3vf/hclgevf_main.c | 52 ++++++++++++-------
+ 2 files changed, 64 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 72d55c028ac4..40c4949eed4d 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -4734,6 +4734,24 @@ static int hclge_get_rss(struct hnae3_handle *handle, u32 *indir,
+ return 0;
+ }
+
++static int hclge_parse_rss_hfunc(struct hclge_vport *vport, const u8 hfunc,
++ u8 *hash_algo)
++{
++ switch (hfunc) {
++ case ETH_RSS_HASH_TOP:
++ *hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
++ return 0;
++ case ETH_RSS_HASH_XOR:
++ *hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
++ return 0;
++ case ETH_RSS_HASH_NO_CHANGE:
++ *hash_algo = vport->rss_algo;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
+ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+ {
+@@ -4743,30 +4761,27 @@ static int hclge_set_rss(struct hnae3_handle *handle, const u32 *indir,
+ u8 hash_algo;
+ int ret, i;
+
++ ret = hclge_parse_rss_hfunc(vport, hfunc, &hash_algo);
++ if (ret) {
++ dev_err(&hdev->pdev->dev, "invalid hfunc type %u\n", hfunc);
++ return ret;
++ }
++
+ /* Set the RSS Hash Key if specififed by the user */
+ if (key) {
+- switch (hfunc) {
+- case ETH_RSS_HASH_TOP:
+- hash_algo = HCLGE_RSS_HASH_ALGO_TOEPLITZ;
+- break;
+- case ETH_RSS_HASH_XOR:
+- hash_algo = HCLGE_RSS_HASH_ALGO_SIMPLE;
+- break;
+- case ETH_RSS_HASH_NO_CHANGE:
+- hash_algo = vport->rss_algo;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+ ret = hclge_set_rss_algo_key(hdev, hash_algo, key);
+ if (ret)
+ return ret;
+
+ /* Update the shadow RSS key with user specified qids */
+ memcpy(vport->rss_hash_key, key, HCLGE_RSS_KEY_SIZE);
+- vport->rss_algo = hash_algo;
++ } else {
++ ret = hclge_set_rss_algo_key(hdev, hash_algo,
++ vport->rss_hash_key);
++ if (ret)
++ return ret;
+ }
++ vport->rss_algo = hash_algo;
+
+ /* Update the shadow RSS table with user specified qids */
+ for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++)
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+index be3ea7023ed8..22cf66004dfa 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+@@ -814,40 +814,56 @@ static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
+ return 0;
+ }
+
++static int hclgevf_parse_rss_hfunc(struct hclgevf_dev *hdev, const u8 hfunc,
++ u8 *hash_algo)
++{
++ switch (hfunc) {
++ case ETH_RSS_HASH_TOP:
++ *hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
++ return 0;
++ case ETH_RSS_HASH_XOR:
++ *hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
++ return 0;
++ case ETH_RSS_HASH_NO_CHANGE:
++ *hash_algo = hdev->rss_cfg.hash_algo;
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
+ static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
+ const u8 *key, const u8 hfunc)
+ {
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+ struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
++ u8 hash_algo;
+ int ret, i;
+
+ if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
++ ret = hclgevf_parse_rss_hfunc(hdev, hfunc, &hash_algo);
++ if (ret)
++ return ret;
++
+ /* Set the RSS Hash Key if specififed by the user */
+ if (key) {
+- switch (hfunc) {
+- case ETH_RSS_HASH_TOP:
+- rss_cfg->hash_algo =
+- HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
+- break;
+- case ETH_RSS_HASH_XOR:
+- rss_cfg->hash_algo =
+- HCLGEVF_RSS_HASH_ALGO_SIMPLE;
+- break;
+- case ETH_RSS_HASH_NO_CHANGE:
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
+- key);
+- if (ret)
++ ret = hclgevf_set_rss_algo_key(hdev, hash_algo, key);
++ if (ret) {
++ dev_err(&hdev->pdev->dev,
++ "invalid hfunc type %u\n", hfunc);
+ return ret;
++ }
+
+ /* Update the shadow RSS key with user specified qids */
+ memcpy(rss_cfg->rss_hash_key, key,
+ HCLGEVF_RSS_KEY_SIZE);
++ } else {
++ ret = hclgevf_set_rss_algo_key(hdev, hash_algo,
++ rss_cfg->rss_hash_key);
++ if (ret)
++ return ret;
+ }
++ rss_cfg->hash_algo = hash_algo;
+ }
+
+ /* update the shadow RSS table with user specified qids */
+--
+2.33.0
+
--- /dev/null
+From 488c5269b77c657b1523dbefde95331b8be1d403 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:07 +0800
+Subject: net: hns3: fix inconsistent vf id print
+
+From: Jian Shen <shenjian15@huawei.com>
+
+[ Upstream commit 91bc0d5272d3a4dc3d4fd2a74387c7e7361bbe96 ]
+
+The vf id from ethtool is added 1 before configured to driver.
+So it's necessary to minus 1 when printing it, in order to
+keep consistent with user's configuration.
+
+Fixes: dd74f815dd41 ("net: hns3: Add support for rule add/delete for flow director")
+Signed-off-by: Jian Shen <shenjian15@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 40c4949eed4d..45faf924bc36 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -6635,10 +6635,13 @@ static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie,
+ u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
+ u16 tqps;
+
++ /* To keep consistent with user's configuration, minus 1 when
++ * printing 'vf', because vf id from ethtool is added 1 for vf.
++ */
+ if (vf > hdev->num_req_vfs) {
+ dev_err(&hdev->pdev->dev,
+- "Error: vf id (%u) > max vf num (%u)\n",
+- vf, hdev->num_req_vfs);
++ "Error: vf id (%u) should be less than %u\n",
++ vf - 1, hdev->num_req_vfs);
+ return -EINVAL;
+ }
+
+--
+2.33.0
+
--- /dev/null
+From 1c4512efe71744cf3f65712c002f1860847b0d33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Sep 2021 21:52:08 +0800
+Subject: net: hns3: fix misuse vf id and vport id in some logs
+
+From: Jiaran Zhang <zhangjiaran@huawei.com>
+
+[ Upstream commit 311c0aaa9b4bb8dc65f22634e15963316b17c921 ]
+
+vport_id include PF and VFs, vport_id = 0 means PF, other values mean VFs.
+So the actual vf id is equal to vport_id minus 1.
+
+Some VF print logs are actually vport, and logs of vf id actually use
+vport id, so this patch fixes them.
+
+Fixes: ac887be5b0fe ("net: hns3: change print level of RAS error log from warning to error")
+Fixes: adcf738b804b ("net: hns3: cleanup some print format warning")
+Signed-off-by: Jiaran Zhang <zhangjiaran@huawei.com>
+Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c | 8 ++++----
+ .../net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 10 ++++++----
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +-
+ drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c | 2 +-
+ 4 files changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+index ec9a7f8bc3fe..2eeafd61a07e 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+@@ -1878,12 +1878,12 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev,
+ return;
+ }
+
+- dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vf_id(%u), queue_id(%u)\n",
++ dev_err(dev, "PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found, vport(%u), queue_id(%u)\n",
+ vf_id, q_id);
+
+ if (vf_id) {
+ if (vf_id >= hdev->num_alloc_vport) {
+- dev_err(dev, "invalid vf id(%u)\n", vf_id);
++ dev_err(dev, "invalid vport(%u)\n", vf_id);
+ return;
+ }
+
+@@ -1896,8 +1896,8 @@ static void hclge_handle_over_8bd_err(struct hclge_dev *hdev,
+
+ ret = hclge_inform_reset_assert_to_vf(&hdev->vport[vf_id]);
+ if (ret)
+- dev_err(dev, "inform reset to vf(%u) failed %d!\n",
+- hdev->vport->vport_id, ret);
++ dev_err(dev, "inform reset to vport(%u) failed %d!\n",
++ vf_id, ret);
+ } else {
+ set_bit(HNAE3_FUNC_RESET, reset_requests);
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 45faf924bc36..3f8d56ccc057 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -3660,7 +3660,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "set vf(%u) rst failed %d!\n",
+- vport->vport_id, ret);
++ vport->vport_id - HCLGE_VF_VPORT_START_NUM,
++ ret);
+ return ret;
+ }
+
+@@ -3675,7 +3676,8 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset)
+ if (ret)
+ dev_warn(&hdev->pdev->dev,
+ "inform reset to vf(%u) failed %d!\n",
+- vport->vport_id, ret);
++ vport->vport_id - HCLGE_VF_VPORT_START_NUM,
++ ret);
+ }
+
+ return 0;
+@@ -11460,11 +11462,11 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev)
+ struct hclge_vport *vport = &hdev->vport[i];
+ int ret;
+
+- /* Send cmd to clear VF's FUNC_RST_ING */
++ /* Send cmd to clear vport's FUNC_RST_ING */
+ ret = hclge_set_vf_rst(hdev, vport->vport_id, false);
+ if (ret)
+ dev_warn(&hdev->pdev->dev,
+- "clear vf(%u) rst failed %d!\n",
++ "clear vport(%u) rst failed %d!\n",
+ vport->vport_id, ret);
+ }
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+index 0dbed35645ed..91c32f99b644 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+@@ -564,7 +564,7 @@ static int hclge_reset_vf(struct hclge_vport *vport)
+ struct hclge_dev *hdev = vport->back;
+
+ dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!",
+- vport->vport_id);
++ vport->vport_id - HCLGE_VF_VPORT_START_NUM);
+
+ return hclge_func_reset_cmd(hdev, vport->vport_id);
+ }
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+index 78d5bf1ea561..44618cc4cca1 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+@@ -581,7 +581,7 @@ int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate)
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+- "vf%u, qs%u failed to set tx_rate:%d, ret=%d\n",
++ "vport%u, qs%u failed to set tx_rate:%d, ret=%d\n",
+ vport->vport_id, shap_cfg_cmd->qs_id,
+ max_tx_rate, ret);
+ return ret;
+--
+2.33.0
+
--- /dev/null
+From 35cfd3da7421aee86b5c11b996b16ca19a00527f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Sep 2021 09:51:45 +0300
+Subject: net/mlx4_en: Don't allow aRFS for encapsulated packets
+
+From: Aya Levin <ayal@nvidia.com>
+
+[ Upstream commit fdbccea419dc782079ce5881d2705cc9e3881480 ]
+
+Driver doesn't support aRFS for encapsulated packets, return early error
+in such a case.
+
+Fixes: 1eb8c695bda9 ("net/mlx4_en: Add accelerated RFS support")
+Signed-off-by: Aya Levin <ayal@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index c3171b5f6431..a6878e5f922a 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -372,6 +372,9 @@ mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+ int nhoff = skb_network_offset(skb);
+ int ret = 0;
+
++ if (skb->encapsulation)
++ return -EPROTONOSUPPORT;
++
+ if (skb->protocol != htons(ETH_P_IP))
+ return -EPROTONOSUPPORT;
+
+--
+2.33.0
+
--- /dev/null
+From 548f95a57741c4879bc873aee299f1dcf6c602a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 19 Sep 2021 14:55:45 +0300
+Subject: net/mlx4_en: Resolve bad operstate value
+
+From: Lama Kayal <lkayal@nvidia.com>
+
+[ Upstream commit 72a3c58d18fd780eecd80178bb2132ce741a0a74 ]
+
+Any link state change that's done prior to net device registration
+isn't reflected on the state, thus the operational state is left
+obsolete, with 'UNKNOWN' status.
+
+To resolve the issue, query link state from FW upon open operations
+to ensure operational state is updated.
+
+Fixes: c27a02cd94d6 ("mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC")
+Signed-off-by: Lama Kayal <lkayal@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx4/en_netdev.c | 47 ++++++++++++-------
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 -
+ 2 files changed, 29 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+index 5d0c9c62382d..c3171b5f6431 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
++++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+@@ -1269,7 +1269,6 @@ static void mlx4_en_do_set_rx_mode(struct work_struct *work)
+ if (!netif_carrier_ok(dev)) {
+ if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
+ if (priv->port_state.link_state) {
+- priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
+ netif_carrier_on(dev);
+ en_dbg(LINK, priv, "Link Up\n");
+ }
+@@ -1557,26 +1556,36 @@ static void mlx4_en_service_task(struct work_struct *work)
+ mutex_unlock(&mdev->state_lock);
+ }
+
+-static void mlx4_en_linkstate(struct work_struct *work)
++static void mlx4_en_linkstate(struct mlx4_en_priv *priv)
++{
++ struct mlx4_en_port_state *port_state = &priv->port_state;
++ struct mlx4_en_dev *mdev = priv->mdev;
++ struct net_device *dev = priv->dev;
++ bool up;
++
++ if (mlx4_en_QUERY_PORT(mdev, priv->port))
++ port_state->link_state = MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN;
++
++ up = port_state->link_state == MLX4_PORT_STATE_DEV_EVENT_PORT_UP;
++ if (up == netif_carrier_ok(dev))
++ netif_carrier_event(dev);
++ if (!up) {
++ en_info(priv, "Link Down\n");
++ netif_carrier_off(dev);
++ } else {
++ en_info(priv, "Link Up\n");
++ netif_carrier_on(dev);
++ }
++}
++
++static void mlx4_en_linkstate_work(struct work_struct *work)
+ {
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ linkstate_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+- int linkstate = priv->link_state;
+
+ mutex_lock(&mdev->state_lock);
+- /* If observable port state changed set carrier state and
+- * report to system log */
+- if (priv->last_link_state != linkstate) {
+- if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
+- en_info(priv, "Link Down\n");
+- netif_carrier_off(priv->dev);
+- } else {
+- en_info(priv, "Link Up\n");
+- netif_carrier_on(priv->dev);
+- }
+- }
+- priv->last_link_state = linkstate;
++ mlx4_en_linkstate(priv);
+ mutex_unlock(&mdev->state_lock);
+ }
+
+@@ -2079,9 +2088,11 @@ static int mlx4_en_open(struct net_device *dev)
+ mlx4_en_clear_stats(dev);
+
+ err = mlx4_en_start_port(dev);
+- if (err)
++ if (err) {
+ en_err(priv, "Failed starting port:%d\n", priv->port);
+-
++ goto out;
++ }
++ mlx4_en_linkstate(priv);
+ out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+@@ -3168,7 +3179,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ spin_lock_init(&priv->stats_lock);
+ INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
+ INIT_WORK(&priv->restart_task, mlx4_en_restart);
+- INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
++ INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate_work);
+ INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
+ INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
+ #ifdef CONFIG_RFS_ACCEL
+diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+index f3d1a20201ef..6bf558c5ec10 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+@@ -552,7 +552,6 @@ struct mlx4_en_priv {
+
+ struct mlx4_hwq_resources res;
+ int link_state;
+- int last_link_state;
+ bool port_up;
+ int port;
+ int registered;
+--
+2.33.0
+
--- /dev/null
+From abda04aac4792a6f6935caa46097f35617fb9e66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 19:03:38 -0700
+Subject: net: mscc: ocelot: fix forwarding from BLOCKING ports remaining
+ enabled
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit acc64f52afac15e9e44d9b5253271346841786e0 ]
+
+The blamed commit made the fatally incorrect assumption that ports which
+aren't in the FORWARDING STP state should not have packets forwarded
+towards them, and that is all that needs to be done.
+
+However, that logic alone permits BLOCKING ports to forward to
+FORWARDING ports, which of course allows packet storms to occur when
+there is an L2 loop.
+
+The ocelot_get_bridge_fwd_mask should not only ask "what can the bridge
+do for you", but "what can you do for the bridge". This way, only
+FORWARDING ports forward to the other FORWARDING ports from the same
+bridging domain, and we are still compatible with the idea of multiple
+bridges.
+
+Fixes: df291e54ccca ("net: ocelot: support multiple bridges")
+Suggested-by: Colin Foster <colin.foster@in-advantage.com>
+Reported-by: Colin Foster <colin.foster@in-advantage.com>
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mscc/ocelot.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
+index 2948d731a1c1..512dff955166 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -1260,14 +1260,19 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond,
+ return mask;
+ }
+
+-static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot,
++static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, int src_port,
+ struct net_device *bridge)
+ {
++ struct ocelot_port *ocelot_port = ocelot->ports[src_port];
+ u32 mask = 0;
+ int port;
+
++ if (!ocelot_port || ocelot_port->bridge != bridge ||
++ ocelot_port->stp_state != BR_STATE_FORWARDING)
++ return 0;
++
+ for (port = 0; port < ocelot->num_phys_ports; port++) {
+- struct ocelot_port *ocelot_port = ocelot->ports[port];
++ ocelot_port = ocelot->ports[port];
+
+ if (!ocelot_port)
+ continue;
+@@ -1333,7 +1338,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
+ struct net_device *bridge = ocelot_port->bridge;
+ struct net_device *bond = ocelot_port->bond;
+
+- mask = ocelot_get_bridge_fwd_mask(ocelot, bridge);
++ mask = ocelot_get_bridge_fwd_mask(ocelot, port, bridge);
+ mask |= cpu_fwd_mask;
+ mask &= ~BIT(port);
+ if (bond) {
+--
+2.33.0
+
--- /dev/null
+From 3ced899f64f9ba7a20eaea302c5751da1ad3f568 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Sep 2021 21:18:14 +0200
+Subject: net/smc: add missing error check in smc_clc_prfx_set()
+
+From: Karsten Graul <kgraul@linux.ibm.com>
+
+[ Upstream commit 6c90731980655280ea07ce4b21eb97457bf86286 ]
+
+Coverity stumbled over a missing error check in smc_clc_prfx_set():
+
+*** CID 1475954: Error handling issues (CHECKED_RETURN)
+/net/smc/smc_clc.c: 233 in smc_clc_prfx_set()
+>>> CID 1475954: Error handling issues (CHECKED_RETURN)
+>>> Calling "kernel_getsockname" without checking return value (as is done elsewhere 8 out of 10 times).
+233 kernel_getsockname(clcsock, (struct sockaddr *)&addrs);
+
+Add the return code check in smc_clc_prfx_set().
+
+Fixes: c246d942eabc ("net/smc: restructure netinfo for CLC proposal msgs")
+Reported-by: Julian Wiedmann <jwi@linux.ibm.com>
+Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_clc.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
+index e286dafd6e88..6ec1ebe878ae 100644
+--- a/net/smc/smc_clc.c
++++ b/net/smc/smc_clc.c
+@@ -230,7 +230,8 @@ static int smc_clc_prfx_set(struct socket *clcsock,
+ goto out_rel;
+ }
+ /* get address to which the internal TCP socket is bound */
+- kernel_getsockname(clcsock, (struct sockaddr *)&addrs);
++ if (kernel_getsockname(clcsock, (struct sockaddr *)&addrs) < 0)
++ goto out_rel;
+ /* analyze IP specific data of net_device belonging to TCP socket */
+ addr6 = (struct sockaddr_in6 *)&addrs;
+ rcu_read_lock();
+--
+2.33.0
+
--- /dev/null
+From 9c16827976a9392bcbcdd81270f92cb1465a0863 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Sep 2021 21:18:15 +0200
+Subject: net/smc: fix 'workqueue leaked lock' in smc_conn_abort_work
+
+From: Karsten Graul <kgraul@linux.ibm.com>
+
+[ Upstream commit a18cee4791b1123d0a6579a7c89f4b87e48abe03 ]
+
+The abort_work is scheduled when a connection was detected to be
+out-of-sync after a link failure. The work calls smc_conn_kill(),
+which calls smc_close_active_abort() and that might end up calling
+smc_close_cancel_work().
+smc_close_cancel_work() cancels any pending close_work and tx_work but
+needs to release the sock_lock before and acquires the sock_lock again
+afterwards. So when the sock_lock was NOT acquired before then it may
+be held after the abort_work completes. Thats why the sock_lock is
+acquired before the call to smc_conn_kill() in __smc_lgr_terminate(),
+but this is missing in smc_conn_abort_work().
+
+Fix that by acquiring the sock_lock first and release it after the
+call to smc_conn_kill().
+
+Fixes: b286a0651e44 ("net/smc: handle incoming CDC validation message")
+Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/smc_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
+index c160ff50c053..116cfd6fac1f 100644
+--- a/net/smc/smc_core.c
++++ b/net/smc/smc_core.c
+@@ -1474,7 +1474,9 @@ static void smc_conn_abort_work(struct work_struct *work)
+ abort_work);
+ struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
+
++ lock_sock(&smc->sk);
+ smc_conn_kill(conn, true);
++ release_sock(&smc->sk);
+ sock_put(&smc->sk); /* sock_hold done by schedulers of abort_work */
+ }
+
+--
+2.33.0
+
--- /dev/null
+From 1295362df462ffbab7d2c6d1ef4e0d1cc97a1286 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 13:25:40 +0300
+Subject: nexthop: Fix memory leaks in nexthop notification chain listeners
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 3106a0847525befe3e22fc723909d1b21eb0d520 ]
+
+syzkaller discovered memory leaks [1] that can be reduced to the
+following commands:
+
+ # ip nexthop add id 1 blackhole
+ # devlink dev reload pci/0000:06:00.0
+
+As part of the reload flow, mlxsw will unregister its netdevs and then
+unregister from the nexthop notification chain. Before unregistering
+from the notification chain, mlxsw will receive delete notifications for
+nexthop objects using netdevs registered by mlxsw or their uppers. mlxsw
+will not receive notifications for nexthops using netdevs that are not
+dismantled as part of the reload flow. For example, the blackhole
+nexthop above that internally uses the loopback netdev as its nexthop
+device.
+
+One way to fix this problem is to have listeners flush their nexthop
+tables after unregistering from the notification chain. This is
+error-prone as evident by this patch and also not symmetric with the
+registration path where a listener receives a dump of all the existing
+nexthops.
+
+Therefore, fix this problem by replaying delete notifications for the
+listener being unregistered. This is symmetric to the registration path
+and also consistent with the netdev notification chain.
+
+The above means that unregister_nexthop_notifier(), like
+register_nexthop_notifier(), will have to take RTNL in order to iterate
+over the existing nexthops and that any callers of the function cannot
+hold RTNL. This is true for mlxsw and netdevsim, but not for the VXLAN
+driver. To avoid a deadlock, change the latter to unregister its nexthop
+listener without holding RTNL, making it symmetric to the registration
+path.
+
+[1]
+unreferenced object 0xffff88806173d600 (size 512):
+ comm "syz-executor.0", pid 1290, jiffies 4295583142 (age 143.507s)
+ hex dump (first 32 bytes):
+ 41 9d 1e 60 80 88 ff ff 08 d6 73 61 80 88 ff ff A..`......sa....
+ 08 d6 73 61 80 88 ff ff 01 00 00 00 00 00 00 00 ..sa............
+ backtrace:
+ [<ffffffff81a6b576>] kmemleak_alloc_recursive include/linux/kmemleak.h:43 [inline]
+ [<ffffffff81a6b576>] slab_post_alloc_hook+0x96/0x490 mm/slab.h:522
+ [<ffffffff81a716d3>] slab_alloc_node mm/slub.c:3206 [inline]
+ [<ffffffff81a716d3>] slab_alloc mm/slub.c:3214 [inline]
+ [<ffffffff81a716d3>] kmem_cache_alloc_trace+0x163/0x370 mm/slub.c:3231
+ [<ffffffff82e8681a>] kmalloc include/linux/slab.h:591 [inline]
+ [<ffffffff82e8681a>] kzalloc include/linux/slab.h:721 [inline]
+ [<ffffffff82e8681a>] mlxsw_sp_nexthop_obj_group_create drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:4918 [inline]
+ [<ffffffff82e8681a>] mlxsw_sp_nexthop_obj_new drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:5054 [inline]
+ [<ffffffff82e8681a>] mlxsw_sp_nexthop_obj_event+0x59a/0x2910 drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c:5239
+ [<ffffffff813ef67d>] notifier_call_chain+0xbd/0x210 kernel/notifier.c:83
+ [<ffffffff813f0662>] blocking_notifier_call_chain kernel/notifier.c:318 [inline]
+ [<ffffffff813f0662>] blocking_notifier_call_chain+0x72/0xa0 kernel/notifier.c:306
+ [<ffffffff8384b9c6>] call_nexthop_notifiers+0x156/0x310 net/ipv4/nexthop.c:244
+ [<ffffffff83852bd8>] insert_nexthop net/ipv4/nexthop.c:2336 [inline]
+ [<ffffffff83852bd8>] nexthop_add net/ipv4/nexthop.c:2644 [inline]
+ [<ffffffff83852bd8>] rtm_new_nexthop+0x14e8/0x4d10 net/ipv4/nexthop.c:2913
+ [<ffffffff833e9a78>] rtnetlink_rcv_msg+0x448/0xbf0 net/core/rtnetlink.c:5572
+ [<ffffffff83608703>] netlink_rcv_skb+0x173/0x480 net/netlink/af_netlink.c:2504
+ [<ffffffff833de032>] rtnetlink_rcv+0x22/0x30 net/core/rtnetlink.c:5590
+ [<ffffffff836069de>] netlink_unicast_kernel net/netlink/af_netlink.c:1314 [inline]
+ [<ffffffff836069de>] netlink_unicast+0x5ae/0x7f0 net/netlink/af_netlink.c:1340
+ [<ffffffff83607501>] netlink_sendmsg+0x8e1/0xe30 net/netlink/af_netlink.c:1929
+ [<ffffffff832fde84>] sock_sendmsg_nosec net/socket.c:704 [inline]
+ [<ffffffff832fde84>] sock_sendmsg net/socket.c:724 [inline]
+ [<ffffffff832fde84>] ____sys_sendmsg+0x874/0x9f0 net/socket.c:2409
+ [<ffffffff83304a44>] ___sys_sendmsg+0x104/0x170 net/socket.c:2463
+ [<ffffffff83304c01>] __sys_sendmsg+0x111/0x1f0 net/socket.c:2492
+ [<ffffffff83304d5d>] __do_sys_sendmsg net/socket.c:2501 [inline]
+ [<ffffffff83304d5d>] __se_sys_sendmsg net/socket.c:2499 [inline]
+ [<ffffffff83304d5d>] __x64_sys_sendmsg+0x7d/0xc0 net/socket.c:2499
+
+Fixes: 2a014b200bbd ("mlxsw: spectrum_router: Add support for nexthop objects")
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan.c | 2 +-
+ net/ipv4/nexthop.c | 19 ++++++++++++++-----
+ 2 files changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
+index 5a8df5a195cb..141635a35c28 100644
+--- a/drivers/net/vxlan.c
++++ b/drivers/net/vxlan.c
+@@ -4756,12 +4756,12 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
+ LIST_HEAD(list);
+ unsigned int h;
+
+- rtnl_lock();
+ list_for_each_entry(net, net_list, exit_list) {
+ struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+
+ unregister_nexthop_notifier(net, &vn->nexthop_notifier_block);
+ }
++ rtnl_lock();
+ list_for_each_entry(net, net_list, exit_list)
+ vxlan_destroy_tunnels(net, &list);
+
+diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
+index 0e75fd3e57b4..9e8100728d46 100644
+--- a/net/ipv4/nexthop.c
++++ b/net/ipv4/nexthop.c
+@@ -3567,6 +3567,7 @@ static struct notifier_block nh_netdev_notifier = {
+ };
+
+ static int nexthops_dump(struct net *net, struct notifier_block *nb,
++ enum nexthop_event_type event_type,
+ struct netlink_ext_ack *extack)
+ {
+ struct rb_root *root = &net->nexthop.rb_root;
+@@ -3577,8 +3578,7 @@ static int nexthops_dump(struct net *net, struct notifier_block *nb,
+ struct nexthop *nh;
+
+ nh = rb_entry(node, struct nexthop, rb_node);
+- err = call_nexthop_notifier(nb, net, NEXTHOP_EVENT_REPLACE, nh,
+- extack);
++ err = call_nexthop_notifier(nb, net, event_type, nh, extack);
+ if (err)
+ break;
+ }
+@@ -3592,7 +3592,7 @@ int register_nexthop_notifier(struct net *net, struct notifier_block *nb,
+ int err;
+
+ rtnl_lock();
+- err = nexthops_dump(net, nb, extack);
++ err = nexthops_dump(net, nb, NEXTHOP_EVENT_REPLACE, extack);
+ if (err)
+ goto unlock;
+ err = blocking_notifier_chain_register(&net->nexthop.notifier_chain,
+@@ -3605,8 +3605,17 @@ EXPORT_SYMBOL(register_nexthop_notifier);
+
+ int unregister_nexthop_notifier(struct net *net, struct notifier_block *nb)
+ {
+- return blocking_notifier_chain_unregister(&net->nexthop.notifier_chain,
+- nb);
++ int err;
++
++ rtnl_lock();
++ err = blocking_notifier_chain_unregister(&net->nexthop.notifier_chain,
++ nb);
++ if (err)
++ goto unlock;
++ nexthops_dump(net, nb, NEXTHOP_EVENT_DEL, NULL);
++unlock:
++ rtnl_unlock();
++ return err;
+ }
+ EXPORT_SYMBOL(unregister_nexthop_notifier);
+
+--
+2.33.0
+
--- /dev/null
+From 4e79527d4b128bdc6923fb517e1c5f1d0000f8d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 19:30:37 +0100
+Subject: nfc: st-nci: Add SPI ID matching DT compatible
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 31339440b2d0a4987030aac026adbaba44e22490 ]
+
+Currently autoloading for SPI devices does not use the DT ID table, it uses
+SPI modalises. Supporting OF modalises is going to be difficult if not
+impractical, an attempt was made but has been reverted, so ensure that
+module autoloading works for this driver by adding the part name used in
+the compatible to the list of SPI IDs.
+
+Fixes: 96c8395e2166 ("spi: Revert modalias changes")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/st-nci/spi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c
+index 250d56f204c3..e62b1a0916d8 100644
+--- a/drivers/nfc/st-nci/spi.c
++++ b/drivers/nfc/st-nci/spi.c
+@@ -278,6 +278,7 @@ static int st_nci_spi_remove(struct spi_device *dev)
+
+ static struct spi_device_id st_nci_spi_id_table[] = {
+ {ST_NCI_SPI_DRIVER_NAME, 0},
++ {"st21nfcb-spi", 0},
+ {}
+ };
+ MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
+--
+2.33.0
+
--- /dev/null
+From e57551cadf48fa479465962c7bedfcb45e1e421b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Sep 2021 17:24:54 -0400
+Subject: NLM: Fix svcxdr_encode_owner()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 89c485c7a3ecbc2ebd568f9c9c2edf3a8cf7485b ]
+
+Dai Ngo reports that, since the XDR overhaul, the NLM server crashes
+when the TEST procedure wants to return NLM_DENIED. There is a bug
+in svcxdr_encode_owner() that none of our standard test cases found.
+
+Replace the open-coded function with a call to an appropriate
+pre-fabricated XDR helper.
+
+Reported-by: Dai Ngo <Dai.Ngo@oracle.com>
+Fixes: a6a63ca5652e ("lockd: Common NLM XDR helpers")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/lockd/svcxdr.h | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+diff --git a/fs/lockd/svcxdr.h b/fs/lockd/svcxdr.h
+index c69a0bb76c94..4f1a451da5ba 100644
+--- a/fs/lockd/svcxdr.h
++++ b/fs/lockd/svcxdr.h
+@@ -134,18 +134,9 @@ svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj)
+ static inline bool
+ svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj)
+ {
+- unsigned int quadlen = XDR_QUADLEN(obj->len);
+- __be32 *p;
+-
+- if (xdr_stream_encode_u32(xdr, obj->len) < 0)
+- return false;
+- p = xdr_reserve_space(xdr, obj->len);
+- if (!p)
++ if (obj->len > XDR_MAX_NETOBJ)
+ return false;
+- p[quadlen - 1] = 0; /* XDR pad */
+- memcpy(p, obj->data, obj->len);
+-
+- return true;
++ return xdr_stream_encode_opaque(xdr, obj->data, obj->len) > 0;
+ }
+
+ #endif /* _LOCKD_SVCXDR_H_ */
+--
+2.33.0
+
--- /dev/null
+From 0d916b317205b9254de5279cbff1b89d0dc19f13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 21:48:29 -0700
+Subject: platform/x86: dell: fix DELL_WMI_PRIVACY dependencies & build error
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 5b72dafaca73b33416c82457ae615e6f2022e901 ]
+
+When DELL_WMI=y, DELL_WMI_PRIVACY=y, and LEDS_TRIGGER_AUDIO=m, there
+is a linker error since the LEDS trigger code is built as a loadable
+module. This happens because DELL_WMI_PRIVACY is a bool that depends
+on a tristate (LEDS_TRIGGER_AUDIO=m), which can be dangerous.
+
+ld: drivers/platform/x86/dell/dell-wmi-privacy.o: in function `dell_privacy_wmi_probe':
+dell-wmi-privacy.c:(.text+0x3df): undefined reference to `ledtrig_audio_get'
+
+Fixes: 8af9fa37b8a3 ("platform/x86: dell-privacy: Add support for Dell hardware privacy")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Perry Yuan <Perry.Yuan@dell.com>
+Cc: Dell.Client.Kernel@dell.com
+Cc: platform-driver-x86@vger.kernel.org
+Cc: Hans de Goede <hdegoede@redhat.com>
+Cc: Mark Gross <mgross@linux.intel.com>
+Link: https://lore.kernel.org/r/20210918044829.19222-1-rdunlap@infradead.org
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/dell/Kconfig | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
+index 9e7314d90bea..1e3da9700005 100644
+--- a/drivers/platform/x86/dell/Kconfig
++++ b/drivers/platform/x86/dell/Kconfig
+@@ -166,8 +166,7 @@ config DELL_WMI
+
+ config DELL_WMI_PRIVACY
+ bool "Dell WMI Hardware Privacy Support"
+- depends on DELL_WMI
+- depends on LEDS_TRIGGER_AUDIO
++ depends on LEDS_TRIGGER_AUDIO = y || DELL_WMI = LEDS_TRIGGER_AUDIO
+ help
+ This option adds integration with the "Dell Hardware Privacy"
+ feature of Dell laptops to the dell-wmi driver.
+--
+2.33.0
+
--- /dev/null
+From 885b7dfc809bad86a3af78286512172c48d89429 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Aug 2021 17:53:10 +0300
+Subject: platform/x86/intel: punit_ipc: Drop wrong use of ACPI_PTR()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 349bff48ae0f5f8aa2075d0bdc2091a30bd634f6 ]
+
+ACPI_PTR() is more harmful than helpful. For example, in this case
+if CONFIG_ACPI=n, the ID table left unused which is not what we want.
+
+Instead of adding ifdeffery here and there, drop ACPI_PTR()
+and unused acpi.h.
+
+Fixes: fdca4f16f57d ("platform:x86: add Intel P-Unit mailbox IPC driver")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Link: https://lore.kernel.org/r/20210827145310.76239-1-andriy.shevchenko@linux.intel.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/intel_punit_ipc.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/intel_punit_ipc.c b/drivers/platform/x86/intel_punit_ipc.c
+index f58b8543f6ac..66bb39fd0ef9 100644
+--- a/drivers/platform/x86/intel_punit_ipc.c
++++ b/drivers/platform/x86/intel_punit_ipc.c
+@@ -8,7 +8,6 @@
+ * which provide mailbox interface for power management usage.
+ */
+
+-#include <linux/acpi.h>
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+@@ -319,7 +318,7 @@ static struct platform_driver intel_punit_ipc_driver = {
+ .remove = intel_punit_ipc_remove,
+ .driver = {
+ .name = "intel_punit_ipc",
+- .acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids),
++ .acpi_match_table = punit_ipc_acpi_ids,
+ },
+ };
+
+--
+2.33.0
+
--- /dev/null
+From f679c882d482b9c0418cca26c958671be3bc8b77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Sep 2021 13:53:26 +0300
+Subject: qed: rdma - don't wait for resources under hw error recovery flow
+
+From: Shai Malin <smalin@marvell.com>
+
+[ Upstream commit 1ea7812326004afd2803cc968a4776ae5120a597 ]
+
+If the HW device is during recovery, the HW resources will never return,
+hence we shouldn't wait for the CID (HW context ID) bitmaps to clear.
+This fix speeds up the error recovery flow.
+
+Fixes: 64515dc899df ("qed: Add infrastructure for error detection and recovery")
+Signed-off-by: Michal Kalderon <mkalderon@marvell.com>
+Signed-off-by: Ariel Elior <aelior@marvell.com>
+Signed-off-by: Shai Malin <smalin@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/qlogic/qed/qed_iwarp.c | 8 ++++++++
+ drivers/net/ethernet/qlogic/qed/qed_roce.c | 8 ++++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
+index a99861124630..68fbe536a1f3 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
+@@ -1297,6 +1297,14 @@ qed_iwarp_wait_cid_map_cleared(struct qed_hwfn *p_hwfn, struct qed_bmap *bmap)
+ prev_weight = weight;
+
+ while (weight) {
++ /* If the HW device is during recovery, all resources are
++ * immediately reset without receiving a per-cid indication
++ * from HW. In this case we don't expect the cid_map to be
++ * cleared.
++ */
++ if (p_hwfn->cdev->recov_in_prog)
++ return 0;
++
+ msleep(QED_IWARP_MAX_CID_CLEAN_TIME);
+
+ weight = bitmap_weight(bmap->bitmap, bmap->max_count);
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c
+index f16a157bb95a..cf5baa5e59bc 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_roce.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c
+@@ -77,6 +77,14 @@ void qed_roce_stop(struct qed_hwfn *p_hwfn)
+ * Beyond the added delay we clear the bitmap anyway.
+ */
+ while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) {
++ /* If the HW device is during recovery, all resources are
++ * immediately reset without receiving a per-cid indication
++ * from HW. In this case we don't expect the cid bitmap to be
++ * cleared.
++ */
++ if (p_hwfn->cdev->recov_in_prog)
++ return;
++
+ msleep(100);
+ if (wait_count++ > 20) {
+ DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n");
+--
+2.33.0
+
--- /dev/null
+From bc8597ba213190fa4fd80f5f90008f59d43e9a76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Sep 2021 16:41:02 +0200
+Subject: regulator: max14577: Revert "regulator: max14577: Add proper module
+ aliases strings"
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+[ Upstream commit dc9660590d106bb58d145233fffca4efadad3655 ]
+
+This reverts commit 0da6736ecd10b45e535b100acd58df2db4c099d8.
+
+The MODULE_DEVICE_TABLE already creates proper alias. Having another
+MODULE_ALIAS causes the alias to be duplicated:
+
+ $ modinfo max14577-regulator.ko
+
+ alias: platform:max77836-regulator
+ alias: platform:max14577-regulator
+ description: Maxim 14577/77836 regulator driver
+ alias: platform:max77836-regulator
+ alias: platform:max14577-regulator
+
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Fixes: 0da6736ecd10 ("regulator: max14577: Add proper module aliases strings")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Link: https://lore.kernel.org/r/20210916144102.120980-1-krzysztof.kozlowski@canonical.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/max14577-regulator.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/regulator/max14577-regulator.c b/drivers/regulator/max14577-regulator.c
+index 1d78b455cc48..e34face736f4 100644
+--- a/drivers/regulator/max14577-regulator.c
++++ b/drivers/regulator/max14577-regulator.c
+@@ -269,5 +269,3 @@ module_exit(max14577_regulator_exit);
+ MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
+ MODULE_DESCRIPTION("Maxim 14577/77836 regulator driver");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("platform:max14577-regulator");
+-MODULE_ALIAS("platform:max77836-regulator");
+--
+2.33.0
+
--- /dev/null
+From 6e722e572ad63e29284fc219cf733f25e668d552 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 Sep 2021 14:43:50 +0300
+Subject: regulator: qcom-rpmh-regulator: fix pm8009-1 ldo7 resource name
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 863580418bc82062083be854355f2213d3d804f5 ]
+
+Fix a typo in the pm8009 LDO7 declaration, it uses resource name ldo%s6
+instead of ldo%s7.
+
+Fixes: 951384cabc5d ("regulator: qcom-rpmh-regulator: add pm8009-1 chip revision")
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
+Link: https://lore.kernel.org/r/20210901114350.1106073-1-dmitry.baryshkov@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/qcom-rpmh-regulator.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c
+index 6cca910a76de..7f458d510483 100644
+--- a/drivers/regulator/qcom-rpmh-regulator.c
++++ b/drivers/regulator/qcom-rpmh-regulator.c
+@@ -991,7 +991,7 @@ static const struct rpmh_vreg_init_data pm8009_1_vreg_data[] = {
+ RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"),
+ RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6"),
+ RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6"),
+- RPMH_VREG("ldo7", "ldo%s6", &pmic5_pldo_lv, "vdd-l7"),
++ RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo_lv, "vdd-l7"),
+ {}
+ };
+
+--
+2.33.0
+
--- /dev/null
+From 44f2950e4583910b42bbd6534292658832d84a39 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 16:52:17 +0200
+Subject: s390/qeth: fix deadlock during failing recovery
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit d2b59bd4b06d84a4eadb520b0f71c62fe8ec0a62 ]
+
+Commit 0b9902c1fcc5 ("s390/qeth: fix deadlock during recovery") removed
+taking discipline_mutex inside qeth_do_reset(), fixing potential
+deadlocks. An error path was missed though, that still takes
+discipline_mutex and thus has the original deadlock potential.
+
+Intermittent deadlocks were seen when a qeth channel path is configured
+offline, causing a race between qeth_do_reset and ccwgroup_remove.
+Call qeth_set_offline() directly in the qeth_do_reset() error case and
+then a new variant of ccwgroup_set_offline(), without taking
+discipline_mutex.
+
+Fixes: b41b554c1ee7 ("s390/qeth: fix locking for discipline setup / removal")
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Reviewed-by: Julian Wiedmann <jwi@linux.ibm.com>
+Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/ccwgroup.h | 2 +-
+ drivers/s390/cio/ccwgroup.c | 10 ++++++++--
+ drivers/s390/net/qeth_core_main.c | 3 ++-
+ 3 files changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h
+index 20f169b6db4e..d97301d9d0b8 100644
+--- a/arch/s390/include/asm/ccwgroup.h
++++ b/arch/s390/include/asm/ccwgroup.h
+@@ -57,7 +57,7 @@ struct ccwgroup_device *get_ccwgroupdev_by_busid(struct ccwgroup_driver *gdrv,
+ char *bus_id);
+
+ extern int ccwgroup_set_online(struct ccwgroup_device *gdev);
+-extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);
++int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv);
+
+ extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
+ extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
+diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
+index 9748165e08e9..f19f02e75115 100644
+--- a/drivers/s390/cio/ccwgroup.c
++++ b/drivers/s390/cio/ccwgroup.c
+@@ -77,12 +77,13 @@ EXPORT_SYMBOL(ccwgroup_set_online);
+ /**
+ * ccwgroup_set_offline() - disable a ccwgroup device
+ * @gdev: target ccwgroup device
++ * @call_gdrv: Call the registered gdrv set_offline function
+ *
+ * This function attempts to put the ccwgroup device into the offline state.
+ * Returns:
+ * %0 on success and a negative error value on failure.
+ */
+-int ccwgroup_set_offline(struct ccwgroup_device *gdev)
++int ccwgroup_set_offline(struct ccwgroup_device *gdev, bool call_gdrv)
+ {
+ struct ccwgroup_driver *gdrv = to_ccwgroupdrv(gdev->dev.driver);
+ int ret = -EINVAL;
+@@ -91,11 +92,16 @@ int ccwgroup_set_offline(struct ccwgroup_device *gdev)
+ return -EAGAIN;
+ if (gdev->state == CCWGROUP_OFFLINE)
+ goto out;
++ if (!call_gdrv) {
++ ret = 0;
++ goto offline;
++ }
+ if (gdrv->set_offline)
+ ret = gdrv->set_offline(gdev);
+ if (ret)
+ goto out;
+
++offline:
+ gdev->state = CCWGROUP_OFFLINE;
+ out:
+ atomic_set(&gdev->onoff, 0);
+@@ -124,7 +130,7 @@ static ssize_t ccwgroup_online_store(struct device *dev,
+ if (value == 1)
+ ret = ccwgroup_set_online(gdev);
+ else if (value == 0)
+- ret = ccwgroup_set_offline(gdev);
++ ret = ccwgroup_set_offline(gdev, true);
+ else
+ ret = -EINVAL;
+ out:
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+index 51f7f4e680c3..52dabdb32efb 100644
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -5556,7 +5556,8 @@ static int qeth_do_reset(void *data)
+ dev_info(&card->gdev->dev,
+ "Device successfully recovered!\n");
+ } else {
+- ccwgroup_set_offline(card->gdev);
++ qeth_set_offline(card, disc, true);
++ ccwgroup_set_offline(card->gdev, false);
+ dev_warn(&card->gdev->dev,
+ "The qeth device driver failed to recover an error on the device\n");
+ }
+--
+2.33.0
+
--- /dev/null
+From 17985268dcd078691463d45b3b8eb53b45b2229b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 16:52:15 +0200
+Subject: s390/qeth: fix NULL deref in qeth_clear_working_pool_list()
+
+From: Julian Wiedmann <jwi@linux.ibm.com>
+
+[ Upstream commit 248f064af222a1f97ee02c84a98013dfbccad386 ]
+
+When qeth_set_online() calls qeth_clear_working_pool_list() to roll
+back after an error exit from qeth_hardsetup_card(), we are at risk of
+accessing card->qdio.in_q before it was allocated by
+qeth_alloc_qdio_queues() via qeth_mpc_initialize().
+
+qeth_clear_working_pool_list() then dereferences NULL, and by writing to
+queue->bufs[i].pool_entry scribbles all over the CPU's lowcore.
+Resulting in a crash when those lowcore areas are used next (eg. on
+the next machine-check interrupt).
+
+Such a scenario would typically happen when the device is first set
+online and its queues aren't allocated yet. An early IO error or certain
+misconfigs (eg. mismatched transport mode, bad portno) then cause us to
+error out from qeth_hardsetup_card() with card->qdio.in_q still being
+NULL.
+
+Fix it by checking the pointer for NULL before accessing it.
+
+Note that we also have (rare) paths inside qeth_mpc_initialize() where
+a configuration change can cause us to free the existing queues,
+expecting that subsequent code will allocate them again. If we then
+error out before that re-allocation happens, the same bug occurs.
+
+Fixes: eff73e16ee11 ("s390/qeth: tolerate pre-filled RX buffer")
+Reported-by: Stefan Raspl <raspl@linux.ibm.com>
+Root-caused-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/net/qeth_core_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+index 62f88ccbd03f..51f7f4e680c3 100644
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -207,6 +207,9 @@ static void qeth_clear_working_pool_list(struct qeth_card *card)
+ &card->qdio.in_buf_pool.entry_list, list)
+ list_del(&pool_entry->list);
+
++ if (!queue)
++ return;
++
+ for (i = 0; i < ARRAY_SIZE(queue->bufs); i++)
+ queue->bufs[i].pool_entry = NULL;
+ }
+--
+2.33.0
+
arm64-restore-forced-disabling-of-kpti-on-thunderx.patch
arm64-mitigate-mte-issues-with-str-n-cmp.patch
comedi-fix-memory-leak-in-compat_insnlist.patch
+regulator-qcom-rpmh-regulator-fix-pm8009-1-ldo7-reso.patch
+afs-fix-page-leak.patch
+afs-fix-incorrect-triggering-of-sillyrename-on-3rd-p.patch
+afs-fix-corruption-in-reads-at-fpos-2g-4g-from-an-op.patch
+afs-fix-updating-of-i_blocks-on-file-dir-extension.patch
+platform-x86-intel-punit_ipc-drop-wrong-use-of-acpi_.patch
+regulator-max14577-revert-regulator-max14577-add-pro.patch
+nlm-fix-svcxdr_encode_owner.patch
+net-dsa-hellcreek-be-compatible-with-masters-which-u.patch
+net-dsa-microchip-ksz8863-be-compatible-with-masters.patch
+net-dsa-xrs700x-be-compatible-with-masters-which-unr.patch
+virtio-net-fix-pages-leaking-when-building-skb-in-bi.patch
+enetc-fix-illegal-access-when-reading-affinity_hint.patch
+enetc-fix-uninitialized-struct-dim_sample-field-usag.patch
+igc-fix-build-errors-for-ptp.patch
+net-dsa-tear-down-devlink-port-regions-when-tearing-.patch
+net-bgmac-bcma-handle-deferred-probe-error-due-to-ma.patch
+net-mlx4_en-resolve-bad-operstate-value.patch
+napi-fix-race-inside-napi_enable.patch
+bnxt_en-fix-tx-timeout-when-tx-ring-size-is-set-to-t.patch
+net-hns3-fix-change-rss-hfunc-ineffective-issue.patch
+net-hns3-fix-inconsistent-vf-id-print.patch
+net-hns3-fix-misuse-vf-id-and-vport-id-in-some-logs.patch
+net-hns3-check-queue-id-range-before-using.patch
+net-hns3-check-vlan-id-before-using-it.patch
+net-hns3-fix-a-return-value-error-in-hclge_get_reset.patch
+net-smc-add-missing-error-check-in-smc_clc_prfx_set.patch
+net-smc-fix-workqueue-leaked-lock-in-smc_conn_abort_.patch
+net-dsa-fix-dsa_tree_setup-error-path.patch
+net-dsa-don-t-allocate-the-slave_mii_bus-using-devre.patch
+net-dsa-realtek-register-the-mdio-bus-under-devres.patch
+platform-x86-dell-fix-dell_wmi_privacy-dependencies-.patch
+kselftest-arm64-signal-add-sve-to-the-set-of-feature.patch
+kselftest-arm64-signal-skip-tests-if-required-featur.patch
+spi-revert-modalias-changes.patch
+s390-qeth-fix-null-deref-in-qeth_clear_working_pool_.patch
+s390-qeth-fix-deadlock-during-failing-recovery.patch
+gpiolib-acpi-make-set-debounce-timeout-failures-non-.patch
+gpio-uniphier-fix-void-functions-to-remove-return-va.patch
+qed-rdma-don-t-wait-for-resources-under-hw-error-rec.patch
+mptcp-ensure-tx-skbs-always-have-the-mptcp-ext.patch
+nexthop-fix-memory-leaks-in-nexthop-notification-cha.patch
+nfc-st-nci-add-spi-id-matching-dt-compatible.patch
+net-ethernet-mtk_eth_soc-avoid-creating-duplicate-of.patch
+net-mscc-ocelot-fix-forwarding-from-blocking-ports-r.patch
+net-mlx4_en-don-t-allow-arfs-for-encapsulated-packet.patch
+atlantic-fix-issue-in-the-pm-resume-flow.patch
+drm-amdkfd-map-svm-range-with-correct-access-permiss.patch
+drm-amdkfd-fix-dma-mapping-leaking-warning.patch
--- /dev/null
+From 6db202052a792a3e8d78ce1a7ef4e93683d6b529 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Sep 2021 15:44:06 +0100
+Subject: spi: Revert modalias changes
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 96c8395e2166efa86082f3b71567ffd84936439b ]
+
+During the v5.13 cycle we updated the SPI subsystem to generate OF style
+modaliases for SPI devices, replacing the old Linux style modalises we
+used to generate based on spi_device_id which are the DT style name with
+the vendor removed. Unfortunately this means that we start only
+reporting OF style modalises and not the old ones and there is nothing
+that ensures that drivers list every possible OF compatible string in
+their OF ID table. The result is that there are systems which have been
+relying on loading modules based on the old style that are now broken,
+as found by Russell King with spi-nor on Macchiatobin.
+
+spi-nor is a particularly problematic case for this, it only lists a
+single generic DT compatible jedec,spi-nor in the driver but supports a
+huge raft of device specific compatibles, with a large set of part
+numbers many of which are offered by multiple vendors. Russell's
+searches of upstream device trees has turned up examples with vendor
+names written in non-standard ways too. To make matters worse up until
+8ff16cf77ce3 ("Documentation: devicetree: m25p80: add "nor-jedec"
+binding") the generic compatible was not part of the binding so there
+are device trees out there written to that binding version which don't
+list it all. The sheer number of parts supported together with our
+previous approach of ignoring the vendor ID makes robustly fixing this
+by adding compatibles to the spi-nor driver seem problematic, the
+current DT binding document does not list all the parts supported by the
+driver at the minute (further patches will fix this).
+
+I've also investigated supporting both formats of modalias
+simultaneously but that doesn't seem possible, especially without
+breaking our userspace ABI which is obviously not viable.
+
+Instead revert the relevant changes for now:
+
+e09f2ab8eecc ("spi: update modalias_show after of_device_uevent_modalias support")
+3ce6c9e2617e ("spi: add of_device_uevent_modalias support")
+
+This will unfortunately mean that any system which had started having
+modules autoload based on the OF compatibles for drivers that list
+things there but not in the spi_device_ids will now not have those
+modules load which is itself a regression. Since it affects a narrower
+time window and the particularly problematic spi-nor driver may be
+critical to system boot on smaller systems this seems the best of a
+series of bad options. I will start an audit of SPI drivers to identify
+and fix cases where things won't autoload using spi_device_id, this is
+not great but seems to be the best way forward that anyone has been able
+to identify.
+
+Thanks to Russell for both his report and the additional diagnostic and
+analysis work he has done here, the detailed research above was his
+work.
+
+Fixes: e09f2ab8eecc ("spi: update modalias_show after of_device_uevent_modalias support")
+Fixes: 3ce6c9e2617e ("spi: add of_device_uevent_modalias support")
+Reported-by: Russell King (Oracle) <linux@armlinux.org.uk>
+Suggested-by: Russell King (Oracle) <linux@armlinux.org.uk>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Tested-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Cc: Andreas Schwab <schwab@suse.de>
+Cc: Marco Felsch <m.felsch@pengutronix.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/spi/spi.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index e4dc593b1f32..f95f7666cb5b 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -58,10 +58,6 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
+ const struct spi_device *spi = to_spi_device(dev);
+ int len;
+
+- len = of_device_modalias(dev, buf, PAGE_SIZE);
+- if (len != -ENODEV)
+- return len;
+-
+ len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
+ if (len != -ENODEV)
+ return len;
+@@ -367,10 +363,6 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
+ const struct spi_device *spi = to_spi_device(dev);
+ int rc;
+
+- rc = of_device_uevent_modalias(dev, env);
+- if (rc != -ENODEV)
+- return rc;
+-
+ rc = acpi_device_uevent_modalias(dev, env);
+ if (rc != -ENODEV)
+ return rc;
+--
+2.33.0
+
--- /dev/null
+From 9a700429bbb267c9789aafca0ca50763c4104370 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Sep 2021 16:34:06 +0800
+Subject: virtio-net: fix pages leaking when building skb in big mode
+
+From: Jason Wang <jasowang@redhat.com>
+
+[ Upstream commit afd92d82c9d715fb97565408755acad81573591a ]
+
+We try to use build_skb() if we had sufficient tailroom. But we forget
+to release the unused pages chained via private in big mode which will
+leak pages. Fixing this by release the pages after building the skb in
+big mode.
+
+Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Fixes: fb32856b16ad ("virtio-net: page_to_skb() use build_skb when there's sufficient tailroom")
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/virtio_net.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index eee493685aad..fb96658bb91f 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -435,6 +435,10 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
+
+ skb_reserve(skb, p - buf);
+ skb_put(skb, len);
++
++ page = (struct page *)page->private;
++ if (page)
++ give_pages(rq, page);
+ goto ok;
+ }
+
+--
+2.33.0
+