--- /dev/null
+From 6363cd4a14c1bf4eed3d9e9266152249da6eb41f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Oct 2020 14:22:12 +0100
+Subject: afs: Fix deadlock between writeback and truncate
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit ec0fa0b659144d9c68204d23f627b6a65fa53e50 ]
+
+The afs filesystem has a lock[*] that it uses to serialise I/O operations
+going to the server (vnode->io_lock), as the server will only perform one
+modification operation at a time on any given file or directory. This
+prevents the the filesystem from filling up all the call slots to a server
+with calls that aren't going to be executed in parallel anyway, thereby
+allowing operations on other files to obtain slots.
+
+ [*] Note that is probably redundant for directories at least since
+ i_rwsem is used to serialise directory modifications and
+ lookup/reading vs modification. The server does allow parallel
+ non-modification ops, however.
+
+When a file truncation op completes, we truncate the in-memory copy of the
+file to match - but we do it whilst still holding the io_lock, the idea
+being to prevent races with other operations.
+
+However, if writeback starts in a worker thread simultaneously with
+truncation (whilst notify_change() is called with i_rwsem locked, writeback
+pays it no heed), it may manage to set PG_writeback bits on the pages that
+will get truncated before afs_setattr_success() manages to call
+truncate_pagecache(). Truncate will then wait for those pages - whilst
+still inside io_lock:
+
+ # cat /proc/8837/stack
+ [<0>] wait_on_page_bit_common+0x184/0x1e7
+ [<0>] truncate_inode_pages_range+0x37f/0x3eb
+ [<0>] truncate_pagecache+0x3c/0x53
+ [<0>] afs_setattr_success+0x4d/0x6e
+ [<0>] afs_wait_for_operation+0xd8/0x169
+ [<0>] afs_do_sync_operation+0x16/0x1f
+ [<0>] afs_setattr+0x1fb/0x25d
+ [<0>] notify_change+0x2cf/0x3c4
+ [<0>] do_truncate+0x7f/0xb2
+ [<0>] do_sys_ftruncate+0xd1/0x104
+ [<0>] do_syscall_64+0x2d/0x3a
+ [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+The writeback operation, however, stalls indefinitely because it needs to
+get the io_lock to proceed:
+
+ # cat /proc/5940/stack
+ [<0>] afs_get_io_locks+0x58/0x1ae
+ [<0>] afs_begin_vnode_operation+0xc7/0xd1
+ [<0>] afs_store_data+0x1b2/0x2a3
+ [<0>] afs_write_back_from_locked_page+0x418/0x57c
+ [<0>] afs_writepages_region+0x196/0x224
+ [<0>] afs_writepages+0x74/0x156
+ [<0>] do_writepages+0x2d/0x56
+ [<0>] __writeback_single_inode+0x84/0x207
+ [<0>] writeback_sb_inodes+0x238/0x3cf
+ [<0>] __writeback_inodes_wb+0x68/0x9f
+ [<0>] wb_writeback+0x145/0x26c
+ [<0>] wb_do_writeback+0x16a/0x194
+ [<0>] wb_workfn+0x74/0x177
+ [<0>] process_one_work+0x174/0x264
+ [<0>] worker_thread+0x117/0x1b9
+ [<0>] kthread+0xec/0xf1
+ [<0>] ret_from_fork+0x1f/0x30
+
+and thus deadlock has occurred.
+
+Note that whilst afs_setattr() calls filemap_write_and_wait(), the fact
+that the caller is holding i_rwsem doesn't preclude more pages being
+dirtied through an mmap'd region.
+
+Fix this by:
+
+ (1) Use the vnode validate_lock to mediate access between afs_setattr()
+ and afs_writepages():
+
+ (a) Exclusively lock validate_lock in afs_setattr() around the whole
+ RPC operation.
+
+ (b) If WB_SYNC_ALL isn't set on entry to afs_writepages(), trying to
+ shared-lock validate_lock and returning immediately if we couldn't
+ get it.
+
+ (c) If WB_SYNC_ALL is set, wait for the lock.
+
+ The validate_lock is also used to validate a file and to zap its cache
+ if the file was altered by a third party, so it's probably a good fit
+ for this.
+
+ (2) Move the truncation outside of the io_lock in setattr, using the same
+ hook as is used for local directory editing.
+
+ This requires the old i_size to be retained in the operation record as
+ we commit the revised status to the inode members inside the io_lock
+ still, but we still need to know if we reduced the file size.
+
+Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/inode.c | 47 ++++++++++++++++++++++++++++++++++++++---------
+ fs/afs/internal.h | 1 +
+ fs/afs/write.c | 11 +++++++++++
+ 3 files changed, 50 insertions(+), 9 deletions(-)
+
+diff --git a/fs/afs/inode.c b/fs/afs/inode.c
+index 1d13d2e882ada..0fe8844b4bee2 100644
+--- a/fs/afs/inode.c
++++ b/fs/afs/inode.c
+@@ -810,14 +810,32 @@ void afs_evict_inode(struct inode *inode)
+
+ static void afs_setattr_success(struct afs_operation *op)
+ {
+- struct inode *inode = &op->file[0].vnode->vfs_inode;
++ struct afs_vnode_param *vp = &op->file[0];
++ struct inode *inode = &vp->vnode->vfs_inode;
++ loff_t old_i_size = i_size_read(inode);
++
++ op->setattr.old_i_size = old_i_size;
++ afs_vnode_commit_status(op, vp);
++ /* inode->i_size has now been changed. */
++
++ if (op->setattr.attr->ia_valid & ATTR_SIZE) {
++ loff_t size = op->setattr.attr->ia_size;
++ if (size > old_i_size)
++ pagecache_isize_extended(inode, old_i_size, size);
++ }
++}
++
++static void afs_setattr_edit_file(struct afs_operation *op)
++{
++ struct afs_vnode_param *vp = &op->file[0];
++ struct inode *inode = &vp->vnode->vfs_inode;
+
+- afs_vnode_commit_status(op, &op->file[0]);
+ if (op->setattr.attr->ia_valid & ATTR_SIZE) {
+- loff_t i_size = inode->i_size, size = op->setattr.attr->ia_size;
+- if (size > i_size)
+- pagecache_isize_extended(inode, i_size, size);
+- truncate_pagecache(inode, size);
++ loff_t size = op->setattr.attr->ia_size;
++ loff_t i_size = op->setattr.old_i_size;
++
++ if (size < i_size)
++ truncate_pagecache(inode, size);
+ }
+ }
+
+@@ -825,6 +843,7 @@ static const struct afs_operation_ops afs_setattr_operation = {
+ .issue_afs_rpc = afs_fs_setattr,
+ .issue_yfs_rpc = yfs_fs_setattr,
+ .success = afs_setattr_success,
++ .edit_dir = afs_setattr_edit_file,
+ };
+
+ /*
+@@ -863,11 +882,16 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
+ if (S_ISREG(vnode->vfs_inode.i_mode))
+ filemap_write_and_wait(vnode->vfs_inode.i_mapping);
+
++ /* Prevent any new writebacks from starting whilst we do this. */
++ down_write(&vnode->validate_lock);
++
+ op = afs_alloc_operation(((attr->ia_valid & ATTR_FILE) ?
+ afs_file_key(attr->ia_file) : NULL),
+ vnode->volume);
+- if (IS_ERR(op))
+- return PTR_ERR(op);
++ if (IS_ERR(op)) {
++ ret = PTR_ERR(op);
++ goto out_unlock;
++ }
+
+ afs_op_set_vnode(op, 0, vnode);
+ op->setattr.attr = attr;
+@@ -880,5 +904,10 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
+ op->file[0].update_ctime = 1;
+
+ op->ops = &afs_setattr_operation;
+- return afs_do_sync_operation(op);
++ ret = afs_do_sync_operation(op);
++
++out_unlock:
++ up_write(&vnode->validate_lock);
++ _leave(" = %d", ret);
++ return ret;
+ }
+diff --git a/fs/afs/internal.h b/fs/afs/internal.h
+index 792ac711985eb..e1ebead2e505a 100644
+--- a/fs/afs/internal.h
++++ b/fs/afs/internal.h
+@@ -810,6 +810,7 @@ struct afs_operation {
+ } store;
+ struct {
+ struct iattr *attr;
++ loff_t old_i_size;
+ } setattr;
+ struct afs_acl *acl;
+ struct yfs_acl *yacl;
+diff --git a/fs/afs/write.c b/fs/afs/write.c
+index a121c247d95a3..0a98cf36e78a3 100644
+--- a/fs/afs/write.c
++++ b/fs/afs/write.c
+@@ -738,11 +738,21 @@ static int afs_writepages_region(struct address_space *mapping,
+ int afs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
++ struct afs_vnode *vnode = AFS_FS_I(mapping->host);
+ pgoff_t start, end, next;
+ int ret;
+
+ _enter("");
+
++ /* We have to be careful as we can end up racing with setattr()
++ * truncating the pagecache since the caller doesn't take a lock here
++ * to prevent it.
++ */
++ if (wbc->sync_mode == WB_SYNC_ALL)
++ down_read(&vnode->validate_lock);
++ else if (!down_read_trylock(&vnode->validate_lock))
++ return 0;
++
+ if (wbc->range_cyclic) {
+ start = mapping->writeback_index;
+ end = -1;
+@@ -762,6 +772,7 @@ int afs_writepages(struct address_space *mapping,
+ ret = afs_writepages_region(mapping, wbc, start, end, &next);
+ }
+
++ up_read(&vnode->validate_lock);
+ _leave(" = %d", ret);
+ return ret;
+ }
+--
+2.25.1
+
--- /dev/null
+From ad49b3af34bfb062b57f370f9002f03e803eee03 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Sep 2020 06:38:07 -0700
+Subject: bonding: set dev->needed_headroom in bond_setup_by_slave()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit f32f19339596b214c208c0dba716f4b6cc4f6958 ]
+
+syzbot managed to crash a host by creating a bond
+with a GRE device.
+
+For non Ethernet device, bonding calls bond_setup_by_slave()
+instead of ether_setup(), and unfortunately dev->needed_headroom
+was not copied from the new added member.
+
+[ 171.243095] skbuff: skb_under_panic: text:ffffffffa184b9ea len:116 put:20 head:ffff883f84012dc0 data:ffff883f84012dbc tail:0x70 end:0xd00 dev:bond0
+[ 171.243111] ------------[ cut here ]------------
+[ 171.243112] kernel BUG at net/core/skbuff.c:112!
+[ 171.243117] invalid opcode: 0000 [#1] SMP KASAN PTI
+[ 171.243469] gsmi: Log Shutdown Reason 0x03
+[ 171.243505] Call Trace:
+[ 171.243506] <IRQ>
+[ 171.243512] [<ffffffffa171be59>] skb_push+0x49/0x50
+[ 171.243516] [<ffffffffa184b9ea>] ipgre_header+0x2a/0xf0
+[ 171.243520] [<ffffffffa17452d7>] neigh_connected_output+0xb7/0x100
+[ 171.243524] [<ffffffffa186f1d3>] ip6_finish_output2+0x383/0x490
+[ 171.243528] [<ffffffffa186ede2>] __ip6_finish_output+0xa2/0x110
+[ 171.243531] [<ffffffffa186acbc>] ip6_finish_output+0x2c/0xa0
+[ 171.243534] [<ffffffffa186abe9>] ip6_output+0x69/0x110
+[ 171.243537] [<ffffffffa186ac90>] ? ip6_output+0x110/0x110
+[ 171.243541] [<ffffffffa189d952>] mld_sendpack+0x1b2/0x2d0
+[ 171.243544] [<ffffffffa189d290>] ? mld_send_report+0xf0/0xf0
+[ 171.243548] [<ffffffffa189c797>] mld_ifc_timer_expire+0x2d7/0x3b0
+[ 171.243551] [<ffffffffa189c4c0>] ? mld_gq_timer_expire+0x50/0x50
+[ 171.243556] [<ffffffffa0fea270>] call_timer_fn+0x30/0x130
+[ 171.243559] [<ffffffffa0fea17c>] expire_timers+0x4c/0x110
+[ 171.243563] [<ffffffffa0fea0e3>] __run_timers+0x213/0x260
+[ 171.243566] [<ffffffffa0fecb7d>] ? ktime_get+0x3d/0xa0
+[ 171.243570] [<ffffffffa0ff9c4e>] ? clockevents_program_event+0x7e/0xe0
+[ 171.243574] [<ffffffffa0f7e5d5>] ? sched_clock_cpu+0x15/0x190
+[ 171.243577] [<ffffffffa0fe973d>] run_timer_softirq+0x1d/0x40
+[ 171.243581] [<ffffffffa1c00152>] __do_softirq+0x152/0x2f0
+[ 171.243585] [<ffffffffa0f44e1f>] irq_exit+0x9f/0xb0
+[ 171.243588] [<ffffffffa1a02e1d>] smp_apic_timer_interrupt+0xfd/0x1a0
+[ 171.243591] [<ffffffffa1a01ea6>] apic_timer_interrupt+0x86/0x90
+
+Fixes: f5184d267c1a ("net: Allow netdevices to specify needed head/tailroom")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 500aa3e19a4c7..fddf7c502355b 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1195,6 +1195,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
+
+ bond_dev->type = slave_dev->type;
+ bond_dev->hard_header_len = slave_dev->hard_header_len;
++ bond_dev->needed_headroom = slave_dev->needed_headroom;
+ bond_dev->addr_len = slave_dev->addr_len;
+
+ memcpy(bond_dev->broadcast, slave_dev->broadcast,
+--
+2.25.1
+
--- /dev/null
+From 81df94accb34d9f236d24a135cbffe18dcc01330 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 25 Jul 2020 15:11:19 +0800
+Subject: hinic: add log in exception handling processes
+
+From: Luo bin <luobin9@huawei.com>
+
+[ Upstream commit 90f86b8a36c065286b743eed29661fc5cd00d342 ]
+
+improve the error message when functions return failure and dump
+relevant registers in some exception handling processes
+
+Signed-off-by: Luo bin <luobin9@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/huawei/hinic/hinic_hw_api_cmd.c | 27 +++++++-
+ .../ethernet/huawei/hinic/hinic_hw_api_cmd.h | 4 ++
+ .../net/ethernet/huawei/hinic/hinic_hw_cmdq.c | 2 +
+ .../net/ethernet/huawei/hinic/hinic_hw_cmdq.h | 2 +
+ .../net/ethernet/huawei/hinic/hinic_hw_dev.c | 12 ++--
+ .../net/ethernet/huawei/hinic/hinic_hw_eqs.c | 39 ++++++++++++
+ .../net/ethernet/huawei/hinic/hinic_hw_eqs.h | 6 +-
+ .../net/ethernet/huawei/hinic/hinic_hw_if.c | 23 +++++++
+ .../net/ethernet/huawei/hinic/hinic_hw_if.h | 10 ++-
+ .../net/ethernet/huawei/hinic/hinic_hw_mbox.c | 2 +
+ .../net/ethernet/huawei/hinic/hinic_hw_mgmt.c | 1 +
+ .../net/ethernet/huawei/hinic/hinic_port.c | 62 +++++++++----------
+ .../net/ethernet/huawei/hinic/hinic_sriov.c | 6 +-
+ 13 files changed, 151 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
+index 583fd24c29cf6..29e88e25a4a4f 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.c
+@@ -112,6 +112,26 @@ static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain)
+ return HINIC_API_CMD_STATUS_GET(val, CONS_IDX);
+ }
+
++static void dump_api_chain_reg(struct hinic_api_cmd_chain *chain)
++{
++ u32 addr, val;
++
++ addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type);
++ val = hinic_hwif_read_reg(chain->hwif, addr);
++
++ dev_err(&chain->hwif->pdev->dev, "Chain type: 0x%x, cpld error: 0x%x, check error: 0x%x, current fsm: 0x%x\n",
++ chain->chain_type, HINIC_API_CMD_STATUS_GET(val, CPLD_ERR),
++ HINIC_API_CMD_STATUS_GET(val, CHKSUM_ERR),
++ HINIC_API_CMD_STATUS_GET(val, FSM));
++
++ dev_err(&chain->hwif->pdev->dev, "Chain hw current ci: 0x%x\n",
++ HINIC_API_CMD_STATUS_GET(val, CONS_IDX));
++
++ addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type);
++ val = hinic_hwif_read_reg(chain->hwif, addr);
++ dev_err(&chain->hwif->pdev->dev, "Chain hw current pi: 0x%x\n", val);
++}
++
+ /**
+ * chain_busy - check if the chain is still processing last requests
+ * @chain: chain to check
+@@ -131,8 +151,10 @@ static int chain_busy(struct hinic_api_cmd_chain *chain)
+
+ /* check for a space for a new command */
+ if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) {
+- dev_err(&pdev->dev, "API CMD chain %d is busy\n",
+- chain->chain_type);
++ dev_err(&pdev->dev, "API CMD chain %d is busy, cons_idx: %d, prod_idx: %d\n",
++ chain->chain_type, chain->cons_idx,
++ chain->prod_idx);
++ dump_api_chain_reg(chain);
+ return -EBUSY;
+ }
+ break;
+@@ -332,6 +354,7 @@ static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain)
+ err = wait_for_status_poll(chain);
+ if (err) {
+ dev_err(&pdev->dev, "API CMD Poll status timeout\n");
++ dump_api_chain_reg(chain);
+ break;
+ }
+ break;
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h
+index 0ba00fd828dfc..6d1654b050ad5 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_api_cmd.h
+@@ -103,10 +103,14 @@
+ HINIC_API_CMD_STATUS_HEADER_##member##_MASK)
+
+ #define HINIC_API_CMD_STATUS_CONS_IDX_SHIFT 0
++#define HINIC_API_CMD_STATUS_FSM_SHIFT 24
+ #define HINIC_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28
++#define HINIC_API_CMD_STATUS_CPLD_ERR_SHIFT 30
+
+ #define HINIC_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFF
++#define HINIC_API_CMD_STATUS_FSM_MASK 0xFU
+ #define HINIC_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3
++#define HINIC_API_CMD_STATUS_CPLD_ERR_MASK 0x1U
+
+ #define HINIC_API_CMD_STATUS_GET(val, member) \
+ (((val) >> HINIC_API_CMD_STATUS_##member##_SHIFT) & \
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
+index cb5b6e5f787f2..e0eb294779ec1 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
+@@ -401,6 +401,7 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,
+
+ spin_unlock_bh(&cmdq->cmdq_lock);
+
++ hinic_dump_ceq_info(cmdq->hwdev);
+ return -ETIMEDOUT;
+ }
+
+@@ -807,6 +808,7 @@ static int init_cmdqs_ctxt(struct hinic_hwdev *hwdev,
+
+ cmdq_type = HINIC_CMDQ_SYNC;
+ for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
++ cmdqs->cmdq[cmdq_type].hwdev = hwdev;
+ err = init_cmdq(&cmdqs->cmdq[cmdq_type],
+ &cmdqs->saved_wqs[cmdq_type], cmdq_type,
+ db_area[cmdq_type]);
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h
+index 3e4b0aef9fe6c..f40c31e1879f1 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h
+@@ -130,6 +130,8 @@ struct hinic_cmdq_ctxt {
+ };
+
+ struct hinic_cmdq {
++ struct hinic_hwdev *hwdev;
++
+ struct hinic_wq *wq;
+
+ enum hinic_cmdq_type cmdq_type;
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+index b735bc537508f..298ceb930cc62 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+@@ -253,9 +253,9 @@ static int init_fw_ctxt(struct hinic_hwdev *hwdev)
+ &fw_ctxt, sizeof(fw_ctxt),
+ &fw_ctxt, &out_size);
+ if (err || (out_size != sizeof(fw_ctxt)) || fw_ctxt.status) {
+- dev_err(&pdev->dev, "Failed to init FW ctxt, ret = %d\n",
+- fw_ctxt.status);
+- return -EFAULT;
++ dev_err(&pdev->dev, "Failed to init FW ctxt, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, fw_ctxt.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -420,9 +420,9 @@ static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
+ &cmd_base_qpn, sizeof(cmd_base_qpn),
+ &cmd_base_qpn, &out_size);
+ if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) {
+- dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n",
+- cmd_base_qpn.status);
+- return -EFAULT;
++ dev_err(&pdev->dev, "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, cmd_base_qpn.status, out_size);
++ return -EIO;
+ }
+
+ *base_qpn = cmd_base_qpn.qpn;
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
+index 397936cac304c..ca8cb68a8d206 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
+@@ -953,3 +953,42 @@ void hinic_ceqs_free(struct hinic_ceqs *ceqs)
+ for (q_id = 0; q_id < ceqs->num_ceqs; q_id++)
+ remove_eq(&ceqs->ceq[q_id]);
+ }
++
++void hinic_dump_ceq_info(struct hinic_hwdev *hwdev)
++{
++ struct hinic_eq *eq = NULL;
++ u32 addr, ci, pi;
++ int q_id;
++
++ for (q_id = 0; q_id < hwdev->func_to_io.ceqs.num_ceqs; q_id++) {
++ eq = &hwdev->func_to_io.ceqs.ceq[q_id];
++ addr = EQ_CONS_IDX_REG_ADDR(eq);
++ ci = hinic_hwif_read_reg(hwdev->hwif, addr);
++ addr = EQ_PROD_IDX_REG_ADDR(eq);
++ pi = hinic_hwif_read_reg(hwdev->hwif, addr);
++ dev_err(&hwdev->hwif->pdev->dev, "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, tasklet_state: 0x%lx, wrap: %d, ceqe: 0x%x\n",
++ q_id, ci, eq->cons_idx, pi,
++ eq->ceq_tasklet.state,
++ eq->wrapped, be32_to_cpu(*(__be32 *)(GET_CURR_CEQ_ELEM(eq))));
++ }
++}
++
++void hinic_dump_aeq_info(struct hinic_hwdev *hwdev)
++{
++ struct hinic_aeq_elem *aeqe_pos = NULL;
++ struct hinic_eq *eq = NULL;
++ u32 addr, ci, pi;
++ int q_id;
++
++ for (q_id = 0; q_id < hwdev->aeqs.num_aeqs; q_id++) {
++ eq = &hwdev->aeqs.aeq[q_id];
++ addr = EQ_CONS_IDX_REG_ADDR(eq);
++ ci = hinic_hwif_read_reg(hwdev->hwif, addr);
++ addr = EQ_PROD_IDX_REG_ADDR(eq);
++ pi = hinic_hwif_read_reg(hwdev->hwif, addr);
++ aeqe_pos = GET_CURR_AEQ_ELEM(eq);
++ dev_err(&hwdev->hwif->pdev->dev, "Aeq id: %d, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %d, desc: 0x%x\n",
++ q_id, ci, pi, work_busy(&eq->aeq_work.work),
++ eq->wrapped, be32_to_cpu(aeqe_pos->desc));
++ }
++}
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h
+index 74b9ff90640c2..43065fc708693 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.h
+@@ -162,7 +162,7 @@ enum hinic_eqe_state {
+
+ struct hinic_aeq_elem {
+ u8 data[HINIC_AEQE_DATA_SIZE];
+- u32 desc;
++ __be32 desc;
+ };
+
+ struct hinic_eq_work {
+@@ -254,4 +254,8 @@ int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif,
+
+ void hinic_ceqs_free(struct hinic_ceqs *ceqs);
+
++void hinic_dump_ceq_info(struct hinic_hwdev *hwdev);
++
++void hinic_dump_aeq_info(struct hinic_hwdev *hwdev);
++
+ #endif
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
+index cf127d896ba69..bc8925c0c982c 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c
+@@ -21,6 +21,8 @@
+
+ #define WAIT_HWIF_READY_TIMEOUT 10000
+
++#define HINIC_SELFTEST_RESULT 0x883C
++
+ /**
+ * hinic_msix_attr_set - set message attribute for msix entry
+ * @hwif: the HW interface of a pci function device
+@@ -369,6 +371,26 @@ u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif)
+ return HINIC_FA0_GET(attr0, PF_IDX);
+ }
+
++static void __print_selftest_reg(struct hinic_hwif *hwif)
++{
++ u32 addr, attr0, attr1;
++
++ addr = HINIC_CSR_FUNC_ATTR1_ADDR;
++ attr1 = hinic_hwif_read_reg(hwif, addr);
++
++ if (attr1 == HINIC_PCIE_LINK_DOWN) {
++ dev_err(&hwif->pdev->dev, "PCIE is link down\n");
++ return;
++ }
++
++ addr = HINIC_CSR_FUNC_ATTR0_ADDR;
++ attr0 = hinic_hwif_read_reg(hwif, addr);
++ if (HINIC_FA0_GET(attr0, FUNC_TYPE) != HINIC_VF &&
++ !HINIC_FA0_GET(attr0, PCI_INTF_IDX))
++ dev_err(&hwif->pdev->dev, "Selftest reg: 0x%08x\n",
++ hinic_hwif_read_reg(hwif, HINIC_SELFTEST_RESULT));
++}
++
+ /**
+ * hinic_init_hwif - initialize the hw interface
+ * @hwif: the HW interface of a pci function device
+@@ -398,6 +420,7 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
+ err = wait_hwif_ready(hwif);
+ if (err) {
+ dev_err(&pdev->dev, "HW interface is not ready\n");
++ __print_selftest_reg(hwif);
+ goto err_hwif_ready;
+ }
+
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
+index 0872e035faa11..c06f2253151e2 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
+@@ -12,6 +12,8 @@
+ #include <linux/types.h>
+ #include <asm/byteorder.h>
+
++#define HINIC_PCIE_LINK_DOWN 0xFFFFFFFF
++
+ #define HINIC_DMA_ATTR_ST_SHIFT 0
+ #define HINIC_DMA_ATTR_AT_SHIFT 8
+ #define HINIC_DMA_ATTR_PH_SHIFT 10
+@@ -249,13 +251,17 @@ struct hinic_hwif {
+
+ static inline u32 hinic_hwif_read_reg(struct hinic_hwif *hwif, u32 reg)
+ {
+- return be32_to_cpu(readl(hwif->cfg_regs_bar + reg));
++ u32 out = readl(hwif->cfg_regs_bar + reg);
++
++ return be32_to_cpu(*(__be32 *)&out);
+ }
+
+ static inline void hinic_hwif_write_reg(struct hinic_hwif *hwif, u32 reg,
+ u32 val)
+ {
+- writel(cpu_to_be32(val), hwif->cfg_regs_bar + reg);
++ __be32 in = cpu_to_be32(val);
++
++ writel(*(u32 *)&in, hwif->cfg_regs_bar + reg);
+ }
+
+ int hinic_msix_attr_set(struct hinic_hwif *hwif, u16 msix_index,
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
+index bc2f87e6cb5d7..47c93f946b94d 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c
+@@ -650,6 +650,7 @@ wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func,
+ if (!wait_for_completion_timeout(done, jif)) {
+ dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout\n");
+ dump_mox_reg(hwdev);
++ hinic_dump_aeq_info(hwdev);
+ return -ETIMEDOUT;
+ }
+
+@@ -897,6 +898,7 @@ int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
+ set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
+ dev_err(&func_to_func->hwif->pdev->dev,
+ "Send mbox msg timeout, msg_id: %d\n", msg_info.msg_id);
++ hinic_dump_aeq_info(func_to_func->hwdev);
+ err = -ETIMEDOUT;
+ goto err_send_mbox;
+ }
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
+index 7fe39a155b329..070288c8b4f37 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
+@@ -276,6 +276,7 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
+
+ if (!wait_for_completion_timeout(recv_done, timeo)) {
+ dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
++ hinic_dump_aeq_info(pf_to_mgmt->hwdev);
+ err = -ETIMEDOUT;
+ goto unlock_sync_msg;
+ }
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
+index 175c0ee000384..82d5c50630e64 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
+@@ -61,8 +61,8 @@ static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
+ (port_mac_cmd.status &&
+ port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY &&
+ port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
+- dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
+- port_mac_cmd.status);
++ dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, port_mac_cmd.status, out_size);
+ return -EFAULT;
+ }
+
+@@ -129,8 +129,8 @@ int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
+ &port_mac_cmd, sizeof(port_mac_cmd),
+ &port_mac_cmd, &out_size);
+ if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
+- dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
+- port_mac_cmd.status);
++ dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, port_mac_cmd.status, out_size);
+ return -EFAULT;
+ }
+
+@@ -172,9 +172,9 @@ int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
+ &port_mtu_cmd, sizeof(port_mtu_cmd),
+ &port_mtu_cmd, &out_size);
+- if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
+- dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
+- port_mtu_cmd.status);
++ if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {
++ dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, port_mtu_cmd.status, out_size);
+ return -EFAULT;
+ }
+
+@@ -264,8 +264,8 @@ int hinic_port_link_state(struct hinic_dev *nic_dev,
+ &link_cmd, sizeof(link_cmd),
+ &link_cmd, &out_size);
+ if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
+- dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
+- link_cmd.status);
++ dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, link_cmd.status, out_size);
+ return -EINVAL;
+ }
+
+@@ -298,8 +298,8 @@ int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
+ &port_state, sizeof(port_state),
+ &port_state, &out_size);
+ if (err || (out_size != sizeof(port_state)) || port_state.status) {
+- dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
+- port_state.status);
++ dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, port_state.status, out_size);
+ return -EFAULT;
+ }
+
+@@ -330,8 +330,8 @@ int hinic_port_set_func_state(struct hinic_dev *nic_dev,
+ &func_state, sizeof(func_state),
+ &func_state, &out_size);
+ if (err || (out_size != sizeof(func_state)) || func_state.status) {
+- dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
+- func_state.status);
++ dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, func_state.status, out_size);
+ return -EFAULT;
+ }
+
+@@ -361,9 +361,9 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev,
+ port_cap, &out_size);
+ if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
+ dev_err(&pdev->dev,
+- "Failed to get port capabilities, ret = %d\n",
+- port_cap->status);
+- return -EINVAL;
++ "Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, port_cap->status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -393,9 +393,9 @@ int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
+ &tso_cfg, &out_size);
+ if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
+ dev_err(&pdev->dev,
+- "Failed to set port tso, ret = %d\n",
+- tso_cfg.status);
+- return -EINVAL;
++ "Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, tso_cfg.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -423,9 +423,9 @@ int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
+ &rx_csum_cfg, &out_size);
+ if (err || !out_size || rx_csum_cfg.status) {
+ dev_err(&pdev->dev,
+- "Failed to set rx csum offload, ret = %d\n",
+- rx_csum_cfg.status);
+- return -EINVAL;
++ "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, rx_csum_cfg.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -480,9 +480,9 @@ int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
+ &rq_num, &out_size);
+ if (err || !out_size || rq_num.status) {
+ dev_err(&pdev->dev,
+- "Failed to rxq number, ret = %d\n",
+- rq_num.status);
+- return -EINVAL;
++ "Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, rq_num.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -508,9 +508,9 @@ static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
+ &lro_cfg, &out_size);
+ if (err || !out_size || lro_cfg.status) {
+ dev_err(&pdev->dev,
+- "Failed to set lro offload, ret = %d\n",
+- lro_cfg.status);
+- return -EINVAL;
++ "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, lro_cfg.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+@@ -542,10 +542,10 @@ static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
+
+ if (err || !out_size || lro_timer.status) {
+ dev_err(&pdev->dev,
+- "Failed to set lro timer, ret = %d\n",
+- lro_timer.status);
++ "Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, lro_timer.status, out_size);
+
+- return -EINVAL;
++ return -EIO;
+ }
+
+ return 0;
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+index efab2dd2c889b..1043389754df0 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+@@ -40,9 +40,9 @@ static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
+ if (err || out_size != sizeof(mac_info) ||
+ (mac_info.status && mac_info.status != HINIC_PF_SET_VF_ALREADY &&
+ mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
+- dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to change MAC, ret = %d\n",
+- mac_info.status);
+- return -EFAULT;
++ dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
++ err, mac_info.status, out_size);
++ return -EIO;
+ }
+
+ return 0;
+--
+2.25.1
+
--- /dev/null
+From 14e1094642c4b02bc436f6e3f95f4f1b2fc87941 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Sep 2020 09:31:51 +0800
+Subject: hinic: fix wrong return value of mac-set cmd
+
+From: Luo bin <luobin9@huawei.com>
+
+[ Upstream commit f68910a8056f9451ee9fe7e1b962f7d90d326ad3 ]
+
+It should also be regarded as an error when hw return status=4 for PF's
+setting mac cmd. Only if PF return status=4 to VF should this cmd be
+taken special treatment.
+
+Fixes: 7dd29ee12865 ("hinic: add sriov feature support")
+Signed-off-by: Luo bin <luobin9@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/huawei/hinic/hinic_port.c | 6 +++---
+ drivers/net/ethernet/huawei/hinic/hinic_sriov.c | 12 ++----------
+ 2 files changed, 5 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
+index 82d5c50630e64..2be7c254cca90 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
+@@ -58,9 +58,9 @@ static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
+ sizeof(port_mac_cmd),
+ &port_mac_cmd, &out_size);
+ if (err || out_size != sizeof(port_mac_cmd) ||
+- (port_mac_cmd.status &&
+- port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY &&
+- port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
++ (port_mac_cmd.status &&
++ (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&
++ port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
+ dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, port_mac_cmd.status, out_size);
+ return -EFAULT;
+diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+index 1043389754df0..b757f7057b8fe 100644
+--- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
++++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+@@ -38,8 +38,7 @@ static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
+ err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
+ sizeof(mac_info), &mac_info, &out_size);
+ if (err || out_size != sizeof(mac_info) ||
+- (mac_info.status && mac_info.status != HINIC_PF_SET_VF_ALREADY &&
+- mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
++ (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
+ dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, mac_info.status, out_size);
+ return -EIO;
+@@ -452,8 +451,7 @@ struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev)
+
+ static int hinic_check_mac_info(u8 status, u16 vlan_id)
+ {
+- if ((status && status != HINIC_MGMT_STATUS_EXIST &&
+- status != HINIC_PF_SET_VF_ALREADY) ||
++ if ((status && status != HINIC_MGMT_STATUS_EXIST) ||
+ (vlan_id & CHECK_IPSU_15BIT &&
+ status == HINIC_MGMT_STATUS_EXIST))
+ return -EINVAL;
+@@ -495,12 +493,6 @@ static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac,
+ return -EINVAL;
+ }
+
+- if (mac_info.status == HINIC_PF_SET_VF_ALREADY) {
+- dev_warn(&hwdev->hwif->pdev->dev,
+- "PF has already set VF MAC. Ignore update operation\n");
+- return HINIC_PF_SET_VF_ALREADY;
+- }
+-
+ if (mac_info.status == HINIC_MGMT_STATUS_EXIST)
+ dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n");
+
+--
+2.25.1
+
--- /dev/null
+From cc7541d5ca5e81e749490a5ea65d1cede0dbaefb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Oct 2020 10:07:49 +0200
+Subject: i2c: meson: fix clock setting overwrite
+
+From: Jerome Brunet <jbrunet@baylibre.com>
+
+[ Upstream commit 28683e847e2f20eed22cdd24f185d7783db396d3 ]
+
+When the slave address is written in do_start(), SLAVE_ADDR is written
+completely. This may overwrite some setting related to the clock rate
+or signal filtering.
+
+Fix this by writing only the bits related to slave address. To avoid
+causing unexpected changed, explicitly disable filtering or high/low
+clock mode which may have been left over by the bootloader.
+
+Fixes: 30021e3707a7 ("i2c: add support for Amlogic Meson I2C controller")
+Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-meson.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
+index ef73a42577cc7..a85a40fdf2f6e 100644
+--- a/drivers/i2c/busses/i2c-meson.c
++++ b/drivers/i2c/busses/i2c-meson.c
+@@ -43,6 +43,12 @@
+ #define REG_SLV_SCL_LOW GENMASK(27, 16)
+ #define REG_SLV_SCL_LOW_EN BIT(28)
+
++#define REG_SLV_ADDR GENMASK(7, 0)
++#define REG_SLV_SDA_FILTER GENMASK(10, 8)
++#define REG_SLV_SCL_FILTER GENMASK(13, 11)
++#define REG_SLV_SCL_LOW GENMASK(27, 16)
++#define REG_SLV_SCL_LOW_EN BIT(28)
++
+ #define I2C_TIMEOUT_MS 500
+ #define FILTER_DELAY 15
+
+@@ -158,6 +164,9 @@ static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
+ /* Disable HIGH/LOW mode */
+ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
+
++ /* Disable HIGH/LOW mode */
++ meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
++
+ dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
+ clk_rate, freq, div);
+ }
+--
+2.25.1
+
--- /dev/null
+From cbf584431870e096c0ee647a0b80f4737723a9f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Sep 2020 12:54:59 +0000
+Subject: iavf: Fix incorrect adapter get in iavf_resume
+
+From: Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
+
+[ Upstream commit 75598a8fc0e0dff2aa5d46c62531b36a595f1d4f ]
+
+When calling iavf_resume there was a crash because wrong
+function was used to get iavf_adapter and net_device pointers.
+Changed how iavf_resume is getting iavf_adapter and net_device
+pointers from pci_dev.
+
+Fixes: 5eae00c57f5e ("i40evf: main driver core")
+Signed-off-by: Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
+Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
+Tested-by: Aaron Brown <aaron.f.brown@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index b3b349ecb0a8d..91343e2d3a145 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -3817,8 +3817,8 @@ static int __maybe_unused iavf_suspend(struct device *dev_d)
+ static int __maybe_unused iavf_resume(struct device *dev_d)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev_d);
+- struct iavf_adapter *adapter = pci_get_drvdata(pdev);
+- struct net_device *netdev = adapter->netdev;
++ struct net_device *netdev = pci_get_drvdata(pdev);
++ struct iavf_adapter *adapter = netdev_priv(netdev);
+ u32 err;
+
+ pci_set_master(pdev);
+--
+2.25.1
+
--- /dev/null
+From d1447d2ffbeb284928bca6524ea5838510f75b86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Jun 2020 14:59:39 +0530
+Subject: iavf: use generic power management
+
+From: Vaibhav Gupta <vaibhavgupta40@gmail.com>
+
+[ Upstream commit bc5cbd73eb493944b8665dc517f684c40eb18a4a ]
+
+With the support of generic PM callbacks, drivers no longer need to use
+legacy .suspend() and .resume() in which they had to maintain PCI states
+changes and device's power state themselves. The required operations are
+done by PCI core.
+
+PCI drivers are not expected to invoke PCI helper functions like
+pci_save/restore_state(), pci_enable/disable_device(),
+pci_set_power_state(), etc. Their tasks are completed by PCI core itself.
+
+Compile-tested only.
+
+Signed-off-by: Vaibhav Gupta <vaibhavgupta40@gmail.com>
+Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/iavf/iavf_main.c | 45 ++++++---------------
+ 1 file changed, 12 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index d338efe5f3f55..b3b349ecb0a8d 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -3777,7 +3777,6 @@ err_dma:
+ return err;
+ }
+
+-#ifdef CONFIG_PM
+ /**
+ * iavf_suspend - Power management suspend routine
+ * @pdev: PCI device information struct
+@@ -3785,11 +3784,10 @@ err_dma:
+ *
+ * Called when the system (VM) is entering sleep/suspend.
+ **/
+-static int iavf_suspend(struct pci_dev *pdev, pm_message_t state)
++static int __maybe_unused iavf_suspend(struct device *dev_d)
+ {
+- struct net_device *netdev = pci_get_drvdata(pdev);
++ struct net_device *netdev = dev_get_drvdata(dev_d);
+ struct iavf_adapter *adapter = netdev_priv(netdev);
+- int retval = 0;
+
+ netif_device_detach(netdev);
+
+@@ -3807,12 +3805,6 @@ static int iavf_suspend(struct pci_dev *pdev, pm_message_t state)
+
+ clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
+
+- retval = pci_save_state(pdev);
+- if (retval)
+- return retval;
+-
+- pci_disable_device(pdev);
+-
+ return 0;
+ }
+
+@@ -3822,24 +3814,13 @@ static int iavf_suspend(struct pci_dev *pdev, pm_message_t state)
+ *
+ * Called when the system (VM) is resumed from sleep/suspend.
+ **/
+-static int iavf_resume(struct pci_dev *pdev)
++static int __maybe_unused iavf_resume(struct device *dev_d)
+ {
++ struct pci_dev *pdev = to_pci_dev(dev_d);
+ struct iavf_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+ u32 err;
+
+- pci_set_power_state(pdev, PCI_D0);
+- pci_restore_state(pdev);
+- /* pci_restore_state clears dev->state_saved so call
+- * pci_save_state to restore it.
+- */
+- pci_save_state(pdev);
+-
+- err = pci_enable_device_mem(pdev);
+- if (err) {
+- dev_err(&pdev->dev, "Cannot enable PCI device from suspend.\n");
+- return err;
+- }
+ pci_set_master(pdev);
+
+ rtnl_lock();
+@@ -3863,7 +3844,6 @@ static int iavf_resume(struct pci_dev *pdev)
+ return err;
+ }
+
+-#endif /* CONFIG_PM */
+ /**
+ * iavf_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+@@ -3965,16 +3945,15 @@ static void iavf_remove(struct pci_dev *pdev)
+ pci_disable_device(pdev);
+ }
+
++static SIMPLE_DEV_PM_OPS(iavf_pm_ops, iavf_suspend, iavf_resume);
++
+ static struct pci_driver iavf_driver = {
+- .name = iavf_driver_name,
+- .id_table = iavf_pci_tbl,
+- .probe = iavf_probe,
+- .remove = iavf_remove,
+-#ifdef CONFIG_PM
+- .suspend = iavf_suspend,
+- .resume = iavf_resume,
+-#endif
+- .shutdown = iavf_shutdown,
++ .name = iavf_driver_name,
++ .id_table = iavf_pci_tbl,
++ .probe = iavf_probe,
++ .remove = iavf_remove,
++ .driver.pm = &iavf_pm_ops,
++ .shutdown = iavf_shutdown,
+ };
+
+ /**
+--
+2.25.1
+
--- /dev/null
+From e47886203033768701068d4a935a7219a6a0d5e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Sep 2020 08:53:46 -0700
+Subject: ice: fix memory leak if register_netdev_fails
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ Upstream commit 135f4b9e9340dadb78e9737bb4eb9817b9c89dac ]
+
+The ice_setup_pf_sw function can cause a memory leak if register_netdev
+fails, due to accidentally failing to free the VSI rings. Fix the memory
+leak by using ice_vsi_release, ensuring we actually go through the full
+teardown process.
+
+This should be safe even if the netdevice is not registered because we
+will have set the netdev pointer to NULL, ensuring ice_vsi_release won't
+call unregister_netdev.
+
+An alternative fix would be moving management of the PF VSI netdev into
+the main VSI setup code. This is complicated and likely requires
+significant refactor in how we manage VSIs
+
+Fixes: 3a858ba392c3 ("ice: Add support for VSI allocation and deallocation")
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Tested-by: Aaron Brown <aaron.f.brown@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_lib.c | 6 +++---
+ drivers/net/ethernet/intel/ice/ice_lib.h | 6 ------
+ drivers/net/ethernet/intel/ice/ice_main.c | 13 +++----------
+ 3 files changed, 6 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
+index 2e3a39cea2c03..133ba6f08e574 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_lib.c
+@@ -240,7 +240,7 @@ static int ice_get_free_slot(void *array, int size, int curr)
+ * ice_vsi_delete - delete a VSI from the switch
+ * @vsi: pointer to VSI being removed
+ */
+-void ice_vsi_delete(struct ice_vsi *vsi)
++static void ice_vsi_delete(struct ice_vsi *vsi)
+ {
+ struct ice_pf *pf = vsi->back;
+ struct ice_vsi_ctx *ctxt;
+@@ -307,7 +307,7 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
+ *
+ * Returns 0 on success, negative on failure
+ */
+-int ice_vsi_clear(struct ice_vsi *vsi)
++static int ice_vsi_clear(struct ice_vsi *vsi)
+ {
+ struct ice_pf *pf = NULL;
+ struct device *dev;
+@@ -557,7 +557,7 @@ static int ice_vsi_get_qs(struct ice_vsi *vsi)
+ * ice_vsi_put_qs - Release queues from VSI to PF
+ * @vsi: the VSI that is going to release queues
+ */
+-void ice_vsi_put_qs(struct ice_vsi *vsi)
++static void ice_vsi_put_qs(struct ice_vsi *vsi)
+ {
+ struct ice_pf *pf = vsi->back;
+ int i;
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
+index d80e6afa45112..2954b30e6ec79 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.h
++++ b/drivers/net/ethernet/intel/ice/ice_lib.h
+@@ -43,10 +43,6 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);
+
+ void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);
+
+-void ice_vsi_delete(struct ice_vsi *vsi);
+-
+-int ice_vsi_clear(struct ice_vsi *vsi);
+-
+ #ifdef CONFIG_DCB
+ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc);
+ #endif /* CONFIG_DCB */
+@@ -77,8 +73,6 @@ bool ice_is_reset_in_progress(unsigned long *state);
+ void
+ ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio);
+
+-void ice_vsi_put_qs(struct ice_vsi *vsi);
+-
+ void ice_vsi_dis_irq(struct ice_vsi *vsi);
+
+ void ice_vsi_free_irq(struct ice_vsi *vsi);
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index 4cbd49c87568a..4b52f1dea7f3a 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -2605,10 +2605,8 @@ static int ice_setup_pf_sw(struct ice_pf *pf)
+ return -EBUSY;
+
+ vsi = ice_pf_vsi_setup(pf, pf->hw.port_info);
+- if (!vsi) {
+- status = -ENOMEM;
+- goto unroll_vsi_setup;
+- }
++ if (!vsi)
++ return -ENOMEM;
+
+ status = ice_cfg_netdev(vsi);
+ if (status) {
+@@ -2655,12 +2653,7 @@ unroll_napi_add:
+ }
+
+ unroll_vsi_setup:
+- if (vsi) {
+- ice_vsi_free_q_vectors(vsi);
+- ice_vsi_delete(vsi);
+- ice_vsi_put_qs(vsi);
+- ice_vsi_clear(vsi);
+- }
++ ice_vsi_release(vsi);
+ return status;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From dee6e0c675f38a8a5d3087018bb2110bcfe10140 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Sep 2020 08:53:47 -0700
+Subject: ice: fix memory leak in ice_vsi_setup
+
+From: Jacob Keller <jacob.e.keller@intel.com>
+
+[ Upstream commit f6a07271bb1535d9549380461437cc48d9e19958 ]
+
+During ice_vsi_setup, if ice_cfg_vsi_lan fails, it does not properly
+release memory associated with the VSI rings. If we had used devres
+allocations for the rings, this would be ok. However, we use kzalloc and
+kfree_rcu for these ring structures.
+
+Using the correct label to cleanup the rings during ice_vsi_setup
+highlights an issue in the ice_vsi_clear_rings function: it can leave
+behind stale ring pointers in the q_vectors structure.
+
+When releasing rings, we must also ensure that no q_vector associated
+with the VSI will point to this ring again. To resolve this, loop over
+all q_vectors and release their ring mapping. Because we are about to
+free all rings, no q_vector should remain pointing to any of the rings
+in this VSI.
+
+Fixes: 5513b920a4f7 ("ice: Update Tx scheduler tree for VSI multi-Tx queue support")
+Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
+Tested-by: Aaron Brown <aaron.f.brown@intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_lib.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
+index 133ba6f08e574..4c5845a0965a9 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_lib.c
+@@ -1190,6 +1190,18 @@ static void ice_vsi_clear_rings(struct ice_vsi *vsi)
+ {
+ int i;
+
++ /* Avoid stale references by clearing map from vector to ring */
++ if (vsi->q_vectors) {
++ ice_for_each_q_vector(vsi, i) {
++ struct ice_q_vector *q_vector = vsi->q_vectors[i];
++
++ if (q_vector) {
++ q_vector->tx.ring = NULL;
++ q_vector->rx.ring = NULL;
++ }
++ }
++ }
++
+ if (vsi->tx_rings) {
+ for (i = 0; i < vsi->alloc_txq; i++) {
+ if (vsi->tx_rings[i]) {
+@@ -2254,7 +2266,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
+ if (status) {
+ dev_err(dev, "VSI %d failed lan queue config, error %s\n",
+ vsi->vsi_num, ice_stat_str(status));
+- goto unroll_vector_base;
++ goto unroll_clear_rings;
+ }
+
+ /* Add switch rule to drop all Tx Flow Control Frames, of look up
+--
+2.25.1
+
--- /dev/null
+From bd64853b791603930c08d9fc762fc68d5a9cbb65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 26 Sep 2020 21:33:43 -0700
+Subject: mdio: fix mdio-thunder.c dependency & build error
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 7dbbcf496f2a4b6d82cfc7810a0746e160b79762 ]
+
+Fix build error by selecting MDIO_DEVRES for MDIO_THUNDER.
+Fixes this build error:
+
+ld: drivers/net/phy/mdio-thunder.o: in function `thunder_mdiobus_pci_probe':
+drivers/net/phy/mdio-thunder.c:78: undefined reference to `devm_mdiobus_alloc_size'
+
+Fixes: 379d7ac7ca31 ("phy: mdio-thunder: Add driver for Cavium Thunder SoC MDIO buses.")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Cc: Andrew Lunn <andrew@lunn.ch>
+Cc: Heiner Kallweit <hkallweit1@gmail.com>
+Cc: netdev@vger.kernel.org
+Cc: David Daney <david.daney@cavium.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/phy/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
+index e351d65533aa8..06146ae4c6d8d 100644
+--- a/drivers/net/phy/Kconfig
++++ b/drivers/net/phy/Kconfig
+@@ -217,6 +217,7 @@ config MDIO_THUNDER
+ depends on 64BIT
+ depends on PCI
+ select MDIO_CAVIUM
++ select MDIO_DEVRES
+ help
+ This driver supports the MDIO interfaces found on Cavium
+ ThunderX SoCs when the MDIO bus device appears as a PCI
+--
+2.25.1
+
--- /dev/null
+From 38db94f0d730c829bf9ccf494310a0833a78b0a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Sep 2020 09:42:11 +0300
+Subject: mlxsw: spectrum_acl: Fix mlxsw_sp_acl_tcam_group_add()'s error path
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 72865028582a678be1e05240e55d452e5c258eca ]
+
+If mlxsw_sp_acl_tcam_group_id_get() fails, the mutex initialized earlier
+is not destroyed.
+
+Fix this by initializing the mutex after calling the function. This is
+symmetric to mlxsw_sp_acl_tcam_group_del().
+
+Fixes: 5ec2ee28d27b ("mlxsw: spectrum_acl: Introduce a mutex to guard region list updates")
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+index 5c020403342f9..7cccc41dd69c9 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+@@ -292,13 +292,14 @@ mlxsw_sp_acl_tcam_group_add(struct mlxsw_sp_acl_tcam *tcam,
+ int err;
+
+ group->tcam = tcam;
+- mutex_init(&group->lock);
+ INIT_LIST_HEAD(&group->region_list);
+
+ err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
+ if (err)
+ return err;
+
++ mutex_init(&group->lock);
++
+ return 0;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From ec52fc9c1c1659f99f34a68b4dc3aa21e61dfca7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Oct 2020 09:38:52 +0800
+Subject: mmc: core: don't set limits.discard_granularity as 0
+
+From: Coly Li <colyli@suse.de>
+
+[ Upstream commit 4243219141b67d7c2fdb2d8073c17c539b9263eb ]
+
+In mmc_queue_setup_discard() the mmc driver queue's discard_granularity
+might be set as 0 (when card->pref_erase > max_discard) while the mmc
+device still declares to support discard operation. This is buggy and
+triggered the following kernel warning message,
+
+WARNING: CPU: 0 PID: 135 at __blkdev_issue_discard+0x200/0x294
+CPU: 0 PID: 135 Comm: f2fs_discard-17 Not tainted 5.9.0-rc6 #1
+Hardware name: Google Kevin (DT)
+pstate: 00000005 (nzcv daif -PAN -UAO BTYPE=--)
+pc : __blkdev_issue_discard+0x200/0x294
+lr : __blkdev_issue_discard+0x54/0x294
+sp : ffff800011dd3b10
+x29: ffff800011dd3b10 x28: 0000000000000000 x27: ffff800011dd3cc4 x26: ffff800011dd3e18 x25: 000000000004e69b x24: 0000000000000c40 x23: ffff0000f1deaaf0 x22: ffff0000f2849200 x21: 00000000002734d8 x20: 0000000000000008 x19: 0000000000000000 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 x14: 0000000000000394 x13: 0000000000000000 x12: 0000000000000000 x11: 0000000000000000 x10: 00000000000008b0 x9 : ffff800011dd3cb0 x8 : 000000000004e69b x7 : 0000000000000000 x6 : ffff0000f1926400 x5 : ffff0000f1940800 x4 : 0000000000000000 x3 : 0000000000000c40 x2 : 0000000000000008 x1 : 00000000002734d8 x0 : 0000000000000000 Call trace:
+__blkdev_issue_discard+0x200/0x294
+__submit_discard_cmd+0x128/0x374
+__issue_discard_cmd_orderly+0x188/0x244
+__issue_discard_cmd+0x2e8/0x33c
+issue_discard_thread+0xe8/0x2f0
+kthread+0x11c/0x120
+ret_from_fork+0x10/0x1c
+---[ end trace e4c8023d33dfe77a ]---
+
+This patch fixes the issue by setting discard_granularity as SECTOR_SIZE
+instead of 0 when (card->pref_erase > max_discard) is true. Now no more
+complain from __blkdev_issue_discard() for the improper value of discard
+granularity.
+
+This issue is exposed after commit b35fd7422c2f ("block: check queue's
+limits.discard_granularity in __blkdev_issue_discard()"), a "Fixes:" tag
+is also added for the commit to make sure people won't miss this patch
+after applying the change of __blkdev_issue_discard().
+
+Fixes: e056a1b5b67b ("mmc: queue: let host controllers specify maximum discard timeout")
+Fixes: b35fd7422c2f ("block: check queue's limits.discard_granularity in __blkdev_issue_discard()").
+Reported-and-tested-by: Vicente Bergas <vicencb@gmail.com>
+Signed-off-by: Coly Li <colyli@suse.de>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ulf Hansson <ulf.hansson@linaro.org>
+Link: https://lore.kernel.org/r/20201002013852.51968-1-colyli@suse.de
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/core/queue.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c
+index 4b1eb89b401d9..1ad518821157f 100644
+--- a/drivers/mmc/core/queue.c
++++ b/drivers/mmc/core/queue.c
+@@ -190,7 +190,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
+ q->limits.discard_granularity = card->pref_erase << 9;
+ /* granularity must not be greater than max. discard */
+ if (card->pref_erase > max_discard)
+- q->limits.discard_granularity = 0;
++ q->limits.discard_granularity = SECTOR_SIZE;
+ if (mmc_can_secure_erase_trim(card))
+ blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
+ }
+--
+2.25.1
+
--- /dev/null
+From 08c118f7c0d39b3ff8f35351f73f5757dc09cd6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Sep 2020 09:57:46 +0800
+Subject: net: dsa: felix: convert TAS link speed based on phylink speed
+
+From: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
+
+[ Upstream commit dba1e4660a87927bdc03c23e36fd2c81a16a7ab1 ]
+
+state->speed holds a value of 10, 100, 1000 or 2500, but
+QSYS_TAG_CONFIG_LINK_SPEED expects a value of 0, 1, 2, 3. So convert the
+speed to a proper value.
+
+Fixes: de143c0e274b ("net: dsa: felix: Configure Time-Aware Scheduler via taprio offload")
+Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
+Reviewed-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/ocelot/felix_vsc9959.c | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
+index 7c167a394b762..a83ecd1c5d6c2 100644
+--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
+@@ -1215,8 +1215,28 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
+ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
+ u32 speed)
+ {
++ u8 tas_speed;
++
++ switch (speed) {
++ case SPEED_10:
++ tas_speed = OCELOT_SPEED_10;
++ break;
++ case SPEED_100:
++ tas_speed = OCELOT_SPEED_100;
++ break;
++ case SPEED_1000:
++ tas_speed = OCELOT_SPEED_1000;
++ break;
++ case SPEED_2500:
++ tas_speed = OCELOT_SPEED_2500;
++ break;
++ default:
++ tas_speed = OCELOT_SPEED_1000;
++ break;
++ }
++
+ ocelot_rmw_rix(ocelot,
+- QSYS_TAG_CONFIG_LINK_SPEED(speed),
++ QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
+ QSYS_TAG_CONFIG_LINK_SPEED_M,
+ QSYS_TAG_CONFIG, port);
+ }
+--
+2.25.1
+
--- /dev/null
+From 9e7008e4df8f01a06e4b19690ce9f9c414a22d91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Sep 2020 15:44:39 +0300
+Subject: net: ethernet: cavium: octeon_mgmt: use phy_start and phy_stop
+
+From: Ivan Khoronzhuk <ivan.khoronzhuk@gmail.com>
+
+[ Upstream commit 4663ff60257aec4ee1e2e969a7c046f0aff35ab8 ]
+
+To start also "phy state machine", with UP state as it should be,
+the phy_start() has to be used, in another case machine even is not
+triggered. After this change negotiation is supposed to be triggered
+by SM workqueue.
+
+It's not correct usage, but it appears after the following patch,
+so add it as a fix.
+
+Fixes: 74a992b3598a ("net: phy: add phy_check_link_status")
+Signed-off-by: Ivan Khoronzhuk <ikhoronz@cisco.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/cavium/octeon/octeon_mgmt.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+index cbaa1924afbe1..706e959bf02ac 100644
+--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
++++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+@@ -1219,7 +1219,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
+ */
+ if (netdev->phydev) {
+ netif_carrier_off(netdev);
+- phy_start_aneg(netdev->phydev);
++ phy_start(netdev->phydev);
+ }
+
+ netif_wake_queue(netdev);
+@@ -1247,8 +1247,10 @@ static int octeon_mgmt_stop(struct net_device *netdev)
+ napi_disable(&p->napi);
+ netif_stop_queue(netdev);
+
+- if (netdev->phydev)
++ if (netdev->phydev) {
++ phy_stop(netdev->phydev);
+ phy_disconnect(netdev->phydev);
++ }
+
+ netif_carrier_off(netdev);
+
+--
+2.25.1
+
--- /dev/null
+From 099bc6f51926c54ccff81dd23286a7b4ae40093c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Oct 2020 10:54:49 -0700
+Subject: net: hinic: fix DEVLINK build errors
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 1f7e877c20517735bceff1535e1b7fa846b2f215 ]
+
+Fix many (lots deleted here) build errors in hinic by selecting NET_DEVLINK.
+
+ld: drivers/net/ethernet/huawei/hinic/hinic_hw_dev.o: in function `mgmt_watchdog_timeout_event_handler':
+hinic_hw_dev.c:(.text+0x30a): undefined reference to `devlink_health_report'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_fw_reporter_dump':
+hinic_devlink.c:(.text+0x1c): undefined reference to `devlink_fmsg_u32_pair_put'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_fw_reporter_dump':
+hinic_devlink.c:(.text+0x126): undefined reference to `devlink_fmsg_binary_pair_put'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_hw_reporter_dump':
+hinic_devlink.c:(.text+0x1ba): undefined reference to `devlink_fmsg_string_pair_put'
+ld: hinic_devlink.c:(.text+0x227): undefined reference to `devlink_fmsg_u8_pair_put'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_devlink_alloc':
+hinic_devlink.c:(.text+0xaee): undefined reference to `devlink_alloc'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_devlink_free':
+hinic_devlink.c:(.text+0xb04): undefined reference to `devlink_free'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_devlink_register':
+hinic_devlink.c:(.text+0xb26): undefined reference to `devlink_register'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_devlink_unregister':
+hinic_devlink.c:(.text+0xb46): undefined reference to `devlink_unregister'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_health_reporters_create':
+hinic_devlink.c:(.text+0xb75): undefined reference to `devlink_health_reporter_create'
+ld: hinic_devlink.c:(.text+0xb95): undefined reference to `devlink_health_reporter_create'
+ld: hinic_devlink.c:(.text+0xbac): undefined reference to `devlink_health_reporter_destroy'
+ld: drivers/net/ethernet/huawei/hinic/hinic_devlink.o: in function `hinic_health_reporters_destroy':
+
+Fixes: 51ba902a16e6 ("net-next/hinic: Initialize hw interface")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Bin Luo <luobin9@huawei.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Aviad Krawczyk <aviad.krawczyk@huawei.com>
+Cc: Zhao Chen <zhaochen6@huawei.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/huawei/hinic/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/huawei/hinic/Kconfig b/drivers/net/ethernet/huawei/hinic/Kconfig
+index 936e2dd3bb135..b47bd5440c5f0 100644
+--- a/drivers/net/ethernet/huawei/hinic/Kconfig
++++ b/drivers/net/ethernet/huawei/hinic/Kconfig
+@@ -6,6 +6,7 @@
+ config HINIC
+ tristate "Huawei Intelligent PCIE Network Interface Card"
+ depends on (PCI_MSI && (X86 || ARM64))
++ select NET_DEVLINK
+ help
+ This driver supports HiNIC PCIE Ethernet cards.
+ To compile this driver as part of the kernel, choose Y here.
+--
+2.25.1
+
--- /dev/null
+From e4fc4b14a9882fdca0c88ee695afb0f5e98a04a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Aug 2020 15:04:35 +0300
+Subject: net/mlx5: Add retry mechanism to the command entry index allocation
+
+From: Eran Ben Elisha <eranbe@nvidia.com>
+
+[ Upstream commit 410bd754cd73c4a2ac3856d9a03d7b08f9c906bf ]
+
+It is possible that new command entry index allocation will temporarily
+fail. The new command holds the semaphore, so it means that a free entry
+should be ready soon. Add one second retry mechanism before returning an
+error.
+
+Patch "net/mlx5: Avoid possible free of command entry while timeout comp
+handler" increase the possibility to bump into this temporarily failure
+as it delays the entry index release for non-callback commands.
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Eran Ben Elisha <eranbe@nvidia.com>
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 21 ++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index 37dae95e61d5f..2b597ac365f84 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -883,6 +883,25 @@ static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode)
+ return cmd->allowed_opcode == opcode;
+ }
+
++static int cmd_alloc_index_retry(struct mlx5_cmd *cmd)
++{
++ unsigned long alloc_end = jiffies + msecs_to_jiffies(1000);
++ int idx;
++
++retry:
++ idx = cmd_alloc_index(cmd);
++ if (idx < 0 && time_before(jiffies, alloc_end)) {
++ /* Index allocation can fail on heavy load of commands. This is a temporary
++ * situation as the current command already holds the semaphore, meaning that
++ * another command completion is being handled and it is expected to release
++ * the entry index soon.
++ */
++ cpu_relax();
++ goto retry;
++ }
++ return idx;
++}
++
+ static void cmd_work_handler(struct work_struct *work)
+ {
+ struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work);
+@@ -900,7 +919,7 @@ static void cmd_work_handler(struct work_struct *work)
+ sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
+ down(sem);
+ if (!ent->page_queue) {
+- alloc_ret = cmd_alloc_index(cmd);
++ alloc_ret = cmd_alloc_index_retry(cmd);
+ if (alloc_ret < 0) {
+ mlx5_core_err_rl(dev, "failed to allocate command entry\n");
+ if (ent->callback) {
+--
+2.25.1
+
--- /dev/null
+From bb9b3734c22098f899ca675a5933315e495e03a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Aug 2020 10:40:21 +0300
+Subject: net/mlx5: Avoid possible free of command entry while timeout comp
+ handler
+
+From: Eran Ben Elisha <eranbe@mellanox.com>
+
+[ Upstream commit 50b2412b7e7862c5af0cbf4b10d93bc5c712d021 ]
+
+Upon command completion timeout, driver simulates a forced command
+completion. In a rare case where real interrupt for that command arrives
+simultaneously, it might release the command entry while the forced
+handler might still access it.
+
+Fix that by adding an entry refcount, to track current amount of allowed
+handlers. Command entry to be released only when this refcount is
+decremented to zero.
+
+Command refcount is always initialized to one. For callback commands,
+command completion handler is the symmetric flow to decrement it. For
+non-callback commands, it is wait_func().
+
+Before ringing the doorbell, increment the refcount for the real completion
+handler. Once the real completion handler is called, it will decrement it.
+
+For callback commands, once the delayed work is scheduled, increment the
+refcount. Upon callback command completion handler, we will try to cancel
+the timeout callback. In case of success, we need to decrement the callback
+refcount as it will never run.
+
+In addition, gather the entry index free and the entry free into a one
+flow for all command types release.
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
+Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 109 ++++++++++++------
+ include/linux/mlx5/driver.h | 2 +
+ 2 files changed, 73 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index 1d91a0d0ab1d7..c0055f5479ce0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -69,12 +69,10 @@ enum {
+ MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR = 0x10,
+ };
+
+-static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
+- struct mlx5_cmd_msg *in,
+- struct mlx5_cmd_msg *out,
+- void *uout, int uout_size,
+- mlx5_cmd_cbk_t cbk,
+- void *context, int page_queue)
++static struct mlx5_cmd_work_ent *
++cmd_alloc_ent(struct mlx5_cmd *cmd, struct mlx5_cmd_msg *in,
++ struct mlx5_cmd_msg *out, void *uout, int uout_size,
++ mlx5_cmd_cbk_t cbk, void *context, int page_queue)
+ {
+ gfp_t alloc_flags = cbk ? GFP_ATOMIC : GFP_KERNEL;
+ struct mlx5_cmd_work_ent *ent;
+@@ -83,6 +81,7 @@ static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
+ if (!ent)
+ return ERR_PTR(-ENOMEM);
+
++ ent->idx = -EINVAL;
+ ent->in = in;
+ ent->out = out;
+ ent->uout = uout;
+@@ -91,10 +90,16 @@ static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
+ ent->context = context;
+ ent->cmd = cmd;
+ ent->page_queue = page_queue;
++ refcount_set(&ent->refcnt, 1);
+
+ return ent;
+ }
+
++static void cmd_free_ent(struct mlx5_cmd_work_ent *ent)
++{
++ kfree(ent);
++}
++
+ static u8 alloc_token(struct mlx5_cmd *cmd)
+ {
+ u8 token;
+@@ -109,7 +114,7 @@ static u8 alloc_token(struct mlx5_cmd *cmd)
+ return token;
+ }
+
+-static int alloc_ent(struct mlx5_cmd *cmd)
++static int cmd_alloc_index(struct mlx5_cmd *cmd)
+ {
+ unsigned long flags;
+ int ret;
+@@ -123,7 +128,7 @@ static int alloc_ent(struct mlx5_cmd *cmd)
+ return ret < cmd->max_reg_cmds ? ret : -ENOMEM;
+ }
+
+-static void free_ent(struct mlx5_cmd *cmd, int idx)
++static void cmd_free_index(struct mlx5_cmd *cmd, int idx)
+ {
+ unsigned long flags;
+
+@@ -132,6 +137,22 @@ static void free_ent(struct mlx5_cmd *cmd, int idx)
+ spin_unlock_irqrestore(&cmd->alloc_lock, flags);
+ }
+
++static void cmd_ent_get(struct mlx5_cmd_work_ent *ent)
++{
++ refcount_inc(&ent->refcnt);
++}
++
++static void cmd_ent_put(struct mlx5_cmd_work_ent *ent)
++{
++ if (!refcount_dec_and_test(&ent->refcnt))
++ return;
++
++ if (ent->idx >= 0)
++ cmd_free_index(ent->cmd, ent->idx);
++
++ cmd_free_ent(ent);
++}
++
+ static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx)
+ {
+ return cmd->cmd_buf + (idx << cmd->log_stride);
+@@ -219,11 +240,6 @@ static void poll_timeout(struct mlx5_cmd_work_ent *ent)
+ ent->ret = -ETIMEDOUT;
+ }
+
+-static void free_cmd(struct mlx5_cmd_work_ent *ent)
+-{
+- kfree(ent);
+-}
+-
+ static int verify_signature(struct mlx5_cmd_work_ent *ent)
+ {
+ struct mlx5_cmd_mailbox *next = ent->out->next;
+@@ -842,6 +858,7 @@ static void cb_timeout_handler(struct work_struct *work)
+ mlx5_command_str(msg_to_opcode(ent->in)),
+ msg_to_opcode(ent->in));
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
++ cmd_ent_put(ent); /* for the cmd_ent_get() took on schedule delayed work */
+ }
+
+ static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg);
+@@ -873,14 +890,14 @@ static void cmd_work_handler(struct work_struct *work)
+ sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
+ down(sem);
+ if (!ent->page_queue) {
+- alloc_ret = alloc_ent(cmd);
++ alloc_ret = cmd_alloc_index(cmd);
+ if (alloc_ret < 0) {
+ mlx5_core_err_rl(dev, "failed to allocate command entry\n");
+ if (ent->callback) {
+ ent->callback(-EAGAIN, ent->context);
+ mlx5_free_cmd_msg(dev, ent->out);
+ free_msg(dev, ent->in);
+- free_cmd(ent);
++ cmd_ent_put(ent);
+ } else {
+ ent->ret = -EAGAIN;
+ complete(&ent->done);
+@@ -916,8 +933,8 @@ static void cmd_work_handler(struct work_struct *work)
+ ent->ts1 = ktime_get_ns();
+ cmd_mode = cmd->mode;
+
+- if (ent->callback)
+- schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
++ if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, cb_timeout))
++ cmd_ent_get(ent);
+ set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
+
+ /* Skip sending command to fw if internal error */
+@@ -933,13 +950,10 @@ static void cmd_work_handler(struct work_struct *work)
+ MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
+
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+- /* no doorbell, no need to keep the entry */
+- free_ent(cmd, ent->idx);
+- if (ent->callback)
+- free_cmd(ent);
+ return;
+ }
+
++ cmd_ent_get(ent); /* for the _real_ FW event on completion */
+ /* ring doorbell after the descriptor is valid */
+ mlx5_core_dbg(dev, "writing 0x%x to command doorbell\n", 1 << ent->idx);
+ wmb();
+@@ -1039,11 +1053,16 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ if (callback && page_queue)
+ return -EINVAL;
+
+- ent = alloc_cmd(cmd, in, out, uout, uout_size, callback, context,
+- page_queue);
++ ent = cmd_alloc_ent(cmd, in, out, uout, uout_size,
++ callback, context, page_queue);
+ if (IS_ERR(ent))
+ return PTR_ERR(ent);
+
++ /* put for this ent is when consumed, depending on the use case
++ * 1) (!callback) blocking flow: by caller after wait_func completes
++ * 2) (callback) flow: by mlx5_cmd_comp_handler() when ent is handled
++ */
++
+ ent->token = token;
+ ent->polling = force_polling;
+
+@@ -1062,12 +1081,10 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ }
+
+ if (callback)
+- goto out;
++ goto out; /* mlx5_cmd_comp_handler() will put(ent) */
+
+ err = wait_func(dev, ent);
+- if (err == -ETIMEDOUT)
+- goto out;
+- if (err == -ECANCELED)
++ if (err == -ETIMEDOUT || err == -ECANCELED)
+ goto out_free;
+
+ ds = ent->ts2 - ent->ts1;
+@@ -1085,7 +1102,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ *status = ent->status;
+
+ out_free:
+- free_cmd(ent);
++ cmd_ent_put(ent);
+ out:
+ return err;
+ }
+@@ -1516,14 +1533,19 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+ if (!forced) {
+ mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
+ ent->idx);
+- free_ent(cmd, ent->idx);
+- free_cmd(ent);
++ cmd_ent_put(ent);
+ }
+ continue;
+ }
+
+- if (ent->callback)
+- cancel_delayed_work(&ent->cb_timeout_work);
++ if (ent->callback && cancel_delayed_work(&ent->cb_timeout_work))
++ cmd_ent_put(ent); /* timeout work was canceled */
++
++ if (!forced || /* Real FW completion */
++ pci_channel_offline(dev->pdev) || /* FW is inaccessible */
++ dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
++ cmd_ent_put(ent);
++
+ if (ent->page_queue)
+ sem = &cmd->pages_sem;
+ else
+@@ -1545,10 +1567,6 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+ ent->ret, deliv_status_to_str(ent->status), ent->status);
+ }
+
+- /* only real completion will free the entry slot */
+- if (!forced)
+- free_ent(cmd, ent->idx);
+-
+ if (ent->callback) {
+ ds = ent->ts2 - ent->ts1;
+ if (ent->op < MLX5_CMD_OP_MAX) {
+@@ -1576,10 +1594,13 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+ free_msg(dev, ent->in);
+
+ err = err ? err : ent->status;
+- if (!forced)
+- free_cmd(ent);
++ /* final consumer is done, release ent */
++ cmd_ent_put(ent);
+ callback(err, context);
+ } else {
++ /* release wait_func() so mlx5_cmd_invoke()
++ * can make the final ent_put()
++ */
+ complete(&ent->done);
+ }
+ up(sem);
+@@ -1589,8 +1610,11 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
+
+ void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
+ {
++ struct mlx5_cmd *cmd = &dev->cmd;
++ unsigned long bitmask;
+ unsigned long flags;
+ u64 vector;
++ int i;
+
+ /* wait for pending handlers to complete */
+ mlx5_eq_synchronize_cmd_irq(dev);
+@@ -1599,11 +1623,20 @@ void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
+ if (!vector)
+ goto no_trig;
+
++ bitmask = vector;
++ /* we must increment the allocated entries refcount before triggering the completions
++ * to guarantee pending commands will not get freed in the meanwhile.
++ * For that reason, it also has to be done inside the alloc_lock.
++ */
++ for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
++ cmd_ent_get(cmd->ent_arr[i]);
+ vector |= MLX5_TRIGGERED_CMD_COMP;
+ spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
+
+ mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
+ mlx5_cmd_comp_handler(dev, vector, true);
++ for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
++ cmd_ent_put(cmd->ent_arr[i]);
+ return;
+
+ no_trig:
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index 1e6ca716635a9..484cd8ba869c5 100644
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -764,6 +764,8 @@ struct mlx5_cmd_work_ent {
+ u64 ts2;
+ u16 op;
+ bool polling;
++ /* Track the max comp handlers */
++ refcount_t refcnt;
+ };
+
+ struct mlx5_pas {
+--
+2.25.1
+
--- /dev/null
+From d6e2bb53af7adf1d65646f6015381e7d4de4755c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Aug 2020 16:55:20 +0300
+Subject: net/mlx5: Fix a race when moving command interface to polling mode
+
+From: Eran Ben Elisha <eranbe@mellanox.com>
+
+[ Upstream commit 432161ea26d6d5e5c3f7306d9407d26ed1e1953e ]
+
+As part of driver unload, it destroys the commands EQ (via FW command).
+As the commands EQ is destroyed, FW will not generate EQEs for any command
+that driver sends afterwards. Driver should poll for later commands status.
+
+Driver commands mode metadata is updated before the commands EQ is
+actually destroyed. This can lead for double completion handle by the
+driver (polling and interrupt), if a command is executed and completed by
+FW after the mode was changed, but before the EQ was destroyed.
+
+Fix that by using the mlx5_cmd_allowed_opcode mechanism to guarantee
+that only DESTROY_EQ command can be executed during this time period.
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
+Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+index 31ef9f8420c87..1318d774b18f2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+@@ -656,8 +656,10 @@ static void destroy_async_eqs(struct mlx5_core_dev *dev)
+
+ cleanup_async_eq(dev, &table->pages_eq, "pages");
+ cleanup_async_eq(dev, &table->async_eq, "async");
++ mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_DESTROY_EQ);
+ mlx5_cmd_use_polling(dev);
+ cleanup_async_eq(dev, &table->cmd_eq, "cmd");
++ mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL);
+ mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 59366a5aabec18cf14e5a8e68e1bf0aca71ce4ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Aug 2020 21:37:31 +0300
+Subject: net/mlx5: Fix request_irqs error flow
+
+From: Maor Gottlieb <maorg@nvidia.com>
+
+[ Upstream commit 732ebfab7fe96b7ac9a3df3208f14752a4bb6db3 ]
+
+Fix error flow handling in request_irqs which try to free irq
+that we failed to request.
+It fixes the below trace.
+
+WARNING: CPU: 1 PID: 7587 at kernel/irq/manage.c:1684 free_irq+0x4d/0x60
+CPU: 1 PID: 7587 Comm: bash Tainted: G W OE 4.15.15-1.el7MELLANOXsmp-x86_64 #1
+Hardware name: Advantech SKY-6200/SKY-6200, BIOS F2.00 08/06/2020
+RIP: 0010:free_irq+0x4d/0x60
+RSP: 0018:ffffc9000ef47af0 EFLAGS: 00010282
+RAX: ffff88001476ae00 RBX: 0000000000000655 RCX: 0000000000000000
+RDX: ffff88001476ae00 RSI: ffffc9000ef47ab8 RDI: ffff8800398bb478
+RBP: ffff88001476a838 R08: ffff88001476ae00 R09: 000000000000156d
+R10: 0000000000000000 R11: 0000000000000004 R12: ffff88001476a838
+R13: 0000000000000006 R14: ffff88001476a888 R15: 00000000ffffffe4
+FS: 00007efeadd32740(0000) GS:ffff88047fc40000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007fc9cc010008 CR3: 00000001a2380004 CR4: 00000000007606e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+PKRU: 55555554
+Call Trace:
+ mlx5_irq_table_create+0x38d/0x400 [mlx5_core]
+ ? atomic_notifier_chain_register+0x50/0x60
+ mlx5_load_one+0x7ee/0x1130 [mlx5_core]
+ init_one+0x4c9/0x650 [mlx5_core]
+ pci_device_probe+0xb8/0x120
+ driver_probe_device+0x2a1/0x470
+ ? driver_allows_async_probing+0x30/0x30
+ bus_for_each_drv+0x54/0x80
+ __device_attach+0xa3/0x100
+ pci_bus_add_device+0x4a/0x90
+ pci_iov_add_virtfn+0x2dc/0x2f0
+ pci_enable_sriov+0x32e/0x420
+ mlx5_core_sriov_configure+0x61/0x1b0 [mlx5_core]
+ ? kstrtoll+0x22/0x70
+ num_vf_store+0x4b/0x70 [mlx5_core]
+ kernfs_fop_write+0x102/0x180
+ __vfs_write+0x26/0x140
+ ? rcu_all_qs+0x5/0x80
+ ? _cond_resched+0x15/0x30
+ ? __sb_start_write+0x41/0x80
+ vfs_write+0xad/0x1a0
+ SyS_write+0x42/0x90
+ do_syscall_64+0x60/0x110
+ entry_SYSCALL_64_after_hwframe+0x3d/0xa2
+
+Fixes: 24163189da48 ("net/mlx5: Separate IRQ request/free from EQ life cycle")
+Signed-off-by: Maor Gottlieb <maorg@nvidia.com>
+Reviewed-by: Eran Ben Elisha <eranbe@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+index 373981a659c7c..6fd9749203944 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+@@ -115,7 +115,7 @@ static int request_irqs(struct mlx5_core_dev *dev, int nvec)
+ return 0;
+
+ err_request_irq:
+- for (; i >= 0; i--) {
++ while (i--) {
+ struct mlx5_irq *irq = mlx5_irq_get(dev, i);
+ int irqn = pci_irq_vector(dev->pdev, i);
+
+--
+2.25.1
+
--- /dev/null
+From 37d9534d2aa73452a10cbd0864821ad6b89558b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jul 2020 10:25:52 +0300
+Subject: net/mlx5: poll cmd EQ in case of command timeout
+
+From: Eran Ben Elisha <eranbe@mellanox.com>
+
+[ Upstream commit 1d5558b1f0de81f54ddee05f3793acc5260d107f ]
+
+Once driver detects a command interface command timeout, it warns the
+user and returns timeout error to the caller. In such case, the entry of
+the command is not evacuated (because only real event interrupt is allowed
+to clear command interface entry). If the HW event interrupt
+of this entry will never arrive, this entry will be left unused forever.
+Command interface entries are limited and eventually we can end up without
+the ability to post a new command.
+
+In addition, if driver will not consume the EQE of the lost interrupt and
+rearm the EQ, no new interrupts will arrive for other commands.
+
+Add a resiliency mechanism for manually polling the command EQ in case of
+a command timeout. In case resiliency mechanism will find non-handled EQE,
+it will consume it, and the command interface will be fully functional
+again. Once the resiliency flow finished, wait another 5 seconds for the
+command interface to complete for this command entry.
+
+Define mlx5_cmd_eq_recover() to manage the cmd EQ polling resiliency flow.
+Add an async EQ spinlock to avoid races between resiliency flows and real
+interrupts that might run simultaneously.
+
+Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters")
+Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 53 ++++++++++++++++---
+ drivers/net/ethernet/mellanox/mlx5/core/eq.c | 40 +++++++++++++-
+ .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 2 +
+ 3 files changed, 86 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index c0055f5479ce0..37dae95e61d5f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -853,11 +853,21 @@ static void cb_timeout_handler(struct work_struct *work)
+ struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev,
+ cmd);
+
++ mlx5_cmd_eq_recover(dev);
++
++ /* Maybe got handled by eq recover ? */
++ if (!test_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state)) {
++ mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, recovered after timeout\n", ent->idx,
++ mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
++ goto out; /* phew, already handled */
++ }
++
+ ent->ret = -ETIMEDOUT;
+- mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
+- mlx5_command_str(msg_to_opcode(ent->in)),
+- msg_to_opcode(ent->in));
++ mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, timeout. Will cause a leak of a command resource\n",
++ ent->idx, mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
++
++out:
+ cmd_ent_put(ent); /* for the cmd_ent_get() took on schedule delayed work */
+ }
+
+@@ -997,6 +1007,35 @@ static const char *deliv_status_to_str(u8 status)
+ }
+ }
+
++enum {
++ MLX5_CMD_TIMEOUT_RECOVER_MSEC = 5 * 1000,
++};
++
++static void wait_func_handle_exec_timeout(struct mlx5_core_dev *dev,
++ struct mlx5_cmd_work_ent *ent)
++{
++ unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_RECOVER_MSEC);
++
++ mlx5_cmd_eq_recover(dev);
++
++ /* Re-wait on the ent->done after executing the recovery flow. If the
++ * recovery flow (or any other recovery flow running simultaneously)
++ * has recovered an EQE, it should cause the entry to be completed by
++ * the command interface.
++ */
++ if (wait_for_completion_timeout(&ent->done, timeout)) {
++ mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) recovered after timeout\n", ent->idx,
++ mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
++ return;
++ }
++
++ mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) No done completion\n", ent->idx,
++ mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
++
++ ent->ret = -ETIMEDOUT;
++ mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
++}
++
+ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
+ {
+ unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
+@@ -1008,12 +1047,10 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
+ ent->ret = -ECANCELED;
+ goto out_err;
+ }
+- if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
++ if (cmd->mode == CMD_MODE_POLLING || ent->polling)
+ wait_for_completion(&ent->done);
+- } else if (!wait_for_completion_timeout(&ent->done, timeout)) {
+- ent->ret = -ETIMEDOUT;
+- mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+- }
++ else if (!wait_for_completion_timeout(&ent->done, timeout))
++ wait_func_handle_exec_timeout(dev, ent);
+
+ out_err:
+ err = ent->ret;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+index 1318d774b18f2..22a19d391e179 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+@@ -189,6 +189,29 @@ u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq)
+ return count_eqe;
+ }
+
++static void mlx5_eq_async_int_lock(struct mlx5_eq_async *eq, unsigned long *flags)
++ __acquires(&eq->lock)
++{
++ if (in_irq())
++ spin_lock(&eq->lock);
++ else
++ spin_lock_irqsave(&eq->lock, *flags);
++}
++
++static void mlx5_eq_async_int_unlock(struct mlx5_eq_async *eq, unsigned long *flags)
++ __releases(&eq->lock)
++{
++ if (in_irq())
++ spin_unlock(&eq->lock);
++ else
++ spin_unlock_irqrestore(&eq->lock, *flags);
++}
++
++enum async_eq_nb_action {
++ ASYNC_EQ_IRQ_HANDLER = 0,
++ ASYNC_EQ_RECOVER = 1,
++};
++
+ static int mlx5_eq_async_int(struct notifier_block *nb,
+ unsigned long action, void *data)
+ {
+@@ -198,11 +221,14 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
+ struct mlx5_eq_table *eqt;
+ struct mlx5_core_dev *dev;
+ struct mlx5_eqe *eqe;
++ unsigned long flags;
+ int num_eqes = 0;
+
+ dev = eq->dev;
+ eqt = dev->priv.eq_table;
+
++ mlx5_eq_async_int_lock(eq_async, &flags);
++
+ eqe = next_eqe_sw(eq);
+ if (!eqe)
+ goto out;
+@@ -223,8 +249,19 @@ static int mlx5_eq_async_int(struct notifier_block *nb,
+
+ out:
+ eq_update_ci(eq, 1);
++ mlx5_eq_async_int_unlock(eq_async, &flags);
+
+- return 0;
++ return unlikely(action == ASYNC_EQ_RECOVER) ? num_eqes : 0;
++}
++
++void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev)
++{
++ struct mlx5_eq_async *eq = &dev->priv.eq_table->cmd_eq;
++ int eqes;
++
++ eqes = mlx5_eq_async_int(&eq->irq_nb, ASYNC_EQ_RECOVER, NULL);
++ if (eqes)
++ mlx5_core_warn(dev, "Recovered %d EQEs on cmd_eq\n", eqes);
+ }
+
+ static void init_eq_buf(struct mlx5_eq *eq)
+@@ -569,6 +606,7 @@ setup_async_eq(struct mlx5_core_dev *dev, struct mlx5_eq_async *eq,
+ int err;
+
+ eq->irq_nb.notifier_call = mlx5_eq_async_int;
++ spin_lock_init(&eq->lock);
+
+ err = create_async_eq(dev, &eq->core, param);
+ if (err) {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
+index 4aaca7400fb29..5c681e31983bc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
+@@ -37,6 +37,7 @@ struct mlx5_eq {
+ struct mlx5_eq_async {
+ struct mlx5_eq core;
+ struct notifier_block irq_nb;
++ spinlock_t lock; /* To avoid irq EQ handle races with resiliency flows */
+ };
+
+ struct mlx5_eq_comp {
+@@ -81,6 +82,7 @@ void mlx5_cq_tasklet_cb(unsigned long data);
+ struct cpumask *mlx5_eq_comp_cpumask(struct mlx5_core_dev *dev, int ix);
+
+ u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq);
++void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev);
+ void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev);
+ void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev);
+
+--
+2.25.1
+
--- /dev/null
+From 6c0b169fb7769fcc7f294a15c68b6663af98d236 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jul 2020 16:53:18 +0300
+Subject: net/mlx5e: Add resiliency in Striding RQ mode for packets larger than
+ MTU
+
+From: Aya Levin <ayal@mellanox.com>
+
+[ Upstream commit c3c9402373fe20e2d08c04f437ce4dcd252cffb2 ]
+
+Prior to this fix, in Striding RQ mode the driver was vulnerable when
+receiving packets in the range (stride size - headroom, stride size].
+Where stride size is calculated by mtu+headroom+tailroom aligned to the
+closest power of 2.
+Usually, this filtering is performed by the HW, except for a few cases:
+- Between 2 VFs over the same PF with different MTUs
+- On bluefield, when the host physical function sets a larger MTU than
+ the ARM has configured on its representor and uplink representor.
+
+When the HW filtering is not present, packets that are larger than MTU
+might be harmful for the RQ's integrity, in the following impacts:
+1) Overflow from one WQE to the next, causing a memory corruption that
+in most cases is unharmful: as the write happens to the headroom of next
+packet, which will be overwritten by build_skb(). In very rare cases,
+high stress/load, this is harmful. When the next WQE is not yet reposted
+and points to existing SKB head.
+2) Each oversize packet overflows to the headroom of the next WQE. On
+the last WQE of the WQ, where addresses wrap-around, the address of the
+remainder headroom does not belong to the next WQE, but it is out of the
+memory region range. This results in a HW CQE error that moves the RQ
+into an error state.
+
+Solution:
+Add a page buffer at the end of each WQE to absorb the leak. Actually
+the maximal overflow size is headroom but since all memory units must be
+of the same size, we use page size to comply with UMR WQEs. The increase
+in memory consumption is of a single page per RQ. Initialize the mkey
+with all MTTs pointing to a default page. When the channels are
+activated, UMR WQEs will redirect the RX WQEs to the actual memory from
+the RQ's pool, while the overflow MTTs remain mapped to the default page.
+
+Fixes: 73281b78a37a ("net/mlx5e: Derive Striding RQ size from MTU")
+Signed-off-by: Aya Levin <ayal@mellanox.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en.h | 8 ++-
+ .../net/ethernet/mellanox/mlx5/core/en_main.c | 55 +++++++++++++++++--
+ 2 files changed, 58 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+index 76b23ba7a4687..cb3857e136d62 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
+@@ -90,7 +90,12 @@ struct page_pool;
+ #define MLX5_MPWRQ_PAGES_PER_WQE BIT(MLX5_MPWRQ_WQE_PAGE_ORDER)
+
+ #define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2)
+-#define MLX5E_REQUIRED_WQE_MTTS (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
++/* Add another page to MLX5E_REQUIRED_WQE_MTTS as a buffer between
++ * WQEs, This page will absorb write overflow by the hardware, when
++ * receiving packets larger than MTU. These oversize packets are
++ * dropped by the driver at a later stage.
++ */
++#define MLX5E_REQUIRED_WQE_MTTS (ALIGN(MLX5_MPWRQ_PAGES_PER_WQE + 1, 8))
+ #define MLX5E_LOG_ALIGNED_MPWQE_PPW (ilog2(MLX5E_REQUIRED_WQE_MTTS))
+ #define MLX5E_REQUIRED_MTTS(wqes) (wqes * MLX5E_REQUIRED_WQE_MTTS)
+ #define MLX5E_MAX_RQ_NUM_MTTS \
+@@ -621,6 +626,7 @@ struct mlx5e_rq {
+ u32 rqn;
+ struct mlx5_core_dev *mdev;
+ struct mlx5_core_mkey umr_mkey;
++ struct mlx5e_dma_info wqe_overflow;
+
+ /* XDP read-mostly */
+ struct xdp_rxq_info xdp_rxq;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index cccf65fc116ee..b23ad0b6761c4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -258,12 +258,17 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
+
+ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
+ u64 npages, u8 page_shift,
+- struct mlx5_core_mkey *umr_mkey)
++ struct mlx5_core_mkey *umr_mkey,
++ dma_addr_t filler_addr)
+ {
+- int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
++ struct mlx5_mtt *mtt;
++ int inlen;
+ void *mkc;
+ u32 *in;
+ int err;
++ int i;
++
++ inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + sizeof(*mtt) * npages;
+
+ in = kvzalloc(inlen, GFP_KERNEL);
+ if (!in)
+@@ -283,6 +288,18 @@ static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
+ MLX5_SET(mkc, mkc, translations_octword_size,
+ MLX5_MTT_OCTW(npages));
+ MLX5_SET(mkc, mkc, log_page_size, page_shift);
++ MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
++ MLX5_MTT_OCTW(npages));
++
++ /* Initialize the mkey with all MTTs pointing to a default
++ * page (filler_addr). When the channels are activated, UMR
++ * WQEs will redirect the RX WQEs to the actual memory from
++ * the RQ's pool, while the gaps (wqe_overflow) remain mapped
++ * to the default page.
++ */
++ mtt = MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
++ for (i = 0 ; i < npages ; i++)
++ mtt[i].ptag = cpu_to_be64(filler_addr);
+
+ err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
+
+@@ -294,7 +311,8 @@ static int mlx5e_create_rq_umr_mkey(struct mlx5_core_dev *mdev, struct mlx5e_rq
+ {
+ u64 num_mtts = MLX5E_REQUIRED_MTTS(mlx5_wq_ll_get_size(&rq->mpwqe.wq));
+
+- return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
++ return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey,
++ rq->wqe_overflow.addr);
+ }
+
+ static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
+@@ -362,6 +380,28 @@ static void mlx5e_rq_err_cqe_work(struct work_struct *recover_work)
+ mlx5e_reporter_rq_cqe_err(rq);
+ }
+
++static int mlx5e_alloc_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
++{
++ rq->wqe_overflow.page = alloc_page(GFP_KERNEL);
++ if (!rq->wqe_overflow.page)
++ return -ENOMEM;
++
++ rq->wqe_overflow.addr = dma_map_page(rq->pdev, rq->wqe_overflow.page, 0,
++ PAGE_SIZE, rq->buff.map_dir);
++ if (dma_mapping_error(rq->pdev, rq->wqe_overflow.addr)) {
++ __free_page(rq->wqe_overflow.page);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++static void mlx5e_free_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
++{
++ dma_unmap_page(rq->pdev, rq->wqe_overflow.addr, PAGE_SIZE,
++ rq->buff.map_dir);
++ __free_page(rq->wqe_overflow.page);
++}
++
+ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
+ struct mlx5e_params *params,
+ struct mlx5e_xsk_param *xsk,
+@@ -421,6 +461,10 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
+ if (err)
+ goto err_rq_wq_destroy;
+
++ err = mlx5e_alloc_mpwqe_rq_drop_page(rq);
++ if (err)
++ goto err_rq_wq_destroy;
++
+ rq->mpwqe.wq.db = &rq->mpwqe.wq.db[MLX5_RCV_DBR];
+
+ wq_sz = mlx5_wq_ll_get_size(&rq->mpwqe.wq);
+@@ -459,7 +503,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
+
+ err = mlx5e_create_rq_umr_mkey(mdev, rq);
+ if (err)
+- goto err_rq_wq_destroy;
++ goto err_rq_drop_page;
+ rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
+
+ err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+@@ -598,6 +642,8 @@ err_free:
+ case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
+ kvfree(rq->mpwqe.info);
+ mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
++err_rq_drop_page:
++ mlx5e_free_mpwqe_rq_drop_page(rq);
+ break;
+ default: /* MLX5_WQ_TYPE_CYCLIC */
+ kvfree(rq->wqe.frags);
+@@ -631,6 +677,7 @@ static void mlx5e_free_rq(struct mlx5e_rq *rq)
+ case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
+ kvfree(rq->mpwqe.info);
+ mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
++ mlx5e_free_mpwqe_rq_drop_page(rq);
+ break;
+ default: /* MLX5_WQ_TYPE_CYCLIC */
+ kvfree(rq->wqe.frags);
+--
+2.25.1
+
--- /dev/null
+From 828f5136942b591a56332784c07f146a5cf2e9ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Sep 2020 19:59:08 +0300
+Subject: net/mlx5e: Fix race condition on nhe->n pointer in neigh update
+
+From: Vlad Buslov <vladbu@nvidia.com>
+
+[ Upstream commit 1253935ad801485270194d5651acab04abc97b36 ]
+
+Current neigh update event handler implementation takes reference to
+neighbour structure, assigns it to nhe->n, tries to schedule workqueue task
+and releases the reference if task was already enqueued. This results
+potentially overwriting existing nhe->n pointer with another neighbour
+instance, which causes double release of the instance (once in neigh update
+handler that failed to enqueue to workqueue and another one in neigh update
+workqueue task that processes updated nhe->n pointer instead of original
+one):
+
+[ 3376.512806] ------------[ cut here ]------------
+[ 3376.513534] refcount_t: underflow; use-after-free.
+[ 3376.521213] Modules linked in: act_skbedit act_mirred act_tunnel_key vxlan ip6_udp_tunnel udp_tunnel nfnetlink act_gact cls_flower sch_ingress openvswitch nsh nf_conncount nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 mlx5_ib mlx5_core mlxfw pci_hyperv_intf ptp pps_core nfsv3 nfs_acl rpcsec_gss_krb5 auth_rpcgss nfsv4 dns_resolver nfs lockd
+ grace fscache ib_isert iscsi_target_mod ib_srpt target_core_mod ib_srp rpcrdma rdma_ucm ib_umad ib_ipoib ib_iser rdma_cm ib_cm iw_cm rfkill ib_uverbs ib_core sunrpc kvm_intel kvm iTCO_wdt iTCO_vendor_support virtio_net irqbypass net_failover crc32_pclmul lpc_ich i2c_i801 failover pcspkr i2c_smbus mfd_core ghash_clmulni_intel sch_fq_codel drm i2c
+_core ip_tables crc32c_intel serio_raw [last unloaded: mlxfw]
+[ 3376.529468] CPU: 8 PID: 22756 Comm: kworker/u20:5 Not tainted 5.9.0-rc5+ #6
+[ 3376.530399] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
+[ 3376.531975] Workqueue: mlx5e mlx5e_rep_neigh_update [mlx5_core]
+[ 3376.532820] RIP: 0010:refcount_warn_saturate+0xd8/0xe0
+[ 3376.533589] Code: ff 48 c7 c7 e0 b8 27 82 c6 05 0b b6 09 01 01 e8 94 93 c1 ff 0f 0b c3 48 c7 c7 88 b8 27 82 c6 05 f7 b5 09 01 01 e8 7e 93 c1 ff <0f> 0b c3 0f 1f 44 00 00 8b 07 3d 00 00 00 c0 74 12 83 f8 01 74 13
+[ 3376.536017] RSP: 0018:ffffc90002a97e30 EFLAGS: 00010286
+[ 3376.536793] RAX: 0000000000000000 RBX: ffff8882de30d648 RCX: 0000000000000000
+[ 3376.537718] RDX: ffff8882f5c28f20 RSI: ffff8882f5c18e40 RDI: ffff8882f5c18e40
+[ 3376.538654] RBP: ffff8882cdf56c00 R08: 000000000000c580 R09: 0000000000001a4d
+[ 3376.539582] R10: 0000000000000731 R11: ffffc90002a97ccd R12: 0000000000000000
+[ 3376.540519] R13: ffff8882de30d600 R14: ffff8882de30d640 R15: ffff88821e000900
+[ 3376.541444] FS: 0000000000000000(0000) GS:ffff8882f5c00000(0000) knlGS:0000000000000000
+[ 3376.542732] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 3376.543545] CR2: 0000556e5504b248 CR3: 00000002c6f10005 CR4: 0000000000770ee0
+[ 3376.544483] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 3376.545419] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 3376.546344] PKRU: 55555554
+[ 3376.546911] Call Trace:
+[ 3376.547479] mlx5e_rep_neigh_update.cold+0x33/0xe2 [mlx5_core]
+[ 3376.548299] process_one_work+0x1d8/0x390
+[ 3376.548977] worker_thread+0x4d/0x3e0
+[ 3376.549631] ? rescuer_thread+0x3e0/0x3e0
+[ 3376.550295] kthread+0x118/0x130
+[ 3376.550914] ? kthread_create_worker_on_cpu+0x70/0x70
+[ 3376.551675] ret_from_fork+0x1f/0x30
+[ 3376.552312] ---[ end trace d84e8f46d2a77eec ]---
+
+Fix the bug by moving work_struct to dedicated dynamically-allocated
+structure. This enabled every event handler to work on its own private
+neighbour pointer and removes the need for handling the case when task is
+already enqueued.
+
+Fixes: 232c001398ae ("net/mlx5e: Add support to neighbour update flow")
+Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
+Reviewed-by: Roi Dayan <roid@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlx5/core/en/rep/neigh.c | 81 ++++++++++++-------
+ .../net/ethernet/mellanox/mlx5/core/en_rep.h | 6 --
+ 2 files changed, 50 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
+index c3d167fa944c7..6a9d783d129b2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rep/neigh.c
+@@ -109,11 +109,25 @@ static void mlx5e_rep_neigh_stats_work(struct work_struct *work)
+ rtnl_unlock();
+ }
+
++struct neigh_update_work {
++ struct work_struct work;
++ struct neighbour *n;
++ struct mlx5e_neigh_hash_entry *nhe;
++};
++
++static void mlx5e_release_neigh_update_work(struct neigh_update_work *update_work)
++{
++ neigh_release(update_work->n);
++ mlx5e_rep_neigh_entry_release(update_work->nhe);
++ kfree(update_work);
++}
++
+ static void mlx5e_rep_neigh_update(struct work_struct *work)
+ {
+- struct mlx5e_neigh_hash_entry *nhe =
+- container_of(work, struct mlx5e_neigh_hash_entry, neigh_update_work);
+- struct neighbour *n = nhe->n;
++ struct neigh_update_work *update_work = container_of(work, struct neigh_update_work,
++ work);
++ struct mlx5e_neigh_hash_entry *nhe = update_work->nhe;
++ struct neighbour *n = update_work->n;
+ struct mlx5e_encap_entry *e;
+ unsigned char ha[ETH_ALEN];
+ struct mlx5e_priv *priv;
+@@ -145,30 +159,42 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)
+ mlx5e_rep_update_flows(priv, e, neigh_connected, ha);
+ mlx5e_encap_put(priv, e);
+ }
+- mlx5e_rep_neigh_entry_release(nhe);
+ rtnl_unlock();
+- neigh_release(n);
++ mlx5e_release_neigh_update_work(update_work);
+ }
+
+-static void mlx5e_rep_queue_neigh_update_work(struct mlx5e_priv *priv,
+- struct mlx5e_neigh_hash_entry *nhe,
+- struct neighbour *n)
++static struct neigh_update_work *mlx5e_alloc_neigh_update_work(struct mlx5e_priv *priv,
++ struct neighbour *n)
+ {
+- /* Take a reference to ensure the neighbour and mlx5 encap
+- * entry won't be destructed until we drop the reference in
+- * delayed work.
+- */
+- neigh_hold(n);
++ struct neigh_update_work *update_work;
++ struct mlx5e_neigh_hash_entry *nhe;
++ struct mlx5e_neigh m_neigh = {};
+
+- /* This assignment is valid as long as the the neigh reference
+- * is taken
+- */
+- nhe->n = n;
++ update_work = kzalloc(sizeof(*update_work), GFP_ATOMIC);
++ if (WARN_ON(!update_work))
++ return NULL;
+
+- if (!queue_work(priv->wq, &nhe->neigh_update_work)) {
+- mlx5e_rep_neigh_entry_release(nhe);
+- neigh_release(n);
++ m_neigh.dev = n->dev;
++ m_neigh.family = n->ops->family;
++ memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
++
++ /* Obtain reference to nhe as last step in order not to release it in
++ * atomic context.
++ */
++ rcu_read_lock();
++ nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh);
++ rcu_read_unlock();
++ if (!nhe) {
++ kfree(update_work);
++ return NULL;
+ }
++
++ INIT_WORK(&update_work->work, mlx5e_rep_neigh_update);
++ neigh_hold(n);
++ update_work->n = n;
++ update_work->nhe = nhe;
++
++ return update_work;
+ }
+
+ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+@@ -180,7 +206,7 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ struct net_device *netdev = rpriv->netdev;
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_neigh_hash_entry *nhe = NULL;
+- struct mlx5e_neigh m_neigh = {};
++ struct neigh_update_work *update_work;
+ struct neigh_parms *p;
+ struct neighbour *n;
+ bool found = false;
+@@ -195,17 +221,11 @@ static int mlx5e_rep_netevent_event(struct notifier_block *nb,
+ #endif
+ return NOTIFY_DONE;
+
+- m_neigh.dev = n->dev;
+- m_neigh.family = n->ops->family;
+- memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
+-
+- rcu_read_lock();
+- nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh);
+- rcu_read_unlock();
+- if (!nhe)
++ update_work = mlx5e_alloc_neigh_update_work(priv, n);
++ if (!update_work)
+ return NOTIFY_DONE;
+
+- mlx5e_rep_queue_neigh_update_work(priv, nhe, n);
++ queue_work(priv->wq, &update_work->work);
+ break;
+
+ case NETEVENT_DELAY_PROBE_TIME_UPDATE:
+@@ -351,7 +371,6 @@ int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv,
+
+ (*nhe)->priv = priv;
+ memcpy(&(*nhe)->m_neigh, &e->m_neigh, sizeof(e->m_neigh));
+- INIT_WORK(&(*nhe)->neigh_update_work, mlx5e_rep_neigh_update);
+ spin_lock_init(&(*nhe)->encap_list_lock);
+ INIT_LIST_HEAD(&(*nhe)->encap_list);
+ refcount_set(&(*nhe)->refcnt, 1);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+index 1d56698014843..fcaabafb2e56d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
+@@ -133,12 +133,6 @@ struct mlx5e_neigh_hash_entry {
+ /* encap list sharing the same neigh */
+ struct list_head encap_list;
+
+- /* valid only when the neigh reference is taken during
+- * neigh_update_work workqueue callback.
+- */
+- struct neighbour *n;
+- struct work_struct neigh_update_work;
+-
+ /* neigh hash entry can be deleted only when the refcount is zero.
+ * refcount is needed to avoid neigh hash entry removal by TC, while
+ * it's used by the neigh notification call.
+--
+2.25.1
+
--- /dev/null
+From bfe3da92d7e5343a8245298aab8ed064f39674ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Aug 2020 10:44:36 +0300
+Subject: net/mlx5e: Fix return status when setting unsupported FEC mode
+
+From: Aya Levin <ayal@mellanox.com>
+
+[ Upstream commit 2608a2f831c47dfdf18885a7289be5af97182b05 ]
+
+Verify the configured FEC mode is supported by at least a single link
+mode before applying the command. Otherwise fail the command and return
+"Operation not supported".
+Prior to this patch, the command was successful, yet it falsely set all
+link modes to FEC auto mode - like configuring FEC mode to auto. Auto
+mode is the default configuration if a link mode doesn't support the
+configured FEC mode.
+
+Fixes: b5ede32d3329 ("net/mlx5e: Add support for FEC modes based on 50G per lane links")
+Signed-off-by: Aya Levin <ayal@mellanox.com>
+Reviewed-by: Eran Ben Elisha <eranbe@nvidia.com>
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/port.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+index 98e909bf3c1ec..3e32264cf6131 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+@@ -566,6 +566,9 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
+ if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
+ return -EOPNOTSUPP;
+
++ if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
++ return -EOPNOTSUPP;
++
+ MLX5_SET(pplm_reg, in, local_port, 1);
+ err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
+ if (err)
+--
+2.25.1
+
--- /dev/null
+From 439b5b803dd808af8556349bc4ff40a82326e61c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 13 Sep 2020 17:57:23 +0300
+Subject: net/mlx5e: Fix VLAN cleanup flow
+
+From: Aya Levin <ayal@nvidia.com>
+
+[ Upstream commit 8c7353b6f716436ad0bfda2b5c5524ab2dde5894 ]
+
+Prior to this patch unloading an interface in promiscuous mode with RX
+VLAN filtering feature turned off - resulted in a warning. This is due
+to a wrong condition in the VLAN rules cleanup flow, which left the
+any-vid rules in the VLAN steering table. These rules prevented
+destroying the flow group and the flow table.
+
+The any-vid rules are removed in 2 flows, but none of them remove it in
+case both promiscuous is set and VLAN filtering is off. Fix the issue by
+changing the condition of the VLAN table cleanup flow to clean also in
+case of promiscuous mode.
+
+mlx5_core 0000:00:08.0: mlx5_destroy_flow_group:2123:(pid 28729): Flow group 20 wasn't destroyed, refcount > 1
+mlx5_core 0000:00:08.0: mlx5_destroy_flow_group:2123:(pid 28729): Flow group 19 wasn't destroyed, refcount > 1
+mlx5_core 0000:00:08.0: mlx5_destroy_flow_table:2112:(pid 28729): Flow table 262149 wasn't destroyed, refcount > 1
+...
+...
+------------[ cut here ]------------
+FW pages counter is 11560 after reclaiming all pages
+WARNING: CPU: 1 PID: 28729 at
+drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c:660
+mlx5_reclaim_startup_pages+0x178/0x230 [mlx5_core]
+Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
+rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014
+Call Trace:
+ mlx5_function_teardown+0x2f/0x90 [mlx5_core]
+ mlx5_unload_one+0x71/0x110 [mlx5_core]
+ remove_one+0x44/0x80 [mlx5_core]
+ pci_device_remove+0x3e/0xc0
+ device_release_driver_internal+0xfb/0x1c0
+ device_release_driver+0x12/0x20
+ pci_stop_bus_device+0x68/0x90
+ pci_stop_and_remove_bus_device+0x12/0x20
+ hv_eject_device_work+0x6f/0x170 [pci_hyperv]
+ ? __schedule+0x349/0x790
+ process_one_work+0x206/0x400
+ worker_thread+0x34/0x3f0
+ ? process_one_work+0x400/0x400
+ kthread+0x126/0x140
+ ? kthread_park+0x90/0x90
+ ret_from_fork+0x22/0x30
+ ---[ end trace 6283bde8d26170dc ]---
+
+Fixes: 9df30601c843 ("net/mlx5e: Restore vlan filter after seamless reset")
+Signed-off-by: Aya Levin <ayal@nvidia.com>
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+index 73d3dc07331f1..c5be0cdfaf0fa 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+@@ -415,8 +415,12 @@ static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
+ for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
+ mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
+
+- if (priv->fs.vlan.cvlan_filter_disabled &&
+- !(priv->netdev->flags & IFF_PROMISC))
++ WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state)));
++
++ /* must be called after DESTROY bit is set and
++ * set_rx_mode is called and flushed
++ */
++ if (priv->fs.vlan.cvlan_filter_disabled)
+ mlx5e_del_any_vid_rules(priv);
+ }
+
+--
+2.25.1
+
--- /dev/null
+From a73007e120ca239b898ce7c04424d07e4306d248 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 13 Sep 2020 18:05:40 +0300
+Subject: net/mlx5e: Fix VLAN create flow
+
+From: Aya Levin <ayal@nvidia.com>
+
+[ Upstream commit d4a16052bccdd695982f89d815ca075825115821 ]
+
+When interface is attached while in promiscuous mode and with VLAN
+filtering turned off, both configurations are not respected and VLAN
+filtering is performed.
+There are 2 flows which add the any-vid rules during interface attach:
+VLAN creation table and set rx mode. Each is relaying on the other to
+add any-vid rules, eventually non of them does.
+
+Fix this by adding any-vid rules on VLAN creation regardless of
+promiscuous mode.
+
+Fixes: 9df30601c843 ("net/mlx5e: Restore vlan filter after seamless reset")
+Signed-off-by: Aya Levin <ayal@nvidia.com>
+Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_fs.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+index c5be0cdfaf0fa..713dc210f710c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+@@ -217,6 +217,9 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_priv *priv,
+ break;
+ }
+
++ if (WARN_ONCE(*rule_p, "VLAN rule already exists type %d", rule_type))
++ return 0;
++
+ *rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
+
+ if (IS_ERR(*rule_p)) {
+@@ -397,8 +400,7 @@ static void mlx5e_add_vlan_rules(struct mlx5e_priv *priv)
+ for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
+ mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
+
+- if (priv->fs.vlan.cvlan_filter_disabled &&
+- !(priv->netdev->flags & IFF_PROMISC))
++ if (priv->fs.vlan.cvlan_filter_disabled)
+ mlx5e_add_any_vid_rules(priv);
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 756bf7d6fe164f45068d2d64f1fb44668571a305 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Oct 2020 12:09:11 +0300
+Subject: net: mscc: ocelot: divide watermark value by 60 when writing to
+ SYS_ATOP
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 601e984f23abcaa7cf3eb078c13de4db3cf6a4f0 ]
+
+Tail dropping is enabled for a port when:
+
+1. A source port consumes more packet buffers than the watermark encoded
+ in SYS:PORT:ATOP_CFG.ATOP.
+
+AND
+
+2. Total memory use exceeds the consumption watermark encoded in
+ SYS:PAUSE_CFG:ATOP_TOT_CFG.
+
+The unit of these watermarks is a 60 byte memory cell. That unit is
+programmed properly into ATOP_TOT_CFG, but not into ATOP. Actually when
+written into ATOP, it would get truncated and wrap around.
+
+Fixes: a556c76adc05 ("net: mscc: Add initial Ocelot switch support")
+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/ethernet/mscc/ocelot.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
+index 1438839e3f6ea..61bbb7a090042 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -2001,7 +2001,7 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
+ int pause_start, pause_stop;
+- int atop_wm;
++ int atop, atop_tot;
+
+ if (port == ocelot->npi) {
+ maxlen += OCELOT_TAG_LEN;
+@@ -2022,12 +2022,12 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
+ ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_STOP(pause_stop),
+ SYS_PAUSE_CFG_PAUSE_STOP_M, SYS_PAUSE_CFG, port);
+
+- /* Tail dropping watermark */
+- atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
++ /* Tail dropping watermarks */
++ atop_tot = (ocelot->shared_queue_sz - 9 * maxlen) /
+ OCELOT_BUFFER_CELL_SZ;
+- ocelot_write_rix(ocelot, ocelot->ops->wm_enc(9 * maxlen),
+- SYS_ATOP, port);
+- ocelot_write(ocelot, ocelot->ops->wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
++ atop = (9 * maxlen) / OCELOT_BUFFER_CELL_SZ;
++ ocelot_write_rix(ocelot, ocelot->ops->wm_enc(atop), SYS_ATOP, port);
++ ocelot_write(ocelot, ocelot->ops->wm_enc(atop_tot), SYS_ATOP_TOT_CFG);
+ }
+ EXPORT_SYMBOL(ocelot_port_set_maxlen);
+
+--
+2.25.1
+
--- /dev/null
+From 16a55873c5b6ded5eb896fe3f635f63bc233150b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2020 19:57:08 +0300
+Subject: net: mscc: ocelot: extend watermark encoding function
+
+From: Maxim Kochetkov <fido_max@inbox.ru>
+
+[ Upstream commit aa92d836d5c40a7e21e563a272ad177f1bfd44dd ]
+
+The ocelot_wm_encode function deals with setting thresholds for pause
+frame start and stop. In Ocelot and Felix the register layout is the
+same, but for Seville, it isn't. The easiest way to accommodate Seville
+hardware configuration is to introduce a function pointer for setting
+this up.
+
+Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
+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/ocelot/felix_vsc9959.c | 13 +++++++++++++
+ drivers/net/ethernet/mscc/ocelot.c | 16 ++--------------
+ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 13 +++++++++++++
+ include/soc/mscc/ocelot.h | 1 +
+ 4 files changed, 29 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
+index a83ecd1c5d6c2..259a612da0030 100644
+--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
++++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
+@@ -1105,8 +1105,21 @@ static int vsc9959_prevalidate_phy_mode(struct ocelot *ocelot, int port,
+ }
+ }
+
++/* Watermark encode
++ * Bit 8: Unit; 0:1, 1:16
++ * Bit 7-0: Value to be multiplied with unit
++ */
++static u16 vsc9959_wm_enc(u16 value)
++{
++ if (value >= BIT(8))
++ return BIT(8) | (value / 16);
++
++ return value;
++}
++
+ static const struct ocelot_ops vsc9959_ops = {
+ .reset = vsc9959_reset,
++ .wm_enc = vsc9959_wm_enc,
+ };
+
+ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
+diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
+index 6e68713c0ac6b..1438839e3f6ea 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -396,18 +396,6 @@ static void ocelot_vlan_init(struct ocelot *ocelot)
+ }
+ }
+
+-/* Watermark encode
+- * Bit 8: Unit; 0:1, 1:16
+- * Bit 7-0: Value to be multiplied with unit
+- */
+-static u16 ocelot_wm_enc(u16 value)
+-{
+- if (value >= BIT(8))
+- return BIT(8) | (value / 16);
+-
+- return value;
+-}
+-
+ void ocelot_adjust_link(struct ocelot *ocelot, int port,
+ struct phy_device *phydev)
+ {
+@@ -2037,9 +2025,9 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
+ /* Tail dropping watermark */
+ atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
+ OCELOT_BUFFER_CELL_SZ;
+- ocelot_write_rix(ocelot, ocelot_wm_enc(9 * maxlen),
++ ocelot_write_rix(ocelot, ocelot->ops->wm_enc(9 * maxlen),
+ SYS_ATOP, port);
+- ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
++ ocelot_write(ocelot, ocelot->ops->wm_enc(atop_wm), SYS_ATOP_TOT_CFG);
+ }
+ EXPORT_SYMBOL(ocelot_port_set_maxlen);
+
+diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+index 4a15d2ff8b706..66b58b242f778 100644
+--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
++++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+@@ -240,8 +240,21 @@ static int ocelot_reset(struct ocelot *ocelot)
+ return 0;
+ }
+
++/* Watermark encode
++ * Bit 8: Unit; 0:1, 1:16
++ * Bit 7-0: Value to be multiplied with unit
++ */
++static u16 ocelot_wm_enc(u16 value)
++{
++ if (value >= BIT(8))
++ return BIT(8) | (value / 16);
++
++ return value;
++}
++
+ static const struct ocelot_ops ocelot_ops = {
+ .reset = ocelot_reset,
++ .wm_enc = ocelot_wm_enc,
+ };
+
+ static const struct vcap_field vsc7514_vcap_is2_keys[] = {
+diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
+index 4953e9994df34..8e174a24c5757 100644
+--- a/include/soc/mscc/ocelot.h
++++ b/include/soc/mscc/ocelot.h
+@@ -468,6 +468,7 @@ struct ocelot;
+
+ struct ocelot_ops {
+ int (*reset)(struct ocelot *ocelot);
++ u16 (*wm_enc)(u16 value);
+ };
+
+ struct ocelot_acl_block {
+--
+2.25.1
+
--- /dev/null
+From 6d873f8c1ab3be90a82dd1fe0b82df152ff566ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Jun 2020 18:43:39 +0300
+Subject: net: mscc: ocelot: rename ocelot_board.c to ocelot_vsc7514.c
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 589aa6e7c9de322d47eb33a5cee8cc38838319e6 ]
+
+To follow the model of felix and seville where we have one
+platform-specific file, rename this file to the actual SoC it serves.
+
+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/ethernet/mscc/Makefile | 2 +-
+ drivers/net/ethernet/mscc/{ocelot_board.c => ocelot_vsc7514.c} | 0
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+ rename drivers/net/ethernet/mscc/{ocelot_board.c => ocelot_vsc7514.c} (100%)
+
+diff --git a/drivers/net/ethernet/mscc/Makefile b/drivers/net/ethernet/mscc/Makefile
+index 91b33b55054e1..ad97a5cca6f99 100644
+--- a/drivers/net/ethernet/mscc/Makefile
++++ b/drivers/net/ethernet/mscc/Makefile
+@@ -2,4 +2,4 @@
+ obj-$(CONFIG_MSCC_OCELOT_SWITCH) += mscc_ocelot_common.o
+ mscc_ocelot_common-y := ocelot.o ocelot_io.o
+ mscc_ocelot_common-y += ocelot_regs.o ocelot_tc.o ocelot_police.o ocelot_ace.o ocelot_flower.o ocelot_ptp.o
+-obj-$(CONFIG_MSCC_OCELOT_SWITCH_OCELOT) += ocelot_board.o
++obj-$(CONFIG_MSCC_OCELOT_SWITCH_OCELOT) += ocelot_vsc7514.o
+diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+similarity index 100%
+rename from drivers/net/ethernet/mscc/ocelot_board.c
+rename to drivers/net/ethernet/mscc/ocelot_vsc7514.c
+--
+2.25.1
+
--- /dev/null
+From d7691ec043d0d59ccac605702eb4659d5387be0e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jul 2020 19:57:05 +0300
+Subject: net: mscc: ocelot: split writes to pause frame enable bit and to
+ thresholds
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit e8e6e73db14273464b374d49ca7242c0994945f3 ]
+
+We don't want ocelot_port_set_maxlen to enable pause frame TX, just to
+adjust the pause thresholds.
+
+Move the unconditional enabling of pause TX to ocelot_init_port. There
+is no good place to put such setting because it shouldn't be
+unconditional. But at the moment it is, we're not changing that.
+
+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/ethernet/mscc/ocelot.c | 19 ++++++++++++-------
+ 1 file changed, 12 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
+index d0b79cca51840..6e68713c0ac6b 100644
+--- a/drivers/net/ethernet/mscc/ocelot.c
++++ b/drivers/net/ethernet/mscc/ocelot.c
+@@ -2012,6 +2012,7 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
+ {
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
++ int pause_start, pause_stop;
+ int atop_wm;
+
+ if (port == ocelot->npi) {
+@@ -2025,13 +2026,13 @@ void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
+
+ ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
+
+- /* Set Pause WM hysteresis
+- * 152 = 6 * maxlen / OCELOT_BUFFER_CELL_SZ
+- * 101 = 4 * maxlen / OCELOT_BUFFER_CELL_SZ
+- */
+- ocelot_write_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA |
+- SYS_PAUSE_CFG_PAUSE_STOP(101) |
+- SYS_PAUSE_CFG_PAUSE_START(152), SYS_PAUSE_CFG, port);
++ /* Set Pause watermark hysteresis */
++ pause_start = 6 * maxlen / OCELOT_BUFFER_CELL_SZ;
++ pause_stop = 4 * maxlen / OCELOT_BUFFER_CELL_SZ;
++ ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_START(pause_start),
++ SYS_PAUSE_CFG_PAUSE_START_M, SYS_PAUSE_CFG, port);
++ ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_STOP(pause_stop),
++ SYS_PAUSE_CFG_PAUSE_STOP_M, SYS_PAUSE_CFG, port);
+
+ /* Tail dropping watermark */
+ atop_wm = (ocelot->shared_queue_sz - 9 * maxlen) /
+@@ -2094,6 +2095,10 @@ void ocelot_init_port(struct ocelot *ocelot, int port)
+ ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_HIGH_CFG);
+ ocelot_port_writel(ocelot_port, 0, DEV_MAC_FC_MAC_LOW_CFG);
+
++ /* Enable transmission of pause frames */
++ ocelot_rmw_rix(ocelot, SYS_PAUSE_CFG_PAUSE_ENA, SYS_PAUSE_CFG_PAUSE_ENA,
++ SYS_PAUSE_CFG, port);
++
+ /* Drop frames with multicast source address */
+ ocelot_rmw_gix(ocelot, ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
+ ANA_PORT_DROP_CFG_DROP_MC_SMAC_ENA,
+--
+2.25.1
+
--- /dev/null
+From 7d74114c69e99679c6db2696afbf9cf1584879ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 3 Oct 2020 11:51:21 -0700
+Subject: net: mvneta: fix double free of txq->buf
+
+From: Tom Rix <trix@redhat.com>
+
+[ Upstream commit f4544e5361da5050ff5c0330ceea095cb5dbdd72 ]
+
+clang static analysis reports this problem:
+
+drivers/net/ethernet/marvell/mvneta.c:3465:2: warning:
+ Attempt to free released memory
+ kfree(txq->buf);
+ ^~~~~~~~~~~~~~~
+
+When mvneta_txq_sw_init() fails to alloc txq->tso_hdrs,
+it frees without poisoning txq->buf. The error is caught
+in the mvneta_setup_txqs() caller which handles the error
+by cleaning up all of the txqs with a call to
+mvneta_txq_sw_deinit which also frees txq->buf.
+
+Since mvneta_txq_sw_deinit is a general cleaner, all of the
+partial cleaning in mvneta_txq_sw_deinit()'s error handling
+is not needed.
+
+Fixes: 2adb719d74f6 ("net: mvneta: Implement software TSO")
+Signed-off-by: Tom Rix <trix@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
+index 7d5d9d34f4e47..69a234e83b8b7 100644
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -3372,24 +3372,15 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp,
+ txq->last_desc = txq->size - 1;
+
+ txq->buf = kmalloc_array(txq->size, sizeof(*txq->buf), GFP_KERNEL);
+- if (!txq->buf) {
+- dma_free_coherent(pp->dev->dev.parent,
+- txq->size * MVNETA_DESC_ALIGNED_SIZE,
+- txq->descs, txq->descs_phys);
++ if (!txq->buf)
+ return -ENOMEM;
+- }
+
+ /* Allocate DMA buffers for TSO MAC/IP/TCP headers */
+ txq->tso_hdrs = dma_alloc_coherent(pp->dev->dev.parent,
+ txq->size * TSO_HEADER_SIZE,
+ &txq->tso_hdrs_phys, GFP_KERNEL);
+- if (!txq->tso_hdrs) {
+- kfree(txq->buf);
+- dma_free_coherent(pp->dev->dev.parent,
+- txq->size * MVNETA_DESC_ALIGNED_SIZE,
+- txq->descs, txq->descs_phys);
++ if (!txq->tso_hdrs)
+ return -ENOMEM;
+- }
+
+ /* Setup XPS mapping */
+ if (txq_number > 1)
+--
+2.25.1
+
--- /dev/null
+From 381e7d30daf811ed8bfbcf5a386a6099534719fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Sep 2020 10:10:49 +0800
+Subject: net: phy: realtek: fix rtl8211e rx/tx delay config
+
+From: Willy Liu <willy.liu@realtek.com>
+
+[ Upstream commit bbc4d71d63549bcd003a430de18a72a742d8c91e ]
+
+There are two chip pins named TXDLY and RXDLY which actually adds the 2ns
+delays to TXC and RXC for TXD/RXD latching. These two pins can config via
+4.7k-ohm resistor to 3.3V hw setting, but also config via software setting
+(extension page 0xa4 register 0x1c bit13 12 and 11).
+
+The configuration register definitions from table 13 official PHY datasheet:
+PHYAD[2:0] = PHY Address
+AN[1:0] = Auto-Negotiation
+Mode = Interface Mode Select
+RX Delay = RX Delay
+TX Delay = TX Delay
+SELRGV = RGMII/GMII Selection
+
+This table describes how to config these hw pins via external pull-high or pull-
+low resistor.
+
+It is a misunderstanding that mapping it as register bits below:
+8:6 = PHY Address
+5:4 = Auto-Negotiation
+3 = Interface Mode Select
+2 = RX Delay
+1 = TX Delay
+0 = SELRGV
+So I removed these descriptions above and add related settings as below:
+14 = reserved
+13 = force Tx RX Delay controlled by bit12 bit11
+12 = Tx Delay
+11 = Rx Delay
+10:0 = Test && debug settings reserved by realtek
+
+Test && debug settings are not recommend to modify by default.
+
+Fixes: f81dadbcf7fd ("net: phy: realtek: Add rtl8211e rx/tx delays config")
+Signed-off-by: Willy Liu <willy.liu@realtek.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/realtek.c | 31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
+index c7229d022a27b..48ba757046cea 100644
+--- a/drivers/net/phy/realtek.c
++++ b/drivers/net/phy/realtek.c
+@@ -1,6 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0+
+-/*
+- * drivers/net/phy/realtek.c
++/* drivers/net/phy/realtek.c
+ *
+ * Driver for Realtek PHYs
+ *
+@@ -32,9 +31,9 @@
+ #define RTL8211F_TX_DELAY BIT(8)
+ #define RTL8211F_RX_DELAY BIT(3)
+
+-#define RTL8211E_TX_DELAY BIT(1)
+-#define RTL8211E_RX_DELAY BIT(2)
+-#define RTL8211E_MODE_MII_GMII BIT(3)
++#define RTL8211E_CTRL_DELAY BIT(13)
++#define RTL8211E_TX_DELAY BIT(12)
++#define RTL8211E_RX_DELAY BIT(11)
+
+ #define RTL8201F_ISR 0x1e
+ #define RTL8201F_IER 0x13
+@@ -246,16 +245,16 @@ static int rtl8211e_config_init(struct phy_device *phydev)
+ /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+- val = 0;
++ val = RTL8211E_CTRL_DELAY | 0;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_ID:
+- val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
++ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+- val = RTL8211E_RX_DELAY;
++ val = RTL8211E_CTRL_DELAY | RTL8211E_RX_DELAY;
+ break;
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+- val = RTL8211E_TX_DELAY;
++ val = RTL8211E_CTRL_DELAY | RTL8211E_TX_DELAY;
+ break;
+ default: /* the rest of the modes imply leaving delays as is. */
+ return 0;
+@@ -263,11 +262,12 @@ static int rtl8211e_config_init(struct phy_device *phydev)
+
+ /* According to a sample driver there is a 0x1c config register on the
+ * 0xa4 extension page (0x7) layout. It can be used to disable/enable
+- * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
+- * also be used to customize the whole configuration register:
+- * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
+- * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
+- * for details).
++ * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins.
++ * The configuration register definition:
++ * 14 = reserved
++ * 13 = Force Tx RX Delay controlled by bit12 bit11,
++ * 12 = RX Delay, 11 = TX Delay
++ * 10:0 = Test && debug settings reserved by realtek
+ */
+ oldpage = phy_select_page(phydev, 0x7);
+ if (oldpage < 0)
+@@ -277,7 +277,8 @@ static int rtl8211e_config_init(struct phy_device *phydev)
+ if (ret)
+ goto err_restore_page;
+
+- ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
++ ret = __phy_modify(phydev, 0x1c, RTL8211E_CTRL_DELAY
++ | RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
+ val);
+
+ err_restore_page:
+--
+2.25.1
+
--- /dev/null
+From 39cf7098049d671b75bf9ea06fffe7c164e8c0c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Sep 2020 17:54:06 +0800
+Subject: net: stmmac: Fix clock handling on remove path
+
+From: Wong Vee Khee <vee.khee.wong@intel.com>
+
+[ Upstream commit ac322f86b56cb99d1c4224c209095aa67647c967 ]
+
+While unloading the dwmac-intel driver, clk_disable_unprepare() is
+being called twice in stmmac_dvr_remove() and
+intel_eth_pci_remove(). This causes kernel panic on the second call.
+
+Removing the second call of clk_disable_unprepare() in
+intel_eth_pci_remove().
+
+Fixes: 09f012e64e4b ("stmmac: intel: Fix clock handling on error and remove paths")
+Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Voon Weifeng <weifeng.voon@intel.com>
+Signed-off-by: Wong Vee Khee <vee.khee.wong@intel.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+index 2ac9dfb3462c6..9e6d60e75f85d 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
+@@ -653,7 +653,6 @@ static void intel_eth_pci_remove(struct pci_dev *pdev)
+
+ pci_free_irq_vectors(pdev);
+
+- clk_disable_unprepare(priv->plat->stmmac_clk);
+ clk_unregister_fixed_rate(priv->plat->stmmac_clk);
+
+ pcim_iounmap_regions(pdev, BIT(0));
+--
+2.25.1
+
--- /dev/null
+From 29de328e553b5dd1b716a2719c63041c4593686f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Oct 2020 23:56:09 +0800
+Subject: net: stmmac: Modify configuration method of EEE timers
+
+From: Vineetha G. Jaya Kumaran <vineetha.g.jaya.kumaran@intel.com>
+
+[ Upstream commit 388e201d41fa1ed8f2dce0f0567f56f8e919ffb0 ]
+
+Ethtool manual stated that the tx-timer is the "the amount of time the
+device should stay in idle mode prior to asserting its Tx LPI". The
+previous implementation for "ethtool --set-eee tx-timer" sets the LPI TW
+timer duration which is not correct. Hence, this patch fixes the
+"ethtool --set-eee tx-timer" to configure the EEE LPI timer.
+
+The LPI TW Timer will be using the defined default value instead of
+"ethtool --set-eee tx-timer" which follows the EEE LS timer implementation.
+
+Changelog V2
+*Not removing/modifying the eee_timer.
+*EEE LPI timer can be configured through ethtool and also the eee_timer
+module param.
+*EEE TW Timer will be configured with default value only, not able to be
+configured through ethtool or module param. This follows the implementation
+of the EEE LS Timer.
+
+Fixes: d765955d2ae0 ("stmmac: add the Energy Efficient Ethernet support")
+Signed-off-by: Vineetha G. Jaya Kumaran <vineetha.g.jaya.kumaran@intel.com>
+Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 ++
+ .../ethernet/stmicro/stmmac/stmmac_ethtool.c | 12 +++++++++-
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 23 ++++++++++++-------
+ 3 files changed, 28 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index 9c02fc754bf1b..545696971f65e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -203,6 +203,8 @@ struct stmmac_priv {
+ int eee_enabled;
+ int eee_active;
+ int tx_lpi_timer;
++ int tx_lpi_enabled;
++ int eee_tw_timer;
+ unsigned int mode;
+ unsigned int chain_mode;
+ int extend_desc;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+index c16d0cc3e9c44..b82c6715f95f3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+@@ -652,6 +652,7 @@ static int stmmac_ethtool_op_get_eee(struct net_device *dev,
+ edata->eee_enabled = priv->eee_enabled;
+ edata->eee_active = priv->eee_active;
+ edata->tx_lpi_timer = priv->tx_lpi_timer;
++ edata->tx_lpi_enabled = priv->tx_lpi_enabled;
+
+ return phylink_ethtool_get_eee(priv->phylink, edata);
+ }
+@@ -665,6 +666,10 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+ if (!priv->dma_cap.eee)
+ return -EOPNOTSUPP;
+
++ if (priv->tx_lpi_enabled != edata->tx_lpi_enabled)
++ netdev_warn(priv->dev,
++ "Setting EEE tx-lpi is not supported\n");
++
+ if (!edata->eee_enabled)
+ stmmac_disable_eee_mode(priv);
+
+@@ -672,7 +677,12 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+ if (ret)
+ return ret;
+
+- priv->tx_lpi_timer = edata->tx_lpi_timer;
++ if (edata->eee_enabled &&
++ priv->tx_lpi_timer != edata->tx_lpi_timer) {
++ priv->tx_lpi_timer = edata->tx_lpi_timer;
++ stmmac_eee_init(priv);
++ }
++
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 73677c3b33b65..73465e5f5a417 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -94,7 +94,7 @@ static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
+ static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
+ module_param(eee_timer, int, 0644);
+ MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
+-#define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
++#define STMMAC_LPI_T(x) (jiffies + usecs_to_jiffies(x))
+
+ /* By default the driver will use the ring mode to manage tx and rx descriptors,
+ * but allow user to force to use the chain instead of the ring
+@@ -370,7 +370,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
+ struct stmmac_priv *priv = from_timer(priv, t, eee_ctrl_timer);
+
+ stmmac_enable_eee_mode(priv);
+- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
++ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
+ }
+
+ /**
+@@ -383,7 +383,7 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
+ */
+ bool stmmac_eee_init(struct stmmac_priv *priv)
+ {
+- int tx_lpi_timer = priv->tx_lpi_timer;
++ int eee_tw_timer = priv->eee_tw_timer;
+
+ /* Using PCS we cannot dial with the phy registers at this stage
+ * so we do not support extra feature like EEE.
+@@ -403,7 +403,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
+ if (priv->eee_enabled) {
+ netdev_dbg(priv->dev, "disable EEE\n");
+ del_timer_sync(&priv->eee_ctrl_timer);
+- stmmac_set_eee_timer(priv, priv->hw, 0, tx_lpi_timer);
++ stmmac_set_eee_timer(priv, priv->hw, 0, eee_tw_timer);
+ }
+ mutex_unlock(&priv->lock);
+ return false;
+@@ -411,11 +411,12 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
+
+ if (priv->eee_active && !priv->eee_enabled) {
+ timer_setup(&priv->eee_ctrl_timer, stmmac_eee_ctrl_timer, 0);
+- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
+ stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
+- tx_lpi_timer);
++ eee_tw_timer);
+ }
+
++ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
++
+ mutex_unlock(&priv->lock);
+ netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
+ return true;
+@@ -930,6 +931,7 @@ static void stmmac_mac_link_down(struct phylink_config *config,
+
+ stmmac_mac_set(priv, priv->ioaddr, false);
+ priv->eee_active = false;
++ priv->tx_lpi_enabled = false;
+ stmmac_eee_init(priv);
+ stmmac_set_eee_pls(priv, priv->hw, false);
+ }
+@@ -1027,6 +1029,7 @@ static void stmmac_mac_link_up(struct phylink_config *config,
+ if (phy && priv->dma_cap.eee) {
+ priv->eee_active = phy_init_eee(phy, 1) >= 0;
+ priv->eee_enabled = stmmac_eee_init(priv);
++ priv->tx_lpi_enabled = priv->eee_enabled;
+ stmmac_set_eee_pls(priv, priv->hw, true);
+ }
+ }
+@@ -2057,7 +2060,7 @@ static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
+
+ if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
+ stmmac_enable_eee_mode(priv);
+- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
++ mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(priv->tx_lpi_timer));
+ }
+
+ /* We still have pending packets, let's call for a new scheduling */
+@@ -2690,7 +2693,11 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
+ netdev_warn(priv->dev, "PTP init failed\n");
+ }
+
+- priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
++ priv->eee_tw_timer = STMMAC_DEFAULT_TWT_LS;
++
++ /* Convert the timer from msec to usec */
++ if (!priv->tx_lpi_timer)
++ priv->tx_lpi_timer = eee_timer * 1000;
+
+ if (priv->use_riwt) {
+ if (!priv->rx_riwt)
+--
+2.25.1
+
--- /dev/null
+From 8fb800fd4a9ebc0dd2e4b64b9dbc0d7af4b0c295 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Sep 2020 16:56:14 +0800
+Subject: net: stmmac: removed enabling eee in EEE set callback
+
+From: Voon Weifeng <weifeng.voon@intel.com>
+
+[ Upstream commit 7241c5a697479c7d0c5a96595822cdab750d41ae ]
+
+EEE should be only be enabled during stmmac_mac_link_up() when the
+link are up and being set up properly. set_eee should only do settings
+configuration and disabling the eee.
+
+Without this fix, turning on EEE using ethtool will return
+"Operation not supported". This is due to the driver is in a dead loop
+waiting for eee to be advertised in the for eee to be activated but the
+driver will only configure the EEE advertisement after the eee is
+activated.
+
+Ethtool should only return "Operation not supported" if there is no EEE
+capbility in the MAC controller.
+
+Fixes: 8a7493e58ad6 ("net: stmmac: Fix a race in EEE enable callback")
+Signed-off-by: Voon Weifeng <weifeng.voon@intel.com>
+Acked-by: Mark Gross <mgross@linux.intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+index eae11c5850251..c16d0cc3e9c44 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+@@ -662,23 +662,16 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
+ struct stmmac_priv *priv = netdev_priv(dev);
+ int ret;
+
+- if (!edata->eee_enabled) {
++ if (!priv->dma_cap.eee)
++ return -EOPNOTSUPP;
++
++ if (!edata->eee_enabled)
+ stmmac_disable_eee_mode(priv);
+- } else {
+- /* We are asking for enabling the EEE but it is safe
+- * to verify all by invoking the eee_init function.
+- * In case of failure it will return an error.
+- */
+- edata->eee_enabled = stmmac_eee_init(priv);
+- if (!edata->eee_enabled)
+- return -EOPNOTSUPP;
+- }
+
+ ret = phylink_ethtool_set_eee(priv->phylink, edata);
+ if (ret)
+ return ret;
+
+- priv->eee_enabled = edata->eee_enabled;
+ priv->tx_lpi_timer = edata->tx_lpi_timer;
+ return 0;
+ }
+--
+2.25.1
+
--- /dev/null
+From 4aab70f68d7f1d005a88dcf6ccd7cdd185c39be0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Sep 2020 11:01:04 +0200
+Subject: net: usb: ax88179_178a: fix missing stop entry in driver_info
+
+From: Wilken Gottwalt <wilken.gottwalt@mailbox.org>
+
+[ Upstream commit 9666ea66a74adfe295cb3a8760c76e1ef70f9caf ]
+
+Adds the missing .stop entry in the Belkin driver_info structure.
+
+Fixes: e20bd60bf62a ("net: usb: asix88179_178a: Add support for the Belkin B2B128")
+Signed-off-by: Wilken Gottwalt <wilken.gottwalt@mailbox.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/ax88179_178a.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
+index a38e868e44d46..f0ef3706aad96 100644
+--- a/drivers/net/usb/ax88179_178a.c
++++ b/drivers/net/usb/ax88179_178a.c
+@@ -1823,6 +1823,7 @@ static const struct driver_info belkin_info = {
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+ .reset = ax88179_reset,
++ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+ .tx_fixup = ax88179_tx_fixup,
+--
+2.25.1
+
--- /dev/null
+From c00b85434f51c745c21021afa5ffb37d4a60eb45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Sep 2020 21:38:27 +0530
+Subject: octeontx2-af: Fix enable/disable of default NPC entries
+
+From: Subbaraya Sundeep <sbhatta@marvell.com>
+
+[ Upstream commit e154b5b70368a84a19505a0be9b0096c66562b56 ]
+
+Packet replication feature present in Octeontx2
+is a hardware linked list of PF and its VF
+interfaces so that broadcast packets are sent
+to all interfaces present in the list. It is
+driver job to add and delete a PF/VF interface
+to/from the list when the interface is brought
+up and down. This patch fixes the
+npc_enadis_default_entries function to handle
+broadcast replication properly if packet replication
+feature is present.
+
+Fixes: 40df309e4166 ("octeontx2-af: Support to enable/disable default MCAM entries")
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeontx2/af/rvu.h | 3 ++-
+ .../ethernet/marvell/octeontx2/af/rvu_nix.c | 5 ++--
+ .../ethernet/marvell/octeontx2/af/rvu_npc.c | 26 ++++++++++++++-----
+ 3 files changed, 23 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index dcf25a0920084..b89dde2c8b089 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -463,6 +463,7 @@ void rvu_nix_freemem(struct rvu *rvu);
+ int rvu_get_nixlf_count(struct rvu *rvu);
+ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int npalf);
+ int nix_get_nixlf(struct rvu *rvu, u16 pcifunc, int *nixlf, int *nix_blkaddr);
++int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
+
+ /* NPC APIs */
+ int rvu_npc_init(struct rvu *rvu);
+@@ -477,7 +478,7 @@ void rvu_npc_disable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
+ void rvu_npc_enable_promisc_entry(struct rvu *rvu, u16 pcifunc, int nixlf);
+ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
+ int nixlf, u64 chan);
+-void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc);
++void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable);
+ int rvu_npc_update_rxvlan(struct rvu *rvu, u16 pcifunc, int nixlf);
+ void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
+ void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 36953d4f51c73..3495b3a6828c0 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -17,7 +17,6 @@
+ #include "npc.h"
+ #include "cgx.h"
+
+-static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
+ static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
+ int type, int chan_id);
+
+@@ -2020,7 +2019,7 @@ static int nix_update_mce_list(struct nix_mce_list *mce_list,
+ return 0;
+ }
+
+-static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
++int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
+ {
+ int err = 0, idx, next_idx, last_idx;
+ struct nix_mce_list *mce_list;
+@@ -2065,7 +2064,7 @@ static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add)
+
+ /* Disable MCAM entry in NPC */
+ if (!mce_list->count) {
+- rvu_npc_disable_bcast_entry(rvu, pcifunc);
++ rvu_npc_enable_bcast_entry(rvu, pcifunc, false);
+ goto end;
+ }
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 0a214084406a6..fbaf9bcd83f2f 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -530,7 +530,7 @@ void rvu_npc_install_bcast_match_entry(struct rvu *rvu, u16 pcifunc,
+ NIX_INTF_RX, &entry, true);
+ }
+
+-void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc)
++void rvu_npc_enable_bcast_entry(struct rvu *rvu, u16 pcifunc, bool enable)
+ {
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ int blkaddr, index;
+@@ -543,7 +543,7 @@ void rvu_npc_disable_bcast_entry(struct rvu *rvu, u16 pcifunc)
+ pcifunc = pcifunc & ~RVU_PFVF_FUNC_MASK;
+
+ index = npc_get_nixlf_mcam_index(mcam, pcifunc, 0, NIXLF_BCAST_ENTRY);
+- npc_enable_mcam_entry(rvu, mcam, blkaddr, index, false);
++ npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
+ }
+
+ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
+@@ -622,23 +622,35 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
+ nixlf, NIXLF_UCAST_ENTRY);
+ npc_enable_mcam_entry(rvu, mcam, blkaddr, index, enable);
+
+- /* For PF, ena/dis promisc and bcast MCAM match entries */
+- if (pcifunc & RVU_PFVF_FUNC_MASK)
++ /* For PF, ena/dis promisc and bcast MCAM match entries.
++ * For VFs add/delete from bcast list when RX multicast
++ * feature is present.
++ */
++ if (pcifunc & RVU_PFVF_FUNC_MASK && !rvu->hw->cap.nix_rx_multicast)
+ return;
+
+ /* For bcast, enable/disable only if it's action is not
+ * packet replication, incase if action is replication
+- * then this PF's nixlf is removed from bcast replication
++ * then this PF/VF's nixlf is removed from bcast replication
+ * list.
+ */
+- index = npc_get_nixlf_mcam_index(mcam, pcifunc,
++ index = npc_get_nixlf_mcam_index(mcam, pcifunc & ~RVU_PFVF_FUNC_MASK,
+ nixlf, NIXLF_BCAST_ENTRY);
+ bank = npc_get_bank(mcam, index);
+ *(u64 *)&action = rvu_read64(rvu, blkaddr,
+ NPC_AF_MCAMEX_BANKX_ACTION(index & (mcam->banksize - 1), bank));
+- if (action.op != NIX_RX_ACTIONOP_MCAST)
++
++ /* VFs will not have BCAST entry */
++ if (action.op != NIX_RX_ACTIONOP_MCAST &&
++ !(pcifunc & RVU_PFVF_FUNC_MASK)) {
+ npc_enable_mcam_entry(rvu, mcam,
+ blkaddr, index, enable);
++ } else {
++ nix_update_bcast_mce_list(rvu, pcifunc, enable);
++ /* Enable PF's BCAST entry for packet replication */
++ rvu_npc_enable_bcast_entry(rvu, pcifunc, enable);
++ }
++
+ if (enable)
+ rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf);
+ else
+--
+2.25.1
+
--- /dev/null
+From d95cc206fef0dc19efe226ff6c9c7033ae4ea594 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Sep 2020 21:39:35 +0530
+Subject: octeontx2-pf: Fix synchnorization issue in mbox
+
+From: Hariprasad Kelam <hkelam@marvell.com>
+
+[ Upstream commit 66a5209b53418111757716d71e52727b782eabd4 ]
+
+Mbox implementation in octeontx2 driver has three states
+alloc, send and reset in mbox response. VF allocate and
+sends message to PF for processing, PF ACKs them back and
+reset the mbox memory. In some case we see synchronization
+issue where after msgs_acked is incremented and before
+mbox_reset API is called, if current execution is scheduled
+out and a different thread is scheduled in which checks for
+msgs_acked. Since the new thread sees msgs_acked == msgs_sent
+it will try to allocate a new message and to send a new mbox
+message to PF.Now if mbox_reset is scheduled in, PF will see
+'0' in msgs_send.
+This patch fixes the issue by calling mbox_reset before
+incrementing msgs_acked flag for last processing message and
+checks for valid message size.
+
+Fixes: d424b6c02 ("octeontx2-pf: Enable SRIOV and added VF mbox handling")
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/mbox.c | 12 ++++++++++--
+ drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 1 +
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 11 ++++++-----
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 4 ++--
+ 4 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
+index 387e33fa417aa..2718fe201c147 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
+@@ -17,7 +17,7 @@
+
+ static const u16 msgs_offset = ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
+
+-void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
++void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
+ {
+ void *hw_mbase = mbox->hwbase + (devid * MBOX_SIZE);
+ struct otx2_mbox_dev *mdev = &mbox->dev[devid];
+@@ -26,13 +26,21 @@ void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
+ tx_hdr = hw_mbase + mbox->tx_start;
+ rx_hdr = hw_mbase + mbox->rx_start;
+
+- spin_lock(&mdev->mbox_lock);
+ mdev->msg_size = 0;
+ mdev->rsp_size = 0;
+ tx_hdr->num_msgs = 0;
+ tx_hdr->msg_size = 0;
+ rx_hdr->num_msgs = 0;
+ rx_hdr->msg_size = 0;
++}
++EXPORT_SYMBOL(__otx2_mbox_reset);
++
++void otx2_mbox_reset(struct otx2_mbox *mbox, int devid)
++{
++ struct otx2_mbox_dev *mdev = &mbox->dev[devid];
++
++ spin_lock(&mdev->mbox_lock);
++ __otx2_mbox_reset(mbox, devid);
+ spin_unlock(&mdev->mbox_lock);
+ }
+ EXPORT_SYMBOL(otx2_mbox_reset);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+index 6dfd0f90cd704..ab433789d2c31 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+@@ -93,6 +93,7 @@ struct mbox_msghdr {
+ };
+
+ void otx2_mbox_reset(struct otx2_mbox *mbox, int devid);
++void __otx2_mbox_reset(struct otx2_mbox *mbox, int devid);
+ void otx2_mbox_destroy(struct otx2_mbox *mbox);
+ int otx2_mbox_init(struct otx2_mbox *mbox, void __force *hwbase,
+ struct pci_dev *pdev, void __force *reg_base,
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index 5d620a39ea802..2fb45670aca49 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -370,8 +370,8 @@ static int otx2_forward_vf_mbox_msgs(struct otx2_nic *pf,
+ dst_mbox = &pf->mbox;
+ dst_size = dst_mbox->mbox.tx_size -
+ ALIGN(sizeof(*mbox_hdr), MBOX_MSG_ALIGN);
+- /* Check if msgs fit into destination area */
+- if (mbox_hdr->msg_size > dst_size)
++ /* Check if msgs fit into destination area and has valid size */
++ if (mbox_hdr->msg_size > dst_size || !mbox_hdr->msg_size)
+ return -EINVAL;
+
+ dst_mdev = &dst_mbox->mbox.dev[0];
+@@ -526,10 +526,10 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)
+
+ end:
+ offset = mbox->rx_start + msg->next_msgoff;
++ if (mdev->msgs_acked == (vf_mbox->up_num_msgs - 1))
++ __otx2_mbox_reset(mbox, 0);
+ mdev->msgs_acked++;
+ }
+-
+- otx2_mbox_reset(mbox, vf_idx);
+ }
+
+ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+@@ -803,10 +803,11 @@ static void otx2_pfaf_mbox_handler(struct work_struct *work)
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+ otx2_process_pfaf_mbox_msg(pf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
++ if (mdev->msgs_acked == (af_mbox->num_msgs - 1))
++ __otx2_mbox_reset(mbox, 0);
+ mdev->msgs_acked++;
+ }
+
+- otx2_mbox_reset(mbox, 0);
+ }
+
+ static void otx2_handle_link_event(struct otx2_nic *pf)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+index 92a3db69a6cd6..2f90f17214415 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+@@ -99,10 +99,10 @@ static void otx2vf_vfaf_mbox_handler(struct work_struct *work)
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+ otx2vf_process_vfaf_mbox_msg(af_mbox->pfvf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
++ if (mdev->msgs_acked == (af_mbox->num_msgs - 1))
++ __otx2_mbox_reset(mbox, 0);
+ mdev->msgs_acked++;
+ }
+-
+- otx2_mbox_reset(mbox, 0);
+ }
+
+ static int otx2vf_process_mbox_msg_up(struct otx2_nic *vf,
+--
+2.25.1
+
--- /dev/null
+From 945b1fb6238d18809885bb6f517f410e12d89f90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Sep 2020 21:38:52 +0530
+Subject: octeontx2-pf: Fix TCP/UDP checksum offload for IPv6 frames
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit 89eae5e87b4fa799726a3e8911c90d418cb5d2b1 ]
+
+For TCP/UDP checksum offload feature in Octeontx2
+expects L3TYPE to be set irrespective of IP header
+checksum is being offloaded or not. Currently for
+IPv6 frames L3TYPE is not being set resulting in
+packet drop with checksum error. This patch fixes
+this issue.
+
+Fixes: 3ca6c4c88 ("octeontx2-pf: Add packet transmission support")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+index b04f5429d72d9..334eab976ee4a 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+@@ -524,6 +524,7 @@ static void otx2_sqe_add_hdr(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
+ sqe_hdr->ol3type = NIX_SENDL3TYPE_IP4_CKSUM;
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ proto = ipv6_hdr(skb)->nexthdr;
++ sqe_hdr->ol3type = NIX_SENDL3TYPE_IP6;
+ }
+
+ if (proto == IPPROTO_TCP)
+--
+2.25.1
+
--- /dev/null
+From 683674ba6ee5d3ae8545e56208bde08d2e4d8d3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Sep 2020 21:39:14 +0530
+Subject: octeontx2-pf: Fix the device state on error
+
+From: Hariprasad Kelam <hkelam@marvell.com>
+
+[ Upstream commit 1ea0166da0509e987caa42c30a6a71f2c6ca1875 ]
+
+Currently in otx2_open on failure of nix_lf_start
+transmit queues are not stopped which are already
+started in link_event. Since the tx queues are not
+stopped network stack still try's to send the packets
+leading to driver crash while access the device resources.
+
+Fixes: 50fe6c02e ("octeontx2-pf: Register and handle link notifications")
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index 75a8c407e815c..5d620a39ea802 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -1560,10 +1560,13 @@ int otx2_open(struct net_device *netdev)
+
+ err = otx2_rxtx_enable(pf, true);
+ if (err)
+- goto err_free_cints;
++ goto err_tx_stop_queues;
+
+ return 0;
+
++err_tx_stop_queues:
++ netif_tx_stop_all_queues(netdev);
++ netif_carrier_off(netdev);
+ err_free_cints:
+ otx2_free_cints(pf, qidx);
+ vec = pci_irq_vector(pf->pdev,
+--
+2.25.1
+
--- /dev/null
+From 0a2000dbaf1285b6d4e3b4cc8d255f89bf94d506 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Aug 2020 12:17:32 +0530
+Subject: perf: Fix task_function_call() error handling
+
+From: Kajol Jain <kjain@linux.ibm.com>
+
+[ Upstream commit 6d6b8b9f4fceab7266ca03d194f60ec72bd4b654 ]
+
+The error handling introduced by commit:
+
+ 2ed6edd33a21 ("perf: Add cond_resched() to task_function_call()")
+
+looses any return value from smp_call_function_single() that is not
+{0, -EINVAL}. This is a problem because it will return -EXNIO when the
+target CPU is offline. Worse, in that case it'll turn into an infinite
+loop.
+
+Fixes: 2ed6edd33a21 ("perf: Add cond_resched() to task_function_call()")
+Reported-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
+Signed-off-by: Kajol Jain <kjain@linux.ibm.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Barret Rhoden <brho@google.com>
+Tested-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
+Link: https://lkml.kernel.org/r/20200827064732.20860-1-kjain@linux.ibm.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/events/core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/events/core.c b/kernel/events/core.c
+index 856d98c36f562..fd8cd00099dae 100644
+--- a/kernel/events/core.c
++++ b/kernel/events/core.c
+@@ -99,7 +99,7 @@ static void remote_function(void *data)
+ * retry due to any failures in smp_call_function_single(), such as if the
+ * task_cpu() goes offline concurrently.
+ *
+- * returns @func return value or -ESRCH when the process isn't running
++ * returns @func return value or -ESRCH or -ENXIO when the process isn't running
+ */
+ static int
+ task_function_call(struct task_struct *p, remote_function_f func, void *info)
+@@ -115,7 +115,8 @@ task_function_call(struct task_struct *p, remote_function_f func, void *info)
+ for (;;) {
+ ret = smp_call_function_single(task_cpu(p), remote_function,
+ &data, 1);
+- ret = !ret ? data.ret : -EAGAIN;
++ if (!ret)
++ ret = data.ret;
+
+ if (ret != -EAGAIN)
+ break;
+--
+2.25.1
+
--- /dev/null
+From aa49f48a540c33b9727766728007adc3b0ba59fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Oct 2020 08:50:55 -0400
+Subject: pipe: Fix memory leaks in create_pipe_files()
+
+From: Qian Cai <cai@redhat.com>
+
+[ Upstream commit 8a018eb55e3ac033592afbcb476b0ffe64465b12 ]
+
+ Calling pipe2() with O_NOTIFICATION_PIPE could results in memory
+leaks unless watch_queue_init() is successful.
+
+ In case of watch_queue_init() failure in pipe2() we are left
+with inode and pipe_inode_info instances that need to be freed. That
+failure exit has been introduced in commit c73be61cede5 ("pipe: Add
+general notification queue support") and its handling should've been
+identical to nearby treatment of alloc_file_pseudo() failures - it
+is dealing with the same situation. As it is, the mainline kernel
+leaks in that case.
+
+ Another problem is that CONFIG_WATCH_QUEUE and !CONFIG_WATCH_QUEUE
+cases are treated differently (and the former leaks just pipe_inode_info,
+the latter - both pipe_inode_info and inode).
+
+ Fixed by providing a dummy wacth_queue_init() in !CONFIG_WATCH_QUEUE
+case and by having failures of wacth_queue_init() handled the same way
+we handle alloc_file_pseudo() ones.
+
+Fixes: c73be61cede5 ("pipe: Add general notification queue support")
+Signed-off-by: Qian Cai <cai@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pipe.c | 11 +++++------
+ include/linux/watch_queue.h | 6 ++++++
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 117db82b10af5..0ac197658a2d6 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -894,19 +894,18 @@ int create_pipe_files(struct file **res, int flags)
+ {
+ struct inode *inode = get_pipe_inode();
+ struct file *f;
++ int error;
+
+ if (!inode)
+ return -ENFILE;
+
+ if (flags & O_NOTIFICATION_PIPE) {
+-#ifdef CONFIG_WATCH_QUEUE
+- if (watch_queue_init(inode->i_pipe) < 0) {
++ error = watch_queue_init(inode->i_pipe);
++ if (error) {
++ free_pipe_info(inode->i_pipe);
+ iput(inode);
+- return -ENOMEM;
++ return error;
+ }
+-#else
+- return -ENOPKG;
+-#endif
+ }
+
+ f = alloc_file_pseudo(inode, pipe_mnt, "",
+diff --git a/include/linux/watch_queue.h b/include/linux/watch_queue.h
+index 5e08db2adc319..c994d1b2cdbaa 100644
+--- a/include/linux/watch_queue.h
++++ b/include/linux/watch_queue.h
+@@ -122,6 +122,12 @@ static inline void remove_watch_list(struct watch_list *wlist, u64 id)
+ */
+ #define watch_sizeof(STRUCT) (sizeof(STRUCT) << WATCH_INFO_LENGTH__SHIFT)
+
++#else
++static inline int watch_queue_init(struct pipe_inode_info *pipe)
++{
++ return -ENOPKG;
++}
++
+ #endif
+
+ #endif /* _LINUX_WATCH_QUEUE_H */
+--
+2.25.1
+
--- /dev/null
+From b7fdec6b486de64111a449f3f842374b40997a6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Sep 2020 19:16:53 +0300
+Subject: platform/x86: fix kconfig dependency warning for FUJITSU_LAPTOP
+
+From: Necip Fazil Yildiran <fazilyildiran@gmail.com>
+
+[ Upstream commit afdd1ebb72051e8b6b83c4d7dc542a9be0e1352d ]
+
+When FUJITSU_LAPTOP is enabled and NEW_LEDS is disabled, it results in the
+following Kbuild warning:
+
+WARNING: unmet direct dependencies detected for LEDS_CLASS
+ Depends on [n]: NEW_LEDS [=n]
+ Selected by [y]:
+ - FUJITSU_LAPTOP [=y] && X86 [=y] && X86_PLATFORM_DEVICES [=y] && ACPI [=y] && INPUT [=y] && BACKLIGHT_CLASS_DEVICE [=y] && (ACPI_VIDEO [=n] || ACPI_VIDEO [=n]=n)
+
+The reason is that FUJITSU_LAPTOP selects LEDS_CLASS without depending on
+or selecting NEW_LEDS while LEDS_CLASS is subordinate to NEW_LEDS.
+
+Honor the kconfig menu hierarchy to remove kconfig dependency warnings.
+
+Reported-by: Hans de Goede <hdegoede@redhat.com>
+Fixes: d89bcc83e709 ("platform/x86: fujitsu-laptop: select LEDS_CLASS")
+Signed-off-by: Necip Fazil Yildiran <fazilyildiran@gmail.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index e1668a9538c8f..a5ad36083b671 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -469,6 +469,7 @@ config FUJITSU_LAPTOP
+ depends on BACKLIGHT_CLASS_DEVICE
+ depends on ACPI_VIDEO || ACPI_VIDEO = n
+ select INPUT_SPARSEKMAP
++ select NEW_LEDS
+ select LEDS_CLASS
+ help
+ This is a driver for laptops built by Fujitsu:
+--
+2.25.1
+
--- /dev/null
+From 06f583650ac148554057e626b96ecaceb57dc18f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Sep 2020 12:09:23 +0300
+Subject: platform/x86: fix kconfig dependency warning for LG_LAPTOP
+
+From: Necip Fazil Yildiran <fazilyildiran@gmail.com>
+
+[ Upstream commit 8f0c01e666685c4d2e1a233e6f4d7ab16c9f8b2a ]
+
+When LG_LAPTOP is enabled and NEW_LEDS is disabled, it results in the
+following Kbuild warning:
+
+WARNING: unmet direct dependencies detected for LEDS_CLASS
+ Depends on [n]: NEW_LEDS [=n]
+ Selected by [y]:
+ - LG_LAPTOP [=y] && X86 [=y] && X86_PLATFORM_DEVICES [=y] && ACPI [=y] && ACPI_WMI [=y] && INPUT [=y]
+
+The reason is that LG_LAPTOP selects LEDS_CLASS without depending on or
+selecting NEW_LEDS while LEDS_CLASS is subordinate to NEW_LEDS.
+
+Honor the kconfig menu hierarchy to remove kconfig dependency warnings.
+
+Fixes: dbf0c5a6b1f8 ("platform/x86: Add LG Gram laptop special features driver")
+Signed-off-by: Necip Fazil Yildiran <fazilyildiran@gmail.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: mark gross <mgross@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index 0581a54cf562f..e1668a9538c8f 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -1091,6 +1091,7 @@ config LG_LAPTOP
+ depends on ACPI_WMI
+ depends on INPUT
+ select INPUT_SPARSEKMAP
++ select NEW_LEDS
+ select LEDS_CLASS
+ help
+ This driver adds support for hotkeys as well as control of keyboard
+--
+2.25.1
+
--- /dev/null
+From 6a64cf74cc352a1564768ee225bc204851a370d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Sep 2020 19:44:29 +0200
+Subject: r8169: fix RTL8168f/RTL8411 EPHY config
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 709a16be0593c08190982cfbdca6df95e6d5823b ]
+
+Mistakenly bit 2 was set instead of bit 3 as in the vendor driver.
+
+Fixes: a7a92cf81589 ("r8169: sync PCIe PHY init with vendor driver 8.047.01")
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index a5d54fa012213..fe173ea894e2c 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2958,7 +2958,7 @@ static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
+ { 0x08, 0x0001, 0x0002 },
+ { 0x09, 0x0000, 0x0080 },
+ { 0x19, 0x0000, 0x0224 },
+- { 0x00, 0x0000, 0x0004 },
++ { 0x00, 0x0000, 0x0008 },
+ { 0x0c, 0x3df0, 0x0200 },
+ };
+
+@@ -2975,7 +2975,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp)
+ { 0x06, 0x00c0, 0x0020 },
+ { 0x0f, 0xffff, 0x5200 },
+ { 0x19, 0x0000, 0x0224 },
+- { 0x00, 0x0000, 0x0004 },
++ { 0x00, 0x0000, 0x0008 },
+ { 0x0c, 0x3df0, 0x0200 },
+ };
+
+--
+2.25.1
+
--- /dev/null
+From 45d553032ea1640cba86f1d5372a4d5e959d76d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Sep 2020 22:09:04 +0100
+Subject: rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 9a059cd5ca7d9c5c4ca5a6e755cf72f230176b6a ]
+
+If rxrpc_read() (which allows KEYCTL_READ to read a key), sees a token of a
+type it doesn't recognise, it can BUG in a couple of places, which is
+unnecessary as it can easily get back to userspace.
+
+Fix this to print an error message instead.
+
+Fixes: 99455153d067 ("RxRPC: Parse security index 5 keys (Kerberos 5)")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rxrpc/key.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
+index d77e89766406a..32f46edcf7c67 100644
+--- a/net/rxrpc/key.c
++++ b/net/rxrpc/key.c
+@@ -1108,7 +1108,8 @@ static long rxrpc_read(const struct key *key,
+ break;
+
+ default: /* we have a ticket we can't encode */
+- BUG();
++ pr_err("Unsupported key token type (%u)\n",
++ token->security_index);
+ continue;
+ }
+
+@@ -1224,7 +1225,6 @@ static long rxrpc_read(const struct key *key,
+ break;
+
+ default:
+- BUG();
+ break;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From b77cfb367121de563b936fa94561e519d9efb30e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Sep 2020 14:01:24 -0300
+Subject: rxrpc: Fix rxkad token xdr encoding
+
+From: Marc Dionne <marc.dionne@auristor.com>
+
+[ Upstream commit 56305118e05b2db8d0395bba640ac9a3aee92624 ]
+
+The session key should be encoded with just the 8 data bytes and
+no length; ENCODE_DATA precedes it with a 4 byte length, which
+confuses some existing tools that try to parse this format.
+
+Add an ENCODE_BYTES macro that does not include a length, and use
+it for the key. Also adjust the expected length.
+
+Note that commit 774521f353e1d ("rxrpc: Fix an assertion in
+rxrpc_read()") had fixed a BUG by changing the length rather than
+fixing the encoding. The original length was correct.
+
+Fixes: 99455153d067 ("RxRPC: Parse security index 5 keys (Kerberos 5)")
+Signed-off-by: Marc Dionne <marc.dionne@auristor.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rxrpc/key.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
+index 0c98313dd7a8c..d77e89766406a 100644
+--- a/net/rxrpc/key.c
++++ b/net/rxrpc/key.c
+@@ -1073,7 +1073,7 @@ static long rxrpc_read(const struct key *key,
+
+ switch (token->security_index) {
+ case RXRPC_SECURITY_RXKAD:
+- toksize += 9 * 4; /* viceid, kvno, key*2 + len, begin,
++ toksize += 8 * 4; /* viceid, kvno, key*2, begin,
+ * end, primary, tktlen */
+ toksize += RND(token->kad->ticket_len);
+ break;
+@@ -1139,6 +1139,14 @@ static long rxrpc_read(const struct key *key,
+ memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
+ xdr += (_l + 3) >> 2; \
+ } while(0)
++#define ENCODE_BYTES(l, s) \
++ do { \
++ u32 _l = (l); \
++ memcpy(xdr, (s), _l); \
++ if (_l & 3) \
++ memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3)); \
++ xdr += (_l + 3) >> 2; \
++ } while(0)
+ #define ENCODE64(x) \
+ do { \
+ __be64 y = cpu_to_be64(x); \
+@@ -1166,7 +1174,7 @@ static long rxrpc_read(const struct key *key,
+ case RXRPC_SECURITY_RXKAD:
+ ENCODE(token->kad->vice_id);
+ ENCODE(token->kad->kvno);
+- ENCODE_DATA(8, token->kad->session_key);
++ ENCODE_BYTES(8, token->kad->session_key);
+ ENCODE(token->kad->start);
+ ENCODE(token->kad->expiry);
+ ENCODE(token->kad->primary_flag);
+--
+2.25.1
+
--- /dev/null
+From fe62be4b36ee352077f12cc85db025eb1e662fc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Oct 2020 14:04:51 +0100
+Subject: rxrpc: Fix server keyring leak
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit 38b1dc47a35ba14c3f4472138ea56d014c2d609b ]
+
+If someone calls setsockopt() twice to set a server key keyring, the first
+keyring is leaked.
+
+Fix it to return an error instead if the server key keyring is already set.
+
+Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rxrpc/key.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
+index 64cbbd2f16944..85a9ff8cd236a 100644
+--- a/net/rxrpc/key.c
++++ b/net/rxrpc/key.c
+@@ -903,7 +903,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen)
+
+ _enter("");
+
+- if (optlen <= 0 || optlen > PAGE_SIZE - 1)
++ if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
+ return -EINVAL;
+
+ description = memdup_user_nul(optval, optlen);
+--
+2.25.1
+
--- /dev/null
+From 923313ac0f53f60652490440bfee4b3fdabfeb96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Oct 2020 11:57:40 +0100
+Subject: rxrpc: Fix some missing _bh annotations on locking conn->state_lock
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit fa1d113a0f96f9ab7e4fe4f8825753ba1e34a9d3 ]
+
+conn->state_lock may be taken in softirq mode, but a previous patch
+replaced an outer lock in the response-packet event handling code, and lost
+the _bh from that when doing so.
+
+Fix this by applying the _bh annotation to the state_lock locking.
+
+Fixes: a1399f8bb033 ("rxrpc: Call channels should have separate call number spaces")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rxrpc/conn_event.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
+index 447f55ca68860..6e972b4823efa 100644
+--- a/net/rxrpc/conn_event.c
++++ b/net/rxrpc/conn_event.c
+@@ -340,18 +340,18 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
+ return ret;
+
+ spin_lock(&conn->channel_lock);
+- spin_lock(&conn->state_lock);
++ spin_lock_bh(&conn->state_lock);
+
+ if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
+ conn->state = RXRPC_CONN_SERVICE;
+- spin_unlock(&conn->state_lock);
++ spin_unlock_bh(&conn->state_lock);
+ for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
+ rxrpc_call_is_secure(
+ rcu_dereference_protected(
+ conn->channels[loop].call,
+ lockdep_is_held(&conn->channel_lock)));
+ } else {
+- spin_unlock(&conn->state_lock);
++ spin_unlock_bh(&conn->state_lock);
+ }
+
+ spin_unlock(&conn->channel_lock);
+--
+2.25.1
+
--- /dev/null
+From 4be391491415826e942f4082a5c3094ed4f69605 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Sep 2020 19:52:08 +0100
+Subject: rxrpc: The server keyring isn't network-namespaced
+
+From: David Howells <dhowells@redhat.com>
+
+[ Upstream commit fea99111244bae44e7d82a973744d27ea1567814 ]
+
+The keyring containing the server's tokens isn't network-namespaced, so it
+shouldn't be looked up with a network namespace. It is expected to be
+owned specifically by the server, so namespacing is unnecessary.
+
+Fixes: a58946c158a0 ("keys: Pass the network namespace into request_key mechanism")
+Signed-off-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/rxrpc/key.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c
+index 32f46edcf7c67..64cbbd2f16944 100644
+--- a/net/rxrpc/key.c
++++ b/net/rxrpc/key.c
+@@ -941,7 +941,7 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval,
+ if (IS_ERR(description))
+ return PTR_ERR(description);
+
+- key = request_key_net(&key_type_keyring, description, sock_net(&rx->sk), NULL);
++ key = request_key(&key_type_keyring, description, NULL);
+ if (IS_ERR(key)) {
+ kfree(description);
+ _leave(" = %ld", PTR_ERR(key));
+--
+2.25.1
+
drm-vmwgfx-fix-error-handling-in-get_node.patch
btrfs-move-btrfs_rm_dev_replace_free_srcdev-outside-.patch
iommu-vt-d-fix-lockdep-splat-in-iommu_flush_dev_iotl.patch
+xfrm-clone-xfrma_set_mark-in-xfrm_do_migrate.patch
+xfrm-clone-xfrma_replay_esn_val-in-xfrm_do_migrate.patch
+xfrm-clone-xfrma_sec_ctx-in-xfrm_do_migrate.patch
+xfrm-clone-whole-liftime_cur-structure-in-xfrm_do_mi.patch
+xsk-do-not-discard-packet-when-netdev_tx_busy.patch
+net-stmmac-removed-enabling-eee-in-eee-set-callback.patch
+platform-x86-fix-kconfig-dependency-warning-for-lg_l.patch
+platform-x86-fix-kconfig-dependency-warning-for-fuji.patch
+hinic-add-log-in-exception-handling-processes.patch
+hinic-fix-wrong-return-value-of-mac-set-cmd.patch
+net-dsa-felix-convert-tas-link-speed-based-on-phylin.patch
+xfrm-use-correct-address-family-in-xfrm_state_find.patch
+iavf-use-generic-power-management.patch
+iavf-fix-incorrect-adapter-get-in-iavf_resume.patch
+ice-fix-memory-leak-if-register_netdev_fails.patch
+ice-fix-memory-leak-in-ice_vsi_setup.patch
+vmxnet3-fix-cksum-offload-issues-for-non-udp-tunnels.patch
+net-stmmac-fix-clock-handling-on-remove-path.patch
+net-ethernet-cavium-octeon_mgmt-use-phy_start-and-ph.patch
+bonding-set-dev-needed_headroom-in-bond_setup_by_sla.patch
+mdio-fix-mdio-thunder.c-dependency-build-error.patch
+mlxsw-spectrum_acl-fix-mlxsw_sp_acl_tcam_group_add-s.patch
+r8169-fix-rtl8168f-rtl8411-ephy-config.patch
+net-usb-ax88179_178a-fix-missing-stop-entry-in-drive.patch
+virtio-net-don-t-disable-guest-csum-when-disable-lro.patch
+net-phy-realtek-fix-rtl8211e-rx-tx-delay-config.patch
+octeontx2-af-fix-enable-disable-of-default-npc-entri.patch
+octeontx2-pf-fix-tcp-udp-checksum-offload-for-ipv6-f.patch
+octeontx2-pf-fix-the-device-state-on-error.patch
+octeontx2-pf-fix-synchnorization-issue-in-mbox.patch
+pipe-fix-memory-leaks-in-create_pipe_files.patch
+net-mlx5-fix-a-race-when-moving-command-interface-to.patch
+net-mlx5-avoid-possible-free-of-command-entry-while-.patch
+net-mlx5-poll-cmd-eq-in-case-of-command-timeout.patch
+net-mlx5-add-retry-mechanism-to-the-command-entry-in.patch
+net-mlx5-fix-request_irqs-error-flow.patch
+net-mlx5e-add-resiliency-in-striding-rq-mode-for-pac.patch
+net-mlx5e-fix-return-status-when-setting-unsupported.patch
+net-mlx5e-fix-vlan-cleanup-flow.patch
+net-mlx5e-fix-vlan-create-flow.patch
+net-mlx5e-fix-race-condition-on-nhe-n-pointer-in-nei.patch
+net-stmmac-modify-configuration-method-of-eee-timers.patch
+net-hinic-fix-devlink-build-errors.patch
+vhost-vdpa-fix-vhost_vdpa_map-on-error-condition.patch
+vhost-vdpa-fix-page-pinning-leakage-in-error-path.patch
+net-mvneta-fix-double-free-of-txq-buf.patch
+rxrpc-fix-rxkad-token-xdr-encoding.patch
+rxrpc-downgrade-the-bug-for-unsupported-token-type-i.patch
+rxrpc-fix-some-missing-_bh-annotations-on-locking-co.patch
+rxrpc-the-server-keyring-isn-t-network-namespaced.patch
+rxrpc-fix-server-keyring-leak.patch
+net-mscc-ocelot-rename-ocelot_board.c-to-ocelot_vsc7.patch
+net-mscc-ocelot-split-writes-to-pause-frame-enable-b.patch
+net-mscc-ocelot-extend-watermark-encoding-function.patch
+net-mscc-ocelot-divide-watermark-value-by-60-when-wr.patch
+i2c-meson-fix-clock-setting-overwrite.patch-20597
+afs-fix-deadlock-between-writeback-and-truncate.patch
+perf-fix-task_function_call-error-handling.patch
+mmc-core-don-t-set-limits.discard_granularity-as-0.patch
--- /dev/null
+From 6098a4938ee29ac1e249c3c9edd2f4bf7484879d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 3 Oct 2020 01:02:10 -0400
+Subject: vhost-vdpa: fix page pinning leakage in error path
+
+From: Si-Wei Liu <si-wei.liu@oracle.com>
+
+[ Upstream commit 7ed9e3d97c32d969caded2dfb6e67c1a2cc5a0b1 ]
+
+Pinned pages are not properly accounted particularly when
+mapping error occurs on IOTLB update. Clean up dangling
+pinned pages for the error path. As the inflight pinned
+pages, specifically for memory region that strides across
+multiple chunks, would need more than one free page for
+book keeping and accounting. For simplicity, pin pages
+for all memory in the IOVA range in one go rather than
+have multiple pin_user_pages calls to make up the entire
+region. This way it's easier to track and account the
+pages already mapped, particularly for clean-up in the
+error path.
+
+Fixes: 4c8cf31885f6 ("vhost: introduce vDPA-based backend")
+Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com>
+Link: https://lore.kernel.org/r/1601701330-16837-3-git-send-email-si-wei.liu@oracle.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 119 ++++++++++++++++++++++++++-----------------
+ 1 file changed, 71 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index 5259f5210b375..e172c2efc663c 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -555,21 +555,19 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
+ struct vhost_dev *dev = &v->vdev;
+ struct vhost_iotlb *iotlb = dev->iotlb;
+ struct page **page_list;
+- unsigned long list_size = PAGE_SIZE / sizeof(struct page *);
++ struct vm_area_struct **vmas;
+ unsigned int gup_flags = FOLL_LONGTERM;
+- unsigned long npages, cur_base, map_pfn, last_pfn = 0;
+- unsigned long locked, lock_limit, pinned, i;
++ unsigned long map_pfn, last_pfn = 0;
++ unsigned long npages, lock_limit;
++ unsigned long i, nmap = 0;
+ u64 iova = msg->iova;
++ long pinned;
+ int ret = 0;
+
+ if (vhost_iotlb_itree_first(iotlb, msg->iova,
+ msg->iova + msg->size - 1))
+ return -EEXIST;
+
+- page_list = (struct page **) __get_free_page(GFP_KERNEL);
+- if (!page_list)
+- return -ENOMEM;
+-
+ if (msg->perm & VHOST_ACCESS_WO)
+ gup_flags |= FOLL_WRITE;
+
+@@ -577,61 +575,86 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
+ if (!npages)
+ return -EINVAL;
+
++ page_list = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
++ vmas = kvmalloc_array(npages, sizeof(struct vm_area_struct *),
++ GFP_KERNEL);
++ if (!page_list || !vmas) {
++ ret = -ENOMEM;
++ goto free;
++ }
++
+ mmap_read_lock(dev->mm);
+
+- locked = atomic64_add_return(npages, &dev->mm->pinned_vm);
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+-
+- if (locked > lock_limit) {
++ if (npages + atomic64_read(&dev->mm->pinned_vm) > lock_limit) {
+ ret = -ENOMEM;
+- goto out;
++ goto unlock;
+ }
+
+- cur_base = msg->uaddr & PAGE_MASK;
+- iova &= PAGE_MASK;
++ pinned = pin_user_pages(msg->uaddr & PAGE_MASK, npages, gup_flags,
++ page_list, vmas);
++ if (npages != pinned) {
++ if (pinned < 0) {
++ ret = pinned;
++ } else {
++ unpin_user_pages(page_list, pinned);
++ ret = -ENOMEM;
++ }
++ goto unlock;
++ }
+
+- while (npages) {
+- pinned = min_t(unsigned long, npages, list_size);
+- ret = pin_user_pages(cur_base, pinned,
+- gup_flags, page_list, NULL);
+- if (ret != pinned)
+- goto out;
+-
+- if (!last_pfn)
+- map_pfn = page_to_pfn(page_list[0]);
+-
+- for (i = 0; i < ret; i++) {
+- unsigned long this_pfn = page_to_pfn(page_list[i]);
+- u64 csize;
+-
+- if (last_pfn && (this_pfn != last_pfn + 1)) {
+- /* Pin a contiguous chunk of memory */
+- csize = (last_pfn - map_pfn + 1) << PAGE_SHIFT;
+- if (vhost_vdpa_map(v, iova, csize,
+- map_pfn << PAGE_SHIFT,
+- msg->perm))
+- goto out;
+- map_pfn = this_pfn;
+- iova += csize;
++ iova &= PAGE_MASK;
++ map_pfn = page_to_pfn(page_list[0]);
++
++ /* One more iteration to avoid extra vdpa_map() call out of loop. */
++ for (i = 0; i <= npages; i++) {
++ unsigned long this_pfn;
++ u64 csize;
++
++ /* The last chunk may have no valid PFN next to it */
++ this_pfn = i < npages ? page_to_pfn(page_list[i]) : -1UL;
++
++ if (last_pfn && (this_pfn == -1UL ||
++ this_pfn != last_pfn + 1)) {
++ /* Pin a contiguous chunk of memory */
++ csize = last_pfn - map_pfn + 1;
++ ret = vhost_vdpa_map(v, iova, csize << PAGE_SHIFT,
++ map_pfn << PAGE_SHIFT,
++ msg->perm);
++ if (ret) {
++ /*
++ * Unpin the rest chunks of memory on the
++ * flight with no corresponding vdpa_map()
++ * calls having been made yet. On the other
++ * hand, vdpa_unmap() in the failure path
++ * is in charge of accounting the number of
++ * pinned pages for its own.
++ * This asymmetrical pattern of accounting
++ * is for efficiency to pin all pages at
++ * once, while there is no other callsite
++ * of vdpa_map() than here above.
++ */
++ unpin_user_pages(&page_list[nmap],
++ npages - nmap);
++ goto out;
+ }
+-
+- last_pfn = this_pfn;
++ atomic64_add(csize, &dev->mm->pinned_vm);
++ nmap += csize;
++ iova += csize << PAGE_SHIFT;
++ map_pfn = this_pfn;
+ }
+-
+- cur_base += ret << PAGE_SHIFT;
+- npages -= ret;
++ last_pfn = this_pfn;
+ }
+
+- /* Pin the rest chunk */
+- ret = vhost_vdpa_map(v, iova, (last_pfn - map_pfn + 1) << PAGE_SHIFT,
+- map_pfn << PAGE_SHIFT, msg->perm);
++ WARN_ON(nmap != npages);
+ out:
+- if (ret) {
++ if (ret)
+ vhost_vdpa_unmap(v, msg->iova, msg->size);
+- atomic64_sub(npages, &dev->mm->pinned_vm);
+- }
++unlock:
+ mmap_read_unlock(dev->mm);
+- free_page((unsigned long)page_list);
++free:
++ kvfree(vmas);
++ kvfree(page_list);
+ return ret;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 6e289072fcf3bd115f394124c6e6e7ef912ab09a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 3 Oct 2020 01:02:09 -0400
+Subject: vhost-vdpa: fix vhost_vdpa_map() on error condition
+
+From: Si-Wei Liu <si-wei.liu@oracle.com>
+
+[ Upstream commit 1477c8aebb94a1db398c12d929a9d27bbd678d8c ]
+
+vhost_vdpa_map() should remove the iotlb entry just added
+if the corresponding mapping fails to set up properly.
+
+Fixes: 4c8cf31885f6 ("vhost: introduce vDPA-based backend")
+Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com>
+Link: https://lore.kernel.org/r/1601701330-16837-2-git-send-email-si-wei.liu@oracle.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vhost/vdpa.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
+index a54b60d6623f0..5259f5210b375 100644
+--- a/drivers/vhost/vdpa.c
++++ b/drivers/vhost/vdpa.c
+@@ -527,6 +527,9 @@ static int vhost_vdpa_map(struct vhost_vdpa *v,
+ r = iommu_map(v->domain, iova, pa, size,
+ perm_to_iommu_flags(perm));
+
++ if (r)
++ vhost_iotlb_del_range(dev->iotlb, iova, iova + size - 1);
++
+ return r;
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 1eadbc0bd166a51c8a5acdd0f4b6bdb5e482409a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Sep 2020 09:58:06 +0800
+Subject: virtio-net: don't disable guest csum when disable LRO
+
+From: Tonghao Zhang <xiangxia.m.yue@gmail.com>
+
+[ Upstream commit 1a03b8a35a957f9f38ecb8a97443b7380bbf6a8b ]
+
+Open vSwitch and Linux bridge will disable LRO of the interface
+when this interface added to them. Now when disable the LRO, the
+virtio-net csum is disable too. That drops the forwarding performance.
+
+Fixes: a02e8964eaf9 ("virtio-net: ethtool configurable LRO")
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: Willem de Bruijn <willemb@google.com>
+Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
+Acked-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/virtio_net.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index ba38765dc4905..c34927b1d806e 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -63,6 +63,11 @@ static const unsigned long guest_offloads[] = {
+ VIRTIO_NET_F_GUEST_CSUM
+ };
+
++#define GUEST_OFFLOAD_LRO_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
++ (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
++ (1ULL << VIRTIO_NET_F_GUEST_ECN) | \
++ (1ULL << VIRTIO_NET_F_GUEST_UFO))
++
+ struct virtnet_stat_desc {
+ char desc[ETH_GSTRING_LEN];
+ size_t offset;
+@@ -2547,7 +2552,8 @@ static int virtnet_set_features(struct net_device *dev,
+ if (features & NETIF_F_LRO)
+ offloads = vi->guest_offloads_capable;
+ else
+- offloads = 0;
++ offloads = vi->guest_offloads_capable &
++ ~GUEST_OFFLOAD_LRO_MASK;
+
+ err = virtnet_set_guest_offloads(vi, offloads);
+ if (err)
+--
+2.25.1
+
--- /dev/null
+From d643ec2a060b329712672580c46168a0f6f23bbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Sep 2020 23:11:29 -0700
+Subject: vmxnet3: fix cksum offload issues for non-udp tunnels
+
+From: Ronak Doshi <doshir@vmware.com>
+
+[ Upstream commit 1dac3b1bc66dc68dbb0c9f43adac71a7d0a0331a ]
+
+Commit dacce2be3312 ("vmxnet3: add geneve and vxlan tunnel offload
+support") added support for encapsulation offload. However, the inner
+offload capability is to be restrictued to UDP tunnels.
+
+This patch fixes the issue for non-udp tunnels by adding features
+check capability and filtering appropriate features for non-udp tunnels.
+
+Fixes: dacce2be3312 ("vmxnet3: add geneve and vxlan tunnel offload support")
+Signed-off-by: Ronak Doshi <doshir@vmware.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vmxnet3/vmxnet3_drv.c | 5 ++---
+ drivers/net/vmxnet3/vmxnet3_ethtool.c | 28 +++++++++++++++++++++++++++
+ drivers/net/vmxnet3/vmxnet3_int.h | 4 ++++
+ 3 files changed, 34 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
+index 2818015324b8b..336504b7531d9 100644
+--- a/drivers/net/vmxnet3/vmxnet3_drv.c
++++ b/drivers/net/vmxnet3/vmxnet3_drv.c
+@@ -1032,7 +1032,6 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+ /* Use temporary descriptor to avoid touching bits multiple times */
+ union Vmxnet3_GenericDesc tempTxDesc;
+ #endif
+- struct udphdr *udph;
+
+ count = txd_estimate(skb);
+
+@@ -1135,8 +1134,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
+ gdesc->txd.om = VMXNET3_OM_ENCAP;
+ gdesc->txd.msscof = ctx.mss;
+
+- udph = udp_hdr(skb);
+- if (udph->check)
++ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)
+ gdesc->txd.oco = 1;
+ } else {
+ gdesc->txd.hlen = ctx.l4_offset + ctx.l4_hdr_size;
+@@ -3371,6 +3369,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
+ .ndo_change_mtu = vmxnet3_change_mtu,
+ .ndo_fix_features = vmxnet3_fix_features,
+ .ndo_set_features = vmxnet3_set_features,
++ .ndo_features_check = vmxnet3_features_check,
+ .ndo_get_stats64 = vmxnet3_get_stats64,
+ .ndo_tx_timeout = vmxnet3_tx_timeout,
+ .ndo_set_rx_mode = vmxnet3_set_mc,
+diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
+index def27afa1c69f..3586677920046 100644
+--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
++++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
+@@ -267,6 +267,34 @@ netdev_features_t vmxnet3_fix_features(struct net_device *netdev,
+ return features;
+ }
+
++netdev_features_t vmxnet3_features_check(struct sk_buff *skb,
++ struct net_device *netdev,
++ netdev_features_t features)
++{
++ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
++
++ /* Validate if the tunneled packet is being offloaded by the device */
++ if (VMXNET3_VERSION_GE_4(adapter) &&
++ skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) {
++ u8 l4_proto = 0;
++
++ switch (vlan_get_protocol(skb)) {
++ case htons(ETH_P_IP):
++ l4_proto = ip_hdr(skb)->protocol;
++ break;
++ case htons(ETH_P_IPV6):
++ l4_proto = ipv6_hdr(skb)->nexthdr;
++ break;
++ default:
++ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
++ }
++
++ if (l4_proto != IPPROTO_UDP)
++ return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
++ }
++ return features;
++}
++
+ static void vmxnet3_enable_encap_offloads(struct net_device *netdev)
+ {
+ struct vmxnet3_adapter *adapter = netdev_priv(netdev);
+diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
+index 5d2b062215a27..d958b92c94299 100644
+--- a/drivers/net/vmxnet3/vmxnet3_int.h
++++ b/drivers/net/vmxnet3/vmxnet3_int.h
+@@ -470,6 +470,10 @@ vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter);
+ netdev_features_t
+ vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features);
+
++netdev_features_t
++vmxnet3_features_check(struct sk_buff *skb,
++ struct net_device *netdev, netdev_features_t features);
++
+ int
+ vmxnet3_set_features(struct net_device *netdev, netdev_features_t features);
+
+--
+2.25.1
+
--- /dev/null
+From 9a61b4626f16987ee72bd78cf32c273060e119c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Sep 2020 08:50:29 +0200
+Subject: xfrm: clone whole liftime_cur structure in xfrm_do_migrate
+
+From: Antony Antony <antony.antony@secunet.com>
+
+[ Upstream commit 8366685b2883e523f91e9816d7be371eb1144749 ]
+
+When we clone state only add_time was cloned. It missed values like
+bytes, packets. Now clone the all members of the structure.
+
+v1->v3:
+ - use memcpy to copy the entire structure
+
+Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)")
+Signed-off-by: Antony Antony <antony.antony@secunet.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 3a2c1f15d31dd..6b431a3830721 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1550,7 +1550,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+ x->tfcpad = orig->tfcpad;
+ x->replay_maxdiff = orig->replay_maxdiff;
+ x->replay_maxage = orig->replay_maxage;
+- x->curlft.add_time = orig->curlft.add_time;
++ memcpy(&x->curlft, &orig->curlft, sizeof(x->curlft));
+ x->km.state = orig->km.state;
+ x->km.seq = orig->km.seq;
+ x->replay = orig->replay;
+--
+2.25.1
+
--- /dev/null
+From 120ca7918e12c6d70eebbb2f020a9e6269b362ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Sep 2020 08:49:55 +0200
+Subject: xfrm: clone XFRMA_REPLAY_ESN_VAL in xfrm_do_migrate
+
+From: Antony Antony <antony.antony@secunet.com>
+
+[ Upstream commit 91a46c6d1b4fcbfa4773df9421b8ad3e58088101 ]
+
+XFRMA_REPLAY_ESN_VAL was not cloned completely from the old to the new.
+Migrate this attribute during XFRMA_MSG_MIGRATE
+
+v1->v2:
+ - move curleft cloning to a separate patch
+
+Fixes: af2f464e326e ("xfrm: Assign esn pointers when cloning a state")
+Signed-off-by: Antony Antony <antony.antony@secunet.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xfrm.h | 16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 51f65d23ebafa..2e32cb10ac16b 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -1767,21 +1767,17 @@ static inline unsigned int xfrm_replay_state_esn_len(struct xfrm_replay_state_es
+ static inline int xfrm_replay_clone(struct xfrm_state *x,
+ struct xfrm_state *orig)
+ {
+- x->replay_esn = kzalloc(xfrm_replay_state_esn_len(orig->replay_esn),
++
++ x->replay_esn = kmemdup(orig->replay_esn,
++ xfrm_replay_state_esn_len(orig->replay_esn),
+ GFP_KERNEL);
+ if (!x->replay_esn)
+ return -ENOMEM;
+-
+- x->replay_esn->bmp_len = orig->replay_esn->bmp_len;
+- x->replay_esn->replay_window = orig->replay_esn->replay_window;
+-
+- x->preplay_esn = kmemdup(x->replay_esn,
+- xfrm_replay_state_esn_len(x->replay_esn),
++ x->preplay_esn = kmemdup(orig->preplay_esn,
++ xfrm_replay_state_esn_len(orig->preplay_esn),
+ GFP_KERNEL);
+- if (!x->preplay_esn) {
+- kfree(x->replay_esn);
++ if (!x->preplay_esn)
+ return -ENOMEM;
+- }
+
+ return 0;
+ }
+--
+2.25.1
+
--- /dev/null
+From d2586ede1aee870625c6c631945e4c6805a179fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Sep 2020 08:50:11 +0200
+Subject: xfrm: clone XFRMA_SEC_CTX in xfrm_do_migrate
+
+From: Antony Antony <antony.antony@secunet.com>
+
+[ Upstream commit 7aa05d304785204703a67a6aa7f1db402889a172 ]
+
+XFRMA_SEC_CTX was not cloned from the old to the new.
+Migrate this attribute during XFRMA_MSG_MIGRATE
+
+v1->v2:
+ - return -ENOMEM on error
+v2->v3:
+ - fix return type to int
+
+Fixes: 80c9abaabf42 ("[XFRM]: Extension for dynamic update of endpoint address(es)")
+Signed-off-by: Antony Antony <antony.antony@secunet.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 8ec3a6a12dd34..3a2c1f15d31dd 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1441,6 +1441,30 @@ out:
+ EXPORT_SYMBOL(xfrm_state_add);
+
+ #ifdef CONFIG_XFRM_MIGRATE
++static inline int clone_security(struct xfrm_state *x, struct xfrm_sec_ctx *security)
++{
++ struct xfrm_user_sec_ctx *uctx;
++ int size = sizeof(*uctx) + security->ctx_len;
++ int err;
++
++ uctx = kmalloc(size, GFP_KERNEL);
++ if (!uctx)
++ return -ENOMEM;
++
++ uctx->exttype = XFRMA_SEC_CTX;
++ uctx->len = size;
++ uctx->ctx_doi = security->ctx_doi;
++ uctx->ctx_alg = security->ctx_alg;
++ uctx->ctx_len = security->ctx_len;
++ memcpy(uctx + 1, security->ctx_str, security->ctx_len);
++ err = security_xfrm_state_alloc(x, uctx);
++ kfree(uctx);
++ if (err)
++ return err;
++
++ return 0;
++}
++
+ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+ struct xfrm_encap_tmpl *encap)
+ {
+@@ -1497,6 +1521,10 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+ goto error;
+ }
+
++ if (orig->security)
++ if (clone_security(x, orig->security))
++ goto error;
++
+ if (orig->coaddr) {
+ x->coaddr = kmemdup(orig->coaddr, sizeof(*x->coaddr),
+ GFP_KERNEL);
+--
+2.25.1
+
--- /dev/null
+From cf6513a3038dfd88448d5f2db01fc6cc31808b9b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Sep 2020 08:49:38 +0200
+Subject: xfrm: clone XFRMA_SET_MARK in xfrm_do_migrate
+
+From: Antony Antony <antony.antony@secunet.com>
+
+[ Upstream commit 545e5c571662b1cd79d9588f9d3b6e36985b8007 ]
+
+XFRMA_SET_MARK and XFRMA_SET_MARK_MASK was not cloned from the old
+to the new. Migrate these two attributes during XFRMA_MSG_MIGRATE
+
+Fixes: 9b42c1f179a6 ("xfrm: Extend the output_mark to support input direction and masking.")
+Signed-off-by: Antony Antony <antony.antony@secunet.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 8be2d926acc21..8ec3a6a12dd34 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1510,6 +1510,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+ }
+
+ memcpy(&x->mark, &orig->mark, sizeof(x->mark));
++ memcpy(&x->props.smark, &orig->props.smark, sizeof(x->props.smark));
+
+ if (xfrm_init_state(x) < 0)
+ goto error;
+--
+2.25.1
+
--- /dev/null
+From b05b44fbe46e60572c96afecee04829e4df41743 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Sep 2020 14:42:56 +1000
+Subject: xfrm: Use correct address family in xfrm_state_find
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+[ Upstream commit e94ee171349db84c7cfdc5fefbebe414054d0924 ]
+
+The struct flowi must never be interpreted by itself as its size
+depends on the address family. Therefore it must always be grouped
+with its original family value.
+
+In this particular instance, the original family value is lost in
+the function xfrm_state_find. Therefore we get a bogus read when
+it's coupled with the wrong family which would occur with inter-
+family xfrm states.
+
+This patch fixes it by keeping the original family value.
+
+Note that the same bug could potentially occur in LSM through
+the xfrm_state_pol_flow_match hook. I checked the current code
+there and it seems to be safe for now as only secid is used which
+is part of struct flowi_common. But that API should be changed
+so that so that we don't get new bugs in the future. We could
+do that by replacing fl with just secid or adding a family field.
+
+Reported-by: syzbot+577fbac3145a6eb2e7a5@syzkaller.appspotmail.com
+Fixes: 48b8d78315bf ("[XFRM]: State selection update to use inner...")
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 6b431a3830721..158510cd34ae8 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1019,7 +1019,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
+ */
+ if (x->km.state == XFRM_STATE_VALID) {
+ if ((x->sel.family &&
+- !xfrm_selector_match(&x->sel, fl, x->sel.family)) ||
++ (x->sel.family != family ||
++ !xfrm_selector_match(&x->sel, fl, family))) ||
+ !security_xfrm_state_pol_flow_match(x, pol, fl))
+ return;
+
+@@ -1032,7 +1033,9 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
+ *acq_in_progress = 1;
+ } else if (x->km.state == XFRM_STATE_ERROR ||
+ x->km.state == XFRM_STATE_EXPIRED) {
+- if (xfrm_selector_match(&x->sel, fl, x->sel.family) &&
++ if ((!x->sel.family ||
++ (x->sel.family == family &&
++ xfrm_selector_match(&x->sel, fl, family))) &&
+ security_xfrm_state_pol_flow_match(x, pol, fl))
+ *error = -ESRCH;
+ }
+@@ -1072,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
+ tmpl->mode == x->props.mode &&
+ tmpl->id.proto == x->id.proto &&
+ (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
+- xfrm_state_look_at(pol, x, fl, encap_family,
++ xfrm_state_look_at(pol, x, fl, family,
+ &best, &acquire_in_progress, &error);
+ }
+ if (best || acquire_in_progress)
+@@ -1089,7 +1092,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
+ tmpl->mode == x->props.mode &&
+ tmpl->id.proto == x->id.proto &&
+ (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
+- xfrm_state_look_at(pol, x, fl, encap_family,
++ xfrm_state_look_at(pol, x, fl, family,
+ &best, &acquire_in_progress, &error);
+ }
+
+--
+2.25.1
+
--- /dev/null
+From 5ad4437b7eb8ffe86631333e2d93ef35d0c5a55a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Sep 2020 14:00:25 +0200
+Subject: xsk: Do not discard packet when NETDEV_TX_BUSY
+
+From: Magnus Karlsson <magnus.karlsson@intel.com>
+
+[ Upstream commit 642e450b6b5955f2059d0ae372183f7c6323f951 ]
+
+In the skb Tx path, transmission of a packet is performed with
+dev_direct_xmit(). When NETDEV_TX_BUSY is set in the drivers, it
+signifies that it was not possible to send the packet right now,
+please try later. Unfortunately, the xsk transmit code discarded the
+packet and returned EBUSY to the application. Fix this unnecessary
+packet loss, by not discarding the packet in the Tx ring and return
+EAGAIN. As EAGAIN is returned to the application, it can then retry
+the send operation later and the packet will then likely be sent as
+the driver will then likely have space/resources to send the packet.
+
+In summary, EAGAIN tells the application that the packet was not
+discarded from the Tx ring and that it needs to call send()
+again. EBUSY, on the other hand, signifies that the packet was not
+sent and discarded from the Tx ring. The application needs to put
+the packet on the Tx ring again if it wants it to be sent.
+
+Fixes: 35fcde7f8deb ("xsk: support for Tx")
+Reported-by: Arkadiusz Zema <A.Zema@falconvsystems.com>
+Suggested-by: Arkadiusz Zema <A.Zema@falconvsystems.com>
+Suggested-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Magnus Karlsson <magnus.karlsson@intel.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Link: https://lore.kernel.org/bpf/1600257625-2353-1-git-send-email-magnus.karlsson@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xsk.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index 3700266229f63..dcce888b8ef54 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -375,15 +375,30 @@ static int xsk_generic_xmit(struct sock *sk)
+ skb_shinfo(skb)->destructor_arg = (void *)(long)desc.addr;
+ skb->destructor = xsk_destruct_skb;
+
++ /* Hinder dev_direct_xmit from freeing the packet and
++ * therefore completing it in the destructor
++ */
++ refcount_inc(&skb->users);
+ err = dev_direct_xmit(skb, xs->queue_id);
++ if (err == NETDEV_TX_BUSY) {
++ /* Tell user-space to retry the send */
++ skb->destructor = sock_wfree;
++ /* Free skb without triggering the perf drop trace */
++ consume_skb(skb);
++ err = -EAGAIN;
++ goto out;
++ }
++
+ xskq_cons_release(xs->tx);
+ /* Ignore NET_XMIT_CN as packet might have been sent */
+- if (err == NET_XMIT_DROP || err == NETDEV_TX_BUSY) {
++ if (err == NET_XMIT_DROP) {
+ /* SKB completed but not sent */
++ kfree_skb(skb);
+ err = -EBUSY;
+ goto out;
+ }
+
++ consume_skb(skb);
+ sent_frame = true;
+ }
+
+--
+2.25.1
+