--- /dev/null
+From e40d0d60d2c1e1cf43d222db49ed94322e32d6f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Jul 2022 17:26:29 -0400
+Subject: __follow_mount_rcu(): verify that mount_lock remains unchanged
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 20aac6c60981f5bfacd66661d090d907bf1482f0 ]
+
+Validate mount_lock seqcount as soon as we cross into mount in RCU
+mode. Sure, ->mnt_root is pinned and will remain so until we
+do rcu_read_unlock() anyway, and we will eventually fail to unlazy if
+the mount_lock had been touched, but we might run into a hard error
+(e.g. -ENOENT) before trying to unlazy. And it's possible to end
+up with RCU pathwalk racing with rename() and umount() in a way
+that would fail with -ENOENT while non-RCU pathwalk would've
+succeeded with any timings.
+
+Once upon a time we hadn't needed that, but analysis had been subtle,
+brittle and went out of window as soon as RENAME_EXCHANGE had been
+added.
+
+It's narrow, hard to hit and won't get you anything other than
+stray -ENOENT that could be arranged in much easier way with the
+same priveleges, but it's a bug all the same.
+
+Cc: stable@kernel.org
+X-sky-is-falling: unlikely
+Fixes: da1ce0670c14 "vfs: add cross-rename"
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/namei.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 66e0fe262a89..1fd854d4cd2c 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1461,6 +1461,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
+ * becoming unpinned.
+ */
+ flags = dentry->d_flags;
++ if (read_seqretry(&mount_lock, nd->m_seq))
++ return false;
+ continue;
+ }
+ if (read_seqretry(&mount_lock, nd->m_seq))
+--
+2.35.1
+
--- /dev/null
+From 17cafc5c8190f0164683e76dd6d0bc673a2679af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Jul 2022 19:41:10 +0200
+Subject: ACPI: CPPC: Do not prevent CPPC from working in the future
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 4f4179fcf420873002035cf1941d844c9e0e7cb3 ]
+
+There is a problem with the current revision checks in
+is_cppc_supported() that they essentially prevent the CPPC support
+from working if a new _CPC package format revision being a proper
+superset of the v3 and only causing _CPC to return a package with more
+entries (while retaining the types and meaning of the entries defined by
+the v3) is introduced in the future and used by the platform firmware.
+
+In that case, as long as the number of entries in the _CPC return
+package is at least CPPC_V3_NUM_ENT, it should be perfectly fine to
+use the v3 support code and disregard the additional package entries
+added by the new package format revision.
+
+For this reason, drop is_cppc_supported() altogether, put the revision
+checks directly into acpi_cppc_processor_probe() so they are easier to
+follow and rework them to take the case mentioned above into account.
+
+Fixes: 4773e77cdc9b ("ACPI / CPPC: Add support for CPPC v3")
+Cc: 4.18+ <stable@vger.kernel.org> # 4.18+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/cppc_acpi.c | 54 ++++++++++++++++++----------------------
+ include/acpi/cppc_acpi.h | 2 +-
+ 2 files changed, 25 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index ed1341030684..7cc9183c8dc8 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -597,33 +597,6 @@ static int pcc_data_alloc(int pcc_ss_id)
+ return 0;
+ }
+
+-/* Check if CPPC revision + num_ent combination is supported */
+-static bool is_cppc_supported(int revision, int num_ent)
+-{
+- int expected_num_ent;
+-
+- switch (revision) {
+- case CPPC_V2_REV:
+- expected_num_ent = CPPC_V2_NUM_ENT;
+- break;
+- case CPPC_V3_REV:
+- expected_num_ent = CPPC_V3_NUM_ENT;
+- break;
+- default:
+- pr_debug("Firmware exports unsupported CPPC revision: %d\n",
+- revision);
+- return false;
+- }
+-
+- if (expected_num_ent != num_ent) {
+- pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n",
+- num_ent, expected_num_ent, revision);
+- return false;
+- }
+-
+- return true;
+-}
+-
+ /*
+ * An example CPC table looks like the following.
+ *
+@@ -723,7 +696,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ cpc_obj->type);
+ goto out_free;
+ }
+- cpc_ptr->num_entries = num_ent;
+
+ /* Second entry should be revision. */
+ cpc_obj = &out_obj->package.elements[1];
+@@ -734,10 +706,32 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ cpc_obj->type);
+ goto out_free;
+ }
+- cpc_ptr->version = cpc_rev;
+
+- if (!is_cppc_supported(cpc_rev, num_ent))
++ if (cpc_rev < CPPC_V2_REV) {
++ pr_debug("Unsupported _CPC Revision (%d) for CPU:%d\n", cpc_rev,
++ pr->id);
++ goto out_free;
++ }
++
++ /*
++ * Disregard _CPC if the number of entries in the return pachage is not
++ * as expected, but support future revisions being proper supersets of
++ * the v3 and only causing more entries to be returned by _CPC.
++ */
++ if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) ||
++ (cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) ||
++ (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) {
++ pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n",
++ num_ent, pr->id);
+ goto out_free;
++ }
++ if (cpc_rev > CPPC_V3_REV) {
++ num_ent = CPPC_V3_NUM_ENT;
++ cpc_rev = CPPC_V3_REV;
++ }
++
++ cpc_ptr->num_entries = num_ent;
++ cpc_ptr->version = cpc_rev;
+
+ /* Iterate through remaining entries in _CPC */
+ for (i = 2; i < num_ent; i++) {
+diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
+index bc159a9b4a73..6b14414b9ec1 100644
+--- a/include/acpi/cppc_acpi.h
++++ b/include/acpi/cppc_acpi.h
+@@ -17,7 +17,7 @@
+ #include <acpi/pcc.h>
+ #include <acpi/processor.h>
+
+-/* Support CPPCv2 and CPPCv3 */
++/* CPPCv2 and CPPCv3 support */
+ #define CPPC_V2_REV 2
+ #define CPPC_V3_REV 3
+ #define CPPC_V2_NUM_ENT 21
+--
+2.35.1
+
--- /dev/null
+From c31c587677dced7d7175db5a9f0873480eb388fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Oct 2021 09:15:34 +0200
+Subject: ARM: remove some dead code
+
+From: Ard Biesheuvel <ardb@kernel.org>
+
+[ Upstream commit 08572cd41955166e387d9b4984294d37f8f7526c ]
+
+This code appears to be no longer used so let's get rid of it.
+
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Linus Walleij <linus.walleij@linaro.org>
+Tested-by: Keith Packard <keithpac@amazon.com>
+Tested-by: Marc Zyngier <maz@kernel.org>
+Tested-by: Vladimir Murzin <vladimir.murzin@arm.com> # ARMv7M
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/include/asm/entry-macro-multi.S | 24 ------------------------
+ arch/arm/include/asm/smp.h | 5 -----
+ arch/arm/kernel/smp.c | 5 -----
+ 3 files changed, 34 deletions(-)
+
+diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
+index dfc6bfa43012..24486dad9e19 100644
+--- a/arch/arm/include/asm/entry-macro-multi.S
++++ b/arch/arm/include/asm/entry-macro-multi.S
+@@ -13,28 +13,4 @@
+ @
+ badrne lr, 1b
+ bne asm_do_IRQ
+-
+-#ifdef CONFIG_SMP
+- /*
+- * XXX
+- *
+- * this macro assumes that irqstat (r2) and base (r6) are
+- * preserved from get_irqnr_and_base above
+- */
+- ALT_SMP(test_for_ipi r0, r2, r6, lr)
+- ALT_UP_B(9997f)
+- movne r1, sp
+- badrne lr, 1b
+- bne do_IPI
+-#endif
+-9997:
+- .endm
+-
+- .macro arch_irq_handler, symbol_name
+- .align 5
+- .global \symbol_name
+-\symbol_name:
+- mov r8, lr
+- arch_irq_handler_default
+- ret r8
+ .endm
+diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
+index 5d508f5d56c4..fc11ddf13b8f 100644
+--- a/arch/arm/include/asm/smp.h
++++ b/arch/arm/include/asm/smp.h
+@@ -24,11 +24,6 @@ struct seq_file;
+ */
+ extern void show_ipi_list(struct seq_file *, int);
+
+-/*
+- * Called from assembly code, this handles an IPI.
+- */
+-asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
+-
+ /*
+ * Called from C code, this handles an IPI.
+ */
+diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
+index 842427ff2b3c..23d369ab7e03 100644
+--- a/arch/arm/kernel/smp.c
++++ b/arch/arm/kernel/smp.c
+@@ -622,11 +622,6 @@ static void ipi_complete(unsigned int cpu)
+ /*
+ * Main handler for inter-processor interrupts
+ */
+-asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
+-{
+- handle_IPI(ipinr, regs);
+-}
+-
+ static void do_handle_IPI(int ipinr)
+ {
+ unsigned int cpu = smp_processor_id();
+--
+2.35.1
+
--- /dev/null
+From ef0f2fd061fc2f3fe75df0dc806453625cc94a6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Jul 2022 17:36:16 +0800
+Subject: block: don't allow the same type rq_qos add more than once
+
+From: Jinke Han <hanjinke.666@bytedance.com>
+
+[ Upstream commit 14a6e2eb7df5c7897c15b109cba29ab0c4a791b6 ]
+
+In our test of iocost, we encountered some list add/del corruptions of
+inner_walk list in ioc_timer_fn.
+
+The reason can be described as follows:
+
+cpu 0 cpu 1
+ioc_qos_write ioc_qos_write
+
+ioc = q_to_ioc(queue);
+if (!ioc) {
+ ioc = kzalloc();
+ ioc = q_to_ioc(queue);
+ if (!ioc) {
+ ioc = kzalloc();
+ ...
+ rq_qos_add(q, rqos);
+ }
+ ...
+ rq_qos_add(q, rqos);
+ ...
+}
+
+When the io.cost.qos file is written by two cpus concurrently, rq_qos may
+be added to one disk twice. In that case, there will be two iocs enabled
+and running on one disk. They own different iocgs on their active list. In
+the ioc_timer_fn function, because of the iocgs from two iocs have the
+same root iocg, the root iocg's walk_list may be overwritten by each other
+and this leads to list add/del corruptions in building or destroying the
+inner_walk list.
+
+And so far, the blk-rq-qos framework works in case that one instance for
+one type rq_qos per queue by default. This patch make this explicit and
+also fix the crash above.
+
+Signed-off-by: Jinke Han <hanjinke.666@bytedance.com>
+Reviewed-by: Muchun Song <songmuchun@bytedance.com>
+Acked-by: Tejun Heo <tj@kernel.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20220720093616.70584-1-hanjinke.666@bytedance.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-iocost.c | 20 +++++++++++++-------
+ block/blk-iolatency.c | 18 +++++++++++-------
+ block/blk-rq-qos.h | 11 ++++++++++-
+ block/blk-wbt.c | 12 +++++++++++-
+ 4 files changed, 45 insertions(+), 16 deletions(-)
+
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 10851493940c..069193dee95b 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -2893,15 +2893,21 @@ static int blk_iocost_init(struct request_queue *q)
+ * called before policy activation completion, can't assume that the
+ * target bio has an iocg associated and need to test for NULL iocg.
+ */
+- rq_qos_add(q, rqos);
++ ret = rq_qos_add(q, rqos);
++ if (ret)
++ goto err_free_ioc;
++
+ ret = blkcg_activate_policy(q, &blkcg_policy_iocost);
+- if (ret) {
+- rq_qos_del(q, rqos);
+- free_percpu(ioc->pcpu_stat);
+- kfree(ioc);
+- return ret;
+- }
++ if (ret)
++ goto err_del_qos;
+ return 0;
++
++err_del_qos:
++ rq_qos_del(q, rqos);
++err_free_ioc:
++ free_percpu(ioc->pcpu_stat);
++ kfree(ioc);
++ return ret;
+ }
+
+ static struct blkcg_policy_data *ioc_cpd_alloc(gfp_t gfp)
+diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
+index d85f30a85ee7..bdef8395af6e 100644
+--- a/block/blk-iolatency.c
++++ b/block/blk-iolatency.c
+@@ -772,19 +772,23 @@ int blk_iolatency_init(struct request_queue *q)
+ rqos->ops = &blkcg_iolatency_ops;
+ rqos->q = q;
+
+- rq_qos_add(q, rqos);
+-
++ ret = rq_qos_add(q, rqos);
++ if (ret)
++ goto err_free;
+ ret = blkcg_activate_policy(q, &blkcg_policy_iolatency);
+- if (ret) {
+- rq_qos_del(q, rqos);
+- kfree(blkiolat);
+- return ret;
+- }
++ if (ret)
++ goto err_qos_del;
+
+ timer_setup(&blkiolat->timer, blkiolatency_timer_fn, 0);
+ INIT_WORK(&blkiolat->enable_work, blkiolatency_enable_work_fn);
+
+ return 0;
++
++err_qos_del:
++ rq_qos_del(q, rqos);
++err_free:
++ kfree(blkiolat);
++ return ret;
+ }
+
+ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
+diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h
+index 68267007da1c..1655f76b6a1b 100644
+--- a/block/blk-rq-qos.h
++++ b/block/blk-rq-qos.h
+@@ -86,7 +86,7 @@ static inline void rq_wait_init(struct rq_wait *rq_wait)
+ init_waitqueue_head(&rq_wait->wait);
+ }
+
+-static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
++static inline int rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
+ {
+ /*
+ * No IO can be in-flight when adding rqos, so freeze queue, which
+@@ -98,6 +98,8 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
+ blk_mq_freeze_queue(q);
+
+ spin_lock_irq(&q->queue_lock);
++ if (rq_qos_id(q, rqos->id))
++ goto ebusy;
+ rqos->next = q->rq_qos;
+ q->rq_qos = rqos;
+ spin_unlock_irq(&q->queue_lock);
+@@ -106,6 +108,13 @@ static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
+
+ if (rqos->ops->debugfs_attrs)
+ blk_mq_debugfs_register_rqos(rqos);
++
++ return 0;
++ebusy:
++ spin_unlock_irq(&q->queue_lock);
++ blk_mq_unfreeze_queue(q);
++ return -EBUSY;
++
+ }
+
+ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos)
+diff --git a/block/blk-wbt.c b/block/blk-wbt.c
+index 0c119be0e813..ae6ea0b54579 100644
+--- a/block/blk-wbt.c
++++ b/block/blk-wbt.c
+@@ -820,6 +820,7 @@ int wbt_init(struct request_queue *q)
+ {
+ struct rq_wb *rwb;
+ int i;
++ int ret;
+
+ rwb = kzalloc(sizeof(*rwb), GFP_KERNEL);
+ if (!rwb)
+@@ -846,7 +847,10 @@ int wbt_init(struct request_queue *q)
+ /*
+ * Assign rwb and add the stats callback.
+ */
+- rq_qos_add(q, &rwb->rqos);
++ ret = rq_qos_add(q, &rwb->rqos);
++ if (ret)
++ goto err_free;
++
+ blk_stat_add_callback(q, rwb->cb);
+
+ rwb->min_lat_nsec = wbt_default_latency_nsec(q);
+@@ -855,4 +859,10 @@ int wbt_init(struct request_queue *q)
+ wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
+
+ return 0;
++
++err_free:
++ blk_stat_free_callback(rwb->cb);
++ kfree(rwb);
++ return ret;
++
+ }
+--
+2.35.1
+
--- /dev/null
+From 5f5103d02c0fcb8444d03ad19e6686db42d157de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Sep 2021 14:33:22 +0200
+Subject: block: remove the struct blk_queue_ctx forward declaration
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 9778ac77c2027827ffdbb33d3e936b3a0ae9f0f9 ]
+
+This type doesn't exist at all, so no need to forward declare it.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Link: https://lore.kernel.org/r/20210920123328.1399408-12-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/blkdev.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index aebe67ed7a73..8863b4a378af 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -261,8 +261,6 @@ static inline unsigned short req_get_ioprio(struct request *req)
+
+ #include <linux/elevator.h>
+
+-struct blk_queue_ctx;
+-
+ struct bio_vec;
+
+ enum blk_eh_timer_return {
+--
+2.35.1
+
--- /dev/null
+From a4558e5dece194a423b115a2dbd28ff7850f6208 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 21 Jun 2022 15:40:59 +0900
+Subject: btrfs: ensure pages are unlocked on cow_file_range() failure
+
+From: Naohiro Aota <naohiro.aota@wdc.com>
+
+[ Upstream commit 9ce7466f372d83054c7494f6b3e4b9abaf3f0355 ]
+
+There is a hung_task report on zoned btrfs like below.
+
+https://github.com/naota/linux/issues/59
+
+ [726.328648] INFO: task rocksdb:high0:11085 blocked for more than 241 seconds.
+ [726.329839] Not tainted 5.16.0-rc1+ #1
+ [726.330484] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+ [726.331603] task:rocksdb:high0 state:D stack: 0 pid:11085 ppid: 11082 flags:0x00000000
+ [726.331608] Call Trace:
+ [726.331611] <TASK>
+ [726.331614] __schedule+0x2e5/0x9d0
+ [726.331622] schedule+0x58/0xd0
+ [726.331626] io_schedule+0x3f/0x70
+ [726.331629] __folio_lock+0x125/0x200
+ [726.331634] ? find_get_entries+0x1bc/0x240
+ [726.331638] ? filemap_invalidate_unlock_two+0x40/0x40
+ [726.331642] truncate_inode_pages_range+0x5b2/0x770
+ [726.331649] truncate_inode_pages_final+0x44/0x50
+ [726.331653] btrfs_evict_inode+0x67/0x480
+ [726.331658] evict+0xd0/0x180
+ [726.331661] iput+0x13f/0x200
+ [726.331664] do_unlinkat+0x1c0/0x2b0
+ [726.331668] __x64_sys_unlink+0x23/0x30
+ [726.331670] do_syscall_64+0x3b/0xc0
+ [726.331674] entry_SYSCALL_64_after_hwframe+0x44/0xae
+ [726.331677] RIP: 0033:0x7fb9490a171b
+ [726.331681] RSP: 002b:00007fb943ffac68 EFLAGS: 00000246 ORIG_RAX: 0000000000000057
+ [726.331684] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fb9490a171b
+ [726.331686] RDX: 00007fb943ffb040 RSI: 000055a6bbe6ec20 RDI: 00007fb94400d300
+ [726.331687] RBP: 00007fb943ffad00 R08: 0000000000000000 R09: 0000000000000000
+ [726.331688] R10: 0000000000000031 R11: 0000000000000246 R12: 00007fb943ffb000
+ [726.331690] R13: 00007fb943ffb040 R14: 0000000000000000 R15: 00007fb943ffd260
+ [726.331693] </TASK>
+
+While we debug the issue, we found running fstests generic/551 on 5GB
+non-zoned null_blk device in the emulated zoned mode also had a
+similar hung issue.
+
+Also, we can reproduce the same symptom with an error injected
+cow_file_range() setup.
+
+The hang occurs when cow_file_range() fails in the middle of
+allocation. cow_file_range() called from do_allocation_zoned() can
+split the give region ([start, end]) for allocation depending on
+current block group usages. When btrfs can allocate bytes for one part
+of the split regions but fails for the other region (e.g. because of
+-ENOSPC), we return the error leaving the pages in the succeeded regions
+locked. Technically, this occurs only when @unlock == 0. Otherwise, we
+unlock the pages in an allocated region after creating an ordered
+extent.
+
+Considering the callers of cow_file_range(unlock=0) won't write out
+the pages, we can unlock the pages on error exit from
+cow_file_range(). So, we can ensure all the pages except @locked_page
+are unlocked on error case.
+
+In summary, cow_file_range now behaves like this:
+
+- page_started == 1 (return value)
+ - All the pages are unlocked. IO is started.
+- unlock == 1
+ - All the pages except @locked_page are unlocked in any case
+- unlock == 0
+ - On success, all the pages are locked for writing out them
+ - On failure, all the pages except @locked_page are unlocked
+
+Fixes: 42c011000963 ("btrfs: zoned: introduce dedicated data write path for zoned filesystems")
+CC: stable@vger.kernel.org # 5.12+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 72 ++++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 64 insertions(+), 8 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 1b4fee8a2f28..20d0dea1d0c4 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1053,6 +1053,28 @@ static u64 get_extent_allocation_hint(struct btrfs_inode *inode, u64 start,
+ * *page_started is set to one if we unlock locked_page and do everything
+ * required to start IO on it. It may be clean and already done with
+ * IO when we return.
++ *
++ * When unlock == 1, we unlock the pages in successfully allocated regions.
++ * When unlock == 0, we leave them locked for writing them out.
++ *
++ * However, we unlock all the pages except @locked_page in case of failure.
++ *
++ * In summary, page locking state will be as follow:
++ *
++ * - page_started == 1 (return value)
++ * - All the pages are unlocked. IO is started.
++ * - Note that this can happen only on success
++ * - unlock == 1
++ * - All the pages except @locked_page are unlocked in any case
++ * - unlock == 0
++ * - On success, all the pages are locked for writing out them
++ * - On failure, all the pages except @locked_page are unlocked
++ *
++ * When a failure happens in the second or later iteration of the
++ * while-loop, the ordered extents created in previous iterations are kept
++ * intact. So, the caller must clean them up by calling
++ * btrfs_cleanup_ordered_extents(). See btrfs_run_delalloc_range() for
++ * example.
+ */
+ static noinline int cow_file_range(struct btrfs_inode *inode,
+ struct page *locked_page,
+@@ -1062,6 +1084,7 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+ struct btrfs_root *root = inode->root;
+ struct btrfs_fs_info *fs_info = root->fs_info;
+ u64 alloc_hint = 0;
++ u64 orig_start = start;
+ u64 num_bytes;
+ unsigned long ram_size;
+ u64 cur_alloc_size = 0;
+@@ -1245,18 +1268,44 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+ btrfs_dec_block_group_reservations(fs_info, ins.objectid);
+ btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
+ out_unlock:
++ /*
++ * Now, we have three regions to clean up:
++ *
++ * |-------(1)----|---(2)---|-------------(3)----------|
++ * `- orig_start `- start `- start + cur_alloc_size `- end
++ *
++ * We process each region below.
++ */
++
+ clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+ EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV;
+ page_ops = PAGE_UNLOCK | PAGE_START_WRITEBACK | PAGE_END_WRITEBACK;
++
+ /*
+- * If we reserved an extent for our delalloc range (or a subrange) and
+- * failed to create the respective ordered extent, then it means that
+- * when we reserved the extent we decremented the extent's size from
+- * the data space_info's bytes_may_use counter and incremented the
+- * space_info's bytes_reserved counter by the same amount. We must make
+- * sure extent_clear_unlock_delalloc() does not try to decrement again
+- * the data space_info's bytes_may_use counter, therefore we do not pass
+- * it the flag EXTENT_CLEAR_DATA_RESV.
++ * For the range (1). We have already instantiated the ordered extents
++ * for this region. They are cleaned up by
++ * btrfs_cleanup_ordered_extents() in e.g,
++ * btrfs_run_delalloc_range(). EXTENT_LOCKED | EXTENT_DELALLOC are
++ * already cleared in the above loop. And, EXTENT_DELALLOC_NEW |
++ * EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV are handled by the cleanup
++ * function.
++ *
++ * However, in case of unlock == 0, we still need to unlock the pages
++ * (except @locked_page) to ensure all the pages are unlocked.
++ */
++ if (!unlock && orig_start < start)
++ extent_clear_unlock_delalloc(inode, orig_start, start - 1,
++ locked_page, 0, page_ops);
++
++ /*
++ * For the range (2). If we reserved an extent for our delalloc range
++ * (or a subrange) and failed to create the respective ordered extent,
++ * then it means that when we reserved the extent we decremented the
++ * extent's size from the data space_info's bytes_may_use counter and
++ * incremented the space_info's bytes_reserved counter by the same
++ * amount. We must make sure extent_clear_unlock_delalloc() does not try
++ * to decrement again the data space_info's bytes_may_use counter,
++ * therefore we do not pass it the flag EXTENT_CLEAR_DATA_RESV.
+ */
+ if (extent_reserved) {
+ extent_clear_unlock_delalloc(inode, start,
+@@ -1268,6 +1317,13 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
+ if (start >= end)
+ goto out;
+ }
++
++ /*
++ * For the range (3). We never touched the region. In addition to the
++ * clear_bits above, we add EXTENT_CLEAR_DATA_RESV to release the data
++ * space_info's bytes_may_use counter, reserved in
++ * btrfs_check_data_free_space().
++ */
+ extent_clear_unlock_delalloc(inode, start, end, locked_page,
+ clear_bits | EXTENT_CLEAR_DATA_RESV,
+ page_ops);
+--
+2.35.1
+
--- /dev/null
+From 6b607f1c8790fef2b56dd25d1d5caaff57970c9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 10:55:47 +0300
+Subject: btrfs: properly flag filesystem with
+ BTRFS_FEATURE_INCOMPAT_BIG_METADATA
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+[ Upstream commit e26b04c4c91925dba57324db177a24e18e2d0013 ]
+
+Commit 6f93e834fa7c seemingly inadvertently moved the code responsible
+for flagging the filesystem as having BIG_METADATA to a place where
+setting the flag was essentially lost. This means that
+filesystems created with kernels containing this bug (starting with 5.15)
+can potentially be mounted by older (pre-3.4) kernels. In reality
+chances for this happening are low because there are other incompat
+flags introduced in the mean time. Still the correct behavior is to set
+INCOMPAT_BIG_METADATA flag and persist this in the superblock.
+
+Fixes: 6f93e834fa7c ("btrfs: fix upper limit for max_inline for page size 64K")
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 383e9c861306..e65c3039caf1 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -3337,16 +3337,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+ */
+ fs_info->compress_type = BTRFS_COMPRESS_ZLIB;
+
+- /*
+- * Flag our filesystem as having big metadata blocks if they are bigger
+- * than the page size.
+- */
+- if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) {
+- if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA))
+- btrfs_info(fs_info,
+- "flagging fs with big metadata feature");
+- features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;
+- }
+
+ /* Set up fs_info before parsing mount options */
+ nodesize = btrfs_super_nodesize(disk_super);
+@@ -3387,6 +3377,17 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+ if (features & BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA)
+ btrfs_info(fs_info, "has skinny extents");
+
++ /*
++ * Flag our filesystem as having big metadata blocks if they are bigger
++ * than the page size.
++ */
++ if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) {
++ if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA))
++ btrfs_info(fs_info,
++ "flagging fs with big metadata feature");
++ features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA;
++ }
++
+ /*
+ * mixed block groups end up with duplicate but slightly offset
+ * extent buffers for the same range. It leads to corruptions
+--
+2.35.1
+
--- /dev/null
+From 0775fc483ddd36d1168678ec927a972779daa0cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 18:31:17 -0400
+Subject: btrfs: reset block group chunk force if we have to wait
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 1314ca78b2c35d3e7d0f097268a2ee6dc0d369ef ]
+
+If you try to force a chunk allocation, but you race with another chunk
+allocation, you will end up waiting on the chunk allocation that just
+occurred and then allocate another chunk. If you have many threads all
+doing this at once you can way over-allocate chunks.
+
+Fix this by resetting force to NO_FORCE, that way if we think we need to
+allocate we can, otherwise we don't force another chunk allocation if
+one is already happening.
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+CC: stable@vger.kernel.org # 5.4+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/block-group.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index c6c5a22ff6e8..4b2282aa274e 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3632,6 +3632,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
+ * attempt.
+ */
+ wait_for_alloc = true;
++ force = CHUNK_ALLOC_NO_FORCE;
+ spin_unlock(&space_info->lock);
+ mutex_lock(&fs_info->chunk_mutex);
+ mutex_unlock(&fs_info->chunk_mutex);
+--
+2.35.1
+
--- /dev/null
+From c8305bb9801b29944fcf91a8e2a7690b48bcf387 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 28 May 2022 21:44:07 +0200
+Subject: crypto: blake2s - remove shash module
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit 2d16803c562ecc644803d42ba98a8e0aef9c014e ]
+
+BLAKE2s has no currently known use as an shash. Just remove all of this
+unnecessary plumbing. Removing this shash was something we talked about
+back when we were making BLAKE2s a built-in, but I simply never got
+around to doing it. So this completes that project.
+
+Importantly, this fixs a bug in which the lib code depends on
+crypto_simd_disabled_for_test, causing linker errors.
+
+Also add more alignment tests to the selftests and compare SIMD and
+non-SIMD compression functions, to make up for what we lose from
+testmgr.c.
+
+Reported-by: gaochao <gaochao49@huawei.com>
+Cc: Eric Biggers <ebiggers@kernel.org>
+Cc: Ard Biesheuvel <ardb@kernel.org>
+Cc: stable@vger.kernel.org
+Fixes: 6048fdcc5f26 ("lib/crypto: blake2s: include as built-in")
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/crypto/Kconfig | 2 +-
+ arch/arm/crypto/Makefile | 4 +-
+ arch/arm/crypto/blake2s-shash.c | 75 -----------
+ arch/x86/crypto/Makefile | 4 +-
+ arch/x86/crypto/blake2s-glue.c | 3 +-
+ arch/x86/crypto/blake2s-shash.c | 77 -----------
+ crypto/Kconfig | 20 +--
+ crypto/Makefile | 1 -
+ crypto/blake2s_generic.c | 75 -----------
+ crypto/tcrypt.c | 12 --
+ crypto/testmgr.c | 24 ----
+ crypto/testmgr.h | 217 ------------------------------
+ include/crypto/internal/blake2s.h | 108 ---------------
+ lib/crypto/blake2s-selftest.c | 41 ++++++
+ lib/crypto/blake2s.c | 37 ++++-
+ 15 files changed, 76 insertions(+), 624 deletions(-)
+ delete mode 100644 arch/arm/crypto/blake2s-shash.c
+ delete mode 100644 arch/x86/crypto/blake2s-shash.c
+ delete mode 100644 crypto/blake2s_generic.c
+
+diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
+index e4dba5461cb3..149a5bd6b88c 100644
+--- a/arch/arm/crypto/Kconfig
++++ b/arch/arm/crypto/Kconfig
+@@ -63,7 +63,7 @@ config CRYPTO_SHA512_ARM
+ using optimized ARM assembler and NEON, when available.
+
+ config CRYPTO_BLAKE2S_ARM
+- tristate "BLAKE2s digest algorithm (ARM)"
++ bool "BLAKE2s digest algorithm (ARM)"
+ select CRYPTO_ARCH_HAVE_LIB_BLAKE2S
+ help
+ BLAKE2s digest algorithm optimized with ARM scalar instructions. This
+diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
+index 0274f81cc8ea..971e74546fb1 100644
+--- a/arch/arm/crypto/Makefile
++++ b/arch/arm/crypto/Makefile
+@@ -9,8 +9,7 @@ obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
+ obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
+ obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
+ obj-$(CONFIG_CRYPTO_SHA512_ARM) += sha512-arm.o
+-obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += blake2s-arm.o
+-obj-$(if $(CONFIG_CRYPTO_BLAKE2S_ARM),y) += libblake2s-arm.o
++obj-$(CONFIG_CRYPTO_BLAKE2S_ARM) += libblake2s-arm.o
+ obj-$(CONFIG_CRYPTO_BLAKE2B_NEON) += blake2b-neon.o
+ obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
+ obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o
+@@ -32,7 +31,6 @@ sha256-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha256_neon_glue.o
+ sha256-arm-y := sha256-core.o sha256_glue.o $(sha256-arm-neon-y)
+ sha512-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha512-neon-glue.o
+ sha512-arm-y := sha512-core.o sha512-glue.o $(sha512-arm-neon-y)
+-blake2s-arm-y := blake2s-shash.o
+ libblake2s-arm-y:= blake2s-core.o blake2s-glue.o
+ blake2b-neon-y := blake2b-neon-core.o blake2b-neon-glue.o
+ sha1-arm-ce-y := sha1-ce-core.o sha1-ce-glue.o
+diff --git a/arch/arm/crypto/blake2s-shash.c b/arch/arm/crypto/blake2s-shash.c
+deleted file mode 100644
+index 763c73beea2d..000000000000
+--- a/arch/arm/crypto/blake2s-shash.c
++++ /dev/null
+@@ -1,75 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-/*
+- * BLAKE2s digest algorithm, ARM scalar implementation
+- *
+- * Copyright 2020 Google LLC
+- */
+-
+-#include <crypto/internal/blake2s.h>
+-#include <crypto/internal/hash.h>
+-
+-#include <linux/module.h>
+-
+-static int crypto_blake2s_update_arm(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen)
+-{
+- return crypto_blake2s_update(desc, in, inlen, false);
+-}
+-
+-static int crypto_blake2s_final_arm(struct shash_desc *desc, u8 *out)
+-{
+- return crypto_blake2s_final(desc, out, false);
+-}
+-
+-#define BLAKE2S_ALG(name, driver_name, digest_size) \
+- { \
+- .base.cra_name = name, \
+- .base.cra_driver_name = driver_name, \
+- .base.cra_priority = 200, \
+- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \
+- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \
+- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \
+- .base.cra_module = THIS_MODULE, \
+- .digestsize = digest_size, \
+- .setkey = crypto_blake2s_setkey, \
+- .init = crypto_blake2s_init, \
+- .update = crypto_blake2s_update_arm, \
+- .final = crypto_blake2s_final_arm, \
+- .descsize = sizeof(struct blake2s_state), \
+- }
+-
+-static struct shash_alg blake2s_arm_algs[] = {
+- BLAKE2S_ALG("blake2s-128", "blake2s-128-arm", BLAKE2S_128_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-160", "blake2s-160-arm", BLAKE2S_160_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-224", "blake2s-224-arm", BLAKE2S_224_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-256", "blake2s-256-arm", BLAKE2S_256_HASH_SIZE),
+-};
+-
+-static int __init blake2s_arm_mod_init(void)
+-{
+- return IS_REACHABLE(CONFIG_CRYPTO_HASH) ?
+- crypto_register_shashes(blake2s_arm_algs,
+- ARRAY_SIZE(blake2s_arm_algs)) : 0;
+-}
+-
+-static void __exit blake2s_arm_mod_exit(void)
+-{
+- if (IS_REACHABLE(CONFIG_CRYPTO_HASH))
+- crypto_unregister_shashes(blake2s_arm_algs,
+- ARRAY_SIZE(blake2s_arm_algs));
+-}
+-
+-module_init(blake2s_arm_mod_init);
+-module_exit(blake2s_arm_mod_exit);
+-
+-MODULE_DESCRIPTION("BLAKE2s digest algorithm, ARM scalar implementation");
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
+-MODULE_ALIAS_CRYPTO("blake2s-128");
+-MODULE_ALIAS_CRYPTO("blake2s-128-arm");
+-MODULE_ALIAS_CRYPTO("blake2s-160");
+-MODULE_ALIAS_CRYPTO("blake2s-160-arm");
+-MODULE_ALIAS_CRYPTO("blake2s-224");
+-MODULE_ALIAS_CRYPTO("blake2s-224-arm");
+-MODULE_ALIAS_CRYPTO("blake2s-256");
+-MODULE_ALIAS_CRYPTO("blake2s-256-arm");
+diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
+index c3af959648e6..fce05e9df56d 100644
+--- a/arch/x86/crypto/Makefile
++++ b/arch/x86/crypto/Makefile
+@@ -61,9 +61,7 @@ sha256-ssse3-$(CONFIG_AS_SHA256_NI) += sha256_ni_asm.o
+ obj-$(CONFIG_CRYPTO_SHA512_SSSE3) += sha512-ssse3.o
+ sha512-ssse3-y := sha512-ssse3-asm.o sha512-avx-asm.o sha512-avx2-asm.o sha512_ssse3_glue.o
+
+-obj-$(CONFIG_CRYPTO_BLAKE2S_X86) += blake2s-x86_64.o
+-blake2s-x86_64-y := blake2s-shash.o
+-obj-$(if $(CONFIG_CRYPTO_BLAKE2S_X86),y) += libblake2s-x86_64.o
++obj-$(CONFIG_CRYPTO_BLAKE2S_X86) += libblake2s-x86_64.o
+ libblake2s-x86_64-y := blake2s-core.o blake2s-glue.o
+
+ obj-$(CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL) += ghash-clmulni-intel.o
+diff --git a/arch/x86/crypto/blake2s-glue.c b/arch/x86/crypto/blake2s-glue.c
+index 69853c13e8fb..aaba21230528 100644
+--- a/arch/x86/crypto/blake2s-glue.c
++++ b/arch/x86/crypto/blake2s-glue.c
+@@ -4,7 +4,6 @@
+ */
+
+ #include <crypto/internal/blake2s.h>
+-#include <crypto/internal/simd.h>
+
+ #include <linux/types.h>
+ #include <linux/jump_label.h>
+@@ -33,7 +32,7 @@ void blake2s_compress(struct blake2s_state *state, const u8 *block,
+ /* SIMD disables preemption, so relax after processing each page. */
+ BUILD_BUG_ON(SZ_4K / BLAKE2S_BLOCK_SIZE < 8);
+
+- if (!static_branch_likely(&blake2s_use_ssse3) || !crypto_simd_usable()) {
++ if (!static_branch_likely(&blake2s_use_ssse3) || !may_use_simd()) {
+ blake2s_compress_generic(state, block, nblocks, inc);
+ return;
+ }
+diff --git a/arch/x86/crypto/blake2s-shash.c b/arch/x86/crypto/blake2s-shash.c
+deleted file mode 100644
+index 59ae28abe35c..000000000000
+--- a/arch/x86/crypto/blake2s-shash.c
++++ /dev/null
+@@ -1,77 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0 OR MIT
+-/*
+- * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+- */
+-
+-#include <crypto/internal/blake2s.h>
+-#include <crypto/internal/simd.h>
+-#include <crypto/internal/hash.h>
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/sizes.h>
+-
+-#include <asm/cpufeature.h>
+-#include <asm/processor.h>
+-
+-static int crypto_blake2s_update_x86(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen)
+-{
+- return crypto_blake2s_update(desc, in, inlen, false);
+-}
+-
+-static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out)
+-{
+- return crypto_blake2s_final(desc, out, false);
+-}
+-
+-#define BLAKE2S_ALG(name, driver_name, digest_size) \
+- { \
+- .base.cra_name = name, \
+- .base.cra_driver_name = driver_name, \
+- .base.cra_priority = 200, \
+- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \
+- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \
+- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \
+- .base.cra_module = THIS_MODULE, \
+- .digestsize = digest_size, \
+- .setkey = crypto_blake2s_setkey, \
+- .init = crypto_blake2s_init, \
+- .update = crypto_blake2s_update_x86, \
+- .final = crypto_blake2s_final_x86, \
+- .descsize = sizeof(struct blake2s_state), \
+- }
+-
+-static struct shash_alg blake2s_algs[] = {
+- BLAKE2S_ALG("blake2s-128", "blake2s-128-x86", BLAKE2S_128_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-160", "blake2s-160-x86", BLAKE2S_160_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-224", "blake2s-224-x86", BLAKE2S_224_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-256", "blake2s-256-x86", BLAKE2S_256_HASH_SIZE),
+-};
+-
+-static int __init blake2s_mod_init(void)
+-{
+- if (IS_REACHABLE(CONFIG_CRYPTO_HASH) && boot_cpu_has(X86_FEATURE_SSSE3))
+- return crypto_register_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs));
+- return 0;
+-}
+-
+-static void __exit blake2s_mod_exit(void)
+-{
+- if (IS_REACHABLE(CONFIG_CRYPTO_HASH) && boot_cpu_has(X86_FEATURE_SSSE3))
+- crypto_unregister_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs));
+-}
+-
+-module_init(blake2s_mod_init);
+-module_exit(blake2s_mod_exit);
+-
+-MODULE_ALIAS_CRYPTO("blake2s-128");
+-MODULE_ALIAS_CRYPTO("blake2s-128-x86");
+-MODULE_ALIAS_CRYPTO("blake2s-160");
+-MODULE_ALIAS_CRYPTO("blake2s-160-x86");
+-MODULE_ALIAS_CRYPTO("blake2s-224");
+-MODULE_ALIAS_CRYPTO("blake2s-224-x86");
+-MODULE_ALIAS_CRYPTO("blake2s-256");
+-MODULE_ALIAS_CRYPTO("blake2s-256-x86");
+-MODULE_LICENSE("GPL v2");
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index f0743ac4e820..db260ccfba51 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -684,26 +684,8 @@ config CRYPTO_BLAKE2B
+
+ See https://blake2.net for further information.
+
+-config CRYPTO_BLAKE2S
+- tristate "BLAKE2s digest algorithm"
+- select CRYPTO_LIB_BLAKE2S_GENERIC
+- select CRYPTO_HASH
+- help
+- Implementation of cryptographic hash function BLAKE2s
+- optimized for 8-32bit platforms and can produce digests of any size
+- between 1 to 32. The keyed hash is also implemented.
+-
+- This module provides the following algorithms:
+-
+- - blake2s-128
+- - blake2s-160
+- - blake2s-224
+- - blake2s-256
+-
+- See https://blake2.net for further information.
+-
+ config CRYPTO_BLAKE2S_X86
+- tristate "BLAKE2s digest algorithm (x86 accelerated version)"
++ bool "BLAKE2s digest algorithm (x86 accelerated version)"
+ depends on X86 && 64BIT
+ select CRYPTO_LIB_BLAKE2S_GENERIC
+ select CRYPTO_ARCH_HAVE_LIB_BLAKE2S
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 78b5ab05d6ed..429591ffeb5d 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -83,7 +83,6 @@ obj-$(CONFIG_CRYPTO_STREEBOG) += streebog_generic.o
+ obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+ CFLAGS_wp512.o := $(call cc-option,-fno-schedule-insns) # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79149
+ obj-$(CONFIG_CRYPTO_BLAKE2B) += blake2b_generic.o
+-obj-$(CONFIG_CRYPTO_BLAKE2S) += blake2s_generic.o
+ obj-$(CONFIG_CRYPTO_GF128MUL) += gf128mul.o
+ obj-$(CONFIG_CRYPTO_ECB) += ecb.o
+ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+diff --git a/crypto/blake2s_generic.c b/crypto/blake2s_generic.c
+deleted file mode 100644
+index 5f96a21f8788..000000000000
+--- a/crypto/blake2s_generic.c
++++ /dev/null
+@@ -1,75 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0 OR MIT
+-/*
+- * shash interface to the generic implementation of BLAKE2s
+- *
+- * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+- */
+-
+-#include <crypto/internal/blake2s.h>
+-#include <crypto/internal/hash.h>
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-
+-static int crypto_blake2s_update_generic(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen)
+-{
+- return crypto_blake2s_update(desc, in, inlen, true);
+-}
+-
+-static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out)
+-{
+- return crypto_blake2s_final(desc, out, true);
+-}
+-
+-#define BLAKE2S_ALG(name, driver_name, digest_size) \
+- { \
+- .base.cra_name = name, \
+- .base.cra_driver_name = driver_name, \
+- .base.cra_priority = 100, \
+- .base.cra_flags = CRYPTO_ALG_OPTIONAL_KEY, \
+- .base.cra_blocksize = BLAKE2S_BLOCK_SIZE, \
+- .base.cra_ctxsize = sizeof(struct blake2s_tfm_ctx), \
+- .base.cra_module = THIS_MODULE, \
+- .digestsize = digest_size, \
+- .setkey = crypto_blake2s_setkey, \
+- .init = crypto_blake2s_init, \
+- .update = crypto_blake2s_update_generic, \
+- .final = crypto_blake2s_final_generic, \
+- .descsize = sizeof(struct blake2s_state), \
+- }
+-
+-static struct shash_alg blake2s_algs[] = {
+- BLAKE2S_ALG("blake2s-128", "blake2s-128-generic",
+- BLAKE2S_128_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-160", "blake2s-160-generic",
+- BLAKE2S_160_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-224", "blake2s-224-generic",
+- BLAKE2S_224_HASH_SIZE),
+- BLAKE2S_ALG("blake2s-256", "blake2s-256-generic",
+- BLAKE2S_256_HASH_SIZE),
+-};
+-
+-static int __init blake2s_mod_init(void)
+-{
+- return crypto_register_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs));
+-}
+-
+-static void __exit blake2s_mod_exit(void)
+-{
+- crypto_unregister_shashes(blake2s_algs, ARRAY_SIZE(blake2s_algs));
+-}
+-
+-subsys_initcall(blake2s_mod_init);
+-module_exit(blake2s_mod_exit);
+-
+-MODULE_ALIAS_CRYPTO("blake2s-128");
+-MODULE_ALIAS_CRYPTO("blake2s-128-generic");
+-MODULE_ALIAS_CRYPTO("blake2s-160");
+-MODULE_ALIAS_CRYPTO("blake2s-160-generic");
+-MODULE_ALIAS_CRYPTO("blake2s-224");
+-MODULE_ALIAS_CRYPTO("blake2s-224-generic");
+-MODULE_ALIAS_CRYPTO("blake2s-256");
+-MODULE_ALIAS_CRYPTO("blake2s-256-generic");
+-MODULE_LICENSE("GPL v2");
+diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
+index 00149657a4bc..3362897bf61b 100644
+--- a/crypto/tcrypt.c
++++ b/crypto/tcrypt.c
+@@ -1863,10 +1863,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
+ ret += tcrypt_test("rmd160");
+ break;
+
+- case 41:
+- ret += tcrypt_test("blake2s-256");
+- break;
+-
+ case 42:
+ ret += tcrypt_test("blake2b-512");
+ break;
+@@ -2434,10 +2430,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
+ test_hash_speed("rmd160", sec, generic_hash_speed_template);
+ if (mode > 300 && mode < 400) break;
+ fallthrough;
+- case 316:
+- test_hash_speed("blake2s-256", sec, generic_hash_speed_template);
+- if (mode > 300 && mode < 400) break;
+- fallthrough;
+ case 317:
+ test_hash_speed("blake2b-512", sec, generic_hash_speed_template);
+ if (mode > 300 && mode < 400) break;
+@@ -2546,10 +2538,6 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb)
+ test_ahash_speed("rmd160", sec, generic_hash_speed_template);
+ if (mode > 400 && mode < 500) break;
+ fallthrough;
+- case 416:
+- test_ahash_speed("blake2s-256", sec, generic_hash_speed_template);
+- if (mode > 400 && mode < 500) break;
+- fallthrough;
+ case 417:
+ test_ahash_speed("blake2b-512", sec, generic_hash_speed_template);
+ if (mode > 400 && mode < 500) break;
+diff --git a/crypto/testmgr.c b/crypto/testmgr.c
+index 70f69f0910c9..163a1283a866 100644
+--- a/crypto/testmgr.c
++++ b/crypto/testmgr.c
+@@ -4329,30 +4329,6 @@ static const struct alg_test_desc alg_test_descs[] = {
+ .suite = {
+ .hash = __VECS(blake2b_512_tv_template)
+ }
+- }, {
+- .alg = "blake2s-128",
+- .test = alg_test_hash,
+- .suite = {
+- .hash = __VECS(blakes2s_128_tv_template)
+- }
+- }, {
+- .alg = "blake2s-160",
+- .test = alg_test_hash,
+- .suite = {
+- .hash = __VECS(blakes2s_160_tv_template)
+- }
+- }, {
+- .alg = "blake2s-224",
+- .test = alg_test_hash,
+- .suite = {
+- .hash = __VECS(blakes2s_224_tv_template)
+- }
+- }, {
+- .alg = "blake2s-256",
+- .test = alg_test_hash,
+- .suite = {
+- .hash = __VECS(blakes2s_256_tv_template)
+- }
+ }, {
+ .alg = "cbc(aes)",
+ .test = alg_test_skcipher,
+diff --git a/crypto/testmgr.h b/crypto/testmgr.h
+index e6fca34b5b25..2be20a590a60 100644
+--- a/crypto/testmgr.h
++++ b/crypto/testmgr.h
+@@ -32583,221 +32583,4 @@ static const struct hash_testvec blake2b_512_tv_template[] = {{
+ 0xae, 0x15, 0x81, 0x15, 0xd0, 0x88, 0xa0, 0x3c, },
+ }};
+
+-static const struct hash_testvec blakes2s_128_tv_template[] = {{
+- .digest = (u8[]){ 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
+- 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c, },
+-}, {
+- .plaintext = blake2_ordered_sequence,
+- .psize = 64,
+- .digest = (u8[]){ 0xdc, 0x66, 0xca, 0x8f, 0x03, 0x86, 0x58, 0x01,
+- 0xb0, 0xff, 0xe0, 0x6e, 0xd8, 0xa1, 0xa9, 0x0e, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 1,
+- .digest = (u8[]){ 0x88, 0x1e, 0x42, 0xe7, 0xbb, 0x35, 0x80, 0x82,
+- 0x63, 0x7c, 0x0a, 0x0f, 0xd7, 0xec, 0x6c, 0x2f, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 7,
+- .digest = (u8[]){ 0xcf, 0x9e, 0x07, 0x2a, 0xd5, 0x22, 0xf2, 0xcd,
+- 0xa2, 0xd8, 0x25, 0x21, 0x80, 0x86, 0x73, 0x1c, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 15,
+- .digest = (u8[]){ 0xf6, 0x33, 0x5a, 0x2c, 0x22, 0xa0, 0x64, 0xb2,
+- 0xb6, 0x3f, 0xeb, 0xbc, 0xd1, 0xc3, 0xe5, 0xb2, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 247,
+- .digest = (u8[]){ 0x72, 0x66, 0x49, 0x60, 0xf9, 0x4a, 0xea, 0xbe,
+- 0x1f, 0xf4, 0x60, 0xce, 0xb7, 0x81, 0xcb, 0x09, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 256,
+- .digest = (u8[]){ 0xd5, 0xa4, 0x0e, 0xc3, 0x16, 0xc7, 0x51, 0xa6,
+- 0x3c, 0xd0, 0xd9, 0x11, 0x57, 0xfa, 0x1e, 0xbb, },
+-}};
+-
+-static const struct hash_testvec blakes2s_160_tv_template[] = {{
+- .plaintext = blake2_ordered_sequence,
+- .psize = 7,
+- .digest = (u8[]){ 0xb4, 0xf2, 0x03, 0x49, 0x37, 0xed, 0xb1, 0x3e,
+- 0x5b, 0x2a, 0xca, 0x64, 0x82, 0x74, 0xf6, 0x62,
+- 0xe3, 0xf2, 0x84, 0xff, },
+-}, {
+- .plaintext = blake2_ordered_sequence,
+- .psize = 256,
+- .digest = (u8[]){ 0xaa, 0x56, 0x9b, 0xdc, 0x98, 0x17, 0x75, 0xf2,
+- 0xb3, 0x68, 0x83, 0xb7, 0x9b, 0x8d, 0x48, 0xb1,
+- 0x9b, 0x2d, 0x35, 0x05, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .digest = (u8[]){ 0x50, 0x16, 0xe7, 0x0c, 0x01, 0xd0, 0xd3, 0xc3,
+- 0xf4, 0x3e, 0xb1, 0x6e, 0x97, 0xa9, 0x4e, 0xd1,
+- 0x79, 0x65, 0x32, 0x93, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 1,
+- .digest = (u8[]){ 0x1c, 0x2b, 0xcd, 0x9a, 0x68, 0xca, 0x8c, 0x71,
+- 0x90, 0x29, 0x6c, 0x54, 0xfa, 0x56, 0x4a, 0xef,
+- 0xa2, 0x3a, 0x56, 0x9c, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 15,
+- .digest = (u8[]){ 0x36, 0xc3, 0x5f, 0x9a, 0xdc, 0x7e, 0xbf, 0x19,
+- 0x68, 0xaa, 0xca, 0xd8, 0x81, 0xbf, 0x09, 0x34,
+- 0x83, 0x39, 0x0f, 0x30, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 64,
+- .digest = (u8[]){ 0x86, 0x80, 0x78, 0xa4, 0x14, 0xec, 0x03, 0xe5,
+- 0xb6, 0x9a, 0x52, 0x0e, 0x42, 0xee, 0x39, 0x9d,
+- 0xac, 0xa6, 0x81, 0x63, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 247,
+- .digest = (u8[]){ 0x2d, 0xd8, 0xd2, 0x53, 0x66, 0xfa, 0xa9, 0x01,
+- 0x1c, 0x9c, 0xaf, 0xa3, 0xe2, 0x9d, 0x9b, 0x10,
+- 0x0a, 0xf6, 0x73, 0xe8, },
+-}};
+-
+-static const struct hash_testvec blakes2s_224_tv_template[] = {{
+- .plaintext = blake2_ordered_sequence,
+- .psize = 1,
+- .digest = (u8[]){ 0x61, 0xb9, 0x4e, 0xc9, 0x46, 0x22, 0xa3, 0x91,
+- 0xd2, 0xae, 0x42, 0xe6, 0x45, 0x6c, 0x90, 0x12,
+- 0xd5, 0x80, 0x07, 0x97, 0xb8, 0x86, 0x5a, 0xfc,
+- 0x48, 0x21, 0x97, 0xbb, },
+-}, {
+- .plaintext = blake2_ordered_sequence,
+- .psize = 247,
+- .digest = (u8[]){ 0x9e, 0xda, 0xc7, 0x20, 0x2c, 0xd8, 0x48, 0x2e,
+- 0x31, 0x94, 0xab, 0x46, 0x6d, 0x94, 0xd8, 0xb4,
+- 0x69, 0xcd, 0xae, 0x19, 0x6d, 0x9e, 0x41, 0xcc,
+- 0x2b, 0xa4, 0xd5, 0xf6, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .digest = (u8[]){ 0x32, 0xc0, 0xac, 0xf4, 0x3b, 0xd3, 0x07, 0x9f,
+- 0xbe, 0xfb, 0xfa, 0x4d, 0x6b, 0x4e, 0x56, 0xb3,
+- 0xaa, 0xd3, 0x27, 0xf6, 0x14, 0xbf, 0xb9, 0x32,
+- 0xa7, 0x19, 0xfc, 0xb8, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 7,
+- .digest = (u8[]){ 0x73, 0xad, 0x5e, 0x6d, 0xb9, 0x02, 0x8e, 0x76,
+- 0xf2, 0x66, 0x42, 0x4b, 0x4c, 0xfa, 0x1f, 0xe6,
+- 0x2e, 0x56, 0x40, 0xe5, 0xa2, 0xb0, 0x3c, 0xe8,
+- 0x7b, 0x45, 0xfe, 0x05, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 15,
+- .digest = (u8[]){ 0x16, 0x60, 0xfb, 0x92, 0x54, 0xb3, 0x6e, 0x36,
+- 0x81, 0xf4, 0x16, 0x41, 0xc3, 0x3d, 0xd3, 0x43,
+- 0x84, 0xed, 0x10, 0x6f, 0x65, 0x80, 0x7a, 0x3e,
+- 0x25, 0xab, 0xc5, 0x02, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 64,
+- .digest = (u8[]){ 0xca, 0xaa, 0x39, 0x67, 0x9c, 0xf7, 0x6b, 0xc7,
+- 0xb6, 0x82, 0xca, 0x0e, 0x65, 0x36, 0x5b, 0x7c,
+- 0x24, 0x00, 0xfa, 0x5f, 0xda, 0x06, 0x91, 0x93,
+- 0x6a, 0x31, 0x83, 0xb5, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 256,
+- .digest = (u8[]){ 0x90, 0x02, 0x26, 0xb5, 0x06, 0x9c, 0x36, 0x86,
+- 0x94, 0x91, 0x90, 0x1e, 0x7d, 0x2a, 0x71, 0xb2,
+- 0x48, 0xb5, 0xe8, 0x16, 0xfd, 0x64, 0x33, 0x45,
+- 0xb3, 0xd7, 0xec, 0xcc, },
+-}};
+-
+-static const struct hash_testvec blakes2s_256_tv_template[] = {{
+- .plaintext = blake2_ordered_sequence,
+- .psize = 15,
+- .digest = (u8[]){ 0xd9, 0x7c, 0x82, 0x8d, 0x81, 0x82, 0xa7, 0x21,
+- 0x80, 0xa0, 0x6a, 0x78, 0x26, 0x83, 0x30, 0x67,
+- 0x3f, 0x7c, 0x4e, 0x06, 0x35, 0x94, 0x7c, 0x04,
+- 0xc0, 0x23, 0x23, 0xfd, 0x45, 0xc0, 0xa5, 0x2d, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .digest = (u8[]){ 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b,
+- 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b,
+- 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a,
+- 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 1,
+- .digest = (u8[]){ 0x22, 0x27, 0xae, 0xaa, 0x6e, 0x81, 0x56, 0x03,
+- 0xa7, 0xe3, 0xa1, 0x18, 0xa5, 0x9a, 0x2c, 0x18,
+- 0xf4, 0x63, 0xbc, 0x16, 0x70, 0xf1, 0xe7, 0x4b,
+- 0x00, 0x6d, 0x66, 0x16, 0xae, 0x9e, 0x74, 0x4e, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 7,
+- .digest = (u8[]){ 0x58, 0x5d, 0xa8, 0x60, 0x1c, 0xa4, 0xd8, 0x03,
+- 0x86, 0x86, 0x84, 0x64, 0xd7, 0xa0, 0x8e, 0x15,
+- 0x2f, 0x05, 0xa2, 0x1b, 0xbc, 0xef, 0x7a, 0x34,
+- 0xb3, 0xc5, 0xbc, 0x4b, 0xf0, 0x32, 0xeb, 0x12, },
+-}, {
+- .ksize = 32,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 64,
+- .digest = (u8[]){ 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66,
+- 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26,
+- 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab,
+- 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4, },
+-}, {
+- .ksize = 1,
+- .key = "B",
+- .plaintext = blake2_ordered_sequence,
+- .psize = 247,
+- .digest = (u8[]){ 0x2e, 0x74, 0x1c, 0x1d, 0x03, 0xf4, 0x9d, 0x84,
+- 0x6f, 0xfc, 0x86, 0x32, 0x92, 0x49, 0x7e, 0x66,
+- 0xd7, 0xc3, 0x10, 0x88, 0xfe, 0x28, 0xb3, 0xe0,
+- 0xbf, 0x50, 0x75, 0xad, 0x8e, 0xa4, 0xe6, 0xb2, },
+-}, {
+- .ksize = 16,
+- .key = blake2_ordered_sequence,
+- .plaintext = blake2_ordered_sequence,
+- .psize = 256,
+- .digest = (u8[]){ 0xb9, 0xd2, 0x81, 0x0e, 0x3a, 0xb1, 0x62, 0x9b,
+- 0xad, 0x44, 0x05, 0xf4, 0x92, 0x2e, 0x99, 0xc1,
+- 0x4a, 0x47, 0xbb, 0x5b, 0x6f, 0xb2, 0x96, 0xed,
+- 0xd5, 0x06, 0xb5, 0x3a, 0x7c, 0x7a, 0x65, 0x1d, },
+-}};
+-
+ #endif /* _CRYPTO_TESTMGR_H */
+diff --git a/include/crypto/internal/blake2s.h b/include/crypto/internal/blake2s.h
+index 52363eee2b20..506d56530ca9 100644
+--- a/include/crypto/internal/blake2s.h
++++ b/include/crypto/internal/blake2s.h
+@@ -8,7 +8,6 @@
+ #define _CRYPTO_INTERNAL_BLAKE2S_H
+
+ #include <crypto/blake2s.h>
+-#include <crypto/internal/hash.h>
+ #include <linux/string.h>
+
+ void blake2s_compress_generic(struct blake2s_state *state, const u8 *block,
+@@ -19,111 +18,4 @@ void blake2s_compress(struct blake2s_state *state, const u8 *block,
+
+ bool blake2s_selftest(void);
+
+-static inline void blake2s_set_lastblock(struct blake2s_state *state)
+-{
+- state->f[0] = -1;
+-}
+-
+-/* Helper functions for BLAKE2s shared by the library and shash APIs */
+-
+-static __always_inline void
+-__blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen,
+- bool force_generic)
+-{
+- const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
+-
+- if (unlikely(!inlen))
+- return;
+- if (inlen > fill) {
+- memcpy(state->buf + state->buflen, in, fill);
+- if (force_generic)
+- blake2s_compress_generic(state, state->buf, 1,
+- BLAKE2S_BLOCK_SIZE);
+- else
+- blake2s_compress(state, state->buf, 1,
+- BLAKE2S_BLOCK_SIZE);
+- state->buflen = 0;
+- in += fill;
+- inlen -= fill;
+- }
+- if (inlen > BLAKE2S_BLOCK_SIZE) {
+- const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
+- /* Hash one less (full) block than strictly possible */
+- if (force_generic)
+- blake2s_compress_generic(state, in, nblocks - 1,
+- BLAKE2S_BLOCK_SIZE);
+- else
+- blake2s_compress(state, in, nblocks - 1,
+- BLAKE2S_BLOCK_SIZE);
+- in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
+- inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
+- }
+- memcpy(state->buf + state->buflen, in, inlen);
+- state->buflen += inlen;
+-}
+-
+-static __always_inline void
+-__blake2s_final(struct blake2s_state *state, u8 *out, bool force_generic)
+-{
+- blake2s_set_lastblock(state);
+- memset(state->buf + state->buflen, 0,
+- BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
+- if (force_generic)
+- blake2s_compress_generic(state, state->buf, 1, state->buflen);
+- else
+- blake2s_compress(state, state->buf, 1, state->buflen);
+- cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
+- memcpy(out, state->h, state->outlen);
+-}
+-
+-/* Helper functions for shash implementations of BLAKE2s */
+-
+-struct blake2s_tfm_ctx {
+- u8 key[BLAKE2S_KEY_SIZE];
+- unsigned int keylen;
+-};
+-
+-static inline int crypto_blake2s_setkey(struct crypto_shash *tfm,
+- const u8 *key, unsigned int keylen)
+-{
+- struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm);
+-
+- if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE)
+- return -EINVAL;
+-
+- memcpy(tctx->key, key, keylen);
+- tctx->keylen = keylen;
+-
+- return 0;
+-}
+-
+-static inline int crypto_blake2s_init(struct shash_desc *desc)
+-{
+- const struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
+- struct blake2s_state *state = shash_desc_ctx(desc);
+- unsigned int outlen = crypto_shash_digestsize(desc->tfm);
+-
+- __blake2s_init(state, outlen, tctx->key, tctx->keylen);
+- return 0;
+-}
+-
+-static inline int crypto_blake2s_update(struct shash_desc *desc,
+- const u8 *in, unsigned int inlen,
+- bool force_generic)
+-{
+- struct blake2s_state *state = shash_desc_ctx(desc);
+-
+- __blake2s_update(state, in, inlen, force_generic);
+- return 0;
+-}
+-
+-static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out,
+- bool force_generic)
+-{
+- struct blake2s_state *state = shash_desc_ctx(desc);
+-
+- __blake2s_final(state, out, force_generic);
+- return 0;
+-}
+-
+ #endif /* _CRYPTO_INTERNAL_BLAKE2S_H */
+diff --git a/lib/crypto/blake2s-selftest.c b/lib/crypto/blake2s-selftest.c
+index 409e4b728770..66f505220f43 100644
+--- a/lib/crypto/blake2s-selftest.c
++++ b/lib/crypto/blake2s-selftest.c
+@@ -4,6 +4,8 @@
+ */
+
+ #include <crypto/internal/blake2s.h>
++#include <linux/kernel.h>
++#include <linux/random.h>
+ #include <linux/string.h>
+
+ /*
+@@ -587,5 +589,44 @@ bool __init blake2s_selftest(void)
+ }
+ }
+
++ for (i = 0; i < 32; ++i) {
++ enum { TEST_ALIGNMENT = 16 };
++ u8 unaligned_block[BLAKE2S_BLOCK_SIZE + TEST_ALIGNMENT - 1]
++ __aligned(TEST_ALIGNMENT);
++ u8 blocks[BLAKE2S_BLOCK_SIZE * 3];
++ struct blake2s_state state1, state2;
++
++ get_random_bytes(blocks, sizeof(blocks));
++ get_random_bytes(&state, sizeof(state));
++
++#if defined(CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC) && \
++ defined(CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S)
++ memcpy(&state1, &state, sizeof(state1));
++ memcpy(&state2, &state, sizeof(state2));
++ blake2s_compress(&state1, blocks, 3, BLAKE2S_BLOCK_SIZE);
++ blake2s_compress_generic(&state2, blocks, 3, BLAKE2S_BLOCK_SIZE);
++ if (memcmp(&state1, &state2, sizeof(state1))) {
++ pr_err("blake2s random compress self-test %d: FAIL\n",
++ i + 1);
++ success = false;
++ }
++#endif
++
++ memcpy(&state1, &state, sizeof(state1));
++ blake2s_compress(&state1, blocks, 1, BLAKE2S_BLOCK_SIZE);
++ for (l = 1; l < TEST_ALIGNMENT; ++l) {
++ memcpy(unaligned_block + l, blocks,
++ BLAKE2S_BLOCK_SIZE);
++ memcpy(&state2, &state, sizeof(state2));
++ blake2s_compress(&state2, unaligned_block + l, 1,
++ BLAKE2S_BLOCK_SIZE);
++ if (memcmp(&state1, &state2, sizeof(state1))) {
++ pr_err("blake2s random compress align %d self-test %d: FAIL\n",
++ l, i + 1);
++ success = false;
++ }
++ }
++ }
++
+ return success;
+ }
+diff --git a/lib/crypto/blake2s.c b/lib/crypto/blake2s.c
+index c71c09621c09..98e688c6d891 100644
+--- a/lib/crypto/blake2s.c
++++ b/lib/crypto/blake2s.c
+@@ -16,16 +16,44 @@
+ #include <linux/init.h>
+ #include <linux/bug.h>
+
++static inline void blake2s_set_lastblock(struct blake2s_state *state)
++{
++ state->f[0] = -1;
++}
++
+ void blake2s_update(struct blake2s_state *state, const u8 *in, size_t inlen)
+ {
+- __blake2s_update(state, in, inlen, false);
++ const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
++
++ if (unlikely(!inlen))
++ return;
++ if (inlen > fill) {
++ memcpy(state->buf + state->buflen, in, fill);
++ blake2s_compress(state, state->buf, 1, BLAKE2S_BLOCK_SIZE);
++ state->buflen = 0;
++ in += fill;
++ inlen -= fill;
++ }
++ if (inlen > BLAKE2S_BLOCK_SIZE) {
++ const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
++ blake2s_compress(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE);
++ in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
++ inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
++ }
++ memcpy(state->buf + state->buflen, in, inlen);
++ state->buflen += inlen;
+ }
+ EXPORT_SYMBOL(blake2s_update);
+
+ void blake2s_final(struct blake2s_state *state, u8 *out)
+ {
+ WARN_ON(IS_ENABLED(DEBUG) && !out);
+- __blake2s_final(state, out, false);
++ blake2s_set_lastblock(state);
++ memset(state->buf + state->buflen, 0,
++ BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
++ blake2s_compress(state, state->buf, 1, state->buflen);
++ cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
++ memcpy(out, state->h, state->outlen);
+ memzero_explicit(state, sizeof(*state));
+ }
+ EXPORT_SYMBOL(blake2s_final);
+@@ -38,12 +66,7 @@ static int __init blake2s_mod_init(void)
+ return 0;
+ }
+
+-static void __exit blake2s_mod_exit(void)
+-{
+-}
+-
+ module_init(blake2s_mod_init);
+-module_exit(blake2s_mod_exit);
+ MODULE_LICENSE("GPL v2");
+ MODULE_DESCRIPTION("BLAKE2s hash function");
+ MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
+--
+2.35.1
+
--- /dev/null
+From eb5c27f4c1e650acfdefdba676b5ddc2591cd52a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Jul 2022 14:33:52 -0400
+Subject: dm raid: fix address sanitizer warning in raid_resume
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit 7dad24db59d2d2803576f2e3645728866a056dab ]
+
+There is a KASAN warning in raid_resume when running the lvm test
+lvconvert-raid.sh. The reason for the warning is that mddev->raid_disks
+is greater than rs->raid_disks, so the loop touches one entry beyond
+the allocated length.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-raid.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index 5f7e40c48e47..eba277bb8a1f 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3824,7 +3824,7 @@ static void attempt_restore_of_faulty_devices(struct raid_set *rs)
+
+ memset(cleared_failed_devices, 0, sizeof(cleared_failed_devices));
+
+- for (i = 0; i < mddev->raid_disks; i++) {
++ for (i = 0; i < rs->raid_disks; i++) {
+ r = &rs->dev[i].rdev;
+ /* HM FIXME: enhance journal device recovery processing */
+ if (test_bit(Journal, &r->flags))
+--
+2.35.1
+
--- /dev/null
+From 7cb190fc09a2445aa081c2713c06ecbd2a93b3fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Jul 2022 14:31:35 -0400
+Subject: dm raid: fix address sanitizer warning in raid_status
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit 1fbeea217d8f297fe0e0956a1516d14ba97d0396 ]
+
+There is this warning when using a kernel with the address sanitizer
+and running this testsuite:
+https://gitlab.com/cki-project/kernel-tests/-/tree/main/storage/swraid/scsi_raid
+
+==================================================================
+BUG: KASAN: slab-out-of-bounds in raid_status+0x1747/0x2820 [dm_raid]
+Read of size 4 at addr ffff888079d2c7e8 by task lvcreate/13319
+CPU: 0 PID: 13319 Comm: lvcreate Not tainted 5.18.0-0.rc3.<snip> #1
+Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x6a/0x9c
+ print_address_description.constprop.0+0x1f/0x1e0
+ print_report.cold+0x55/0x244
+ kasan_report+0xc9/0x100
+ raid_status+0x1747/0x2820 [dm_raid]
+ dm_ima_measure_on_table_load+0x4b8/0xca0 [dm_mod]
+ table_load+0x35c/0x630 [dm_mod]
+ ctl_ioctl+0x411/0x630 [dm_mod]
+ dm_ctl_ioctl+0xa/0x10 [dm_mod]
+ __x64_sys_ioctl+0x12a/0x1a0
+ do_syscall_64+0x5b/0x80
+
+The warning is caused by reading conf->max_nr_stripes in raid_status. The
+code in raid_status reads mddev->private, casts it to struct r5conf and
+reads the entry max_nr_stripes.
+
+However, if we have different raid type than 4/5/6, mddev->private
+doesn't point to struct r5conf; it may point to struct r0conf, struct
+r1conf, struct r10conf or struct mpconf. If we cast a pointer to one
+of these structs to struct r5conf, we will be reading invalid memory
+and KASAN warns about it.
+
+Fix this bug by reading struct r5conf only if raid type is 4, 5 or 6.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-raid.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index b0566aabc186..5f7e40c48e47 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3514,7 +3514,7 @@ static void raid_status(struct dm_target *ti, status_type_t type,
+ {
+ struct raid_set *rs = ti->private;
+ struct mddev *mddev = &rs->md;
+- struct r5conf *conf = mddev->private;
++ struct r5conf *conf = rs_is_raid456(rs) ? mddev->private : NULL;
+ int i, max_nr_stripes = conf ? conf->max_nr_stripes : 0;
+ unsigned long recovery;
+ unsigned int raid_param_cnt = 1; /* at least 1 for chunksize */
+--
+2.35.1
+
--- /dev/null
+From 875865ffbe115bafceb09867b999cfe17a0dc5df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 19:28:25 +0800
+Subject: dm thin: fix use-after-free crash in
+ dm_sm_register_threshold_callback
+
+From: Luo Meng <luomeng12@huawei.com>
+
+[ Upstream commit 3534e5a5ed2997ca1b00f44a0378a075bd05e8a3 ]
+
+Fault inject on pool metadata device reports:
+ BUG: KASAN: use-after-free in dm_pool_register_metadata_threshold+0x40/0x80
+ Read of size 8 at addr ffff8881b9d50068 by task dmsetup/950
+
+ CPU: 7 PID: 950 Comm: dmsetup Tainted: G W 5.19.0-rc6 #1
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x34/0x44
+ print_address_description.constprop.0.cold+0xeb/0x3f4
+ kasan_report.cold+0xe6/0x147
+ dm_pool_register_metadata_threshold+0x40/0x80
+ pool_ctr+0xa0a/0x1150
+ dm_table_add_target+0x2c8/0x640
+ table_load+0x1fd/0x430
+ ctl_ioctl+0x2c4/0x5a0
+ dm_ctl_ioctl+0xa/0x10
+ __x64_sys_ioctl+0xb3/0xd0
+ do_syscall_64+0x35/0x80
+ entry_SYSCALL_64_after_hwframe+0x46/0xb0
+
+This can be easily reproduced using:
+ echo offline > /sys/block/sda/device/state
+ dd if=/dev/zero of=/dev/mapper/thin bs=4k count=10
+ dmsetup load pool --table "0 20971520 thin-pool /dev/sda /dev/sdb 128 0 0"
+
+If a metadata commit fails, the transaction will be aborted and the
+metadata space maps will be destroyed. If a DM table reload then
+happens for this failed thin-pool, a use-after-free will occur in
+dm_sm_register_threshold_callback (called from
+dm_pool_register_metadata_threshold).
+
+Fix this by in dm_pool_register_metadata_threshold() by returning the
+-EINVAL error if the thin-pool is in fail mode. Also fail pool_ctr()
+with a new error message: "Error registering metadata threshold".
+
+Fixes: ac8c3f3df65e4 ("dm thin: generate event when metadata threshold passed")
+Cc: stable@vger.kernel.org
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Luo Meng <luomeng12@huawei.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-thin-metadata.c | 7 +++++--
+ drivers/md/dm-thin.c | 4 +++-
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
+index c88ed14d49e6..0ada99572b68 100644
+--- a/drivers/md/dm-thin-metadata.c
++++ b/drivers/md/dm-thin-metadata.c
+@@ -2073,10 +2073,13 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
+ dm_sm_threshold_fn fn,
+ void *context)
+ {
+- int r;
++ int r = -EINVAL;
+
+ pmd_write_lock_in_core(pmd);
+- r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
++ if (!pmd->fail_io) {
++ r = dm_sm_register_threshold_callback(pmd->metadata_sm,
++ threshold, fn, context);
++ }
+ pmd_write_unlock(pmd);
+
+ return r;
+diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
+index 4c67b77c23c1..0a85e4cd607c 100644
+--- a/drivers/md/dm-thin.c
++++ b/drivers/md/dm-thin.c
+@@ -3401,8 +3401,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+ calc_metadata_threshold(pt),
+ metadata_low_callback,
+ pool);
+- if (r)
++ if (r) {
++ ti->error = "Error registering metadata threshold";
+ goto out_flags_changed;
++ }
+
+ dm_pool_register_pre_commit_callback(pool->pmd,
+ metadata_pre_commit_callback, pool);
+--
+2.35.1
+
--- /dev/null
+From 6ded3ae94fbe69ecdb10b7b5e2c8aa48e7400731 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Jul 2022 07:09:04 -0400
+Subject: dm writecache: set a default MAX_WRITEBACK_JOBS
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit ca7dc242e358e46d963b32f9d9dd829785a9e957 ]
+
+dm-writecache has the capability to limit the number of writeback jobs
+in progress. However, this feature was off by default. As such there
+were some out-of-memory crashes observed when lowering the low
+watermark while the cache is full.
+
+This commit enables writeback limit by default. It is set to 256MiB or
+1/16 of total system memory, whichever is smaller.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-writecache.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
+index c3e59d8af76f..dfb55fe09ce1 100644
+--- a/drivers/md/dm-writecache.c
++++ b/drivers/md/dm-writecache.c
+@@ -22,7 +22,7 @@
+
+ #define HIGH_WATERMARK 50
+ #define LOW_WATERMARK 45
+-#define MAX_WRITEBACK_JOBS 0
++#define MAX_WRITEBACK_JOBS min(0x10000000 / PAGE_SIZE, totalram_pages() / 16)
+ #define ENDIO_LATENCY 16
+ #define WRITEBACK_LATENCY 64
+ #define AUTOCOMMIT_BLOCKS_SSD 65536
+--
+2.35.1
+
--- /dev/null
+From 40c1b27ca3a22ee15423a5f6e890084576809c2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Jul 2022 09:49:24 -0400
+Subject: drivers/base: fix userspace break from using bin_attributes for
+ cpumap and cpulist
+
+From: Phil Auld <pauld@redhat.com>
+
+[ Upstream commit 7ee951acd31a88f941fd6535fbdee3a1567f1d63 ]
+
+Using bin_attributes with a 0 size causes fstat and friends to return that
+0 size. This breaks userspace code that retrieves the size before reading
+the file. Rather than reverting 75bd50fa841 ("drivers/base/node.c: use
+bin_attribute to break the size limitation of cpumap ABI") let's put in a
+size value at compile time.
+
+For cpulist the maximum size is on the order of
+ NR_CPUS * (ceil(log10(NR_CPUS)) + 1)/2
+
+which for 8192 is 20480 (8192 * 5)/2. In order to get near that you'd need
+a system with every other CPU on one node. For example: (0,2,4,8, ... ).
+To simplify the math and support larger NR_CPUS in the future we are using
+(NR_CPUS * 7)/2. We also set it to a min of PAGE_SIZE to retain the older
+behavior for smaller NR_CPUS.
+
+The cpumap file the size works out to be NR_CPUS/4 + NR_CPUS/32 - 1
+(or NR_CPUS * 9/32 - 1) including the ","s.
+
+Add a set of macros for these values to cpumask.h so they can be used in
+multiple places. Apply these to the handful of such files in
+drivers/base/topology.c as well as node.c.
+
+As an example, on an 80 cpu 4-node system (NR_CPUS == 8192):
+
+before:
+
+-r--r--r--. 1 root root 0 Jul 12 14:08 system/node/node0/cpulist
+-r--r--r--. 1 root root 0 Jul 11 17:25 system/node/node0/cpumap
+
+after:
+
+-r--r--r--. 1 root root 28672 Jul 13 11:32 system/node/node0/cpulist
+-r--r--r--. 1 root root 4096 Jul 13 11:31 system/node/node0/cpumap
+
+CONFIG_NR_CPUS = 16384
+-r--r--r--. 1 root root 57344 Jul 13 14:03 system/node/node0/cpulist
+-r--r--r--. 1 root root 4607 Jul 13 14:02 system/node/node0/cpumap
+
+The actual number of cpus doesn't matter for the reported size since they
+are based on NR_CPUS.
+
+Fixes: 75bd50fa841d ("drivers/base/node.c: use bin_attribute to break the size limitation of cpumap ABI")
+Fixes: bb9ec13d156e ("topology: use bin_attribute to break the size limitation of cpumap ABI")
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "Rafael J. Wysocki" <rafael@kernel.org>
+Cc: Yury Norov <yury.norov@gmail.com>
+Cc: stable@vger.kernel.org
+Acked-by: Yury Norov <yury.norov@gmail.com> (for include/linux/cpumask.h)
+Signed-off-by: Phil Auld <pauld@redhat.com>
+Link: https://lore.kernel.org/r/20220715134924.3466194-1-pauld@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/node.c | 4 ++--
+ drivers/base/topology.c | 32 ++++++++++++++++----------------
+ include/linux/cpumask.h | 18 ++++++++++++++++++
+ 3 files changed, 36 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index 0f5319b79fad..5366d1b5359c 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -45,7 +45,7 @@ static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
+ return n;
+ }
+
+-static BIN_ATTR_RO(cpumap, 0);
++static BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
+
+ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+@@ -66,7 +66,7 @@ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
+ return n;
+ }
+
+-static BIN_ATTR_RO(cpulist, 0);
++static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
+
+ /**
+ * struct node_access_nodes - Access class device to hold user visible
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index 9d049724e4b4..4c8328468e97 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -59,47 +59,47 @@ define_id_show_func(core_id);
+ static DEVICE_ATTR_RO(core_id);
+
+ define_siblings_read_func(thread_siblings, sibling_cpumask);
+-static BIN_ATTR_RO(thread_siblings, 0);
+-static BIN_ATTR_RO(thread_siblings_list, 0);
++static BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
+
+ define_siblings_read_func(core_cpus, sibling_cpumask);
+-static BIN_ATTR_RO(core_cpus, 0);
+-static BIN_ATTR_RO(core_cpus_list, 0);
++static BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
+
+ define_siblings_read_func(core_siblings, core_cpumask);
+-static BIN_ATTR_RO(core_siblings, 0);
+-static BIN_ATTR_RO(core_siblings_list, 0);
++static BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
+
+ #ifdef TOPOLOGY_CLUSTER_SYSFS
+ define_siblings_read_func(cluster_cpus, cluster_cpumask);
+-static BIN_ATTR_RO(cluster_cpus, 0);
+-static BIN_ATTR_RO(cluster_cpus_list, 0);
++static BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
+ #endif
+
+ #ifdef TOPOLOGY_DIE_SYSFS
+ define_siblings_read_func(die_cpus, die_cpumask);
+-static BIN_ATTR_RO(die_cpus, 0);
+-static BIN_ATTR_RO(die_cpus_list, 0);
++static BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
+ #endif
+
+ define_siblings_read_func(package_cpus, core_cpumask);
+-static BIN_ATTR_RO(package_cpus, 0);
+-static BIN_ATTR_RO(package_cpus_list, 0);
++static BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
+
+ #ifdef CONFIG_SCHED_BOOK
+ define_id_show_func(book_id);
+ static DEVICE_ATTR_RO(book_id);
+ define_siblings_read_func(book_siblings, book_cpumask);
+-static BIN_ATTR_RO(book_siblings, 0);
+-static BIN_ATTR_RO(book_siblings_list, 0);
++static BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
+ #endif
+
+ #ifdef CONFIG_SCHED_DRAWER
+ define_id_show_func(drawer_id);
+ static DEVICE_ATTR_RO(drawer_id);
+ define_siblings_read_func(drawer_siblings, drawer_cpumask);
+-static BIN_ATTR_RO(drawer_siblings, 0);
+-static BIN_ATTR_RO(drawer_siblings_list, 0);
++static BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
++static BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
+ #endif
+
+ static struct bin_attribute *bin_attrs[] = {
+diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
+index 1e7399fc69c0..054e654f06de 100644
+--- a/include/linux/cpumask.h
++++ b/include/linux/cpumask.h
+@@ -1045,4 +1045,22 @@ cpumap_print_list_to_buf(char *buf, const struct cpumask *mask,
+ [0] = 1UL \
+ } }
+
++/*
++ * Provide a valid theoretical max size for cpumap and cpulist sysfs files
++ * to avoid breaking userspace which may allocate a buffer based on the size
++ * reported by e.g. fstat.
++ *
++ * for cpumap NR_CPUS * 9/32 - 1 should be an exact length.
++ *
++ * For cpulist 7 is (ceil(log10(NR_CPUS)) + 1) allowing for NR_CPUS to be up
++ * to 2 orders of magnitude larger than 8192. And then we divide by 2 to
++ * cover a worst-case of every other cpu being on one of two nodes for a
++ * very large NR_CPUS.
++ *
++ * Use PAGE_SIZE as a minimum for smaller configurations.
++ */
++#define CPUMAP_FILE_MAX_BYTES ((((NR_CPUS * 9)/32 - 1) > PAGE_SIZE) \
++ ? (NR_CPUS * 9)/32 - 1 : PAGE_SIZE)
++#define CPULIST_FILE_MAX_BYTES (((NR_CPUS * 7)/2 > PAGE_SIZE) ? (NR_CPUS * 7)/2 : PAGE_SIZE)
++
+ #endif /* __LINUX_CPUMASK_H */
+--
+2.35.1
+
--- /dev/null
+From 8694527edadbe03effe336ee4e9544b1cbf0ec56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Jun 2022 12:45:37 +0300
+Subject: drm/dp/mst: Read the extended DPCD capabilities during system resume
+
+From: Imre Deak <imre.deak@intel.com>
+
+[ Upstream commit 7a710a8bc909313951eb9252d8419924c771d7c2 ]
+
+The WD22TB4 Thunderbolt dock at least will revert its DP_MAX_LINK_RATE
+from HBR3 to HBR2 after system suspend/resume if the DP_DP13_DPCD_REV
+registers are not read subsequently also as required.
+
+Fix this by reading DP_DP13_DPCD_REV registers as well, matching what is
+done during connector detection. While at it also fix up the same call
+in drm_dp_mst_dump_topology().
+
+Cc: Lyude Paul <lyude@redhat.com>
+Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5292
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Cc: <stable@vger.kernel.org> # v5.14+
+Reviewed-by: Lyude Paul <lyude@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220614094537.885472-1-imre.deak@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_dp_mst_topology.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
+index b3e3babe18c0..2a586e6489da 100644
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -3860,9 +3860,7 @@ int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
+ if (!mgr->mst_primary)
+ goto out_fail;
+
+- ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, mgr->dpcd,
+- DP_RECEIVER_CAP_SIZE);
+- if (ret != DP_RECEIVER_CAP_SIZE) {
++ if (drm_dp_read_dpcd_caps(mgr->aux, mgr->dpcd) < 0) {
+ drm_dbg_kms(mgr->dev, "dpcd read failed - undocked during suspend?\n");
+ goto out_fail;
+ }
+@@ -4894,8 +4892,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
+ u8 buf[DP_PAYLOAD_TABLE_SIZE];
+ int ret;
+
+- ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
+- if (ret) {
++ if (drm_dp_read_dpcd_caps(mgr->aux, buf) < 0) {
+ seq_printf(m, "dpcd read failed\n");
+ goto out;
+ }
+--
+2.35.1
+
--- /dev/null
+From 243864f2df3daf5d6cb0e245ad8c0e5e86095300 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Feb 2022 10:27:42 +0100
+Subject: drm/mediatek: Allow commands to be sent during video mode
+
+From: Julien STEPHAN <jstephan@baylibre.com>
+
+[ Upstream commit 81cc7e51c4f1686b71e30046437056ece6b2cb4d ]
+
+Mipi dsi panel drivers can use mipi_dsi_dcs_{set,get}_display_brightness()
+to request backlight changes.
+
+This can be done during panel initialization (dsi is in command mode)
+or afterwards (dsi is in Video Mode).
+
+When the DSI is in Video Mode, all commands are rejected.
+
+Detect current DSI mode in mtk_dsi_host_transfer() and switch modes
+temporarily to allow commands to be sent.
+
+Signed-off-by: Julien STEPHAN <jstephan@baylibre.com>
+Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 33 ++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index b0cb0ba53589..ab51656d5dae 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -910,24 +910,33 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ u8 read_data[16];
+ void *src_addr;
+ u8 irq_flag = CMD_DONE_INT_FLAG;
++ u32 dsi_mode;
++ int ret;
+
+- if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) {
+- DRM_ERROR("dsi engine is not command mode\n");
+- return -EINVAL;
++ dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
++ if (dsi_mode & MODE) {
++ mtk_dsi_stop(dsi);
++ ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
++ if (ret)
++ goto restore_dsi_mode;
+ }
+
+ if (MTK_DSI_HOST_IS_READ(msg->type))
+ irq_flag |= LPRX_RD_RDY_INT_FLAG;
+
+- if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0)
+- return -ETIME;
++ ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag);
++ if (ret)
++ goto restore_dsi_mode;
+
+- if (!MTK_DSI_HOST_IS_READ(msg->type))
+- return 0;
++ if (!MTK_DSI_HOST_IS_READ(msg->type)) {
++ recv_cnt = 0;
++ goto restore_dsi_mode;
++ }
+
+ if (!msg->rx_buf) {
+ DRM_ERROR("dsi receive buffer size may be NULL\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto restore_dsi_mode;
+ }
+
+ for (i = 0; i < 16; i++)
+@@ -952,7 +961,13 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n",
+ recv_cnt, *((u8 *)(msg->tx_buf)));
+
+- return recv_cnt;
++restore_dsi_mode:
++ if (dsi_mode & MODE) {
++ mtk_dsi_set_mode(dsi);
++ mtk_dsi_start(dsi);
++ }
++
++ return ret < 0 ? ret : recv_cnt;
+ }
+
+ static const struct mipi_dsi_host_ops mtk_dsi_ops = {
+--
+2.35.1
+
--- /dev/null
+From 7f86de396d1dab9dcb0538a562495d2c6afc5d70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 May 2022 10:00:06 +0800
+Subject: drm/mediatek: Keep dsi as LP00 before dcs cmds transfer
+
+From: Jitao Shi <jitao.shi@mediatek.com>
+
+[ Upstream commit 39e8d062b03c3dc257d880d82bd55cdd9e185a3b ]
+
+To comply with the panel sequence, hold the mipi signal to LP00 before
+the dcs cmds transmission, and pull the mipi signal high from LP00 to
+LP11 until the start of the dcs cmds transmission.
+
+The normal panel timing is :
+(1) pp1800 DC pull up
+(2) avdd & avee AC pull high
+(3) lcm_reset pull high -> pull low -> pull high
+(4) Pull MIPI signal high (LP11) -> initial code -> send video data
+ (HS mode)
+
+The power-off sequence is reversed.
+If dsi is not in cmd mode, then dsi will pull the mipi signal high in
+the mtk_output_dsi_enable function. The delay in lane_ready func is
+the reaction time of dsi_rx after pulling up the mipi signal.
+
+Fixes: 2dd8075d2185 ("drm/mediatek: mtk_dsi: Use the drm_panel_bridge API")
+
+Link: https://patchwork.kernel.org/project/linux-mediatek/patch/1653012007-11854-4-git-send-email-xinlei.lee@mediatek.com/
+Cc: <stable@vger.kernel.org> # 5.10.x: 7f6335c6a258: drm/mediatek: Modify dsi funcs to atomic operations
+Cc: <stable@vger.kernel.org> # 5.10.x: cde7e2e35c28: drm/mediatek: Separate poweron/poweroff from enable/disable and define new funcs
+Cc: <stable@vger.kernel.org> # 5.10.x
+Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
+Signed-off-by: Xinlei Lee <xinlei.lee@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 28 +++++++++++++++++++++-------
+ 1 file changed, 21 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index ab51656d5dae..ac14e598a14f 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -203,6 +203,7 @@ struct mtk_dsi {
+ struct mtk_phy_timing phy_timing;
+ int refcount;
+ bool enabled;
++ bool lanes_ready;
+ u32 irq_data;
+ wait_queue_head_t irq_wait_queue;
+ const struct mtk_dsi_driver_data *driver_data;
+@@ -649,18 +650,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
+ mtk_dsi_reset_engine(dsi);
+ mtk_dsi_phy_timconfig(dsi);
+
+- mtk_dsi_rxtx_control(dsi);
+- usleep_range(30, 100);
+- mtk_dsi_reset_dphy(dsi);
+ mtk_dsi_ps_control_vact(dsi);
+ mtk_dsi_set_vm_cmd(dsi);
+ mtk_dsi_config_vdo_timing(dsi);
+ mtk_dsi_set_interrupt_enable(dsi);
+
+- mtk_dsi_clk_ulp_mode_leave(dsi);
+- mtk_dsi_lane0_ulp_mode_leave(dsi);
+- mtk_dsi_clk_hs_mode(dsi, 0);
+-
+ return 0;
+ err_disable_engine_clk:
+ clk_disable_unprepare(dsi->engine_clk);
+@@ -691,6 +685,23 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
+ clk_disable_unprepare(dsi->digital_clk);
+
+ phy_power_off(dsi->phy);
++
++ dsi->lanes_ready = false;
++}
++
++static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
++{
++ if (!dsi->lanes_ready) {
++ dsi->lanes_ready = true;
++ mtk_dsi_rxtx_control(dsi);
++ usleep_range(30, 100);
++ mtk_dsi_reset_dphy(dsi);
++ mtk_dsi_clk_ulp_mode_leave(dsi);
++ mtk_dsi_lane0_ulp_mode_leave(dsi);
++ mtk_dsi_clk_hs_mode(dsi, 0);
++ msleep(20);
++ /* The reaction time after pulling up the mipi signal for dsi_rx */
++ }
+ }
+
+ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
+@@ -698,6 +709,7 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
+ if (dsi->enabled)
+ return;
+
++ mtk_dsi_lane_ready(dsi);
+ mtk_dsi_set_mode(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 1);
+
+@@ -924,6 +936,8 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ if (MTK_DSI_HOST_IS_READ(msg->type))
+ irq_flag |= LPRX_RD_RDY_INT_FLAG;
+
++ mtk_dsi_lane_ready(dsi);
++
+ ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag);
+ if (ret)
+ goto restore_dsi_mode;
+--
+2.35.1
+
--- /dev/null
+From 06208ff69009db66d711791450761f83b1a35f35 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 16:47:28 +0200
+Subject: drm/vc4: drv: Adopt the dma configuration from the HVS or V3D
+ component
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+
+[ Upstream commit da8e393e23efb60eba8959856c7df88f9859f6eb ]
+
+vc4_drv isn't necessarily under the /soc node in DT as it is a
+virtual device, but it is the one that does the allocations.
+The DMA addresses are consumed by primarily the HVS or V3D, and
+those require VideoCore cache alias address mapping, and so will be
+under /soc.
+
+During probe find the a suitable device node for HVS or V3D,
+and adopt the DMA configuration of that node.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Link: https://lore.kernel.org/r/20220613144800.326124-2-maxime@cerno.tech
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
+index f6c16c5aee68..6e52801e2d99 100644
+--- a/drivers/gpu/drm/vc4/vc4_drv.c
++++ b/drivers/gpu/drm/vc4/vc4_drv.c
+@@ -214,6 +214,15 @@ static void vc4_match_add_drivers(struct device *dev,
+ }
+ }
+
++const struct of_device_id vc4_dma_range_matches[] = {
++ { .compatible = "brcm,bcm2711-hvs" },
++ { .compatible = "brcm,bcm2835-hvs" },
++ { .compatible = "brcm,bcm2835-v3d" },
++ { .compatible = "brcm,cygnus-v3d" },
++ { .compatible = "brcm,vc4-v3d" },
++ {}
++};
++
+ static int vc4_drm_bind(struct device *dev)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+@@ -231,6 +240,16 @@ static int vc4_drm_bind(struct device *dev)
+ vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
+ of_node_put(node);
+
++ node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches,
++ NULL);
++ if (node) {
++ ret = of_dma_configure(dev, node, true);
++ of_node_put(node);
++
++ if (ret)
++ return ret;
++ }
++
+ vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base);
+ if (IS_ERR(vc4))
+ return PTR_ERR(vc4);
+--
+2.35.1
+
--- /dev/null
+From 7e2b828c174bb92b4832b3e238d8d2c193d1a45d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 10:13:55 +0800
+Subject: ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 179b14152dcb6a24c3415200603aebca70ff13af ]
+
+When adding an xattr to an inode, we must ensure that the inode_size is
+not less than EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. Otherwise,
+the end position may be greater than the start position, resulting in UAF.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20220616021358.2504451-2-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 77efb9a627ad..f885f362add4 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -95,6 +95,19 @@ struct ext4_xattr_entry {
+
+ #define EXT4_ZERO_XATTR_VALUE ((void *)-1)
+
++/*
++ * If we want to add an xattr to the inode, we should make sure that
++ * i_extra_isize is not 0 and that the inode size is not less than
++ * EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad.
++ * EXT4_GOOD_OLD_INODE_SIZE extra_isize header entry pad data
++ * |--------------------------|------------|------|---------|---|-------|
++ */
++#define EXT4_INODE_HAS_XATTR_SPACE(inode) \
++ ((EXT4_I(inode)->i_extra_isize != 0) && \
++ (EXT4_GOOD_OLD_INODE_SIZE + EXT4_I(inode)->i_extra_isize + \
++ sizeof(struct ext4_xattr_ibody_header) + EXT4_XATTR_PAD <= \
++ EXT4_INODE_SIZE((inode)->i_sb)))
++
+ struct ext4_xattr_info {
+ const char *name;
+ const void *value;
+--
+2.35.1
+
--- /dev/null
+From 57e37b1671dd15766e9431707d0ba164f9cf767d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Jul 2022 16:27:20 +0200
+Subject: ext4: check if directory block is within i_size
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+[ Upstream commit 65f8ea4cd57dbd46ea13b41dc8bac03176b04233 ]
+
+Currently ext4 directory handling code implicitly assumes that the
+directory blocks are always within the i_size. In fact ext4_append()
+will attempt to allocate next directory block based solely on i_size and
+the i_size is then appropriately increased after a successful
+allocation.
+
+However, for this to work it requires i_size to be correct. If, for any
+reason, the directory inode i_size is corrupted in a way that the
+directory tree refers to a valid directory block past i_size, we could
+end up corrupting parts of the directory tree structure by overwriting
+already used directory blocks when modifying the directory.
+
+Fix it by catching the corruption early in __ext4_read_dirblock().
+
+Addresses Red-Hat-Bugzilla: #2070205
+CVE: CVE-2022-1184
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20220704142721.157985-1-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/namei.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 871eebf12bf4..ac0b7e53591f 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -110,6 +110,13 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
+ struct ext4_dir_entry *dirent;
+ int is_dx_block = 0;
+
++ if (block >= inode->i_size) {
++ ext4_error_inode(inode, func, line, block,
++ "Attempting to read directory block (%u) that is past i_size (%llu)",
++ block, inode->i_size);
++ return ERR_PTR(-EFSCORRUPTED);
++ }
++
+ if (ext4_simulate_fail(inode->i_sb, EXT4_SIM_DIRBLOCK_EIO))
+ bh = ERR_PTR(-EIO);
+ else
+--
+2.35.1
+
--- /dev/null
+From 304c7507b95cfd6985aaa2612801b08d28dc1708 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 10:13:57 +0800
+Subject: ext4: correct max_inline_xattr_value_size computing
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit c9fd167d57133c5b748d16913c4eabc55e531c73 ]
+
+If the ext4 inode does not have xattr space, 0 is returned in the
+get_max_inline_xattr_value_size function. Otherwise, the function returns
+a negative value when the inode does not contain EXT4_STATE_XATTR.
+
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220616021358.2504451-4-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inline.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
+index 28bc431cf5ba..38ad09e802e4 100644
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -35,6 +35,9 @@ static int get_max_inline_xattr_value_size(struct inode *inode,
+ struct ext4_inode *raw_inode;
+ int free, min_offs;
+
++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
++ return 0;
++
+ min_offs = EXT4_SB(inode->i_sb)->s_inode_size -
+ EXT4_GOOD_OLD_INODE_SIZE -
+ EXT4_I(inode)->i_extra_isize -
+--
+2.35.1
+
--- /dev/null
+From d2b4d667e5d2a217a92cd61c2848c0c9a91def6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 10:13:58 +0800
+Subject: ext4: correct the misjudgment in ext4_iget_extra_inode
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit fd7e672ea98b95b9d4c9dae316639f03c16a749d ]
+
+Use the EXT4_INODE_HAS_XATTR_SPACE macro to more accurately
+determine whether the inode have xattr space.
+
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220616021358.2504451-5-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 149377c849ee..f95c73defe05 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4516,8 +4516,7 @@ static inline int ext4_iget_extra_inode(struct inode *inode,
+ __le32 *magic = (void *)raw_inode +
+ EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize;
+
+- if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize + sizeof(__le32) <=
+- EXT4_INODE_SIZE(inode->i_sb) &&
++ if (EXT4_INODE_HAS_XATTR_SPACE(inode) &&
+ *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
+ ext4_set_inode_state(inode, EXT4_STATE_XATTR);
+ return ext4_find_inline_data_nolock(inode);
+--
+2.35.1
+
--- /dev/null
+From 1264125b3b0d6dc51db48c6303bb8fb9bfdd88a2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 12:05:30 -0400
+Subject: ext4: fix extent status tree race in writeback error recovery path
+
+From: Eric Whitney <enwlinux@gmail.com>
+
+[ Upstream commit 7f0d8e1d607c1a4fa9a27362a108921d82230874 ]
+
+A race can occur in the unlikely event ext4 is unable to allocate a
+physical cluster for a delayed allocation in a bigalloc file system
+during writeback. Failure to allocate a cluster forces error recovery
+that includes a call to mpage_release_unused_pages(). That function
+removes any corresponding delayed allocated blocks from the extent
+status tree. If a new delayed write is in progress on the same cluster
+simultaneously, resulting in the addition of an new extent containing
+one or more blocks in that cluster to the extent status tree, delayed
+block accounting can be thrown off if that delayed write then encounters
+a similar cluster allocation failure during future writeback.
+
+Write lock the i_data_sem in mpage_release_unused_pages() to fix this
+problem. Ext4's block/cluster accounting code for bigalloc relies on
+i_data_sem for mutual exclusion, as is found in the delayed write path,
+and the locking in mpage_release_unused_pages() is missing.
+
+Cc: stable@kernel.org
+Reported-by: Ye Bin <yebin10@huawei.com>
+Signed-off-by: Eric Whitney <enwlinux@gmail.com>
+Link: https://lore.kernel.org/r/20220615160530.1928801-1-enwlinux@gmail.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f0350d60ba50..149377c849ee 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1560,7 +1560,14 @@ static void mpage_release_unused_pages(struct mpage_da_data *mpd,
+ ext4_lblk_t start, last;
+ start = index << (PAGE_SHIFT - inode->i_blkbits);
+ last = end << (PAGE_SHIFT - inode->i_blkbits);
++
++ /*
++ * avoid racing with extent status tree scans made by
++ * ext4_insert_delayed_block()
++ */
++ down_write(&EXT4_I(inode)->i_data_sem);
+ ext4_es_remove_extent(inode, start, last - start + 1);
++ up_write(&EXT4_I(inode)->i_data_sem);
+ }
+
+ pagevec_init(&pvec);
+--
+2.35.1
+
--- /dev/null
+From 17452bc7744e3011f61a29340e2e13848eff0020 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 12:54:24 +0200
+Subject: ext4: fix race when reusing xattr blocks
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 65f8b80053a1b2fd602daa6814e62d6fa90e5e9b ]
+
+When ext4_xattr_block_set() decides to remove xattr block the following
+race can happen:
+
+CPU1 CPU2
+ext4_xattr_block_set() ext4_xattr_release_block()
+ new_bh = ext4_xattr_block_cache_find()
+
+ lock_buffer(bh);
+ ref = le32_to_cpu(BHDR(bh)->h_refcount);
+ if (ref == 1) {
+ ...
+ mb_cache_entry_delete();
+ unlock_buffer(bh);
+ ext4_free_blocks();
+ ...
+ ext4_forget(..., bh, ...);
+ jbd2_journal_revoke(..., bh);
+
+ ext4_journal_get_write_access(..., new_bh, ...)
+ do_get_write_access()
+ jbd2_journal_cancel_revoke(..., new_bh);
+
+Later the code in ext4_xattr_block_set() finds out the block got freed
+and cancels reusal of the block but the revoke stays canceled and so in
+case of block reuse and journal replay the filesystem can get corrupted.
+If the race works out slightly differently, we can also hit assertions
+in the jbd2 code.
+
+Fix the problem by making sure that once matching mbcache entry is
+found, code dropping the last xattr block reference (or trying to modify
+xattr block in place) waits until the mbcache entry reference is
+dropped. This way code trying to reuse xattr block is protected from
+someone trying to drop the last reference to xattr block.
+
+Reported-and-tested-by: Ritesh Harjani <ritesh.list@gmail.com>
+CC: stable@vger.kernel.org
+Fixes: 82939d7999df ("ext4: convert to mbcache2")
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220712105436.32204-5-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 67 +++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 45 insertions(+), 22 deletions(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index a25942a74929..533216e80fa2 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -439,9 +439,16 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ /* Remove entry from mbcache when EA inode is getting evicted */
+ void ext4_evict_ea_inode(struct inode *inode)
+ {
+- if (EA_INODE_CACHE(inode))
+- mb_cache_entry_delete(EA_INODE_CACHE(inode),
+- ext4_xattr_inode_get_hash(inode), inode->i_ino);
++ struct mb_cache_entry *oe;
++
++ if (!EA_INODE_CACHE(inode))
++ return;
++ /* Wait for entry to get unused so that we can remove it */
++ while ((oe = mb_cache_entry_delete_or_get(EA_INODE_CACHE(inode),
++ ext4_xattr_inode_get_hash(inode), inode->i_ino))) {
++ mb_cache_entry_wait_unused(oe);
++ mb_cache_entry_put(EA_INODE_CACHE(inode), oe);
++ }
+ }
+
+ static int
+@@ -1229,6 +1236,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+ if (error)
+ goto out;
+
++retry_ref:
+ lock_buffer(bh);
+ hash = le32_to_cpu(BHDR(bh)->h_hash);
+ ref = le32_to_cpu(BHDR(bh)->h_refcount);
+@@ -1238,9 +1246,18 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
+ * This must happen under buffer lock for
+ * ext4_xattr_block_set() to reliably detect freed block
+ */
+- if (ea_block_cache)
+- mb_cache_entry_delete(ea_block_cache, hash,
+- bh->b_blocknr);
++ if (ea_block_cache) {
++ struct mb_cache_entry *oe;
++
++ oe = mb_cache_entry_delete_or_get(ea_block_cache, hash,
++ bh->b_blocknr);
++ if (oe) {
++ unlock_buffer(bh);
++ mb_cache_entry_wait_unused(oe);
++ mb_cache_entry_put(ea_block_cache, oe);
++ goto retry_ref;
++ }
++ }
+ get_bh(bh);
+ unlock_buffer(bh);
+
+@@ -1867,9 +1884,20 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ * ext4_xattr_block_set() to reliably detect modified
+ * block
+ */
+- if (ea_block_cache)
+- mb_cache_entry_delete(ea_block_cache, hash,
+- bs->bh->b_blocknr);
++ if (ea_block_cache) {
++ struct mb_cache_entry *oe;
++
++ oe = mb_cache_entry_delete_or_get(ea_block_cache,
++ hash, bs->bh->b_blocknr);
++ if (oe) {
++ /*
++ * Xattr block is getting reused. Leave
++ * it alone.
++ */
++ mb_cache_entry_put(ea_block_cache, oe);
++ goto clone_block;
++ }
++ }
+ ea_bdebug(bs->bh, "modifying in-place");
+ error = ext4_xattr_set_entry(i, s, handle, inode,
+ true /* is_block */);
+@@ -1885,6 +1913,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ goto cleanup;
+ goto inserted;
+ }
++clone_block:
+ unlock_buffer(bs->bh);
+ ea_bdebug(bs->bh, "cloning");
+ s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
+@@ -1990,18 +2019,13 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ lock_buffer(new_bh);
+ /*
+ * We have to be careful about races with
+- * freeing, rehashing or adding references to
+- * xattr block. Once we hold buffer lock xattr
+- * block's state is stable so we can check
+- * whether the block got freed / rehashed or
+- * not. Since we unhash mbcache entry under
+- * buffer lock when freeing / rehashing xattr
+- * block, checking whether entry is still
+- * hashed is reliable. Same rules hold for
+- * e_reusable handling.
++ * adding references to xattr block. Once we
++ * hold buffer lock xattr block's state is
++ * stable so we can check the additional
++ * reference fits.
+ */
+- if (hlist_bl_unhashed(&ce->e_hash_list) ||
+- !ce->e_reusable) {
++ ref = le32_to_cpu(BHDR(new_bh)->h_refcount) + 1;
++ if (ref > EXT4_XATTR_REFCOUNT_MAX) {
+ /*
+ * Undo everything and check mbcache
+ * again.
+@@ -2016,9 +2040,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ new_bh = NULL;
+ goto inserted;
+ }
+- ref = le32_to_cpu(BHDR(new_bh)->h_refcount) + 1;
+ BHDR(new_bh)->h_refcount = cpu_to_le32(ref);
+- if (ref >= EXT4_XATTR_REFCOUNT_MAX)
++ if (ref == EXT4_XATTR_REFCOUNT_MAX)
+ ce->e_reusable = 0;
+ ea_bdebug(new_bh, "reusing; refcount now=%d",
+ ref);
+--
+2.35.1
+
--- /dev/null
+From 19663aea6ffb8fceab2f77fdc15d6a9bb564cb8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Jun 2022 10:13:56 +0800
+Subject: ext4: fix use-after-free in ext4_xattr_set_entry
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 67d7d8ad99beccd9fe92d585b87f1760dc9018e3 ]
+
+Hulk Robot reported a issue:
+==================================================================
+BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x18ab/0x3500
+Write of size 4105 at addr ffff8881675ef5f4 by task syz-executor.0/7092
+
+CPU: 1 PID: 7092 Comm: syz-executor.0 Not tainted 4.19.90-dirty #17
+Call Trace:
+[...]
+ memcpy+0x34/0x50 mm/kasan/kasan.c:303
+ ext4_xattr_set_entry+0x18ab/0x3500 fs/ext4/xattr.c:1747
+ ext4_xattr_ibody_inline_set+0x86/0x2a0 fs/ext4/xattr.c:2205
+ ext4_xattr_set_handle+0x940/0x1300 fs/ext4/xattr.c:2386
+ ext4_xattr_set+0x1da/0x300 fs/ext4/xattr.c:2498
+ __vfs_setxattr+0x112/0x170 fs/xattr.c:149
+ __vfs_setxattr_noperm+0x11b/0x2a0 fs/xattr.c:180
+ __vfs_setxattr_locked+0x17b/0x250 fs/xattr.c:238
+ vfs_setxattr+0xed/0x270 fs/xattr.c:255
+ setxattr+0x235/0x330 fs/xattr.c:520
+ path_setxattr+0x176/0x190 fs/xattr.c:539
+ __do_sys_lsetxattr fs/xattr.c:561 [inline]
+ __se_sys_lsetxattr fs/xattr.c:557 [inline]
+ __x64_sys_lsetxattr+0xc2/0x160 fs/xattr.c:557
+ do_syscall_64+0xdf/0x530 arch/x86/entry/common.c:298
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+RIP: 0033:0x459fe9
+RSP: 002b:00007fa5e54b4c08 EFLAGS: 00000246 ORIG_RAX: 00000000000000bd
+RAX: ffffffffffffffda RBX: 000000000051bf60 RCX: 0000000000459fe9
+RDX: 00000000200003c0 RSI: 0000000020000180 RDI: 0000000020000140
+RBP: 000000000051bf60 R08: 0000000000000001 R09: 0000000000000000
+R10: 0000000000001009 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007ffc73c93fc0 R14: 000000000051bf60 R15: 00007fa5e54b4d80
+[...]
+==================================================================
+
+Above issue may happen as follows:
+-------------------------------------
+ext4_xattr_set
+ ext4_xattr_set_handle
+ ext4_xattr_ibody_find
+ >> s->end < s->base
+ >> no EXT4_STATE_XATTR
+ >> xattr_check_inode is not executed
+ ext4_xattr_ibody_set
+ ext4_xattr_set_entry
+ >> size_t min_offs = s->end - s->base
+ >> UAF in memcpy
+
+we can easily reproduce this problem with the following commands:
+ mkfs.ext4 -F /dev/sda
+ mount -o debug_want_extra_isize=128 /dev/sda /mnt
+ touch /mnt/file
+ setfattr -n user.cat -v `seq -s z 4096|tr -d '[:digit:]'` /mnt/file
+
+In ext4_xattr_ibody_find, we have the following assignment logic:
+ header = IHDR(inode, raw_inode)
+ = raw_inode + EXT4_GOOD_OLD_INODE_SIZE + i_extra_isize
+ is->s.base = IFIRST(header)
+ = header + sizeof(struct ext4_xattr_ibody_header)
+ is->s.end = raw_inode + s_inode_size
+
+In ext4_xattr_set_entry
+ min_offs = s->end - s->base
+ = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize -
+ sizeof(struct ext4_xattr_ibody_header)
+ last = s->first
+ free = min_offs - ((void *)last - s->base) - sizeof(__u32)
+ = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize -
+ sizeof(struct ext4_xattr_ibody_header) - sizeof(__u32)
+
+In the calculation formula, all values except s_inode_size and
+i_extra_size are fixed values. When i_extra_size is the maximum value
+s_inode_size - EXT4_GOOD_OLD_INODE_SIZE, min_offs is -4 and free is -8.
+The value overflows. As a result, the preceding issue is triggered when
+memcpy is executed.
+
+Therefore, when finding xattr or setting xattr, check whether
+there is space for storing xattr in the inode to resolve this issue.
+
+Cc: stable@kernel.org
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220616021358.2504451-3-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 042325349098..c3c3194f3ee1 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -2176,8 +2176,9 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+ struct ext4_inode *raw_inode;
+ int error;
+
+- if (EXT4_I(inode)->i_extra_isize == 0)
++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
+ return 0;
++
+ raw_inode = ext4_raw_inode(&is->iloc);
+ header = IHDR(inode, raw_inode);
+ is->s.base = is->s.first = IFIRST(header);
+@@ -2205,8 +2206,9 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
+ struct ext4_xattr_search *s = &is->s;
+ int error;
+
+- if (EXT4_I(inode)->i_extra_isize == 0)
++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode))
+ return -ENOSPC;
++
+ error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */);
+ if (error)
+ return error;
+--
+2.35.1
+
--- /dev/null
+From 86911a73bc1d6a5c206fb422230bb328b1df552f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jun 2022 09:39:35 +0800
+Subject: ext4: fix warning in ext4_iomap_begin as race between bmap and write
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 51ae846cff568c8c29921b1b28eb2dfbcd4ac12d ]
+
+We got issue as follows:
+------------[ cut here ]------------
+WARNING: CPU: 3 PID: 9310 at fs/ext4/inode.c:3441 ext4_iomap_begin+0x182/0x5d0
+RIP: 0010:ext4_iomap_begin+0x182/0x5d0
+RSP: 0018:ffff88812460fa08 EFLAGS: 00010293
+RAX: ffff88811f168000 RBX: 0000000000000000 RCX: ffffffff97793c12
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
+RBP: ffff88812c669160 R08: ffff88811f168000 R09: ffffed10258cd20f
+R10: ffff88812c669077 R11: ffffed10258cd20e R12: 0000000000000001
+R13: 00000000000000a4 R14: 000000000000000c R15: ffff88812c6691ee
+FS: 00007fd0d6ff3740(0000) GS:ffff8883af180000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007fd0d6dda290 CR3: 0000000104a62000 CR4: 00000000000006e0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+Call Trace:
+ iomap_apply+0x119/0x570
+ iomap_bmap+0x124/0x150
+ ext4_bmap+0x14f/0x250
+ bmap+0x55/0x80
+ do_vfs_ioctl+0x952/0xbd0
+ __x64_sys_ioctl+0xc6/0x170
+ do_syscall_64+0x33/0x40
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+
+Above issue may happen as follows:
+ bmap write
+bmap
+ ext4_bmap
+ iomap_bmap
+ ext4_iomap_begin
+ ext4_file_write_iter
+ ext4_buffered_write_iter
+ generic_perform_write
+ ext4_da_write_begin
+ ext4_da_write_inline_data_begin
+ ext4_prepare_inline_data
+ ext4_create_inline_data
+ ext4_set_inode_flag(inode,
+ EXT4_INODE_INLINE_DATA);
+ if (WARN_ON_ONCE(ext4_has_inline_data(inode))) ->trigger bug_on
+
+To solved above issue hold inode lock in ext4_bamp.
+
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Link: https://lore.kernel.org/r/20220617013935.397596-1-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index f95c73defe05..360a7d153955 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -3137,13 +3137,15 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ {
+ struct inode *inode = mapping->host;
+ journal_t *journal;
++ sector_t ret = 0;
+ int err;
+
++ inode_lock_shared(inode);
+ /*
+ * We can get here for an inline file via the FIBMAP ioctl
+ */
+ if (ext4_has_inline_data(inode))
+- return 0;
++ goto out;
+
+ if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY) &&
+ test_opt(inode->i_sb, DELALLOC)) {
+@@ -3182,10 +3184,14 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
+ jbd2_journal_unlock_updates(journal);
+
+ if (err)
+- return 0;
++ goto out;
+ }
+
+- return iomap_bmap(mapping, block, &ext4_iomap_ops);
++ ret = iomap_bmap(mapping, block, &ext4_iomap_ops);
++
++out:
++ inode_unlock_shared(inode);
++ return ret;
+ }
+
+ static int ext4_readpage(struct file *file, struct page *page)
+--
+2.35.1
+
--- /dev/null
+From 67f725fbcb44ebec0e5c4353f5a468e6b93886a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Jul 2022 16:27:21 +0200
+Subject: ext4: make sure ext4_append() always allocates new block
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+[ Upstream commit b8a04fe77ef1360fbf73c80fddbdfeaa9407ed1b ]
+
+ext4_append() must always allocate a new block, otherwise we run the
+risk of overwriting existing directory block corrupting the directory
+tree in the process resulting in all manner of problems later on.
+
+Add a sanity check to see if the logical block is already allocated and
+error out if it is.
+
+Cc: stable@kernel.org
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20220704142721.157985-2-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/namei.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index ac0b7e53591f..5821638cb893 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -54,6 +54,7 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ struct inode *inode,
+ ext4_lblk_t *block)
+ {
++ struct ext4_map_blocks map;
+ struct buffer_head *bh;
+ int err;
+
+@@ -63,6 +64,21 @@ static struct buffer_head *ext4_append(handle_t *handle,
+ return ERR_PTR(-ENOSPC);
+
+ *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
++ map.m_lblk = *block;
++ map.m_len = 1;
++
++ /*
++ * We're appending new directory block. Make sure the block is not
++ * allocated yet, otherwise we will end up corrupting the
++ * directory.
++ */
++ err = ext4_map_blocks(NULL, inode, &map, 0);
++ if (err < 0)
++ return ERR_PTR(err);
++ if (err) {
++ EXT4_ERROR_INODE(inode, "Logical block already allocated");
++ return ERR_PTR(-EFSCORRUPTED);
++ }
+
+ bh = ext4_bread(handle, inode, *block, EXT4_GET_BLOCKS_CREATE);
+ if (IS_ERR(bh))
+--
+2.35.1
+
--- /dev/null
+From 723a7030c98ae1a3715d97105b34866cc9df4ec5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 12:54:22 +0200
+Subject: ext4: remove EA inode entry from mbcache on inode eviction
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit 6bc0d63dad7f9f54d381925ee855b402f652fa39 ]
+
+Currently we remove EA inode from mbcache as soon as its xattr refcount
+drops to zero. However there can be pending attempts to reuse the inode
+and thus refcount handling code has to handle the situation when
+refcount increases from zero anyway. So save some work and just keep EA
+inode in mbcache until it is getting evicted. At that moment we are sure
+following iget() of EA inode will fail anyway (or wait for eviction to
+finish and load things from the disk again) and so removing mbcache
+entry at that moment is fine and simplifies the code a bit.
+
+CC: stable@vger.kernel.org
+Fixes: 82939d7999df ("ext4: convert to mbcache2")
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220712105436.32204-3-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 2 ++
+ fs/ext4/xattr.c | 24 ++++++++----------------
+ fs/ext4/xattr.h | 1 +
+ 3 files changed, 11 insertions(+), 16 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 360a7d153955..98f381f6fc18 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -179,6 +179,8 @@ void ext4_evict_inode(struct inode *inode)
+
+ trace_ext4_evict_inode(inode);
+
++ if (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)
++ ext4_evict_ea_inode(inode);
+ if (inode->i_nlink) {
+ /*
+ * When journalling data dirty buffers are tracked only in the
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index c3c3194f3ee1..b57fd07fbdba 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -436,6 +436,14 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
+ return err;
+ }
+
++/* Remove entry from mbcache when EA inode is getting evicted */
++void ext4_evict_ea_inode(struct inode *inode)
++{
++ if (EA_INODE_CACHE(inode))
++ mb_cache_entry_delete(EA_INODE_CACHE(inode),
++ ext4_xattr_inode_get_hash(inode), inode->i_ino);
++}
++
+ static int
+ ext4_xattr_inode_verify_hashes(struct inode *ea_inode,
+ struct ext4_xattr_entry *entry, void *buffer,
+@@ -976,10 +984,8 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
+ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
+ int ref_change)
+ {
+- struct mb_cache *ea_inode_cache = EA_INODE_CACHE(ea_inode);
+ struct ext4_iloc iloc;
+ s64 ref_count;
+- u32 hash;
+ int ret;
+
+ inode_lock(ea_inode);
+@@ -1002,14 +1008,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
+
+ set_nlink(ea_inode, 1);
+ ext4_orphan_del(handle, ea_inode);
+-
+- if (ea_inode_cache) {
+- hash = ext4_xattr_inode_get_hash(ea_inode);
+- mb_cache_entry_create(ea_inode_cache,
+- GFP_NOFS, hash,
+- ea_inode->i_ino,
+- true /* reusable */);
+- }
+ }
+ } else {
+ WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld",
+@@ -1022,12 +1020,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
+
+ clear_nlink(ea_inode);
+ ext4_orphan_add(handle, ea_inode);
+-
+- if (ea_inode_cache) {
+- hash = ext4_xattr_inode_get_hash(ea_inode);
+- mb_cache_entry_delete(ea_inode_cache, hash,
+- ea_inode->i_ino);
+- }
+ }
+ }
+
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index f885f362add4..e5e36bd11f05 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -191,6 +191,7 @@ extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
+
+ extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+ struct ext4_inode *raw_inode, handle_t *handle);
++extern void ext4_evict_ea_inode(struct inode *inode);
+
+ extern const struct xattr_handler *ext4_xattr_handlers[];
+
+--
+2.35.1
+
--- /dev/null
+From 71871a22a9a65e84430055f0429a1b70b0f9286c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 12:54:23 +0200
+Subject: ext4: unindent codeblock in ext4_xattr_block_set()
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit fd48e9acdf26d0cbd80051de07d4a735d05d29b2 ]
+
+Remove unnecessary else (and thus indentation level) from a code block
+in ext4_xattr_block_set(). It will also make following code changes
+easier. No functional changes.
+
+CC: stable@vger.kernel.org
+Fixes: 82939d7999df ("ext4: convert to mbcache2")
+Signed-off-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220712105436.32204-4-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 77 ++++++++++++++++++++++++-------------------------
+ 1 file changed, 38 insertions(+), 39 deletions(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index d92d50de5a01..a25942a74929 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1850,6 +1850,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ #define header(x) ((struct ext4_xattr_header *)(x))
+
+ if (s->base) {
++ int offset = (char *)s->here - bs->bh->b_data;
++
+ BUFFER_TRACE(bs->bh, "get_write_access");
+ error = ext4_journal_get_write_access(handle, sb, bs->bh,
+ EXT4_JTR_NONE);
+@@ -1882,49 +1884,46 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+ if (error)
+ goto cleanup;
+ goto inserted;
+- } else {
+- int offset = (char *)s->here - bs->bh->b_data;
++ }
++ unlock_buffer(bs->bh);
++ ea_bdebug(bs->bh, "cloning");
++ s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
++ error = -ENOMEM;
++ if (s->base == NULL)
++ goto cleanup;
++ s->first = ENTRY(header(s->base)+1);
++ header(s->base)->h_refcount = cpu_to_le32(1);
++ s->here = ENTRY(s->base + offset);
++ s->end = s->base + bs->bh->b_size;
+
+- unlock_buffer(bs->bh);
+- ea_bdebug(bs->bh, "cloning");
+- s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
+- error = -ENOMEM;
+- if (s->base == NULL)
++ /*
++ * If existing entry points to an xattr inode, we need
++ * to prevent ext4_xattr_set_entry() from decrementing
++ * ref count on it because the reference belongs to the
++ * original block. In this case, make the entry look
++ * like it has an empty value.
++ */
++ if (!s->not_found && s->here->e_value_inum) {
++ ea_ino = le32_to_cpu(s->here->e_value_inum);
++ error = ext4_xattr_inode_iget(inode, ea_ino,
++ le32_to_cpu(s->here->e_hash),
++ &tmp_inode);
++ if (error)
+ goto cleanup;
+- s->first = ENTRY(header(s->base)+1);
+- header(s->base)->h_refcount = cpu_to_le32(1);
+- s->here = ENTRY(s->base + offset);
+- s->end = s->base + bs->bh->b_size;
+
+- /*
+- * If existing entry points to an xattr inode, we need
+- * to prevent ext4_xattr_set_entry() from decrementing
+- * ref count on it because the reference belongs to the
+- * original block. In this case, make the entry look
+- * like it has an empty value.
+- */
+- if (!s->not_found && s->here->e_value_inum) {
+- ea_ino = le32_to_cpu(s->here->e_value_inum);
+- error = ext4_xattr_inode_iget(inode, ea_ino,
+- le32_to_cpu(s->here->e_hash),
+- &tmp_inode);
+- if (error)
+- goto cleanup;
+-
+- if (!ext4_test_inode_state(tmp_inode,
+- EXT4_STATE_LUSTRE_EA_INODE)) {
+- /*
+- * Defer quota free call for previous
+- * inode until success is guaranteed.
+- */
+- old_ea_inode_quota = le32_to_cpu(
+- s->here->e_value_size);
+- }
+- iput(tmp_inode);
+-
+- s->here->e_value_inum = 0;
+- s->here->e_value_size = 0;
++ if (!ext4_test_inode_state(tmp_inode,
++ EXT4_STATE_LUSTRE_EA_INODE)) {
++ /*
++ * Defer quota free call for previous
++ * inode until success is guaranteed.
++ */
++ old_ea_inode_quota = le32_to_cpu(
++ s->here->e_value_size);
+ }
++ iput(tmp_inode);
++
++ s->here->e_value_inum = 0;
++ s->here->e_value_size = 0;
+ }
+ } else {
+ /* Allocate a buffer where we construct the new block. */
+--
+2.35.1
+
--- /dev/null
+From aaa919979d4732f24de785c56e839330351ba23c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jun 2022 00:00:25 -0400
+Subject: ext4: update s_overhead_clusters in the superblock during an on-line
+ resize
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+[ Upstream commit de394a86658ffe4e89e5328fd4993abfe41b7435 ]
+
+When doing an online resize, the on-disk superblock on-disk wasn't
+updated. This means that when the file system is unmounted and
+remounted, and the on-disk overhead value is non-zero, this would
+result in the results of statfs(2) to be incorrect.
+
+This was partially fixed by Commits 10b01ee92df5 ("ext4: fix overhead
+calculation to account for the reserved gdt blocks"), 85d825dbf489
+("ext4: force overhead calculation if the s_overhead_cluster makes no
+sense"), and eb7054212eac ("ext4: update the cached overhead value in
+the superblock").
+
+However, since it was too expensive to forcibly recalculate the
+overhead for bigalloc file systems at every mount, this didn't fix the
+problem for bigalloc file systems. This commit should address the
+problem when resizing file systems with the bigalloc feature enabled.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Link: https://lore.kernel.org/r/20220629040026.112371-1-tytso@mit.edu
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/resize.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 56c9ef0687fc..fa3c854125bb 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1472,6 +1472,7 @@ static void ext4_update_super(struct super_block *sb,
+ * Update the fs overhead information
+ */
+ ext4_calculate_overhead(sb);
++ es->s_overhead_clusters = cpu_to_le32(sbi->s_overhead);
+
+ if (test_opt(sb, DEBUG))
+ printk(KERN_DEBUG "EXT4-fs: added group %u:"
+--
+2.35.1
+
--- /dev/null
+From 69601d26ae1f0f5fbd563f58131ba84784faa8f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 25 May 2022 11:01:20 +0800
+Subject: ext4: use kmemdup() to replace kmalloc + memcpy
+
+From: Shuqi Zhang <zhangshuqi3@huawei.com>
+
+[ Upstream commit 4efd9f0d120c55b08852ee5605dbb02a77089a5d ]
+
+Replace kmalloc + memcpy with kmemdup()
+
+Signed-off-by: Shuqi Zhang <zhangshuqi3@huawei.com>
+Reviewed-by: Ritesh Harjani <ritesh.list@gmail.com>
+Link: https://lore.kernel.org/r/20220525030120.803330-1-zhangshuqi3@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index b57fd07fbdba..d92d50de5a01 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1887,11 +1887,10 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,
+
+ unlock_buffer(bs->bh);
+ ea_bdebug(bs->bh, "cloning");
+- s->base = kmalloc(bs->bh->b_size, GFP_NOFS);
++ s->base = kmemdup(BHDR(bs->bh), bs->bh->b_size, GFP_NOFS);
+ error = -ENOMEM;
+ if (s->base == NULL)
+ goto cleanup;
+- memcpy(s->base, BHDR(bs->bh), bs->bh->b_size);
+ s->first = ENTRY(header(s->base)+1);
+ header(s->base)->h_refcount = cpu_to_le32(1);
+ s->here = ENTRY(s->base + offset);
+--
+2.35.1
+
--- /dev/null
+From 80c500ac7a77f89055f67bef3fcee94b3e07bbaa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Jul 2022 17:03:10 +0100
+Subject: firmware: arm_scpi: Ensure scpi_info is not assigned if the probe
+ fails
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 689640efc0a2c4e07e6f88affe6d42cd40cc3f85 ]
+
+When scpi probe fails, at any point, we need to ensure that the scpi_info
+is not set and will remain NULL until the probe succeeds. If it is not
+taken care, then it could result use-after-free as the value is exported
+via get_scpi_ops() and could refer to a memory allocated via devm_kzalloc()
+but freed when the probe fails.
+
+Link: https://lore.kernel.org/r/20220701160310.148344-1-sudeep.holla@arm.com
+Cc: stable@vger.kernel.org # 4.19+
+Reported-by: huhai <huhai@kylinos.cn>
+Reviewed-by: Jackie Liu <liuyun01@kylinos.cn>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_scpi.c | 61 +++++++++++++++++++++----------------
+ 1 file changed, 35 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
+index ddf0b9ff9e15..435d0e2658a4 100644
+--- a/drivers/firmware/arm_scpi.c
++++ b/drivers/firmware/arm_scpi.c
+@@ -815,7 +815,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
+ info->firmware_version = le32_to_cpu(caps.platform_version);
+ }
+ /* Ignore error if not implemented */
+- if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
++ if (info->is_legacy && ret == -EOPNOTSUPP)
+ return 0;
+
+ return ret;
+@@ -913,13 +913,14 @@ static int scpi_probe(struct platform_device *pdev)
+ struct resource res;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
++ struct scpi_drvinfo *scpi_drvinfo;
+
+- scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
+- if (!scpi_info)
++ scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL);
++ if (!scpi_drvinfo)
+ return -ENOMEM;
+
+ if (of_match_device(legacy_scpi_of_match, &pdev->dev))
+- scpi_info->is_legacy = true;
++ scpi_drvinfo->is_legacy = true;
+
+ count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+ if (count < 0) {
+@@ -927,19 +928,19 @@ static int scpi_probe(struct platform_device *pdev)
+ return -ENODEV;
+ }
+
+- scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan),
+- GFP_KERNEL);
+- if (!scpi_info->channels)
++ scpi_drvinfo->channels =
++ devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL);
++ if (!scpi_drvinfo->channels)
+ return -ENOMEM;
+
+- ret = devm_add_action(dev, scpi_free_channels, scpi_info);
++ ret = devm_add_action(dev, scpi_free_channels, scpi_drvinfo);
+ if (ret)
+ return ret;
+
+- for (; scpi_info->num_chans < count; scpi_info->num_chans++) {
++ for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) {
+ resource_size_t size;
+- int idx = scpi_info->num_chans;
+- struct scpi_chan *pchan = scpi_info->channels + idx;
++ int idx = scpi_drvinfo->num_chans;
++ struct scpi_chan *pchan = scpi_drvinfo->channels + idx;
+ struct mbox_client *cl = &pchan->cl;
+ struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
+
+@@ -986,45 +987,53 @@ static int scpi_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+- scpi_info->commands = scpi_std_commands;
++ scpi_drvinfo->commands = scpi_std_commands;
+
+- platform_set_drvdata(pdev, scpi_info);
++ platform_set_drvdata(pdev, scpi_drvinfo);
+
+- if (scpi_info->is_legacy) {
++ if (scpi_drvinfo->is_legacy) {
+ /* Replace with legacy variants */
+ scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
+- scpi_info->commands = scpi_legacy_commands;
++ scpi_drvinfo->commands = scpi_legacy_commands;
+
+ /* Fill priority bitmap */
+ for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
+ set_bit(legacy_hpriority_cmds[idx],
+- scpi_info->cmd_priority);
++ scpi_drvinfo->cmd_priority);
+ }
+
+- ret = scpi_init_versions(scpi_info);
++ scpi_info = scpi_drvinfo;
++
++ ret = scpi_init_versions(scpi_drvinfo);
+ if (ret) {
+ dev_err(dev, "incorrect or no SCP firmware found\n");
++ scpi_info = NULL;
+ return ret;
+ }
+
+- if (scpi_info->is_legacy && !scpi_info->protocol_version &&
+- !scpi_info->firmware_version)
++ if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version &&
++ !scpi_drvinfo->firmware_version)
+ dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n");
+ else
+ dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n",
+ FIELD_GET(PROTO_REV_MAJOR_MASK,
+- scpi_info->protocol_version),
++ scpi_drvinfo->protocol_version),
+ FIELD_GET(PROTO_REV_MINOR_MASK,
+- scpi_info->protocol_version),
++ scpi_drvinfo->protocol_version),
+ FIELD_GET(FW_REV_MAJOR_MASK,
+- scpi_info->firmware_version),
++ scpi_drvinfo->firmware_version),
+ FIELD_GET(FW_REV_MINOR_MASK,
+- scpi_info->firmware_version),
++ scpi_drvinfo->firmware_version),
+ FIELD_GET(FW_REV_PATCH_MASK,
+- scpi_info->firmware_version));
+- scpi_info->scpi_ops = &scpi_ops;
++ scpi_drvinfo->firmware_version));
++
++ scpi_drvinfo->scpi_ops = &scpi_ops;
+
+- return devm_of_platform_populate(dev);
++ ret = devm_of_platform_populate(dev);
++ if (ret)
++ scpi_info = NULL;
++
++ return ret;
+ }
+
+ static const struct of_device_id scpi_of_match[] = {
+--
+2.35.1
+
--- /dev/null
+From 585d0f39ee37d8e804082139876ac4975e04209a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Jul 2022 10:18:51 -0400
+Subject: ftrace/x86: Add back ftrace_expected assignment
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit ac6c1b2ca77e722a1e5d651f12f437f2f237e658 ]
+
+When a ftrace_bug happens (where ftrace fails to modify a location) it is
+helpful to have what was at that location as well as what was expected to
+be there.
+
+But with the conversion to text_poke() the variable that assigns the
+expected for debugging was dropped. Unfortunately, I noticed this when I
+needed it. Add it back.
+
+Link: https://lkml.kernel.org/r/20220726101851.069d2e70@gandalf.local.home
+
+Cc: "x86@kernel.org" <x86@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: stable@vger.kernel.org
+Fixes: 768ae4406a5c ("x86/ftrace: Use text_poke()")
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/ftrace.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
+index 74c2f88a43d0..ceab28277546 100644
+--- a/arch/x86/kernel/ftrace.c
++++ b/arch/x86/kernel/ftrace.c
+@@ -93,6 +93,7 @@ static int ftrace_verify_code(unsigned long ip, const char *old_code)
+
+ /* Make sure it is what we expect it to be */
+ if (memcmp(cur_code, old_code, MCOUNT_INSN_SIZE) != 0) {
++ ftrace_expected = old_code;
+ WARN_ON(1);
+ return -EINVAL;
+ }
+--
+2.35.1
+
--- /dev/null
+From 3650b44badc32848799e20d0626bf23914a67b77 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Aug 2022 15:20:33 +0800
+Subject: Input: gscps2 - check return value of ioremap() in gscps2_probe()
+
+From: Xie Shaowen <studentxswpy@163.com>
+
+[ Upstream commit e61b3125a4f036b3c6b87ffd656fc1ab00440ae9 ]
+
+The function ioremap() in gscps2_probe() can fail, so
+its return value should be checked.
+
+Fixes: 4bdc0d676a643 ("remove ioremap_nocache and devm_ioremap_nocache")
+Cc: <stable@vger.kernel.org> # v5.6+
+Reported-by: Hacash Robot <hacashRobot@santino.com>
+Signed-off-by: Xie Shaowen <studentxswpy@163.com>
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/input/serio/gscps2.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+index a9065c6ab550..da2c67cb8642 100644
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -350,6 +350,10 @@ static int __init gscps2_probe(struct parisc_device *dev)
+ ps2port->port = serio;
+ ps2port->padev = dev;
+ ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
++ if (!ps2port->addr) {
++ ret = -ENOMEM;
++ goto fail_nomem;
++ }
+ spin_lock_init(&ps2port->lock);
+
+ gscps2_reset(ps2port);
+--
+2.35.1
+
--- /dev/null
+From c785bd2648485518b65637389e9a44c9b0add3a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:35 +0300
+Subject: intel_th: pci: Add Meteor Lake-P support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit 802a9a0b1d91274ef10d9fe429b4cc1e8c200aef ]
+
+Add support for the Trace Hub in Meteor Lake-P.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-5-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index fcd0aca75007..41a31c7f505f 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -284,6 +284,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
++ {
++ /* Meteor Lake-P */
++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24),
++ .driver_data = (kernel_ulong_t)&intel_th_2x,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From c84e7921fd6e00cb04aca62790e5c688b9687267 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:37 +0300
+Subject: intel_th: pci: Add Raptor Lake-S CPU support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit ff46a601afc5a66a81c3945b83d0a2caeb88e8bc ]
+
+Add support for the Trace Hub in Raptor Lake-S CPU.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-7-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index 5b6da26f1b63..147d338c191e 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -294,6 +294,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
++ {
++ /* Raptor Lake-S CPU */
++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f),
++ .driver_data = (kernel_ulong_t)&intel_th_2x,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From da8b11da15dd582cd0e1f0d9da07580ec5738564 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:36 +0300
+Subject: intel_th: pci: Add Raptor Lake-S PCH support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit 23e2de5826e2fc4dd43e08bab3a2ea1a5338b063 ]
+
+Add support for the Trace Hub in Raptor Lake-S PCH.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-6-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index 41a31c7f505f..5b6da26f1b63 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -289,6 +289,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
++ {
++ /* Raptor Lake-S */
++ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
++ .driver_data = (kernel_ulong_t)&intel_th_2x,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From 538e6fd1e59662975ef67b348de758020c8f31ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 17:38:36 +0200
+Subject: iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
+
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+
+[ Upstream commit b0b0b77ea611e3088e9523e60860f4f41b62b235 ]
+
+KASAN reports:
+
+[ 4.668325][ T0] BUG: KASAN: wild-memory-access in dmar_parse_one_rhsa (arch/x86/include/asm/bitops.h:214 arch/x86/include/asm/bitops.h:226 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:415 drivers/iommu/intel/dmar.c:497)
+[ 4.676149][ T0] Read of size 8 at addr 1fffffff85115558 by task swapper/0/0
+[ 4.683454][ T0]
+[ 4.685638][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.19.0-rc3-00004-g0e862838f290 #1
+[ 4.694331][ T0] Hardware name: Supermicro SYS-5018D-FN4T/X10SDV-8C-TLN4F, BIOS 1.1 03/02/2016
+[ 4.703196][ T0] Call Trace:
+[ 4.706334][ T0] <TASK>
+[ 4.709133][ T0] ? dmar_parse_one_rhsa (arch/x86/include/asm/bitops.h:214 arch/x86/include/asm/bitops.h:226 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:415 drivers/iommu/intel/dmar.c:497)
+
+after converting the type of the first argument (@nr, bit number)
+of arch_test_bit() from `long` to `unsigned long`[0].
+
+Under certain conditions (for example, when ACPI NUMA is disabled
+via command line), pxm_to_node() can return %NUMA_NO_NODE (-1).
+It is valid 'magic' number of NUMA node, but not valid bit number
+to use in bitops.
+node_online() eventually descends to test_bit() without checking
+for the input, assuming it's on caller side (which might be good
+for perf-critical tasks). There, -1 becomes %ULONG_MAX which leads
+to an insane array index when calculating bit position in memory.
+
+For now, add an explicit check for @node being not %NUMA_NO_NODE
+before calling test_bit(). The actual logics didn't change here
+at all.
+
+[0] https://github.com/norov/linux/commit/0e862838f290147ea9c16db852d8d494b552d38d
+
+Fixes: ee34b32d8c29 ("dmar: support for parsing Remapping Hardware Static Affinity structure")
+Cc: stable@vger.kernel.org # 2.6.33+
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/dmar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index 3d9cb711e87b..f026bd269cb0 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -497,7 +497,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
+ if (drhd->reg_base_addr == rhsa->base_address) {
+ int node = pxm_to_node(rhsa->proximity_domain);
+
+- if (!node_online(node))
++ if (node != NUMA_NO_NODE && !node_online(node))
+ node = NUMA_NO_NODE;
+ drhd->iommu->node = node;
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From 21898a1cb7606e9a5ce4befe24ac82f69647030c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 21:40:27 +0800
+Subject: kexec, KEYS, s390: Make use of built-in and secondary keyring for
+ signature verification
+
+From: Michal Suchanek <msuchanek@suse.de>
+
+[ Upstream commit 0828c4a39be57768b8788e8cbd0d84683ea757e5 ]
+
+commit e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
+adds support for KEXEC_SIG verification with keys from platform keyring
+but the built-in keys and secondary keyring are not used.
+
+Add support for the built-in keys and secondary keyring as x86 does.
+
+Fixes: e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
+Cc: stable@vger.kernel.org
+Cc: Philipp Rudo <prudo@linux.ibm.com>
+Cc: kexec@lists.infradead.org
+Cc: keyrings@vger.kernel.org
+Cc: linux-security-module@vger.kernel.org
+Signed-off-by: Michal Suchanek <msuchanek@suse.de>
+Reviewed-by: "Lee, Chun-Yi" <jlee@suse.com>
+Acked-by: Baoquan He <bhe@redhat.com>
+Signed-off-by: Coiby Xu <coxu@redhat.com>
+Acked-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/machine_kexec_file.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
+index a81d6c43b9b6..3459362c54ac 100644
+--- a/arch/s390/kernel/machine_kexec_file.c
++++ b/arch/s390/kernel/machine_kexec_file.c
+@@ -29,6 +29,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
+ const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
+ struct module_signature *ms;
+ unsigned long sig_len;
++ int ret;
+
+ /* Skip signature verification when not secure IPLed. */
+ if (!ipl_secure_flag)
+@@ -63,11 +64,18 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
+ return -EBADMSG;
+ }
+
+- return verify_pkcs7_signature(kernel, kernel_len,
+- kernel + kernel_len, sig_len,
+- VERIFY_USE_PLATFORM_KEYRING,
+- VERIFYING_MODULE_SIGNATURE,
+- NULL, NULL);
++ ret = verify_pkcs7_signature(kernel, kernel_len,
++ kernel + kernel_len, sig_len,
++ VERIFY_USE_SECONDARY_KEYRING,
++ VERIFYING_MODULE_SIGNATURE,
++ NULL, NULL);
++ if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
++ ret = verify_pkcs7_signature(kernel, kernel_len,
++ kernel + kernel_len, sig_len,
++ VERIFY_USE_PLATFORM_KEYRING,
++ VERIFYING_MODULE_SIGNATURE,
++ NULL, NULL);
++ return ret;
+ }
+ #endif /* CONFIG_KEXEC_SIG */
+
+--
+2.35.1
+
--- /dev/null
+From 5de69edcf45f620aa93d523b42aa99b1a8a2a4e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jun 2022 11:37:20 +0800
+Subject: KEYS: asymmetric: enforce SM2 signature use pkey algo
+
+From: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+
+[ Upstream commit 0815291a8fd66cdcf7db1445d4d99b0d16065829 ]
+
+The signature verification of SM2 needs to add the Za value and
+recalculate sig->digest, which requires the detection of the pkey_algo
+in public_key_verify_signature(). As Eric Biggers said, the pkey_algo
+field in sig is attacker-controlled and should be use pkey->pkey_algo
+instead of sig->pkey_algo, and secondly, if sig->pkey_algo is NULL, it
+will also cause signature verification failure.
+
+The software_key_determine_akcipher() already forces the algorithms
+are matched, so the SM3 algorithm is enforced in the SM2 signature,
+although this has been checked, we still avoid using any algorithm
+information in the signature as input.
+
+Fixes: 215525639631 ("X.509: support OSCCA SM2-with-SM3 certificate verification")
+Reported-by: Eric Biggers <ebiggers@google.com>
+Cc: stable@vger.kernel.org # v5.10+
+Signed-off-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/asymmetric_keys/public_key.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
+index 7c9e6be35c30..2f8352e88860 100644
+--- a/crypto/asymmetric_keys/public_key.c
++++ b/crypto/asymmetric_keys/public_key.c
+@@ -304,6 +304,10 @@ static int cert_sig_digest_update(const struct public_key_signature *sig,
+
+ BUG_ON(!sig->data);
+
++ /* SM2 signatures always use the SM3 hash algorithm */
++ if (!sig->hash_algo || strcmp(sig->hash_algo, "sm3") != 0)
++ return -EINVAL;
++
+ ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID,
+ SM2_DEFAULT_USERID_LEN, dgst);
+ if (ret)
+@@ -414,8 +418,7 @@ int public_key_verify_signature(const struct public_key *pkey,
+ if (ret)
+ goto error_free_key;
+
+- if (sig->pkey_algo && strcmp(sig->pkey_algo, "sm2") == 0 &&
+- sig->data_size) {
++ if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) {
+ ret = cert_sig_digest_update(sig, tfm);
+ if (ret)
+ goto error_free_key;
+--
+2.35.1
+
--- /dev/null
+From 8a7edf17c3f5130188103fb95c52153b2badeabb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jul 2022 22:44:08 +0000
+Subject: KVM: nVMX: Attempt to load PERF_GLOBAL_CTRL on nVMX xfer iff it
+ exists
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 4496a6f9b45e8cd83343ad86a3984d614e22cf54 ]
+
+Attempt to load PERF_GLOBAL_CTRL during nested VM-Enter/VM-Exit if and
+only if the MSR exists (according to the guest vCPU model). KVM has very
+misguided handling of VM_{ENTRY,EXIT}_LOAD_IA32_PERF_GLOBAL_CTRL and
+attempts to force the nVMX MSR settings to match the vPMU model, i.e. to
+hide/expose the control based on whether or not the MSR exists from the
+guest's perspective.
+
+KVM's modifications fail to handle the scenario where the vPMU is hidden
+from the guest _after_ being exposed to the guest, e.g. by userspace
+doing multiple KVM_SET_CPUID2 calls, which is allowed if done before any
+KVM_RUN. nested_vmx_pmu_refresh() is called if and only if there's a
+recognized vPMU, i.e. KVM will leave the bits in the allow state and then
+ultimately reject the MSR load and WARN.
+
+KVM should not force the VMX MSRs in the first place. KVM taking control
+of the MSRs was a misguided attempt at mimicking what commit 5f76f6f5ff96
+("KVM: nVMX: Do not expose MPX VMX controls when guest MPX disabled",
+2018-10-01) did for MPX. However, the MPX commit was a workaround for
+another KVM bug and not something that should be imitated (and it should
+never been done in the first place).
+
+In other words, KVM's ABI _should_ be that userspace has full control
+over the MSRs, at which point triggering the WARN that loading the MSR
+must not fail is trivial.
+
+The intent of the WARN is still valid; KVM has consistency checks to
+ensure that vmcs12->{guest,host}_ia32_perf_global_ctrl is valid. The
+problem is that '0' must be considered a valid value at all times, and so
+the simple/obvious solution is to just not actually load the MSR when it
+does not exist. It is userspace's responsibility to provide a sane vCPU
+model, i.e. KVM is well within its ABI and Intel's VMX architecture to
+skip the loads if the MSR does not exist.
+
+Fixes: 03a8871add95 ("KVM: nVMX: Expose load IA32_PERF_GLOBAL_CTRL VM-{Entry,Exit} control")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220722224409.1336532-5-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index 9f845556dde8..61d601387058 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -2611,6 +2611,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
+ vcpu->arch.walk_mmu->inject_page_fault = vmx_inject_page_fault_nested;
+
+ if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) &&
++ intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)) &&
+ WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL,
+ vmcs12->guest_ia32_perf_global_ctrl))) {
+ *entry_failure_code = ENTRY_FAIL_DEFAULT;
+@@ -4329,7 +4330,8 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
+ vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
+ vcpu->arch.pat = vmcs12->host_ia32_pat;
+ }
+- if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
++ if ((vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL) &&
++ intel_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu)))
+ WARN_ON_ONCE(kvm_set_msr(vcpu, MSR_CORE_PERF_GLOBAL_CTRL,
+ vmcs12->host_ia32_perf_global_ctrl));
+
+--
+2.35.1
+
--- /dev/null
+From 16198eef162b1958bc149d489bec46899d1da19b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 May 2022 08:15:11 +0000
+Subject: KVM: set_msr_mce: Permit guests to ignore single-bit ECC errors
+
+From: Lev Kujawski <lkujaw@member.fsf.org>
+
+[ Upstream commit 0471a7bd1bca2a47a5f378f2222c5cf39ce94152 ]
+
+Certain guest operating systems (e.g., UNIXWARE) clear bit 0 of
+MC1_CTL to ignore single-bit ECC data errors. Single-bit ECC data
+errors are always correctable and thus are safe to ignore because they
+are informational in nature rather than signaling a loss of data
+integrity.
+
+Prior to this patch, these guests would crash upon writing MC1_CTL,
+with resultant error messages like the following:
+
+error: kvm run failed Operation not permitted
+EAX=fffffffe EBX=fffffffe ECX=00000404 EDX=ffffffff
+ESI=ffffffff EDI=00000001 EBP=fffdaba4 ESP=fffdab20
+EIP=c01333a5 EFL=00000246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
+ES =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+CS =0100 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
+SS =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+DS =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+FS =0000 00000000 ffffffff 00c00000
+GS =0000 00000000 ffffffff 00c00000
+LDT=0118 c1026390 00000047 00008200 DPL=0 LDT
+TR =0110 ffff5af0 00000067 00008b00 DPL=0 TSS32-busy
+GDT= ffff5020 000002cf
+IDT= ffff52f0 000007ff
+CR0=8001003b CR2=00000000 CR3=0100a000 CR4=00000230
+DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
+DR6=ffff0ff0 DR7=00000400
+EFER=0000000000000000
+Code=08 89 01 89 51 04 c3 8b 4c 24 08 8b 01 8b 51 04 8b 4c 24 04 <0f>
+30 c3 f7 05 a4 6d ff ff 10 00 00 00 74 03 0f 31 c3 33 c0 33 d2 c3 8d
+74 26 00 0f 31 c3
+
+Signed-off-by: Lev Kujawski <lkujaw@member.fsf.org>
+Message-Id: <20220521081511.187388-1-lkujaw@member.fsf.org>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 24875dc87b13..dac2892d095c 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3102,10 +3102,13 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ /* only 0 or all 1s can be written to IA32_MCi_CTL
+ * some Linux kernels though clear bit 10 in bank 4 to
+ * workaround a BIOS/GART TBL issue on AMD K8s, ignore
+- * this to avoid an uncatched #GP in the guest
++ * this to avoid an uncatched #GP in the guest.
++ *
++ * UNIXWARE clears bit 0 of MC1_CTL to ignore
++ * correctable, single-bit ECC data errors.
+ */
+ if ((offset & 0x3) == 0 &&
+- data != 0 && (data | (1 << 10)) != ~(u64)0)
++ data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
+ return -1;
+
+ /* MCi_STATUS */
+--
+2.35.1
+
--- /dev/null
+From 7e6065df24b496053100812039a3a1e9c70517c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jul 2022 22:44:07 +0000
+Subject: KVM: VMX: Add helper to check if the guest PMU has PERF_GLOBAL_CTRL
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit b663f0b5f3d665c261256d1f76e98f077c6e56af ]
+
+Add a helper to check of the guest PMU has PERF_GLOBAL_CTRL, which is
+unintuitive _and_ diverges from Intel's architecturally defined behavior.
+Even worse, KVM currently implements the check using two different (but
+equivalent) checks, _and_ there has been at least one attempt to add a
+_third_ flavor.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220722224409.1336532-4-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 4 ++--
+ arch/x86/kvm/vmx/vmx.h | 12 ++++++++++++
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index f9054e7ec89e..e624a39365ec 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -104,7 +104,7 @@ static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
+ {
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+
+- if (pmu->version < 2)
++ if (!intel_pmu_has_perf_global_ctrl(pmu))
+ return true;
+
+ return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
+@@ -222,7 +222,7 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
+ case MSR_CORE_PERF_GLOBAL_STATUS:
+ case MSR_CORE_PERF_GLOBAL_CTRL:
+ case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+- ret = pmu->version > 1;
++ return intel_pmu_has_perf_global_ctrl(pmu);
+ break;
+ default:
+ ret = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0) ||
+diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
+index a8b8150252bb..20f1213a9368 100644
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -92,6 +92,18 @@ union vmx_exit_reason {
+ u32 full;
+ };
+
++static inline bool intel_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu)
++{
++ /*
++ * Architecturally, Intel's SDM states that IA32_PERF_GLOBAL_CTRL is
++ * supported if "CPUID.0AH: EAX[7:0] > 0", i.e. if the PMU version is
++ * greater than zero. However, KVM only exposes and emulates the MSR
++ * to/for the guest if the guest PMU supports at least "Architectural
++ * Performance Monitoring Version 2".
++ */
++ return pmu->version > 1;
++}
++
+ #define vcpu_to_lbr_desc(vcpu) (&to_vmx(vcpu)->lbr_desc)
+ #define vcpu_to_lbr_records(vcpu) (&to_vmx(vcpu)->lbr_desc.records)
+
+--
+2.35.1
+
--- /dev/null
+From 7b656117a1d2961bfbbdb1309cb6e5db3135efab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jul 2022 22:44:06 +0000
+Subject: KVM: VMX: Mark all PERF_GLOBAL_(OVF)_CTRL bits reserved if there's no
+ vPMU
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 93255bf92939d948bc86d81c6bb70bb0fecc5db1 ]
+
+Mark all MSR_CORE_PERF_GLOBAL_CTRL and MSR_CORE_PERF_GLOBAL_OVF_CTRL bits
+as reserved if there is no guest vPMU. The nVMX VM-Entry consistency
+checks do not check for a valid vPMU prior to consuming the masks via
+kvm_valid_perf_global_ctrl(), i.e. may incorrectly allow a non-zero mask
+to be loaded via VM-Enter or VM-Exit (well, attempted to be loaded, the
+actual MSR load will be rejected by intel_is_valid_msr()).
+
+Fixes: f5132b01386b ("KVM: Expose a version 2 architectural PMU to a guests")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220722224409.1336532-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index 9aee082deee9..c66edf93e4a8 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -481,6 +481,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
++ pmu->global_ctrl_mask = ~0ull;
++ pmu->global_ovf_ctrl_mask = ~0ull;
+ pmu->fixed_ctr_ctrl_mask = ~0ull;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+--
+2.35.1
+
--- /dev/null
+From f36e7bace71271b84f97a4f4868c7f52799579e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 18:22:02 +0800
+Subject: KVM: x86/pmu: Ignore pmu->global_ctrl check if vPMU doesn't support
+ global_ctrl
+
+From: Like Xu <likexu@tencent.com>
+
+[ Upstream commit 98defd2e17803263f49548fea930cfc974d505aa ]
+
+MSR_CORE_PERF_GLOBAL_CTRL is introduced as part of Architecture PMU V2,
+as indicated by Intel SDM 19.2.2 and the intel_is_valid_msr() function.
+
+So in the absence of global_ctrl support, all PMCs are enabled as AMD does.
+
+Signed-off-by: Like Xu <likexu@tencent.com>
+Message-Id: <20220509102204.62389-1-likexu@tencent.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index c66edf93e4a8..f9054e7ec89e 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -104,6 +104,9 @@ static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
+ {
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+
++ if (pmu->version < 2)
++ return true;
++
+ return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 93487041049f8add6f81d6e3b60db1e844507c08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 18:19:34 +0800
+Subject: KVM: x86/pmu: Introduce the ctrl_mask value for fixed counter
+
+From: Like Xu <like.xu@linux.intel.com>
+
+[ Upstream commit 2c985527dd8d283e786ad7a67e532ef7f6f00fac ]
+
+The mask value of fixed counter control register should be dynamic
+adjusted with the number of fixed counters. This patch introduces a
+variable that includes the reserved bits of fixed counter control
+registers. This is a generic code refactoring.
+
+Co-developed-by: Luwei Kang <luwei.kang@intel.com>
+Signed-off-by: Luwei Kang <luwei.kang@intel.com>
+Signed-off-by: Like Xu <like.xu@linux.intel.com>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Message-Id: <20220411101946.20262-6-likexu@tencent.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/vmx/pmu_intel.c | 6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index 83ec98a527a3..74b5819120da 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -498,6 +498,7 @@ struct kvm_pmu {
+ unsigned nr_arch_fixed_counters;
+ unsigned available_event_types;
+ u64 fixed_ctr_ctrl;
++ u64 fixed_ctr_ctrl_mask;
+ u64 global_ctrl;
+ u64 global_status;
+ u64 global_ovf_ctrl;
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index e7275ce15a8b..9aee082deee9 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -402,7 +402,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+ if (pmu->fixed_ctr_ctrl == data)
+ return 0;
+- if (!(data & 0xfffffffffffff444ull)) {
++ if (!(data & pmu->fixed_ctr_ctrl_mask)) {
+ reprogram_fixed_counters(pmu, data);
+ return 0;
+ }
+@@ -472,6 +472,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ struct kvm_cpuid_entry2 *entry;
+ union cpuid10_eax eax;
+ union cpuid10_edx edx;
++ int i;
+
+ pmu->nr_arch_gp_counters = 0;
+ pmu->nr_arch_fixed_counters = 0;
+@@ -480,6 +481,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
++ pmu->fixed_ctr_ctrl_mask = ~0ull;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+@@ -513,6 +515,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ ((u64)1 << edx.split.bit_width_fixed) - 1;
+ }
+
++ for (i = 0; i < pmu->nr_arch_fixed_counters; i++)
++ pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4));
+ pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
+ (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
+ pmu->global_ctrl_mask = ~pmu->global_ctrl;
+--
+2.35.1
+
--- /dev/null
+From 077cef63d8bd4e55745d198fd7cf2bec15c0c3e5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 22:27:14 +0000
+Subject: KVM: x86: Signal #GP, not -EPERM, on bad WRMSR(MCi_CTL/STATUS)
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 2368048bf5c2ec4b604ac3431564071e89a0bc71 ]
+
+Return '1', not '-1', when handling an illegal WRMSR to a MCi_CTL or
+MCi_STATUS MSR. The behavior of "all zeros' or "all ones" for CTL MSRs
+is architectural, as is the "only zeros" behavior for STATUS MSRs. I.e.
+the intent is to inject a #GP, not exit to userspace due to an unhandled
+emulation case. Returning '-1' gets interpreted as -EPERM up the stack
+and effecitvely kills the guest.
+
+Fixes: 890ca9aefa78 ("KVM: Add MCE support")
+Fixes: 9ffd986c6e4e ("KVM: X86: #GP when guest attempts to write MCi_STATUS register w/o 0")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reviewed-by: Jim Mattson <jmattson@google.com>
+Link: https://lore.kernel.org/r/20220512222716.4112548-2-seanjc@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index dac2892d095c..f5b7a05530eb 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3109,13 +3109,13 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ */
+ if ((offset & 0x3) == 0 &&
+ data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
+- return -1;
++ return 1;
+
+ /* MCi_STATUS */
+ if (!msr_info->host_initiated &&
+ (offset & 0x3) == 1 && data != 0) {
+ if (!can_set_mci_status(vcpu))
+- return -1;
++ return 1;
+ }
+
+ vcpu->arch.mce_banks[offset] = data;
+--
+2.35.1
+
--- /dev/null
+From 452c6339258b2e881f5d086964f3333a511f08fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 May 2022 17:46:39 +0800
+Subject: locking/csd_lock: Change csdlock_debug from early_param to __setup
+
+From: Chen Zhongjin <chenzhongjin@huawei.com>
+
+[ Upstream commit 9c9b26b0df270d4f9246e483a44686fca951a29c ]
+
+The csdlock_debug kernel-boot parameter is parsed by the
+early_param() function csdlock_debug(). If set, csdlock_debug()
+invokes static_branch_enable() to enable csd_lock_wait feature, which
+triggers a panic on arm64 for kernels built with CONFIG_SPARSEMEM=y and
+CONFIG_SPARSEMEM_VMEMMAP=n.
+
+With CONFIG_SPARSEMEM_VMEMMAP=n, __nr_to_section is called in
+static_key_enable() and returns NULL, resulting in a NULL dereference
+because mem_section is initialized only later in sparse_init().
+
+This is also a problem for powerpc because early_param() functions
+are invoked earlier than jump_label_init(), also resulting in
+static_key_enable() failures. These failures cause the warning "static
+key 'xxx' used before call to jump_label_init()".
+
+Thus, early_param is too early for csd_lock_wait to run
+static_branch_enable(), so changes it to __setup to fix these.
+
+Fixes: 8d0968cc6b8f ("locking/csd_lock: Add boot parameter for controlling CSD lock debugging")
+Cc: stable@vger.kernel.org
+Reported-by: Chen jingwen <chenjingwen6@huawei.com>
+Signed-off-by: Chen Zhongjin <chenzhongjin@huawei.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/smp.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/smp.c b/kernel/smp.c
+index b68d63e965db..82825345432c 100644
+--- a/kernel/smp.c
++++ b/kernel/smp.c
+@@ -174,9 +174,9 @@ static int __init csdlock_debug(char *str)
+ if (val)
+ static_branch_enable(&csdlock_debug_enabled);
+
+- return 0;
++ return 1;
+ }
+-early_param("csdlock_debug", csdlock_debug);
++__setup("csdlock_debug=", csdlock_debug);
+
+ static DEFINE_PER_CPU(call_single_data_t *, cur_csd);
+ static DEFINE_PER_CPU(smp_call_func_t, cur_csd_func);
+--
+2.35.1
+
--- /dev/null
+From 8822529cea86104c1bbae6788949871a68c2d490 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Jul 2022 09:14:02 -0500
+Subject: net/9p: Initialize the iounit field during fid creation
+
+From: Tyler Hicks <tyhicks@linux.microsoft.com>
+
+[ Upstream commit aa7aeee169480e98cf41d83c01290a37e569be6d ]
+
+Ensure that the fid's iounit field is set to zero when a new fid is
+created. Certain 9P operations, such as OPEN and CREATE, allow the
+server to reply with an iounit size which the client code assigns to the
+p9_fid struct shortly after the fid is created by p9_fid_create(). On
+the other hand, an XATTRWALK operation doesn't allow for the server to
+specify an iounit value. The iounit field of the newly allocated p9_fid
+struct remained uninitialized in that case. Depending on allocation
+patterns, the iounit value could have been something reasonable that was
+carried over from previously freed fids or, in the worst case, could
+have been arbitrary values from non-fid related usages of the memory
+location.
+
+The bug was detected in the Windows Subsystem for Linux 2 (WSL2) kernel
+after the uninitialized iounit field resulted in the typical sequence of
+two getxattr(2) syscalls, one to get the size of an xattr and another
+after allocating a sufficiently sized buffer to fit the xattr value, to
+hit an unexpected ERANGE error in the second call to getxattr(2). An
+uninitialized iounit field would sometimes force rsize to be smaller
+than the xattr value size in p9_client_read_once() and the 9P server in
+WSL refused to chunk up the READ on the attr_fid and, instead, returned
+ERANGE to the client. The virtfs server in QEMU seems happy to chunk up
+the READ and this problem goes undetected there.
+
+Link: https://lkml.kernel.org/r/20220710141402.803295-1-tyhicks@linux.microsoft.com
+Fixes: ebf46264a004 ("fs/9p: Add support user. xattr")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
+Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>
+Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/9p/client.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index 866f02e88c79..565aee6dfcc6 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -888,16 +888,13 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
+ struct p9_fid *fid;
+
+ p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt);
+- fid = kmalloc(sizeof(*fid), GFP_KERNEL);
++ fid = kzalloc(sizeof(*fid), GFP_KERNEL);
+ if (!fid)
+ return NULL;
+
+- memset(&fid->qid, 0, sizeof(fid->qid));
+ fid->mode = -1;
+ fid->uid = current_fsuid();
+ fid->clnt = clnt;
+- fid->rdir = NULL;
+- fid->fid = 0;
+ refcount_set(&fid->count, 1);
+
+ idr_preload(GFP_KERNEL);
+--
+2.35.1
+
--- /dev/null
+From f32962975fa337d30945cd15f1e428988d87822a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 18:14:41 +0000
+Subject: PCI/AER: Iterate over error counters instead of error strings
+
+From: Mohamed Khalfella <mkhalfella@purestorage.com>
+
+[ Upstream commit 5e6ae050955b566484f3cc6a66e3925eae87a0ed ]
+
+Previously we iterated over AER stat *names*, e.g.,
+aer_correctable_error_string[32], but the actual stat *counters* may not be
+that large, e.g., pdev->aer_stats->dev_cor_errs[16], which means that we
+printed junk in the sysfs stats files.
+
+Iterate over the stat counter arrays instead of the names to avoid this
+junk.
+
+Also, added a build time check to make sure all
+counters have entries in strings array.
+
+Fixes: 0678e3109a3c ("PCI/AER: Simplify __aer_print_error()")
+Link: https://lore.kernel.org/r/20220509181441.31884-1-mkhalfella@purestorage.com
+Reported-by: Meeta Saggi <msaggi@purestorage.com>
+Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Meeta Saggi <msaggi@purestorage.com>
+Reviewed-by: Eric Badger <ebadger@purestorage.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aer.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
+index 80fe3e83c9f5..ca9ac8c6a202 100644
+--- a/drivers/pci/pcie/aer.c
++++ b/drivers/pci/pcie/aer.c
+@@ -538,7 +538,7 @@ static const char *aer_agent_string[] = {
+ u64 *stats = pdev->aer_stats->stats_array; \
+ size_t len = 0; \
+ \
+- for (i = 0; i < ARRAY_SIZE(strings_array); i++) { \
++ for (i = 0; i < ARRAY_SIZE(pdev->aer_stats->stats_array); i++) {\
+ if (strings_array[i]) \
+ len += sysfs_emit_at(buf, len, "%s %llu\n", \
+ strings_array[i], \
+@@ -1347,6 +1347,11 @@ static int aer_probe(struct pcie_device *dev)
+ struct device *device = &dev->device;
+ struct pci_dev *port = dev->port;
+
++ BUILD_BUG_ON(ARRAY_SIZE(aer_correctable_error_string) <
++ AER_MAX_TYPEOF_COR_ERRS);
++ BUILD_BUG_ON(ARRAY_SIZE(aer_uncorrectable_error_string) <
++ AER_MAX_TYPEOF_UNCOR_ERRS);
++
+ /* Limit to Root Ports or Root Complex Event Collectors */
+ if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) &&
+ (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT))
+--
+2.35.1
+
--- /dev/null
+From 5c50abf727e665c6674473b2c2e1016a534cee8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Jun 2022 17:50:03 +0200
+Subject: PCI: qcom: Power on PHY before IPQ8074 DBI register accesses
+
+From: Robert Marko <robimarko@gmail.com>
+
+[ Upstream commit a0e43bb9973b06ce5c666f0901e104e2037c1b34 ]
+
+Currently the Gen2 port in IPQ8074 will cause the system to hang as it
+accesses DBI registers in qcom_pcie_init_2_3_3(), and those are only
+accesible after phy_power_on().
+
+Move the DBI read/writes to a new qcom_pcie_post_init_2_3_3(), which is
+executed after phy_power_on().
+
+Link: https://lore.kernel.org/r/20220623155004.688090-1-robimarko@gmail.com
+Fixes: a0fd361db8e5 ("PCI: dwc: Move "dbi", "dbi2", and "addr_space" resource setup into common code")
+Signed-off-by: Robert Marko <robimarko@gmail.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Cc: stable@vger.kernel.org # v5.11+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-qcom.c | 48 +++++++++++++++-----------
+ 1 file changed, 28 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
+index 45210c6380b1..4c599699e3c8 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -1024,9 +1024,7 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
+ struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3;
+ struct dw_pcie *pci = pcie->pci;
+ struct device *dev = pci->dev;
+- u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+ int i, ret;
+- u32 val;
+
+ for (i = 0; i < ARRAY_SIZE(res->rst); i++) {
+ ret = reset_control_assert(res->rst[i]);
+@@ -1083,6 +1081,33 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
+ goto err_clk_aux;
+ }
+
++ return 0;
++
++err_clk_aux:
++ clk_disable_unprepare(res->ahb_clk);
++err_clk_ahb:
++ clk_disable_unprepare(res->axi_s_clk);
++err_clk_axi_s:
++ clk_disable_unprepare(res->axi_m_clk);
++err_clk_axi_m:
++ clk_disable_unprepare(res->iface);
++err_clk_iface:
++ /*
++ * Not checking for failure, will anyway return
++ * the original failure in 'ret'.
++ */
++ for (i = 0; i < ARRAY_SIZE(res->rst); i++)
++ reset_control_assert(res->rst[i]);
++
++ return ret;
++}
++
++static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie)
++{
++ struct dw_pcie *pci = pcie->pci;
++ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
++ u32 val;
++
+ writel(SLV_ADDR_SPACE_SZ,
+ pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE);
+
+@@ -1110,24 +1135,6 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
+ PCI_EXP_DEVCTL2);
+
+ return 0;
+-
+-err_clk_aux:
+- clk_disable_unprepare(res->ahb_clk);
+-err_clk_ahb:
+- clk_disable_unprepare(res->axi_s_clk);
+-err_clk_axi_s:
+- clk_disable_unprepare(res->axi_m_clk);
+-err_clk_axi_m:
+- clk_disable_unprepare(res->iface);
+-err_clk_iface:
+- /*
+- * Not checking for failure, will anyway return
+- * the original failure in 'ret'.
+- */
+- for (i = 0; i < ARRAY_SIZE(res->rst); i++)
+- reset_control_assert(res->rst[i]);
+-
+- return ret;
+ }
+
+ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
+@@ -1423,6 +1430,7 @@ static const struct qcom_pcie_ops ops_2_4_0 = {
+ static const struct qcom_pcie_ops ops_2_3_3 = {
+ .get_resources = qcom_pcie_get_resources_2_3_3,
+ .init = qcom_pcie_init_2_3_3,
++ .post_init = qcom_pcie_post_init_2_3_3,
+ .deinit = qcom_pcie_deinit_2_3_3,
+ .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
+ };
+--
+2.35.1
+
--- /dev/null
+From a64d93aa22c776f0955f289745e4f34537de308a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Jul 2022 00:32:18 +1000
+Subject: powerpc/powernv/kvm: Use darn for H_RANDOM on Power9
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit 7ef3d06f1bc4a5e62273726f3dc2bd258ae1c71f ]
+
+The existing logic in KVM to support guests calling H_RANDOM only works
+on Power8, because it looks for an RNG in the device tree, but on Power9
+we just use darn.
+
+In addition the existing code needs to work in real mode, so we have the
+special cased powernv_get_random_real_mode() to deal with that.
+
+Instead just have KVM call ppc_md.get_random_seed(), and do the real
+mode check inside of there, that way we use whatever RNG is available,
+including darn on Power9.
+
+Fixes: e928e9cb3601 ("KVM: PPC: Book3S HV: Add fast real-mode H_RANDOM implementation.")
+Cc: stable@vger.kernel.org # v4.1+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Tested-by: Sachin Sant <sachinp@linux.ibm.com>
+[mpe: Rebase on previous commit, update change log appropriately]
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20220727143219.2684192-2-mpe@ellerman.id.au
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/archrandom.h | 5 ----
+ arch/powerpc/kvm/book3s_hv_builtin.c | 7 +++---
+ arch/powerpc/platforms/powernv/rng.c | 36 ++++++---------------------
+ 3 files changed, 12 insertions(+), 36 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
+index 9a53e29680f4..258174304904 100644
+--- a/arch/powerpc/include/asm/archrandom.h
++++ b/arch/powerpc/include/asm/archrandom.h
+@@ -38,12 +38,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
+ #endif /* CONFIG_ARCH_RANDOM */
+
+ #ifdef CONFIG_PPC_POWERNV
+-int powernv_hwrng_present(void);
+ int powernv_get_random_long(unsigned long *v);
+-int powernv_get_random_real_mode(unsigned long *v);
+-#else
+-static inline int powernv_hwrng_present(void) { return 0; }
+-static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
+ #endif
+
+ #endif /* _ASM_POWERPC_ARCHRANDOM_H */
+diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
+index 70b7a8f97153..b148629b7f03 100644
+--- a/arch/powerpc/kvm/book3s_hv_builtin.c
++++ b/arch/powerpc/kvm/book3s_hv_builtin.c
+@@ -20,7 +20,7 @@
+ #include <asm/interrupt.h>
+ #include <asm/kvm_ppc.h>
+ #include <asm/kvm_book3s.h>
+-#include <asm/archrandom.h>
++#include <asm/machdep.h>
+ #include <asm/xics.h>
+ #include <asm/xive.h>
+ #include <asm/dbell.h>
+@@ -177,13 +177,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
+
+ int kvmppc_hwrng_present(void)
+ {
+- return powernv_hwrng_present();
++ return ppc_md.get_random_seed != NULL;
+ }
+ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
+
+ long kvmppc_rm_h_random(struct kvm_vcpu *vcpu)
+ {
+- if (powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]))
++ if (ppc_md.get_random_seed &&
++ ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4]))
+ return H_SUCCESS;
+
+ return H_HARDWARE;
+diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
+index a99033c3dce7..5f81ff9b5265 100644
+--- a/arch/powerpc/platforms/powernv/rng.c
++++ b/arch/powerpc/platforms/powernv/rng.c
+@@ -29,15 +29,6 @@ struct powernv_rng {
+
+ static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
+
+-int powernv_hwrng_present(void)
+-{
+- struct powernv_rng *rng;
+-
+- rng = get_cpu_var(powernv_rng);
+- put_cpu_var(rng);
+- return rng != NULL;
+-}
+-
+ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+ {
+ unsigned long parity;
+@@ -58,19 +49,6 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+ return val;
+ }
+
+-int powernv_get_random_real_mode(unsigned long *v)
+-{
+- struct powernv_rng *rng;
+-
+- rng = raw_cpu_read(powernv_rng);
+- if (!rng)
+- return 0;
+-
+- *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
+-
+- return 1;
+-}
+-
+ static int powernv_get_random_darn(unsigned long *v)
+ {
+ unsigned long val;
+@@ -107,12 +85,14 @@ int powernv_get_random_long(unsigned long *v)
+ {
+ struct powernv_rng *rng;
+
+- rng = get_cpu_var(powernv_rng);
+-
+- *v = rng_whiten(rng, in_be64(rng->regs));
+-
+- put_cpu_var(rng);
+-
++ if (mfmsr() & MSR_DR) {
++ rng = get_cpu_var(powernv_rng);
++ *v = rng_whiten(rng, in_be64(rng->regs));
++ put_cpu_var(rng);
++ } else {
++ rng = raw_cpu_read(powernv_rng);
++ *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
++ }
+ return 1;
+ }
+ EXPORT_SYMBOL_GPL(powernv_get_random_long);
+--
+2.35.1
+
--- /dev/null
+From b1e40f182db9a716acfaa99902ceb83aff08c39b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Sep 2021 16:31:54 -0700
+Subject: scsi: lpfc: Fix EEH support for NVMe I/O
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit 25ac2c970be32993f1dff607f8354f3c053d42bc ]
+
+Injecting errors on the PCI slot while the driver is handling NVMe I/O will
+cause crashes and hangs.
+
+There are several rather difficult scenarios occurring. The main issue is
+that the adapter can report a PCI error before or simultaneously to the PCI
+subsystem reporting the error. Both paths have different entry points and
+currently there is no interlock between them. Thus multiple teardown paths
+are competing and all heck breaks loose.
+
+Complicating things is the NVMs path. To a large degree, I/O was able to be
+shutdown for a full FC port on the SCSI stack. But on NVMe, there isn't a
+similar call. At best, it works on a per-controller basis, but even at the
+controller level, it's a controller "reset" call. All of which means I/O is
+still flowing on different CPUs with reset paths expecting hw access
+(mailbox commands) to execute properly.
+
+The following modifications are made:
+
+ - A new flag is set in PCI error entrypoints so the driver can track being
+ called by that path.
+
+ - An interlock is added in the SLI hw error path and the PCI error path
+ such that only one of the paths proceeds with the teardown logic.
+
+ - RPI cleanup is patched such that RPIs are marked unregistered w/o mbx
+ cmds in cases of hw error.
+
+ - If entering the SLI port re-init calls, a case where SLI error teardown
+ was quick and beat the PCI calls now reporting error, check whether the
+ SLI port is still live on the PCI bus.
+
+ - In the PCI reset code to bring the adapter back, recheck the IRQ
+ settings. Different checks for SLI3 vs SLI4.
+
+ - In I/O completions, that may be called as part of the cleanup or
+ underway just before the hw error, check the state of the adapter. If
+ in error, shortcut handling that would expect further adapter
+ completions as the hw error won't be sending them.
+
+ - In routines waiting on I/O completions, which may have been in progress
+ prior to the hw error, detect the device is being torn down and abort
+ from their waits and just give up. This points to a larger issue in the
+ driver on ref-counting for data structures, as it doesn't have
+ ref-counting on q and port structures. We'll do this fix for now as it
+ would be a major rework to be done differently.
+
+ - Fix the NVMe cleanup to simulate NVMe I/O completions if I/O is being
+ failed back due to hw error.
+
+ - In I/O buf allocation, done at the start of new I/Os, check hw state and
+ fail if hw error.
+
+Link: https://lore.kernel.org/r/20210910233159.115896-10-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 1 +
+ drivers/scsi/lpfc/lpfc_hbadisc.c | 1 +
+ drivers/scsi/lpfc/lpfc_init.c | 31 +++++++++++++++-
+ drivers/scsi/lpfc/lpfc_nvme.c | 53 ++++++++++++++++++++++++++-
+ drivers/scsi/lpfc/lpfc_scsi.c | 63 +++++++++++++++++++++-----------
+ drivers/scsi/lpfc/lpfc_sli.c | 31 +++++++++++++++-
+ drivers/scsi/lpfc/lpfc_sli4.h | 2 +
+ 7 files changed, 154 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 1044832b6054..b2508a00bafd 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -1028,6 +1028,7 @@ struct lpfc_hba {
+ * Firmware supports Forced Link Speed
+ * capability
+ */
++#define HBA_PCI_ERR 0x80000 /* The PCI slot is offline */
+ #define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
+ #define HBA_CGN_RSVD1 0x200000 /* Reserved CGN flag */
+ #define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index 3bb7c2aa949f..4bb0a15cfcc0 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -5349,6 +5349,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
++ ndlp->nlp_flag &= ~NLP_UNREG_INP;
+ mempool_free(mbox, phba->mbox_mem_pool);
+ acc_plogi = 1;
+ }
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index a2694fb32b5d..cda571393a5f 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -1606,6 +1606,11 @@ void
+ lpfc_sli4_offline_eratt(struct lpfc_hba *phba)
+ {
+ spin_lock_irq(&phba->hbalock);
++ if (phba->link_state == LPFC_HBA_ERROR &&
++ phba->hba_flag & HBA_PCI_ERR) {
++ spin_unlock_irq(&phba->hbalock);
++ return;
++ }
+ phba->link_state = LPFC_HBA_ERROR;
+ spin_unlock_irq(&phba->hbalock);
+
+@@ -1945,7 +1950,6 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
+ if (pci_channel_offline(phba->pcidev)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "3166 pci channel is offline\n");
+- lpfc_sli4_offline_eratt(phba);
+ return;
+ }
+
+@@ -3643,6 +3647,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
+ struct lpfc_vport **vports;
+ struct Scsi_Host *shost;
+ int i;
++ int offline = 0;
+
+ if (vport->fc_flag & FC_OFFLINE_MODE)
+ return;
+@@ -3651,6 +3656,8 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
+
+ lpfc_linkdown(phba);
+
++ offline = pci_channel_offline(phba->pcidev);
++
+ /* Issue an unreg_login to all nodes on all vports */
+ vports = lpfc_create_vport_work_array(phba);
+ if (vports != NULL) {
+@@ -3673,7 +3680,14 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
+ ndlp->nlp_flag &= ~NLP_NPR_ADISC;
+ spin_unlock_irq(&ndlp->lock);
+
+- lpfc_unreg_rpi(vports[i], ndlp);
++ if (offline) {
++ spin_lock_irq(&ndlp->lock);
++ ndlp->nlp_flag &= ~(NLP_UNREG_INP |
++ NLP_RPI_REGISTERED);
++ spin_unlock_irq(&ndlp->lock);
++ } else {
++ lpfc_unreg_rpi(vports[i], ndlp);
++ }
+ /*
+ * Whenever an SLI4 port goes offline, free the
+ * RPI. Get a new RPI when the adapter port
+@@ -14070,6 +14084,10 @@ lpfc_pci_resume_one_s3(struct device *dev_d)
+ return error;
+ }
+
++ /* Init cpu_map array */
++ lpfc_cpu_map_array_init(phba);
++ /* Init hba_eq_hdl array */
++ lpfc_hba_eq_hdl_array_init(phba);
+ /* Configure and enable interrupt */
+ intr_mode = lpfc_sli_enable_intr(phba, phba->intr_mode);
+ if (intr_mode == LPFC_INTR_ERROR) {
+@@ -15023,14 +15041,17 @@ lpfc_io_error_detected_s4(struct pci_dev *pdev, pci_channel_state_t state)
+ lpfc_sli4_prep_dev_for_recover(phba);
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ case pci_channel_io_frozen:
++ phba->hba_flag |= HBA_PCI_ERR;
+ /* Fatal error, prepare for slot reset */
+ lpfc_sli4_prep_dev_for_reset(phba);
+ return PCI_ERS_RESULT_NEED_RESET;
+ case pci_channel_io_perm_failure:
++ phba->hba_flag |= HBA_PCI_ERR;
+ /* Permanent failure, prepare for device down */
+ lpfc_sli4_prep_dev_for_perm_failure(phba);
+ return PCI_ERS_RESULT_DISCONNECT;
+ default:
++ phba->hba_flag |= HBA_PCI_ERR;
+ /* Unknown state, prepare and request slot reset */
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "2825 Unknown PCI error state: x%x\n", state);
+@@ -15074,6 +15095,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
+
+ pci_restore_state(pdev);
+
++ phba->hba_flag &= ~HBA_PCI_ERR;
+ /*
+ * As the new kernel behavior of pci_restore_state() API call clears
+ * device saved_state flag, need to save the restored state again.
+@@ -15098,6 +15120,7 @@ lpfc_io_slot_reset_s4(struct pci_dev *pdev)
+ return PCI_ERS_RESULT_DISCONNECT;
+ } else
+ phba->intr_mode = intr_mode;
++ lpfc_cpu_affinity_check(phba, phba->cfg_irq_chann);
+
+ /* Log the current active interrupt mode */
+ lpfc_log_intr_mode(phba, phba->intr_mode);
+@@ -15299,6 +15322,10 @@ lpfc_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+ struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+ pci_ers_result_t rc = PCI_ERS_RESULT_DISCONNECT;
+
++ if (phba->link_state == LPFC_HBA_ERROR &&
++ phba->hba_flag & HBA_IOQ_FLUSH)
++ return PCI_ERS_RESULT_NEED_RESET;
++
+ switch (phba->pci_dev_grp) {
+ case LPFC_PCI_DEV_LP:
+ rc = lpfc_io_error_detected_s3(pdev, state);
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 4fb3dc5092f5..4e0c0b273e5f 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -937,6 +937,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ int cpu;
+ #endif
++ int offline = 0;
+
+ /* Sanity check on return of outstanding command */
+ if (!lpfc_ncmd) {
+@@ -1098,11 +1099,12 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ nCmd->transferred_length = 0;
+ nCmd->rcv_rsplen = 0;
+ nCmd->status = NVME_SC_INTERNAL;
++ offline = pci_channel_offline(vport->phba->pcidev);
+ }
+ }
+
+ /* pick up SLI4 exhange busy condition */
+- if (bf_get(lpfc_wcqe_c_xb, wcqe))
++ if (bf_get(lpfc_wcqe_c_xb, wcqe) && !offline)
+ lpfc_ncmd->flags |= LPFC_SBUF_XBUSY;
+ else
+ lpfc_ncmd->flags &= ~LPFC_SBUF_XBUSY;
+@@ -2174,6 +2176,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
+ abts_nvme = 0;
+ for (i = 0; i < phba->cfg_hdw_queue; i++) {
+ qp = &phba->sli4_hba.hdwq[i];
++ if (!vport || !vport->localport ||
++ !qp || !qp->io_wq)
++ return;
++
+ pring = qp->io_wq->pring;
+ if (!pring)
+ continue;
+@@ -2181,6 +2187,10 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
+ abts_scsi += qp->abts_scsi_io_bufs;
+ abts_nvme += qp->abts_nvme_io_bufs;
+ }
++ if (!vport || !vport->localport ||
++ vport->phba->hba_flag & HBA_PCI_ERR)
++ return;
++
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6176 Lport x%px Localport x%px wait "
+ "timed out. Pending %d [%d:%d]. "
+@@ -2220,6 +2230,8 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
+ return;
+
+ localport = vport->localport;
++ if (!localport)
++ return;
+ lport = (struct lpfc_nvme_lport *)localport->private;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
+@@ -2536,7 +2548,8 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ * return values is ignored. The upcall is a courtesy to the
+ * transport.
+ */
+- if (vport->load_flag & FC_UNLOADING)
++ if (vport->load_flag & FC_UNLOADING ||
++ unlikely(vport->phba->hba_flag & HBA_PCI_ERR))
+ (void)nvme_fc_set_remoteport_devloss(remoteport, 0);
+
+ ret = nvme_fc_unregister_remoteport(remoteport);
+@@ -2564,6 +2577,42 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ vport->localport, ndlp->rport, ndlp->nlp_DID);
+ }
+
++/**
++ * lpfc_sli4_nvme_pci_offline_aborted - Fast-path process of NVME xri abort
++ * @phba: pointer to lpfc hba data structure.
++ * @lpfc_ncmd: The nvme job structure for the request being aborted.
++ *
++ * This routine is invoked by the worker thread to process a SLI4 fast-path
++ * NVME aborted xri. Aborted NVME IO commands are completed to the transport
++ * here.
++ **/
++void
++lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba,
++ struct lpfc_io_buf *lpfc_ncmd)
++{
++ struct nvmefc_fcp_req *nvme_cmd = NULL;
++
++ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
++ "6533 %s nvme_cmd %p tag x%x abort complete and "
++ "xri released\n", __func__,
++ lpfc_ncmd->nvmeCmd,
++ lpfc_ncmd->cur_iocbq.iotag);
++
++ /* Aborted NVME commands are required to not complete
++ * before the abort exchange command fully completes.
++ * Once completed, it is available via the put list.
++ */
++ if (lpfc_ncmd->nvmeCmd) {
++ nvme_cmd = lpfc_ncmd->nvmeCmd;
++ nvme_cmd->transferred_length = 0;
++ nvme_cmd->rcv_rsplen = 0;
++ nvme_cmd->status = NVME_SC_INTERNAL;
++ nvme_cmd->done(nvme_cmd);
++ lpfc_ncmd->nvmeCmd = NULL;
++ }
++ lpfc_release_nvme_buf(phba, lpfc_ncmd);
++}
++
+ /**
+ * lpfc_sli4_nvme_xri_aborted - Fast-path process of NVME xri abort
+ * @phba: pointer to lpfc hba data structure.
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index c6944b282e21..ea93b7e07b7e 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -493,8 +493,8 @@ void
+ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ struct sli4_wcqe_xri_aborted *axri, int idx)
+ {
+- uint16_t xri = bf_get(lpfc_wcqe_xa_xri, axri);
+- uint16_t rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
++ u16 xri = 0;
++ u16 rxid = 0;
+ struct lpfc_io_buf *psb, *next_psb;
+ struct lpfc_sli4_hdw_queue *qp;
+ unsigned long iflag = 0;
+@@ -504,15 +504,22 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ int rrq_empty = 0;
+ struct lpfc_sli_ring *pring = phba->sli4_hba.els_wq->pring;
+ struct scsi_cmnd *cmd;
++ int offline = 0;
+
+ if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
+ return;
+-
++ offline = pci_channel_offline(phba->pcidev);
++ if (!offline) {
++ xri = bf_get(lpfc_wcqe_xa_xri, axri);
++ rxid = bf_get(lpfc_wcqe_xa_remote_xid, axri);
++ }
+ qp = &phba->sli4_hba.hdwq[idx];
+ spin_lock_irqsave(&phba->hbalock, iflag);
+ spin_lock(&qp->abts_io_buf_list_lock);
+ list_for_each_entry_safe(psb, next_psb,
+ &qp->lpfc_abts_io_buf_list, list) {
++ if (offline)
++ xri = psb->cur_iocbq.sli4_xritag;
+ if (psb->cur_iocbq.sli4_xritag == xri) {
+ list_del_init(&psb->list);
+ psb->flags &= ~LPFC_SBUF_XBUSY;
+@@ -521,8 +528,15 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ qp->abts_nvme_io_bufs--;
+ spin_unlock(&qp->abts_io_buf_list_lock);
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+- lpfc_sli4_nvme_xri_aborted(phba, axri, psb);
+- return;
++ if (!offline) {
++ lpfc_sli4_nvme_xri_aborted(phba, axri,
++ psb);
++ return;
++ }
++ lpfc_sli4_nvme_pci_offline_aborted(phba, psb);
++ spin_lock_irqsave(&phba->hbalock, iflag);
++ spin_lock(&qp->abts_io_buf_list_lock);
++ continue;
+ }
+ qp->abts_scsi_io_bufs--;
+ spin_unlock(&qp->abts_io_buf_list_lock);
+@@ -534,13 +548,13 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+
+ rrq_empty = list_empty(&phba->active_rrq_list);
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+- if (ndlp) {
++ if (ndlp && !offline) {
+ lpfc_set_rrq_active(phba, ndlp,
+ psb->cur_iocbq.sli4_lxritag, rxid, 1);
+ lpfc_sli4_abts_err_handler(phba, ndlp, axri);
+ }
+
+- if (phba->cfg_fcp_wait_abts_rsp) {
++ if (phba->cfg_fcp_wait_abts_rsp || offline) {
+ spin_lock_irqsave(&psb->buf_lock, iflag);
+ cmd = psb->pCmd;
+ psb->pCmd = NULL;
+@@ -567,25 +581,30 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ lpfc_release_scsi_buf_s4(phba, psb);
+ if (rrq_empty)
+ lpfc_worker_wake_up(phba);
+- return;
++ if (!offline)
++ return;
++ spin_lock_irqsave(&phba->hbalock, iflag);
++ spin_lock(&qp->abts_io_buf_list_lock);
++ continue;
+ }
+ }
+ spin_unlock(&qp->abts_io_buf_list_lock);
+- for (i = 1; i <= phba->sli.last_iotag; i++) {
+- iocbq = phba->sli.iocbq_lookup[i];
+-
+- if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
+- (iocbq->iocb_flag & LPFC_IO_LIBDFC))
+- continue;
+- if (iocbq->sli4_xritag != xri)
+- continue;
+- psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
+- psb->flags &= ~LPFC_SBUF_XBUSY;
+- spin_unlock_irqrestore(&phba->hbalock, iflag);
+- if (!list_empty(&pring->txq))
+- lpfc_worker_wake_up(phba);
+- return;
++ if (!offline) {
++ for (i = 1; i <= phba->sli.last_iotag; i++) {
++ iocbq = phba->sli.iocbq_lookup[i];
+
++ if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
++ (iocbq->iocb_flag & LPFC_IO_LIBDFC))
++ continue;
++ if (iocbq->sli4_xritag != xri)
++ continue;
++ psb = container_of(iocbq, struct lpfc_io_buf, cur_iocbq);
++ psb->flags &= ~LPFC_SBUF_XBUSY;
++ spin_unlock_irqrestore(&phba->hbalock, iflag);
++ if (!list_empty(&pring->txq))
++ lpfc_worker_wake_up(phba);
++ return;
++ }
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+ }
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index d8d26cde70b6..e905a246a2d6 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -1404,7 +1404,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+ }
+
+ if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
+- (sglq->state != SGL_XRI_ABORTED)) {
++ (!(unlikely(pci_channel_offline(phba->pcidev)))) &&
++ sglq->state != SGL_XRI_ABORTED) {
+ spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock,
+ iflag);
+
+@@ -4583,10 +4584,12 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
+ lpfc_sli_cancel_iocbs(phba, &txq,
+ IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
+- /* Flush the txcmpq */
++ /* Flush the txcmplq */
+ lpfc_sli_cancel_iocbs(phba, &txcmplq,
+ IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
++ if (unlikely(pci_channel_offline(phba->pcidev)))
++ lpfc_sli4_io_xri_aborted(phba, NULL, 0);
+ }
+ } else {
+ pring = &psli->sli3_ring[LPFC_FCP_RING];
+@@ -22035,8 +22038,26 @@ lpfc_get_io_buf_from_multixri_pools(struct lpfc_hba *phba,
+
+ qp = &phba->sli4_hba.hdwq[hwqid];
+ lpfc_ncmd = NULL;
++ if (!qp) {
++ lpfc_printf_log(phba, KERN_INFO,
++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
++ "5556 NULL qp for hwqid x%x\n", hwqid);
++ return lpfc_ncmd;
++ }
+ multixri_pool = qp->p_multixri_pool;
++ if (!multixri_pool) {
++ lpfc_printf_log(phba, KERN_INFO,
++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
++ "5557 NULL multixri for hwqid x%x\n", hwqid);
++ return lpfc_ncmd;
++ }
+ pvt_pool = &multixri_pool->pvt_pool;
++ if (!pvt_pool) {
++ lpfc_printf_log(phba, KERN_INFO,
++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
++ "5558 NULL pvt_pool for hwqid x%x\n", hwqid);
++ return lpfc_ncmd;
++ }
+ multixri_pool->io_req_count++;
+
+ /* If pvt_pool is empty, move some XRIs from public to private pool */
+@@ -22112,6 +22133,12 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba,
+
+ qp = &phba->sli4_hba.hdwq[hwqid];
+ lpfc_cmd = NULL;
++ if (!qp) {
++ lpfc_printf_log(phba, KERN_WARNING,
++ LOG_SLI | LOG_NVME_ABTS | LOG_FCP,
++ "5555 NULL qp for hwqid x%x\n", hwqid);
++ return lpfc_cmd;
++ }
+
+ if (phba->cfg_xri_rebalancing)
+ lpfc_cmd = lpfc_get_io_buf_from_multixri_pools(
+diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
+index 99c5d1e4da5e..5962cf508842 100644
+--- a/drivers/scsi/lpfc/lpfc_sli4.h
++++ b/drivers/scsi/lpfc/lpfc_sli4.h
+@@ -1116,6 +1116,8 @@ void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *);
+ int lpfc_sli4_resume_rpi(struct lpfc_nodelist *,
+ void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *);
+ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba);
++void lpfc_sli4_nvme_pci_offline_aborted(struct lpfc_hba *phba,
++ struct lpfc_io_buf *lpfc_ncmd);
+ void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba,
+ struct sli4_wcqe_xri_aborted *axri,
+ struct lpfc_io_buf *lpfc_ncmd);
+--
+2.35.1
+
--- /dev/null
+From 1b118d426a9477a697c4ec0251b0e68d20125365 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Jul 2022 14:14:17 -0700
+Subject: scsi: lpfc: Remove extra atomic_inc on cmd_pending in queuecommand
+ after VMID
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit 0948a9c5386095baae4012190a6b65aba684a907 ]
+
+VMID introduced an extra increment of cmd_pending, causing double-counting
+of the I/O. The normal increment ios performed in lpfc_get_scsi_buf.
+
+Link: https://lore.kernel.org/r/20220701211425.2708-5-jsmart2021@gmail.com
+Fixes: 33c79741deaf ("scsi: lpfc: vmid: Introduce VMID in I/O path")
+Cc: <stable@vger.kernel.org> # v5.14+
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_scsi.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index b43dfcb81185..7da8e4c845df 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -5707,7 +5707,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ cur_iocbq->cmd_flag |= LPFC_IO_VMID;
+ }
+ }
+- atomic_inc(&ndlp->cmd_pending);
+
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
+--
+2.35.1
+
--- /dev/null
+From 3510446140fedf511836136d992afcfa9e506c3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 18:22:53 -0800
+Subject: scsi: lpfc: SLI path split: Refactor fast and slow paths to native
+ SLI4
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit 1b64aa9eae28ac598a03ed3d62a63ac5e5b295fc ]
+
+Convert the SLI4 fast and slow paths to use native SLI4 wqe constructs
+instead of iocb SLI3-isms.
+
+Includes the following:
+
+ - Create simple get_xxx and set_xxx routines to wrapper access to common
+ elements in both SLI3 and SLI4 commands - allowing calling routines to
+ avoid sli-rev-specific structures to access the elements.
+
+ - using the wqe in the job structure as the primary element
+
+ - use defines from SLI-4, not SLI-3
+
+ - Removal of iocb to wqe conversion from fast and slow path
+
+ - Add below routines to handle fast path
+ lpfc_prep_embed_io - prepares the wqe for fast path
+ lpfc_wqe_bpl2sgl - manages bpl to sgl conversion
+ lpfc_sli_wqe2iocb - converts a WQE to IOCB for SLI-3 path
+
+ - Add lpfc_sli3_iocb2wcqecmpl in completion path to convert an SLI-3
+ iocb completion to wcqe completion
+
+ - Refactor some of the code that works on both revs for clarity
+
+Link: https://lore.kernel.org/r/20220225022308.16486-3-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 36 +++
+ drivers/scsi/lpfc/lpfc_crtn.h | 1 +
+ drivers/scsi/lpfc/lpfc_hw4.h | 7 +
+ drivers/scsi/lpfc/lpfc_sli.c | 513 ++++++++++++++--------------------
+ drivers/scsi/lpfc/lpfc_sli.h | 2 +
+ 5 files changed, 257 insertions(+), 302 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index b2508a00bafd..266d980667b8 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -1803,3 +1803,39 @@ static inline int lpfc_is_vmid_enabled(struct lpfc_hba *phba)
+ {
+ return phba->cfg_vmid_app_header || phba->cfg_vmid_priority_tagging;
+ }
++
++static inline
++u8 get_job_ulpstatus(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++{
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ return bf_get(lpfc_wcqe_c_status, &iocbq->wcqe_cmpl);
++ else
++ return iocbq->iocb.ulpStatus;
++}
++
++static inline
++u32 get_job_word4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++{
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ return iocbq->wcqe_cmpl.parameter;
++ else
++ return iocbq->iocb.un.ulpWord[4];
++}
++
++static inline
++u8 get_job_cmnd(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++{
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ return bf_get(wqe_cmnd, &iocbq->wqe.generic.wqe_com);
++ else
++ return iocbq->iocb.ulpCommand;
++}
++
++static inline
++u16 get_job_ulpcontext(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
++{
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ return bf_get(wqe_ctxt_tag, &iocbq->wqe.generic.wqe_com);
++ else
++ return iocbq->iocb.ulpContext;
++}
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index ed27a0afcb8b..f7bf589b63fb 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -129,6 +129,7 @@ void lpfc_disc_list_loopmap(struct lpfc_vport *);
+ void lpfc_disc_start(struct lpfc_vport *);
+ void lpfc_cleanup_discovery_resources(struct lpfc_vport *);
+ void lpfc_cleanup(struct lpfc_vport *);
++void lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd);
+ void lpfc_disc_timeout(struct timer_list *);
+
+ int lpfc_unregister_fcf_prep(struct lpfc_hba *);
+diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
+index 824fc8c08840..215fbf1c777e 100644
+--- a/drivers/scsi/lpfc/lpfc_hw4.h
++++ b/drivers/scsi/lpfc/lpfc_hw4.h
+@@ -60,6 +60,13 @@
+ ((ptr)->name##_WORD = ((((value) & name##_MASK) << name##_SHIFT) | \
+ ((ptr)->name##_WORD & ~(name##_MASK << name##_SHIFT))))
+
++#define get_wqe_reqtag(x) (((x)->wqe.words[9] >> 0) & 0xFFFF)
++
++#define get_job_ulpword(x, y) ((x)->iocb.un.ulpWord[y])
++
++#define set_job_ulpstatus(x, y) bf_set(lpfc_wcqe_c_status, &(x)->wcqe_cmpl, y)
++#define set_job_ulpword4(x, y) ((&(x)->wcqe_cmpl)->parameter = y)
++
+ struct dma_address {
+ uint32_t addr_lo;
+ uint32_t addr_hi;
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 413824fc9533..464a251bcc88 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -70,8 +70,9 @@ static int lpfc_sli_issue_mbox_s4(struct lpfc_hba *, LPFC_MBOXQ_t *,
+ uint32_t);
+ static int lpfc_sli4_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *,
+ uint8_t *, uint32_t *);
+-static struct lpfc_iocbq *lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *,
+- struct lpfc_iocbq *);
++static struct lpfc_iocbq *
++lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba,
++ struct lpfc_iocbq *rspiocbq);
+ static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
+ struct hbq_dmabuf *);
+ static void lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+@@ -89,6 +90,9 @@ static struct lpfc_cqe *lpfc_sli4_cq_get(struct lpfc_queue *q);
+ static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba,
+ struct lpfc_queue *cq,
+ struct lpfc_cqe *cqe);
++static uint16_t lpfc_wqe_bpl2sgl(struct lpfc_hba *phba,
++ struct lpfc_iocbq *pwqeq,
++ struct lpfc_sglq *sglq);
+
+ union lpfc_wqe128 lpfc_iread_cmd_template;
+ union lpfc_wqe128 lpfc_iwrite_cmd_template;
+@@ -3550,17 +3554,12 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
+ struct lpfc_iocbq *prspiocb)
+ {
+ struct lpfc_iocbq *cmd_iocb = NULL;
+- uint16_t iotag;
+- spinlock_t *temp_lock = NULL;
+- unsigned long iflag = 0;
++ u16 iotag;
+
+ if (phba->sli_rev == LPFC_SLI_REV4)
+- temp_lock = &pring->ring_lock;
++ iotag = get_wqe_reqtag(prspiocb);
+ else
+- temp_lock = &phba->hbalock;
+-
+- spin_lock_irqsave(temp_lock, iflag);
+- iotag = prspiocb->iocb.ulpIoTag;
++ iotag = prspiocb->iocb.ulpIoTag;
+
+ if (iotag != 0 && iotag <= phba->sli.last_iotag) {
+ cmd_iocb = phba->sli.iocbq_lookup[iotag];
+@@ -3569,17 +3568,14 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
+ list_del_init(&cmd_iocb->list);
+ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ pring->txcmplq_cnt--;
+- spin_unlock_irqrestore(temp_lock, iflag);
+ return cmd_iocb;
+ }
+ }
+
+- spin_unlock_irqrestore(temp_lock, iflag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0317 iotag x%x is out of "
+- "range: max iotag x%x wd0 x%x\n",
+- iotag, phba->sli.last_iotag,
+- *(((uint32_t *) &prspiocb->iocb) + 7));
++ "range: max iotag x%x\n",
++ iotag, phba->sli.last_iotag);
+ return NULL;
+ }
+
+@@ -3600,15 +3596,7 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
+ struct lpfc_sli_ring *pring, uint16_t iotag)
+ {
+ struct lpfc_iocbq *cmd_iocb = NULL;
+- spinlock_t *temp_lock = NULL;
+- unsigned long iflag = 0;
+
+- if (phba->sli_rev == LPFC_SLI_REV4)
+- temp_lock = &pring->ring_lock;
+- else
+- temp_lock = &phba->hbalock;
+-
+- spin_lock_irqsave(temp_lock, iflag);
+ if (iotag != 0 && iotag <= phba->sli.last_iotag) {
+ cmd_iocb = phba->sli.iocbq_lookup[iotag];
+ if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) {
+@@ -3616,12 +3604,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
+ list_del_init(&cmd_iocb->list);
+ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ pring->txcmplq_cnt--;
+- spin_unlock_irqrestore(temp_lock, iflag);
+ return cmd_iocb;
+ }
+ }
+
+- spin_unlock_irqrestore(temp_lock, iflag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0372 iotag x%x lookup error: max iotag (x%x) "
+ "cmd_flag x%x\n",
+@@ -3654,18 +3640,29 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ struct lpfc_iocbq *cmdiocbp;
+ int rc = 1;
+ unsigned long iflag;
++ u32 ulp_command, ulp_status, ulp_word4, ulp_context, iotag;
+
+ cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
++
++ ulp_command = get_job_cmnd(phba, saveq);
++ ulp_status = get_job_ulpstatus(phba, saveq);
++ ulp_word4 = get_job_word4(phba, saveq);
++ ulp_context = get_job_ulpcontext(phba, saveq);
++ if (phba->sli_rev == LPFC_SLI_REV4)
++ iotag = get_wqe_reqtag(saveq);
++ else
++ iotag = saveq->iocb.ulpIoTag;
++
+ if (cmdiocbp) {
++ ulp_command = get_job_cmnd(phba, cmdiocbp);
+ if (cmdiocbp->cmd_cmpl) {
+ /*
+ * If an ELS command failed send an event to mgmt
+ * application.
+ */
+- if (saveq->iocb.ulpStatus &&
++ if (ulp_status &&
+ (pring->ringno == LPFC_ELS_RING) &&
+- (cmdiocbp->iocb.ulpCommand ==
+- CMD_ELS_REQUEST64_CR))
++ (ulp_command == CMD_ELS_REQUEST64_CR))
+ lpfc_send_els_failure_event(phba,
+ cmdiocbp, saveq);
+
+@@ -3727,20 +3724,20 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ ~LPFC_DRIVER_ABORTED;
+ spin_unlock_irqrestore(
+ &phba->hbalock, iflag);
+- cmdiocbp->iocb.ulpStatus =
+- IOSTAT_LOCAL_REJECT;
+- cmdiocbp->iocb.un.ulpWord[4] =
+- IOERR_ABORT_REQUESTED;
++ set_job_ulpstatus(cmdiocbp,
++ IOSTAT_LOCAL_REJECT);
++ set_job_ulpword4(cmdiocbp,
++ IOERR_ABORT_REQUESTED);
+ /*
+ * For SLI4, irsiocb contains
+ * NO_XRI in sli_xritag, it
+ * shall not affect releasing
+ * sgl (xri) process.
+ */
+- saveq->iocb.ulpStatus =
+- IOSTAT_LOCAL_REJECT;
+- saveq->iocb.un.ulpWord[4] =
+- IOERR_SLI_ABORTED;
++ set_job_ulpstatus(saveq,
++ IOSTAT_LOCAL_REJECT);
++ set_job_ulpword4(saveq,
++ IOERR_SLI_ABORTED);
+ spin_lock_irqsave(
+ &phba->hbalock, iflag);
+ saveq->cmd_flag |=
+@@ -3768,12 +3765,8 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ "0322 Ring %d handler: "
+ "unexpected completion IoTag x%x "
+ "Data: x%x x%x x%x x%x\n",
+- pring->ringno,
+- saveq->iocb.ulpIoTag,
+- saveq->iocb.ulpStatus,
+- saveq->iocb.un.ulpWord[4],
+- saveq->iocb.ulpCommand,
+- saveq->iocb.ulpContext);
++ pring->ringno, iotag, ulp_status,
++ ulp_word4, ulp_command, ulp_context);
+ }
+ }
+
+@@ -4088,155 +4081,159 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ struct lpfc_iocbq *rspiocbp)
+ {
+ struct lpfc_iocbq *saveq;
+- struct lpfc_iocbq *cmdiocbp;
++ struct lpfc_iocbq *cmdiocb;
+ struct lpfc_iocbq *next_iocb;
+- IOCB_t *irsp = NULL;
++ IOCB_t *irsp;
+ uint32_t free_saveq;
+- uint8_t iocb_cmd_type;
++ u8 cmd_type;
+ lpfc_iocb_type type;
+ unsigned long iflag;
++ u32 ulp_status = get_job_ulpstatus(phba, rspiocbp);
++ u32 ulp_word4 = get_job_word4(phba, rspiocbp);
++ u32 ulp_command = get_job_cmnd(phba, rspiocbp);
+ int rc;
+
+ spin_lock_irqsave(&phba->hbalock, iflag);
+ /* First add the response iocb to the countinueq list */
+- list_add_tail(&rspiocbp->list, &(pring->iocb_continueq));
++ list_add_tail(&rspiocbp->list, &pring->iocb_continueq);
+ pring->iocb_continueq_cnt++;
+
+- /* Now, determine whether the list is completed for processing */
+- irsp = &rspiocbp->iocb;
+- if (irsp->ulpLe) {
+- /*
+- * By default, the driver expects to free all resources
+- * associated with this iocb completion.
+- */
+- free_saveq = 1;
+- saveq = list_get_first(&pring->iocb_continueq,
+- struct lpfc_iocbq, list);
+- irsp = &(saveq->iocb);
+- list_del_init(&pring->iocb_continueq);
+- pring->iocb_continueq_cnt = 0;
++ /*
++ * By default, the driver expects to free all resources
++ * associated with this iocb completion.
++ */
++ free_saveq = 1;
++ saveq = list_get_first(&pring->iocb_continueq,
++ struct lpfc_iocbq, list);
++ list_del_init(&pring->iocb_continueq);
++ pring->iocb_continueq_cnt = 0;
+
+- pring->stats.iocb_rsp++;
++ pring->stats.iocb_rsp++;
+
+- /*
+- * If resource errors reported from HBA, reduce
+- * queuedepths of the SCSI device.
+- */
+- if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
+- ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
+- IOERR_NO_RESOURCES)) {
+- spin_unlock_irqrestore(&phba->hbalock, iflag);
+- phba->lpfc_rampdown_queue_depth(phba);
+- spin_lock_irqsave(&phba->hbalock, iflag);
+- }
++ /*
++ * If resource errors reported from HBA, reduce
++ * queuedepths of the SCSI device.
++ */
++ if (ulp_status == IOSTAT_LOCAL_REJECT &&
++ ((ulp_word4 & IOERR_PARAM_MASK) ==
++ IOERR_NO_RESOURCES)) {
++ spin_unlock_irqrestore(&phba->hbalock, iflag);
++ phba->lpfc_rampdown_queue_depth(phba);
++ spin_lock_irqsave(&phba->hbalock, iflag);
++ }
+
+- if (irsp->ulpStatus) {
+- /* Rsp ring <ringno> error: IOCB */
++ if (ulp_status) {
++ /* Rsp ring <ringno> error: IOCB */
++ if (phba->sli_rev < LPFC_SLI_REV4) {
++ irsp = &rspiocbp->iocb;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+- "0328 Rsp Ring %d error: "
++ "0328 Rsp Ring %d error: ulp_status x%x "
++ "IOCB Data: "
++ "x%08x x%08x x%08x x%08x "
++ "x%08x x%08x x%08x x%08x "
++ "x%08x x%08x x%08x x%08x "
++ "x%08x x%08x x%08x x%08x\n",
++ pring->ringno, ulp_status,
++ get_job_ulpword(rspiocbp, 0),
++ get_job_ulpword(rspiocbp, 1),
++ get_job_ulpword(rspiocbp, 2),
++ get_job_ulpword(rspiocbp, 3),
++ get_job_ulpword(rspiocbp, 4),
++ get_job_ulpword(rspiocbp, 5),
++ *(((uint32_t *)irsp) + 6),
++ *(((uint32_t *)irsp) + 7),
++ *(((uint32_t *)irsp) + 8),
++ *(((uint32_t *)irsp) + 9),
++ *(((uint32_t *)irsp) + 10),
++ *(((uint32_t *)irsp) + 11),
++ *(((uint32_t *)irsp) + 12),
++ *(((uint32_t *)irsp) + 13),
++ *(((uint32_t *)irsp) + 14),
++ *(((uint32_t *)irsp) + 15));
++ } else {
++ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
++ "0321 Rsp Ring %d error: "
+ "IOCB Data: "
+- "x%x x%x x%x x%x "
+- "x%x x%x x%x x%x "
+- "x%x x%x x%x x%x "
+ "x%x x%x x%x x%x\n",
+ pring->ringno,
+- irsp->un.ulpWord[0],
+- irsp->un.ulpWord[1],
+- irsp->un.ulpWord[2],
+- irsp->un.ulpWord[3],
+- irsp->un.ulpWord[4],
+- irsp->un.ulpWord[5],
+- *(((uint32_t *) irsp) + 6),
+- *(((uint32_t *) irsp) + 7),
+- *(((uint32_t *) irsp) + 8),
+- *(((uint32_t *) irsp) + 9),
+- *(((uint32_t *) irsp) + 10),
+- *(((uint32_t *) irsp) + 11),
+- *(((uint32_t *) irsp) + 12),
+- *(((uint32_t *) irsp) + 13),
+- *(((uint32_t *) irsp) + 14),
+- *(((uint32_t *) irsp) + 15));
++ rspiocbp->wcqe_cmpl.word0,
++ rspiocbp->wcqe_cmpl.total_data_placed,
++ rspiocbp->wcqe_cmpl.parameter,
++ rspiocbp->wcqe_cmpl.word3);
+ }
++ }
+
+- /*
+- * Fetch the IOCB command type and call the correct completion
+- * routine. Solicited and Unsolicited IOCBs on the ELS ring
+- * get freed back to the lpfc_iocb_list by the discovery
+- * kernel thread.
+- */
+- iocb_cmd_type = irsp->ulpCommand & CMD_IOCB_MASK;
+- type = lpfc_sli_iocb_cmd_type(iocb_cmd_type);
+- switch (type) {
+- case LPFC_SOL_IOCB:
+- spin_unlock_irqrestore(&phba->hbalock, iflag);
+- rc = lpfc_sli_process_sol_iocb(phba, pring, saveq);
+- spin_lock_irqsave(&phba->hbalock, iflag);
+- break;
+
+- case LPFC_UNSOL_IOCB:
+- spin_unlock_irqrestore(&phba->hbalock, iflag);
+- rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq);
+- spin_lock_irqsave(&phba->hbalock, iflag);
+- if (!rc)
+- free_saveq = 0;
+- break;
+-
+- case LPFC_ABORT_IOCB:
+- cmdiocbp = NULL;
+- if (irsp->ulpCommand != CMD_XRI_ABORTED_CX) {
++ /*
++ * Fetch the iocb command type and call the correct completion
++ * routine. Solicited and Unsolicited IOCBs on the ELS ring
++ * get freed back to the lpfc_iocb_list by the discovery
++ * kernel thread.
++ */
++ cmd_type = ulp_command & CMD_IOCB_MASK;
++ type = lpfc_sli_iocb_cmd_type(cmd_type);
++ switch (type) {
++ case LPFC_SOL_IOCB:
++ spin_unlock_irqrestore(&phba->hbalock, iflag);
++ rc = lpfc_sli_process_sol_iocb(phba, pring, saveq);
++ spin_lock_irqsave(&phba->hbalock, iflag);
++ break;
++ case LPFC_UNSOL_IOCB:
++ spin_unlock_irqrestore(&phba->hbalock, iflag);
++ rc = lpfc_sli_process_unsol_iocb(phba, pring, saveq);
++ spin_lock_irqsave(&phba->hbalock, iflag);
++ if (!rc)
++ free_saveq = 0;
++ break;
++ case LPFC_ABORT_IOCB:
++ cmdiocb = NULL;
++ if (ulp_command != CMD_XRI_ABORTED_CX)
++ cmdiocb = lpfc_sli_iocbq_lookup(phba, pring,
++ saveq);
++ if (cmdiocb) {
++ /* Call the specified completion routine */
++ if (cmdiocb->cmd_cmpl) {
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+- cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring,
+- saveq);
++ cmdiocb->cmd_cmpl(phba, cmdiocb, saveq);
+ spin_lock_irqsave(&phba->hbalock, iflag);
+- }
+- if (cmdiocbp) {
+- /* Call the specified completion routine */
+- if (cmdiocbp->cmd_cmpl) {
+- spin_unlock_irqrestore(&phba->hbalock,
+- iflag);
+- (cmdiocbp->cmd_cmpl)(phba, cmdiocbp,
+- saveq);
+- spin_lock_irqsave(&phba->hbalock,
+- iflag);
+- } else
+- __lpfc_sli_release_iocbq(phba,
+- cmdiocbp);
+- }
+- break;
+-
+- case LPFC_UNKNOWN_IOCB:
+- if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
+- char adaptermsg[LPFC_MAX_ADPTMSG];
+- memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
+- memcpy(&adaptermsg[0], (uint8_t *)irsp,
+- MAX_MSG_DATA);
+- dev_warn(&((phba->pcidev)->dev),
+- "lpfc%d: %s\n",
+- phba->brd_no, adaptermsg);
+ } else {
+- /* Unknown IOCB command */
+- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+- "0335 Unknown IOCB "
+- "command Data: x%x "
+- "x%x x%x x%x\n",
+- irsp->ulpCommand,
+- irsp->ulpStatus,
+- irsp->ulpIoTag,
+- irsp->ulpContext);
++ __lpfc_sli_release_iocbq(phba, cmdiocb);
+ }
+- break;
+ }
++ break;
++ case LPFC_UNKNOWN_IOCB:
++ if (ulp_command == CMD_ADAPTER_MSG) {
++ char adaptermsg[LPFC_MAX_ADPTMSG];
++
++ memset(adaptermsg, 0, LPFC_MAX_ADPTMSG);
++ memcpy(&adaptermsg[0], (uint8_t *)&rspiocbp->wqe,
++ MAX_MSG_DATA);
++ dev_warn(&((phba->pcidev)->dev),
++ "lpfc%d: %s\n",
++ phba->brd_no, adaptermsg);
++ } else {
++ /* Unknown command */
++ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
++ "0335 Unknown IOCB "
++ "command Data: x%x "
++ "x%x x%x x%x\n",
++ ulp_command,
++ ulp_status,
++ get_wqe_reqtag(rspiocbp),
++ get_job_ulpcontext(phba, rspiocbp));
++ }
++ break;
++ }
+
+- if (free_saveq) {
+- list_for_each_entry_safe(rspiocbp, next_iocb,
+- &saveq->list, list) {
+- list_del_init(&rspiocbp->list);
+- __lpfc_sli_release_iocbq(phba, rspiocbp);
+- }
+- __lpfc_sli_release_iocbq(phba, saveq);
++ if (free_saveq) {
++ list_for_each_entry_safe(rspiocbp, next_iocb,
++ &saveq->list, list) {
++ list_del_init(&rspiocbp->list);
++ __lpfc_sli_release_iocbq(phba, rspiocbp);
+ }
+- rspiocbp = NULL;
++ __lpfc_sli_release_iocbq(phba, saveq);
+ }
++ rspiocbp = NULL;
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+ return rspiocbp;
+ }
+@@ -4429,8 +4426,8 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
+ irspiocbq = container_of(cq_event, struct lpfc_iocbq,
+ cq_event);
+ /* Translate ELS WCQE to response IOCBQ */
+- irspiocbq = lpfc_sli4_els_wcqe_to_rspiocbq(phba,
+- irspiocbq);
++ irspiocbq = lpfc_sli4_els_preprocess_rspiocbq(phba,
++ irspiocbq);
+ if (irspiocbq)
+ lpfc_sli_sp_handle_rspiocb(phba, pring,
+ irspiocbq);
+@@ -10974,7 +10971,17 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ int rc;
+ struct lpfc_io_buf *lpfc_cmd =
+ (struct lpfc_io_buf *)piocb->context1;
+- union lpfc_wqe128 *wqe = &piocb->wqe;
++
++ lpfc_prep_embed_io(phba, lpfc_cmd);
++ rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
++ return rc;
++}
++
++void
++lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
++{
++ struct lpfc_iocbq *piocb = &lpfc_cmd->cur_iocbq;
++ union lpfc_wqe128 *wqe = &lpfc_cmd->cur_iocbq.wqe;
+ struct sli4_sge *sgl;
+
+ /* 128 byte wqe support here */
+@@ -11023,8 +11030,6 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ wqe->words[31] = piocb->vmid_tag.app_id;
+ }
+ }
+- rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb);
+- return rc;
+ }
+
+ /**
+@@ -11046,9 +11051,10 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ struct lpfc_iocbq *piocb, uint32_t flag)
+ {
+ struct lpfc_sglq *sglq;
+- union lpfc_wqe128 wqe;
++ union lpfc_wqe128 *wqe;
+ struct lpfc_queue *wq;
+ struct lpfc_sli_ring *pring;
++ u32 ulp_command = get_job_cmnd(phba, piocb);
+
+ /* Get the WQ */
+ if ((piocb->cmd_flag & LPFC_IO_FCP) ||
+@@ -11066,10 +11072,9 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ */
+
+ lockdep_assert_held(&pring->ring_lock);
+-
++ wqe = &piocb->wqe;
+ if (piocb->sli4_xritag == NO_XRI) {
+- if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
+- piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
++ if (ulp_command == CMD_ABORT_XRI_WQE)
+ sglq = NULL;
+ else {
+ if (!list_empty(&pring->txq)) {
+@@ -11110,14 +11115,24 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ if (sglq) {
+ piocb->sli4_lxritag = sglq->sli4_lxritag;
+ piocb->sli4_xritag = sglq->sli4_xritag;
+- if (NO_XRI == lpfc_sli4_bpl2sgl(phba, piocb, sglq))
++
++ /* ABTS sent by initiator to CT exchange, the
++ * RX_ID field will be filled with the newly
++ * allocated responder XRI.
++ */
++ if (ulp_command == CMD_XMIT_BLS_RSP64_CX &&
++ piocb->abort_bls == LPFC_ABTS_UNSOL_INT)
++ bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
++ piocb->sli4_xritag);
++
++ bf_set(wqe_xri_tag, &wqe->generic.wqe_com,
++ piocb->sli4_xritag);
++
++ if (lpfc_wqe_bpl2sgl(phba, piocb, sglq) == NO_XRI)
+ return IOCB_ERROR;
+ }
+
+- if (lpfc_sli4_iocb2wqe(phba, piocb, &wqe))
+- return IOCB_ERROR;
+-
+- if (lpfc_sli4_wq_put(wq, &wqe))
++ if (lpfc_sli4_wq_put(wq, wqe))
+ return IOCB_ERROR;
+ lpfc_sli_ringtxcmpl_put(phba, pring, piocb);
+
+@@ -14115,123 +14130,7 @@ void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba)
+ }
+
+ /**
+- * lpfc_sli4_iocb_param_transfer - Transfer pIocbOut and cmpl status to pIocbIn
+- * @phba: pointer to lpfc hba data structure
+- * @pIocbIn: pointer to the rspiocbq
+- * @pIocbOut: pointer to the cmdiocbq
+- * @wcqe: pointer to the complete wcqe
+- *
+- * This routine transfers the fields of a command iocbq to a response iocbq
+- * by copying all the IOCB fields from command iocbq and transferring the
+- * completion status information from the complete wcqe.
+- **/
+-static void
+-lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
+- struct lpfc_iocbq *pIocbIn,
+- struct lpfc_iocbq *pIocbOut,
+- struct lpfc_wcqe_complete *wcqe)
+-{
+- int numBdes, i;
+- unsigned long iflags;
+- uint32_t status, max_response;
+- struct lpfc_dmabuf *dmabuf;
+- struct ulp_bde64 *bpl, bde;
+- size_t offset = offsetof(struct lpfc_iocbq, iocb);
+-
+- memcpy((char *)pIocbIn + offset, (char *)pIocbOut + offset,
+- sizeof(struct lpfc_iocbq) - offset);
+- /* Map WCQE parameters into irspiocb parameters */
+- status = bf_get(lpfc_wcqe_c_status, wcqe);
+- pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK);
+- if (pIocbOut->cmd_flag & LPFC_IO_FCP)
+- if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
+- pIocbIn->iocb.un.fcpi.fcpi_parm =
+- pIocbOut->iocb.un.fcpi.fcpi_parm -
+- wcqe->total_data_placed;
+- else
+- pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
+- else {
+- pIocbIn->iocb.un.ulpWord[4] = wcqe->parameter;
+- switch (pIocbOut->iocb.ulpCommand) {
+- case CMD_ELS_REQUEST64_CR:
+- dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3;
+- bpl = (struct ulp_bde64 *)dmabuf->virt;
+- bde.tus.w = le32_to_cpu(bpl[1].tus.w);
+- max_response = bde.tus.f.bdeSize;
+- break;
+- case CMD_GEN_REQUEST64_CR:
+- max_response = 0;
+- if (!pIocbOut->context3)
+- break;
+- numBdes = pIocbOut->iocb.un.genreq64.bdl.bdeSize/
+- sizeof(struct ulp_bde64);
+- dmabuf = (struct lpfc_dmabuf *)pIocbOut->context3;
+- bpl = (struct ulp_bde64 *)dmabuf->virt;
+- for (i = 0; i < numBdes; i++) {
+- bde.tus.w = le32_to_cpu(bpl[i].tus.w);
+- if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64)
+- max_response += bde.tus.f.bdeSize;
+- }
+- break;
+- default:
+- max_response = wcqe->total_data_placed;
+- break;
+- }
+- if (max_response < wcqe->total_data_placed)
+- pIocbIn->iocb.un.genreq64.bdl.bdeSize = max_response;
+- else
+- pIocbIn->iocb.un.genreq64.bdl.bdeSize =
+- wcqe->total_data_placed;
+- }
+-
+- /* Convert BG errors for completion status */
+- if (status == CQE_STATUS_DI_ERROR) {
+- pIocbIn->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
+-
+- if (bf_get(lpfc_wcqe_c_bg_edir, wcqe))
+- pIocbIn->iocb.un.ulpWord[4] = IOERR_RX_DMA_FAILED;
+- else
+- pIocbIn->iocb.un.ulpWord[4] = IOERR_TX_DMA_FAILED;
+-
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat = 0;
+- if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
+- BGS_GUARD_ERR_MASK;
+- if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* App Tag Check failed */
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
+- BGS_APPTAG_ERR_MASK;
+- if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* Ref Tag Check failed */
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
+- BGS_REFTAG_ERR_MASK;
+-
+- /* Check to see if there was any good data before the error */
+- if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
+- BGS_HI_WATER_MARK_PRESENT_MASK;
+- pIocbIn->iocb.unsli3.sli3_bg.bghm =
+- wcqe->total_data_placed;
+- }
+-
+- /*
+- * Set ALL the error bits to indicate we don't know what
+- * type of error it is.
+- */
+- if (!pIocbIn->iocb.unsli3.sli3_bg.bgstat)
+- pIocbIn->iocb.unsli3.sli3_bg.bgstat |=
+- (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK |
+- BGS_GUARD_ERR_MASK);
+- }
+-
+- /* Pick up HBA exchange busy condition */
+- if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
+- spin_lock_irqsave(&phba->hbalock, iflags);
+- pIocbIn->cmd_flag |= LPFC_EXCHANGE_BUSY;
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+- }
+-}
+-
+-/**
+- * lpfc_sli4_els_wcqe_to_rspiocbq - Get response iocbq from els wcqe
++ * lpfc_sli4_els_preprocess_rspiocbq - Get response iocbq from els wcqe
+ * @phba: Pointer to HBA context object.
+ * @irspiocbq: Pointer to work-queue completion queue entry.
+ *
+@@ -14242,8 +14141,8 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
+ * Return: Pointer to the receive IOCBQ, NULL otherwise.
+ **/
+ static struct lpfc_iocbq *
+-lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
+- struct lpfc_iocbq *irspiocbq)
++lpfc_sli4_els_preprocess_rspiocbq(struct lpfc_hba *phba,
++ struct lpfc_iocbq *irspiocbq)
+ {
+ struct lpfc_sli_ring *pring;
+ struct lpfc_iocbq *cmdiocbq;
+@@ -14255,11 +14154,13 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
+ return NULL;
+
+ wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
++ spin_lock_irqsave(&pring->ring_lock, iflags);
+ pring->stats.iocb_event++;
+ /* Look up the ELS command IOCB and create pseudo response IOCB */
+ cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
+ bf_get(lpfc_wcqe_c_request_tag, wcqe));
+ if (unlikely(!cmdiocbq)) {
++ spin_unlock_irqrestore(&pring->ring_lock, iflags);
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "0386 ELS complete with no corresponding "
+ "cmdiocb: 0x%x 0x%x 0x%x 0x%x\n",
+@@ -14269,13 +14170,18 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
+ return NULL;
+ }
+
+- spin_lock_irqsave(&pring->ring_lock, iflags);
++ memcpy(&irspiocbq->wqe, &cmdiocbq->wqe, sizeof(union lpfc_wqe128));
++ memcpy(&irspiocbq->wcqe_cmpl, wcqe, sizeof(*wcqe));
++
+ /* Put the iocb back on the txcmplq */
+ lpfc_sli_ringtxcmpl_put(phba, pring, cmdiocbq);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
+
+- /* Fake the irspiocbq and copy necessary response information */
+- lpfc_sli4_iocb_param_transfer(phba, irspiocbq, cmdiocbq, wcqe);
++ if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
++ spin_lock_irqsave(&phba->hbalock, iflags);
++ cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY;
++ spin_unlock_irqrestore(&phba->hbalock, iflags);
++ }
+
+ return irspiocbq;
+ }
+@@ -15101,9 +15007,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
+ /* Look up the FCP command IOCB and create pseudo response IOCB */
+ spin_lock_irqsave(&pring->ring_lock, iflags);
+ pring->stats.iocb_event++;
+- spin_unlock_irqrestore(&pring->ring_lock, iflags);
+ cmdiocbq = lpfc_sli_iocbq_lookup_by_tag(phba, pring,
+ bf_get(lpfc_wcqe_c_request_tag, wcqe));
++ spin_unlock_irqrestore(&pring->ring_lock, iflags);
+ if (unlikely(!cmdiocbq)) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "0374 FCP complete with no corresponding "
+@@ -18964,13 +18870,16 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
+ ctiocb->sli4_lxritag = NO_XRI;
+ ctiocb->sli4_xritag = NO_XRI;
+
+- if (fctl & FC_FC_EX_CTX)
++ if (fctl & FC_FC_EX_CTX) {
+ /* Exchange responder sent the abort so we
+ * own the oxid.
+ */
++ ctiocb->abort_bls = LPFC_ABTS_UNSOL_RSP;
+ xri = oxid;
+- else
++ } else {
++ ctiocb->abort_bls = LPFC_ABTS_UNSOL_INT;
+ xri = rxid;
++ }
+ lxri = lpfc_sli4_xri_inrange(phba, xri);
+ if (lxri != NO_XRI)
+ lpfc_set_rrq_active(phba, ndlp, lxri,
+diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
+index 968c83182643..06682ad8bbe1 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.h
++++ b/drivers/scsi/lpfc/lpfc_sli.h
+@@ -76,6 +76,8 @@ struct lpfc_iocbq {
+ struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
+
+ uint8_t num_bdes;
++ uint8_t abort_bls; /* ABTS by initiator or responder */
++
+ uint8_t priority; /* OAS priority */
+ uint8_t retry; /* retry counter for IOCB cmd - if needed */
+ u32 cmd_flag;
+--
+2.35.1
+
--- /dev/null
+From 34168a969ca406c4f18c1610d38d777788f268d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 18:22:52 -0800
+Subject: scsi: lpfc: SLI path split: Refactor lpfc_iocbq
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit a680a9298e7b4ff344aca3456177356b276e5038 ]
+
+Currently, SLI3 and SLI4 data paths use the same lpfc_iocbq structure.
+This is a "common" structure but many of the components refer to sli-rev
+specific entities which can lead the developer astray as to what they
+actually mean, should be set to, or when they should be used.
+
+This first patch prepares the lpfc_iocbq structure so that elements common
+to both SLI3 and SLI4 data paths are more appropriately named, making it
+clear they apply generically.
+
+Fieldnames based on 'iocb' (sli3) or 'wqe' (sli4) which are actually
+generic to the paths are renamed to 'cmd':
+
+ - iocb_flag is renamed to cmd_flag
+
+ - lpfc_vmid_iocb_tag is renamed to lpfc_vmid_tag
+
+ - fabric_iocb_cmpl is renamed to fabric_cmd_cmpl
+
+ - wait_iocb_cmpl is renamed to wait_cmd_cmpl
+
+ - iocb_cmpl and wqe_cmpl are combined and renamed to cmd_cmpl
+
+ - rsvd2 member is renamed to num_bdes due to pre-existing usage
+
+The structure name itself will retain the iocb reference as changing to a
+more relevant "job" or "cmd" title induces many hundreds of line changes
+for only a name change.
+
+lpfc_post_buffer is also renamed to lpfc_sli3_post_buffer to indicate use
+in the SLI3 path only.
+
+Link: https://lore.kernel.org/r/20220225022308.16486-2-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_bsg.c | 50 ++---
+ drivers/scsi/lpfc/lpfc_crtn.h | 2 +-
+ drivers/scsi/lpfc/lpfc_ct.c | 8 +-
+ drivers/scsi/lpfc/lpfc_els.c | 139 ++++++------
+ drivers/scsi/lpfc/lpfc_init.c | 11 +-
+ drivers/scsi/lpfc/lpfc_nportdisc.c | 4 +-
+ drivers/scsi/lpfc/lpfc_nvme.c | 34 +--
+ drivers/scsi/lpfc/lpfc_nvme.h | 6 +-
+ drivers/scsi/lpfc/lpfc_nvmet.c | 83 +++----
+ drivers/scsi/lpfc/lpfc_scsi.c | 75 +++----
+ drivers/scsi/lpfc/lpfc_sli.c | 340 ++++++++++++++---------------
+ drivers/scsi/lpfc/lpfc_sli.h | 24 +-
+ 12 files changed, 385 insertions(+), 391 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
+index fdf08cb57207..6688a575904f 100644
+--- a/drivers/scsi/lpfc/lpfc_bsg.c
++++ b/drivers/scsi/lpfc/lpfc_bsg.c
+@@ -325,7 +325,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
+
+ /* Close the timeout handler abort window */
+ spin_lock_irqsave(&phba->hbalock, flags);
+- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
+ iocb = &dd_data->context_un.iocb;
+@@ -481,11 +481,11 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
+ cmd->ulpOwner = OWN_CHIP;
+ cmdiocbq->vport = phba->pport;
+ cmdiocbq->context3 = bmp;
+- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
+ timeout = phba->fc_ratov * 2;
+ cmd->ulpTimeout = timeout;
+
+- cmdiocbq->iocb_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
++ cmdiocbq->cmd_cmpl = lpfc_bsg_send_mgmt_cmd_cmp;
+ cmdiocbq->context1 = dd_data;
+ cmdiocbq->context2 = cmp;
+ cmdiocbq->context3 = bmp;
+@@ -516,9 +516,9 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job)
+ if (iocb_stat == IOCB_SUCCESS) {
+ spin_lock_irqsave(&phba->hbalock, flags);
+ /* make sure the I/O had not been completed yet */
+- if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
++ if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) {
+ /* open up abort window to timeout handler */
+- cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
++ cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return 0; /* done for now */
+@@ -600,7 +600,7 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
+
+ /* Close the timeout handler abort window */
+ spin_lock_irqsave(&phba->hbalock, flags);
+- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
+ rsp = &rspiocbq->iocb;
+@@ -726,10 +726,10 @@ lpfc_bsg_rport_els(struct bsg_job *job)
+ cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi];
+ else
+ cmdiocbq->iocb.ulpContext = rpi;
+- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
+ cmdiocbq->context1 = dd_data;
+ cmdiocbq->context_un.ndlp = ndlp;
+- cmdiocbq->iocb_cmpl = lpfc_bsg_rport_els_cmp;
++ cmdiocbq->cmd_cmpl = lpfc_bsg_rport_els_cmp;
+ dd_data->type = TYPE_IOCB;
+ dd_data->set_job = job;
+ dd_data->context_un.iocb.cmdiocbq = cmdiocbq;
+@@ -757,9 +757,9 @@ lpfc_bsg_rport_els(struct bsg_job *job)
+ if (rc == IOCB_SUCCESS) {
+ spin_lock_irqsave(&phba->hbalock, flags);
+ /* make sure the I/O had not been completed/released */
+- if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
++ if (cmdiocbq->cmd_flag & LPFC_IO_LIBDFC) {
+ /* open up abort window to timeout handler */
+- cmdiocbq->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
++ cmdiocbq->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return 0; /* done for now */
+@@ -1053,7 +1053,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ lpfc_in_buf_free(phba,
+ dmabuf);
+ } else {
+- lpfc_post_buffer(phba,
++ lpfc_sli3_post_buffer(phba,
+ pring,
+ 1);
+ }
+@@ -1061,7 +1061,7 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ default:
+ if (!(phba->sli3_options &
+ LPFC_SLI3_HBQ_ENABLED))
+- lpfc_post_buffer(phba,
++ lpfc_sli3_post_buffer(phba,
+ pring,
+ 1);
+ break;
+@@ -1395,7 +1395,7 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
+
+ /* Close the timeout handler abort window */
+ spin_lock_irqsave(&phba->hbalock, flags);
+- cmdiocbq->iocb_flag &= ~LPFC_IO_CMD_OUTSTANDING;
++ cmdiocbq->cmd_flag &= ~LPFC_IO_CMD_OUTSTANDING;
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+
+ ndlp = dd_data->context_un.iocb.ndlp;
+@@ -1549,13 +1549,13 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
+ "2722 Xmit CT response on exchange x%x Data: x%x x%x x%x\n",
+ icmd->ulpContext, icmd->ulpIoTag, tag, phba->link_state);
+
+- ctiocb->iocb_flag |= LPFC_IO_LIBDFC;
++ ctiocb->cmd_flag |= LPFC_IO_LIBDFC;
+ ctiocb->vport = phba->pport;
+ ctiocb->context1 = dd_data;
+ ctiocb->context2 = cmp;
+ ctiocb->context3 = bmp;
+ ctiocb->context_un.ndlp = ndlp;
+- ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp;
++ ctiocb->cmd_cmpl = lpfc_issue_ct_rsp_cmp;
+
+ dd_data->type = TYPE_IOCB;
+ dd_data->set_job = job;
+@@ -1582,9 +1582,9 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag,
+ if (rc == IOCB_SUCCESS) {
+ spin_lock_irqsave(&phba->hbalock, flags);
+ /* make sure the I/O had not been completed/released */
+- if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) {
++ if (ctiocb->cmd_flag & LPFC_IO_LIBDFC) {
+ /* open up abort window to timeout handler */
+- ctiocb->iocb_flag |= LPFC_IO_CMD_OUTSTANDING;
++ ctiocb->cmd_flag |= LPFC_IO_CMD_OUTSTANDING;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return 0; /* done for now */
+@@ -2713,9 +2713,9 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi,
+ cmd->ulpClass = CLASS3;
+ cmd->ulpContext = rpi;
+
+- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
+ cmdiocbq->vport = phba->pport;
+- cmdiocbq->iocb_cmpl = NULL;
++ cmdiocbq->cmd_cmpl = NULL;
+
+ iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+ rspiocbq,
+@@ -3286,10 +3286,10 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
+ cmdiocbq->sli4_xritag = NO_XRI;
+ cmd->unsli3.rcvsli3.ox_id = 0xffff;
+ }
+- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
+- cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK;
++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
++ cmdiocbq->cmd_flag |= LPFC_IO_LOOPBACK;
+ cmdiocbq->vport = phba->pport;
+- cmdiocbq->iocb_cmpl = NULL;
++ cmdiocbq->cmd_cmpl = NULL;
+ iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq,
+ rspiocbq, (phba->fc_ratov * 2) +
+ LPFC_DRVR_TIMEOUT);
+@@ -5273,11 +5273,11 @@ lpfc_menlo_cmd(struct bsg_job *job)
+ cmd->ulpClass = CLASS3;
+ cmd->ulpOwner = OWN_CHIP;
+ cmd->ulpLe = 1; /* Limited Edition */
+- cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC;
++ cmdiocbq->cmd_flag |= LPFC_IO_LIBDFC;
+ cmdiocbq->vport = phba->pport;
+ /* We want the firmware to timeout before we do */
+ cmd->ulpTimeout = MENLO_TIMEOUT - 5;
+- cmdiocbq->iocb_cmpl = lpfc_bsg_menlo_cmd_cmp;
++ cmdiocbq->cmd_cmpl = lpfc_bsg_menlo_cmd_cmp;
+ cmdiocbq->context1 = dd_data;
+ cmdiocbq->context2 = cmp;
+ cmdiocbq->context3 = bmp;
+@@ -6001,7 +6001,7 @@ lpfc_bsg_timeout(struct bsg_job *job)
+
+ spin_lock_irqsave(&phba->hbalock, flags);
+ /* make sure the I/O abort window is still open */
+- if (!(cmdiocb->iocb_flag & LPFC_IO_CMD_OUTSTANDING)) {
++ if (!(cmdiocb->cmd_flag & LPFC_IO_CMD_OUTSTANDING)) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ return -EAGAIN;
+ }
+diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
+index c9770b1d2366..ed27a0afcb8b 100644
+--- a/drivers/scsi/lpfc/lpfc_crtn.h
++++ b/drivers/scsi/lpfc/lpfc_crtn.h
+@@ -210,7 +210,7 @@ int lpfc_config_port_post(struct lpfc_hba *);
+ int lpfc_hba_down_prep(struct lpfc_hba *);
+ int lpfc_hba_down_post(struct lpfc_hba *);
+ void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
+-int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int);
++int lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt);
+ void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
+ int lpfc_online(struct lpfc_hba *);
+ void lpfc_unblock_mgmt_io(struct lpfc_hba *);
+diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
+index dfcb7d4bd7fa..19e2f8086a6d 100644
+--- a/drivers/scsi/lpfc/lpfc_ct.c
++++ b/drivers/scsi/lpfc/lpfc_ct.c
+@@ -239,7 +239,7 @@ lpfc_ct_reject_event(struct lpfc_nodelist *ndlp,
+ cmdiocbq->context1 = lpfc_nlp_get(ndlp);
+ cmdiocbq->context2 = (uint8_t *)mp;
+ cmdiocbq->context3 = (uint8_t *)bmp;
+- cmdiocbq->iocb_cmpl = lpfc_ct_unsol_cmpl;
++ cmdiocbq->cmd_cmpl = lpfc_ct_unsol_cmpl;
+ icmd->ulpContext = rx_id; /* Xri / rx_id */
+ icmd->unsli3.rcvsli3.ox_id = ox_id;
+ icmd->un.ulpWord[3] =
+@@ -370,7 +370,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ /* Not enough posted buffers; Try posting more buffers */
+ phba->fc_stat.NoRcvBuf++;
+ if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+- lpfc_post_buffer(phba, pring, 2);
++ lpfc_sli3_post_buffer(phba, pring, 2);
+ return;
+ }
+
+@@ -447,7 +447,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
+ lpfc_in_buf_free(phba, mp);
+ }
+- lpfc_post_buffer(phba, pring, i);
++ lpfc_sli3_post_buffer(phba, pring, i);
+ }
+ list_del(&head);
+ }
+@@ -652,7 +652,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
+ "Data: x%x x%x\n",
+ ndlp->nlp_DID, icmd->ulpIoTag,
+ vport->port_state);
+- geniocb->iocb_cmpl = cmpl;
++ geniocb->cmd_cmpl = cmpl;
+ geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
+ geniocb->vport = vport;
+ geniocb->retry = retry;
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 5f44a0763f37..0d34a03164f5 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -192,23 +192,23 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
+ (elscmd == ELS_CMD_LOGO)))
+ switch (elscmd) {
+ case ELS_CMD_FLOGI:
+- elsiocb->iocb_flag |=
++ elsiocb->cmd_flag |=
+ ((LPFC_ELS_ID_FLOGI << LPFC_FIP_ELS_ID_SHIFT)
+ & LPFC_FIP_ELS_ID_MASK);
+ break;
+ case ELS_CMD_FDISC:
+- elsiocb->iocb_flag |=
++ elsiocb->cmd_flag |=
+ ((LPFC_ELS_ID_FDISC << LPFC_FIP_ELS_ID_SHIFT)
+ & LPFC_FIP_ELS_ID_MASK);
+ break;
+ case ELS_CMD_LOGO:
+- elsiocb->iocb_flag |=
++ elsiocb->cmd_flag |=
+ ((LPFC_ELS_ID_LOGO << LPFC_FIP_ELS_ID_SHIFT)
+ & LPFC_FIP_ELS_ID_MASK);
+ break;
+ }
+ else
+- elsiocb->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
++ elsiocb->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK;
+
+ icmd = &elsiocb->iocb;
+
+@@ -1252,10 +1252,10 @@ lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ "6445 ELS completes after LINK_DOWN: "
+ " Status %x/%x cmd x%x flg x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4], cmd,
+- cmdiocb->iocb_flag);
++ cmdiocb->cmd_flag);
+
+- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) {
+- cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC) {
++ cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC;
+ atomic_dec(&phba->fabric_iocb_count);
+ }
+ lpfc_els_free_iocb(phba, cmdiocb);
+@@ -1370,7 +1370,7 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ phba->fc_ratov = tmo;
+
+ phba->fc_stat.elsXmitFLOGI++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_flogi;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue FLOGI: opt:x%x",
+@@ -1463,7 +1463,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
+ if (ndlp && ndlp->nlp_DID == Fabric_DID) {
+ if ((phba->pport->fc_flag & FC_PT2PT) &&
+ !(phba->pport->fc_flag & FC_PT2PT_PLOGI))
+- iocb->fabric_iocb_cmpl =
++ iocb->fabric_cmd_cmpl =
+ lpfc_ignore_els_cmpl;
+ lpfc_sli_issue_abort_iotag(phba, pring, iocb,
+ NULL);
+@@ -2226,7 +2226,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
+ }
+
+ phba->fc_stat.elsXmitPLOGI++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_plogi;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue PLOGI: did:x%x refcnt %d",
+@@ -2478,7 +2478,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ /* For FCP support */
+ npr->prliType = PRLI_FCP_TYPE;
+ npr->initiatorFunc = 1;
+- elsiocb->iocb_flag |= LPFC_PRLI_FCP_REQ;
++ elsiocb->cmd_flag |= LPFC_PRLI_FCP_REQ;
+
+ /* Remove FCP type - processed. */
+ local_nlp_type &= ~NLP_FC4_FCP;
+@@ -2512,14 +2512,14 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+
+ npr_nvme->word1 = cpu_to_be32(npr_nvme->word1);
+ npr_nvme->word4 = cpu_to_be32(npr_nvme->word4);
+- elsiocb->iocb_flag |= LPFC_PRLI_NVME_REQ;
++ elsiocb->cmd_flag |= LPFC_PRLI_NVME_REQ;
+
+ /* Remove NVME type - processed. */
+ local_nlp_type &= ~NLP_FC4_NVME;
+ }
+
+ phba->fc_stat.elsXmitPRLI++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_prli;
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag |= NLP_PRLI_SND;
+
+@@ -2842,7 +2842,7 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ ap->DID = be32_to_cpu(vport->fc_myDID);
+
+ phba->fc_stat.elsXmitADISC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_adisc;
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag |= NLP_ADISC_SND;
+ spin_unlock_irq(&ndlp->lock);
+@@ -3065,7 +3065,7 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+
+ phba->fc_stat.elsXmitLOGO++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_logo;
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag |= NLP_LOGO_SND;
+ ndlp->nlp_flag &= ~NLP_ISSUE_LOGO;
+@@ -3417,7 +3417,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
+ ndlp->nlp_DID, 0, 0);
+
+ phba->fc_stat.elsXmitSCR++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -3514,7 +3514,7 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
+ event->portid.rscn_fid[2] = nportid & 0x000000FF;
+
+ phba->fc_stat.elsXmitRSCN++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -3613,7 +3613,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
+ ndlp->nlp_DID, 0, 0);
+
+ phba->fc_stat.elsXmitFARPR++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -3704,7 +3704,7 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
+ phba->cgn_reg_fpin);
+
+ phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -4154,7 +4154,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
+ ndlp->nlp_DID, phba->cgn_reg_signal,
+ phba->cgn_reg_fpin);
+
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -4968,12 +4968,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
+
+ /* context2 = cmd, context2->next = rsp, context3 = bpl */
+ if (elsiocb->context2) {
+- if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) {
++ if (elsiocb->cmd_flag & LPFC_DELAY_MEM_FREE) {
+ /* Firmware could still be in progress of DMAing
+ * payload, so don't free data buffer till after
+ * a hbeat.
+ */
+- elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE;
++ elsiocb->cmd_flag &= ~LPFC_DELAY_MEM_FREE;
+ buf_ptr = elsiocb->context2;
+ elsiocb->context2 = NULL;
+ if (buf_ptr) {
+@@ -5480,9 +5480,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
+ ndlp->nlp_flag & NLP_REG_LOGIN_SEND))
+ ndlp->nlp_flag &= ~NLP_LOGO_ACC;
+ spin_unlock_irq(&ndlp->lock);
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_logo_acc;
+ } else {
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ }
+
+ phba->fc_stat.elsXmitACC++;
+@@ -5577,7 +5577,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
+ ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
+
+ phba->fc_stat.elsXmitLSRJT++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -5657,7 +5657,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ "Issue EDC ACC: did:x%x flg:x%x refcnt %d",
+ ndlp->nlp_DID, ndlp->nlp_flag,
+ kref_read(&ndlp->kref));
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+
+ phba->fc_stat.elsXmitACC++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+@@ -5750,7 +5750,7 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
+ ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
+
+ phba->fc_stat.elsXmitACC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -5924,7 +5924,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
+ ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
+
+ phba->fc_stat.elsXmitACC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -6025,7 +6025,7 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
+ ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
+
+ phba->fc_stat.elsXmitACC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -6139,7 +6139,7 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data,
+ ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref));
+
+ phba->fc_stat.elsXmitACC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -6803,7 +6803,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
+ rdp_context->page_a0, vport);
+
+ rdp_res->length = cpu_to_be32(len - 8);
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+
+ /* Now that we know the true size of the payload, update the BPL */
+ bpl = (struct ulp_bde64 *)
+@@ -6844,7 +6844,7 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context,
+ stat->un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+
+ phba->fc_stat.elsXmitLSRJT++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+ lpfc_els_free_iocb(phba, elsiocb);
+@@ -7066,7 +7066,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ lcb_res->capability = lcb_context->capability;
+ lcb_res->lcb_frequency = lcb_context->frequency;
+ lcb_res->lcb_duration = lcb_context->duration;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitACC++;
+
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+@@ -7105,7 +7105,7 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ if (shdr_add_status == ADD_STATUS_OPERATION_ALREADY_ACTIVE)
+ stat->un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
+
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitLSRJT++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+@@ -8172,7 +8172,7 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitACC++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+@@ -8324,7 +8324,7 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi,
+ rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov);
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitACC++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+@@ -8401,7 +8401,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ "Issue RRQ: did:x%x",
+ did, rrq->xritag, rrq->rxid);
+ elsiocb->context_un.rrq = rrq;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rrq;
+
+ lpfc_nlp_get(ndlp);
+ elsiocb->context1 = ndlp;
+@@ -8507,7 +8507,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_rsp;
+ phba->fc_stat.elsXmitACC++;
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+@@ -8947,7 +8947,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
+ cmd = &piocb->iocb;
+
+- if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
++ if ((piocb->cmd_flag & LPFC_IO_LIBDFC) != 0 ||
+ piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
+ piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+ continue;
+@@ -9060,13 +9060,13 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+
+ /* First we need to issue aborts to outstanding cmds on txcmpl */
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
+- if (piocb->iocb_flag & LPFC_IO_LIBDFC)
++ if (piocb->cmd_flag & LPFC_IO_LIBDFC)
+ continue;
+
+ if (piocb->vport != vport)
+ continue;
+
+- if (piocb->iocb_flag & LPFC_DRIVER_ABORTED)
++ if (piocb->cmd_flag & LPFC_DRIVER_ABORTED)
+ continue;
+
+ /* On the ELS ring we can have ELS_REQUESTs or
+@@ -9084,7 +9084,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ * and avoid any retry logic.
+ */
+ if (phba->link_state == LPFC_LINK_DOWN)
+- piocb->iocb_cmpl = lpfc_cmpl_els_link_down;
++ piocb->cmd_cmpl = lpfc_cmpl_els_link_down;
+ }
+ if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR)
+ list_add_tail(&piocb->dlist, &abort_list);
+@@ -9119,9 +9119,8 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
+ cmd = &piocb->iocb;
+
+- if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
++ if (piocb->cmd_flag & LPFC_IO_LIBDFC)
+ continue;
+- }
+
+ /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
+ if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
+@@ -9766,7 +9765,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len;
+ cmd = *payload;
+ if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
+- lpfc_post_buffer(phba, pring, 1);
++ lpfc_sli3_post_buffer(phba, pring, 1);
+
+ did = icmd->un.rcvels.remoteID;
+ if (icmd->ulpStatus) {
+@@ -10239,7 +10238,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ phba->fc_stat.NoRcvBuf++;
+ /* Not enough posted buffers; Try posting more buffers */
+ if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
+- lpfc_post_buffer(phba, pring, 0);
++ lpfc_sli3_post_buffer(phba, pring, 0);
+ return;
+ }
+
+@@ -10875,7 +10874,7 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ lpfc_set_disctmo(vport);
+
+ phba->fc_stat.elsXmitFDISC++;
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_fdisc;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue FDISC: did:x%x",
+@@ -10999,7 +10998,7 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ "Issue LOGO npiv did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_npiv_logo;
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag |= NLP_LOGO_SND;
+ spin_unlock_irq(&ndlp->lock);
+@@ -11084,9 +11083,9 @@ lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (iocb) {
+- iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+- iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+- iocb->iocb_flag |= LPFC_IO_FABRIC;
++ iocb->fabric_cmd_cmpl = iocb->cmd_cmpl;
++ iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb;
++ iocb->cmd_flag |= LPFC_IO_FABRIC;
+
+ lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+ "Fabric sched1: ste:x%x",
+@@ -11095,13 +11094,13 @@ lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
+ ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0);
+
+ if (ret == IOCB_ERROR) {
+- iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+- iocb->fabric_iocb_cmpl = NULL;
+- iocb->iocb_flag &= ~LPFC_IO_FABRIC;
++ iocb->cmd_cmpl = iocb->fabric_cmd_cmpl;
++ iocb->fabric_cmd_cmpl = NULL;
++ iocb->cmd_flag &= ~LPFC_IO_FABRIC;
+ cmd = &iocb->iocb;
+ cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+ cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+- iocb->iocb_cmpl(phba, iocb, iocb);
++ iocb->cmd_cmpl(phba, iocb, iocb);
+
+ atomic_dec(&phba->fabric_iocb_count);
+ goto repeat;
+@@ -11157,8 +11156,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is the callback function that is put to the fabric iocb's
+- * callback function pointer (iocb->iocb_cmpl). The original iocb's callback
+- * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback
++ * callback function pointer (iocb->cmd_cmpl). The original iocb's callback
++ * function pointer has been stored in iocb->fabric_cmd_cmpl. This callback
+ * function first restores and invokes the original iocb's callback function
+ * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next
+ * fabric bound iocb from the driver internal fabric iocb list onto the wire.
+@@ -11169,7 +11168,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ {
+ struct ls_rjt stat;
+
+- BUG_ON((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC);
++ WARN_ON((cmdiocb->cmd_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC);
+
+ switch (rspiocb->iocb.ulpStatus) {
+ case IOSTAT_NPORT_RJT:
+@@ -11195,10 +11194,10 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+
+ BUG_ON(atomic_read(&phba->fabric_iocb_count) == 0);
+
+- cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
+- cmdiocb->fabric_iocb_cmpl = NULL;
+- cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
+- cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
++ cmdiocb->cmd_cmpl = cmdiocb->fabric_cmd_cmpl;
++ cmdiocb->fabric_cmd_cmpl = NULL;
++ cmdiocb->cmd_flag &= ~LPFC_IO_FABRIC;
++ cmdiocb->cmd_cmpl(phba, cmdiocb, rspiocb);
+
+ atomic_dec(&phba->fabric_iocb_count);
+ if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
+@@ -11249,9 +11248,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
+ atomic_inc(&phba->fabric_iocb_count);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (ready) {
+- iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
+- iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
+- iocb->iocb_flag |= LPFC_IO_FABRIC;
++ iocb->fabric_cmd_cmpl = iocb->cmd_cmpl;
++ iocb->cmd_cmpl = lpfc_cmpl_fabric_iocb;
++ iocb->cmd_flag |= LPFC_IO_FABRIC;
+
+ lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+ "Fabric sched2: ste:x%x",
+@@ -11260,9 +11259,9 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
+ ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocb, 0);
+
+ if (ret == IOCB_ERROR) {
+- iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
+- iocb->fabric_iocb_cmpl = NULL;
+- iocb->iocb_flag &= ~LPFC_IO_FABRIC;
++ iocb->cmd_cmpl = iocb->fabric_cmd_cmpl;
++ iocb->fabric_cmd_cmpl = NULL;
++ iocb->cmd_flag &= ~LPFC_IO_FABRIC;
+ atomic_dec(&phba->fabric_iocb_count);
+ }
+ } else {
+@@ -11655,7 +11654,7 @@ int lpfc_issue_els_qfpa(struct lpfc_vport *vport)
+ *((u32 *)(pcmd)) = ELS_CMD_QFPA;
+ pcmd += 4;
+
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_qfpa;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_qfpa;
+
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+@@ -11738,7 +11737,7 @@ lpfc_vmid_uvem(struct lpfc_vport *vport,
+ }
+ inst_desc->word6 = cpu_to_be32(inst_desc->word6);
+
+- elsiocb->iocb_cmpl = lpfc_cmpl_els_uvem;
++ elsiocb->cmd_cmpl = lpfc_cmpl_els_uvem;
+
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1) {
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index cda571393a5f..2aa729a10b50 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -982,7 +982,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
+ spin_lock_irq(&pring->ring_lock);
+ list_for_each_entry_safe(piocb, next_iocb,
+ &pring->txcmplq, list)
+- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ list_splice_init(&pring->txcmplq, &completions);
+ pring->txcmplq_cnt = 0;
+ spin_unlock_irq(&pring->ring_lock);
+@@ -2643,7 +2643,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
+ }
+
+ /**
+- * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring
++ * lpfc_sli3_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring
+ * @phba: pointer to lpfc hba data structure.
+ * @pring: pointer to a IOCB ring.
+ * @cnt: the number of IOCBs to be posted to the IOCB ring.
+@@ -2655,7 +2655,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
+ * The number of IOCBs NOT able to be posted to the IOCB ring.
+ **/
+ int
+-lpfc_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
++lpfc_sli3_post_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, int cnt)
+ {
+ IOCB_t *icmd;
+ struct lpfc_iocbq *iocb;
+@@ -2761,7 +2761,7 @@ lpfc_post_rcv_buf(struct lpfc_hba *phba)
+ struct lpfc_sli *psli = &phba->sli;
+
+ /* Ring 0, ELS / CT buffers */
+- lpfc_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0);
++ lpfc_sli3_post_buffer(phba, &psli->sli3_ring[LPFC_ELS_RING], LPFC_BUF_RING0);
+ /* Ring 2 - FCP no buffers needed */
+
+ return 0;
+@@ -4215,8 +4215,7 @@ lpfc_io_buf_replenish(struct lpfc_hba *phba, struct list_head *cbuf)
+ qp = &phba->sli4_hba.hdwq[idx];
+ lpfc_cmd->hdwq_no = idx;
+ lpfc_cmd->hdwq = qp;
+- lpfc_cmd->cur_iocbq.wqe_cmpl = NULL;
+- lpfc_cmd->cur_iocbq.iocb_cmpl = NULL;
++ lpfc_cmd->cur_iocbq.cmd_cmpl = NULL;
+ spin_lock(&qp->io_buf_list_put_lock);
+ list_add_tail(&lpfc_cmd->list,
+ &qp->lpfc_io_buf_list_put);
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index 2bd35a7424c2..e788610bc996 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -2139,9 +2139,9 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ npr = NULL;
+ nvpr = NULL;
+ temp_ptr = lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
+- if (cmdiocb->iocb_flag & LPFC_PRLI_FCP_REQ)
++ if (cmdiocb->cmd_flag & LPFC_PRLI_FCP_REQ)
+ npr = (PRLI *) temp_ptr;
+- else if (cmdiocb->iocb_flag & LPFC_PRLI_NVME_REQ)
++ else if (cmdiocb->cmd_flag & LPFC_PRLI_NVME_REQ)
+ nvpr = (struct lpfc_nvme_prli *) temp_ptr;
+
+ irsp = &rspiocb->iocb;
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 4e0c0b273e5f..c74b2187dbad 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -352,11 +352,12 @@ __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
+
+ static void
+ lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_vport *vport = cmdwqe->vport;
+ struct lpfc_nvme_lport *lport;
+ uint32_t status;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+
+ status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
+
+@@ -380,7 +381,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
+ struct lpfc_dmabuf *inp,
+ struct nvmefc_ls_req *pnvme_lsreq,
+ void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
+- struct lpfc_wcqe_complete *),
++ struct lpfc_iocbq *),
+ struct lpfc_nodelist *ndlp, uint32_t num_entry,
+ uint32_t tmo, uint8_t retry)
+ {
+@@ -401,7 +402,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
+ memset(wqe, 0, sizeof(union lpfc_wqe));
+
+ genwqe->context3 = (uint8_t *)bmp;
+- genwqe->iocb_flag |= LPFC_IO_NVME_LS;
++ genwqe->cmd_flag |= LPFC_IO_NVME_LS;
+
+ /* Save for completion so we can release these resources */
+ genwqe->context1 = lpfc_nlp_get(ndlp);
+@@ -432,7 +433,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
+ first_len = xmit_len;
+ }
+
+- genwqe->rsvd2 = num_entry;
++ genwqe->num_bdes = num_entry;
+ genwqe->hba_wqidx = 0;
+
+ /* Words 0 - 2 */
+@@ -483,8 +484,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
+
+
+ /* Issue GEN REQ WQE for NPORT <did> */
+- genwqe->wqe_cmpl = cmpl;
+- genwqe->iocb_cmpl = NULL;
++ genwqe->cmd_cmpl = cmpl;
+ genwqe->drvrTimeout = tmo + LPFC_DRVR_TIMEOUT;
+ genwqe->vport = vport;
+ genwqe->retry = retry;
+@@ -534,7 +534,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ struct nvmefc_ls_req *pnvme_lsreq,
+ void (*gen_req_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe))
++ struct lpfc_iocbq *rspwqe))
+ {
+ struct lpfc_dmabuf *bmp;
+ struct ulp_bde64 *bpl;
+@@ -722,7 +722,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ spin_lock(&pring->ring_lock);
+ list_for_each_entry_safe(wqe, next_wqe, &pring->txcmplq, list) {
+ if (wqe->context2 == pnvme_lsreq) {
+- wqe->iocb_flag |= LPFC_DRIVER_ABORTED;
++ wqe->cmd_flag |= LPFC_DRIVER_ABORTED;
+ foundit = true;
+ break;
+ }
+@@ -906,7 +906,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
+
+
+ /*
+- * lpfc_nvme_io_cmd_wqe_cmpl - Complete an NVME-over-FCP IO
++ * lpfc_nvme_io_cmd_cmpl - Complete an NVME-over-FCP IO
+ *
+ * Driver registers this routine as it io request handler. This
+ * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq
+@@ -917,11 +917,12 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
+ * TODO: What are the failure codes.
+ **/
+ static void
+-lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+- struct lpfc_wcqe_complete *wcqe)
++lpfc_nvme_io_cmd_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
++ struct lpfc_iocbq *pwqeOut)
+ {
+ struct lpfc_io_buf *lpfc_ncmd =
+ (struct lpfc_io_buf *)pwqeIn->context1;
++ struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl;
+ struct lpfc_vport *vport = pwqeIn->vport;
+ struct nvmefc_fcp_req *nCmd;
+ struct nvme_fc_ersp_iu *ep;
+@@ -1873,7 +1874,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
+ }
+
+ /* Don't abort IOs no longer on the pending queue. */
+- if (!(nvmereq_wqe->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
++ if (!(nvmereq_wqe->cmd_flag & LPFC_IO_ON_TXCMPLQ)) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6142 NVME IO req x%px not queued - skipping "
+ "abort req xri x%x\n",
+@@ -1887,7 +1888,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport,
+ nvmereq_wqe->hba_wqidx, pnvme_rport->port_id);
+
+ /* Outstanding abort is in progress */
+- if (nvmereq_wqe->iocb_flag & LPFC_DRIVER_ABORTED) {
++ if (nvmereq_wqe->cmd_flag & LPFC_DRIVER_ABORTED) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "6144 Outstanding NVME I/O Abort Request "
+ "still pending on nvme_fcreq x%px, "
+@@ -1982,8 +1983,8 @@ lpfc_get_nvme_buf(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ /* Setup key fields in buffer that may have been changed
+ * if other protocols used this buffer.
+ */
+- pwqeq->iocb_flag = LPFC_IO_NVME;
+- pwqeq->wqe_cmpl = lpfc_nvme_io_cmd_wqe_cmpl;
++ pwqeq->cmd_flag = LPFC_IO_NVME;
++ pwqeq->cmd_cmpl = lpfc_nvme_io_cmd_cmpl;
+ lpfc_ncmd->start_time = jiffies;
+ lpfc_ncmd->flags = 0;
+
+@@ -2749,6 +2750,7 @@ lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
+ bf_set(lpfc_wcqe_c_xb, wcqep, 1);
+
+- (pwqeIn->wqe_cmpl)(phba, pwqeIn, wcqep);
++ memcpy(&pwqeIn->wcqe_cmpl, wcqep, sizeof(*wcqep));
++ (pwqeIn->cmd_cmpl)(phba, pwqeIn, pwqeIn);
+ #endif
+ }
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
+index cc54ffb5c205..d7698977725e 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.h
++++ b/drivers/scsi/lpfc/lpfc_nvme.h
+@@ -234,7 +234,7 @@ int __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ struct nvmefc_ls_req *pnvme_lsreq,
+ void (*gen_req_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe));
++ struct lpfc_iocbq *rspwqe));
+ void __lpfc_nvme_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_vport *vport,
+ struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
+ int __lpfc_nvme_ls_abort(struct lpfc_vport *vport,
+@@ -248,6 +248,6 @@ int __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ struct nvmefc_ls_rsp *ls_rsp,
+ void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe));
++ struct lpfc_iocbq *rspwqe));
+ void __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba,
+- struct lpfc_iocbq *cmdwqe, struct lpfc_wcqe_complete *wcqe);
++ struct lpfc_iocbq *cmdwqe, struct lpfc_iocbq *rspwqe);
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index 6e3dd0b9bcfa..5188cc8e2413 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -285,7 +285,7 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba,
+ * transmission of an NVME LS response.
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. The function frees memory resources used for the command
+@@ -293,9 +293,10 @@ lpfc_nvmet_defer_release(struct lpfc_hba *phba,
+ **/
+ void
+ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_async_xchg_ctx *axchg = cmdwqe->context2;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+ struct nvmefc_ls_rsp *ls_rsp = &axchg->ls_rsp;
+ uint32_t status, result;
+
+@@ -331,7 +332,7 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for NVME LS commands
+@@ -340,10 +341,11 @@ __lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ **/
+ static void
+ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_nvmet_tgtport *tgtp;
+ uint32_t status, result;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+
+ if (!phba->targetport)
+ goto finish;
+@@ -365,7 +367,7 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ }
+
+ finish:
+- __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, wcqe);
++ __lpfc_nvme_xmt_ls_rsp_cmp(phba, cmdwqe, rspwqe);
+ }
+
+ /**
+@@ -707,7 +709,7 @@ lpfc_nvmet_ktime(struct lpfc_hba *phba,
+ * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for NVME FCP commands
+@@ -715,12 +717,13 @@ lpfc_nvmet_ktime(struct lpfc_hba *phba,
+ **/
+ static void
+ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_nvmet_tgtport *tgtp;
+ struct nvmefc_tgt_fcp_req *rsp;
+ struct lpfc_async_xchg_ctx *ctxp;
+ uint32_t status, result, op, start_clean, logerr;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ int id;
+ #endif
+@@ -817,7 +820,7 @@ lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ /* lpfc_nvmet_xmt_fcp_release() will recycle the context */
+ } else {
+ ctxp->entry_cnt++;
+- start_clean = offsetof(struct lpfc_iocbq, iocb_flag);
++ start_clean = offsetof(struct lpfc_iocbq, cmd_flag);
+ memset(((char *)cmdwqe) + start_clean, 0,
+ (sizeof(struct lpfc_iocbq) - start_clean));
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+@@ -862,7 +865,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ struct nvmefc_ls_rsp *ls_rsp,
+ void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
+ struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe))
++ struct lpfc_iocbq *rspwqe))
+ {
+ struct lpfc_hba *phba = axchg->phba;
+ struct hbq_dmabuf *nvmebuf = (struct hbq_dmabuf *)axchg->rqb_buffer;
+@@ -898,7 +901,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ }
+
+ /* Save numBdes for bpl2sgl */
+- nvmewqeq->rsvd2 = 1;
++ nvmewqeq->num_bdes = 1;
+ nvmewqeq->hba_wqidx = 0;
+ nvmewqeq->context3 = &dmabuf;
+ dmabuf.virt = &bpl;
+@@ -913,8 +916,7 @@ __lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
+ * be referenced after it returns back to this routine.
+ */
+
+- nvmewqeq->wqe_cmpl = xmt_ls_rsp_cmp;
+- nvmewqeq->iocb_cmpl = NULL;
++ nvmewqeq->cmd_cmpl = xmt_ls_rsp_cmp;
+ nvmewqeq->context2 = axchg;
+
+ lpfc_nvmeio_data(phba, "NVMEx LS RSP: xri x%x wqidx x%x len x%x\n",
+@@ -1072,10 +1074,9 @@ lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
+ goto aerr;
+ }
+
+- nvmewqeq->wqe_cmpl = lpfc_nvmet_xmt_fcp_op_cmp;
+- nvmewqeq->iocb_cmpl = NULL;
++ nvmewqeq->cmd_cmpl = lpfc_nvmet_xmt_fcp_op_cmp;
+ nvmewqeq->context2 = ctxp;
+- nvmewqeq->iocb_flag |= LPFC_IO_NVMET;
++ nvmewqeq->cmd_flag |= LPFC_IO_NVMET;
+ ctxp->wqeq->hba_wqidx = rsp->hwqid;
+
+ lpfc_nvmeio_data(phba, "NVMET FCP CMND: xri x%x op x%x len x%x\n",
+@@ -1275,7 +1276,7 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
+ * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request
+ * @phba: Pointer to HBA context object
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * This function is the completion handler for NVME LS requests.
+ * The function updates any states and statistics, then calls the
+@@ -1283,8 +1284,9 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
+ **/
+ static void
+ lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+ __lpfc_nvme_ls_req_cmp(phba, cmdwqe->vport, cmdwqe, wcqe);
+ }
+
+@@ -1581,7 +1583,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
+ "6406 Ran out of NVMET iocb/WQEs\n");
+ return -ENOMEM;
+ }
+- ctx_buf->iocbq->iocb_flag = LPFC_IO_NVMET;
++ ctx_buf->iocbq->cmd_flag = LPFC_IO_NVMET;
+ nvmewqe = ctx_buf->iocbq;
+ wqe = &nvmewqe->wqe;
+
+@@ -2027,8 +2029,10 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq,
+ list_del(&nvmewqeq->list);
+ spin_unlock_irqrestore(&pring->ring_lock,
+ iflags);
++ memcpy(&nvmewqeq->wcqe_cmpl, wcqep,
++ sizeof(*wcqep));
+ lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq,
+- wcqep);
++ nvmewqeq);
+ return;
+ }
+ continue;
+@@ -2036,7 +2040,8 @@ lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq,
+ /* Flush all IOs */
+ list_del(&nvmewqeq->list);
+ spin_unlock_irqrestore(&pring->ring_lock, iflags);
+- lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, wcqep);
++ memcpy(&nvmewqeq->wcqe_cmpl, wcqep, sizeof(*wcqep));
++ lpfc_nvmet_xmt_fcp_op_cmp(phba, nvmewqeq, nvmewqeq);
+ spin_lock_irqsave(&pring->ring_lock, iflags);
+ }
+ }
+@@ -2676,7 +2681,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
+ nvmewqe->retry = 1;
+ nvmewqe->vport = phba->pport;
+ nvmewqe->drvrTimeout = (phba->fc_ratov * 3) + LPFC_DRVR_TIMEOUT;
+- nvmewqe->iocb_flag |= LPFC_IO_NVME_LS;
++ nvmewqe->cmd_flag |= LPFC_IO_NVME_LS;
+
+ /* Xmit NVMET response to remote NPORT <did> */
+ lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
+@@ -3033,7 +3038,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
+ * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for NVME ABTS for FCP cmds
+@@ -3041,13 +3046,14 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
+ **/
+ static void
+ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_async_xchg_ctx *ctxp;
+ struct lpfc_nvmet_tgtport *tgtp;
+ uint32_t result;
+ unsigned long flags;
+ bool released = false;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+
+ ctxp = cmdwqe->context2;
+ result = wcqe->parameter;
+@@ -3102,7 +3108,7 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for NVME ABTS for FCP cmds
+@@ -3110,13 +3116,14 @@ lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ **/
+ static void
+ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_async_xchg_ctx *ctxp;
+ struct lpfc_nvmet_tgtport *tgtp;
+ unsigned long flags;
+ uint32_t result;
+ bool released = false;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+
+ ctxp = cmdwqe->context2;
+ result = wcqe->parameter;
+@@ -3183,7 +3190,7 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS
+ * @phba: Pointer to HBA context object.
+ * @cmdwqe: Pointer to driver command WQE object.
+- * @wcqe: Pointer to driver response CQE object.
++ * @rspwqe: Pointer to driver response WQE object.
+ *
+ * The function is called from SLI ring event handler with no
+ * lock held. This function is the completion handler for NVME ABTS for LS cmds
+@@ -3191,11 +3198,12 @@ lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+ **/
+ static void
+ lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *rspwqe)
+ {
+ struct lpfc_async_xchg_ctx *ctxp;
+ struct lpfc_nvmet_tgtport *tgtp;
+ uint32_t result;
++ struct lpfc_wcqe_complete *wcqe = &rspwqe->wcqe_cmpl;
+
+ ctxp = cmdwqe->context2;
+ result = wcqe->parameter;
+@@ -3319,7 +3327,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
+ abts_wqeq->context1 = ndlp;
+ abts_wqeq->context2 = ctxp;
+ abts_wqeq->context3 = NULL;
+- abts_wqeq->rsvd2 = 0;
++ abts_wqeq->num_bdes = 0;
+ /* hba_wqidx should already be setup from command we are aborting */
+ abts_wqeq->iocb.ulpCommand = CMD_XMIT_SEQUENCE64_CR;
+ abts_wqeq->iocb.ulpLe = 1;
+@@ -3448,7 +3456,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
+ }
+
+ /* Outstanding abort is in progress */
+- if (abts_wqeq->iocb_flag & LPFC_DRIVER_ABORTED) {
++ if (abts_wqeq->cmd_flag & LPFC_DRIVER_ABORTED) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ atomic_inc(&tgtp->xmt_abort_rsp_error);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+@@ -3463,15 +3471,14 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
+ }
+
+ /* Ready - mark outstanding as aborted by driver. */
+- abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED;
++ abts_wqeq->cmd_flag |= LPFC_DRIVER_ABORTED;
+
+ lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt);
+
+ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+ abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx;
+- abts_wqeq->wqe_cmpl = lpfc_nvmet_sol_fcp_abort_cmp;
+- abts_wqeq->iocb_cmpl = NULL;
+- abts_wqeq->iocb_flag |= LPFC_IO_NVME;
++ abts_wqeq->cmd_cmpl = lpfc_nvmet_sol_fcp_abort_cmp;
++ abts_wqeq->cmd_flag |= LPFC_IO_NVME;
+ abts_wqeq->context2 = ctxp;
+ abts_wqeq->vport = phba->pport;
+ if (!ctxp->hdwq)
+@@ -3528,9 +3535,8 @@ lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
+
+ spin_lock_irqsave(&phba->hbalock, flags);
+ abts_wqeq = ctxp->wqeq;
+- abts_wqeq->wqe_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp;
+- abts_wqeq->iocb_cmpl = NULL;
+- abts_wqeq->iocb_flag |= LPFC_IO_NVMET;
++ abts_wqeq->cmd_cmpl = lpfc_nvmet_unsol_fcp_abort_cmp;
++ abts_wqeq->cmd_flag |= LPFC_IO_NVMET;
+ if (!ctxp->hdwq)
+ ctxp->hdwq = &phba->sli4_hba.hdwq[abts_wqeq->hba_wqidx];
+
+@@ -3614,9 +3620,8 @@ lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
+ }
+
+ spin_lock_irqsave(&phba->hbalock, flags);
+- abts_wqeq->wqe_cmpl = lpfc_nvmet_xmt_ls_abort_cmp;
+- abts_wqeq->iocb_cmpl = NULL;
+- abts_wqeq->iocb_flag |= LPFC_IO_NVME_LS;
++ abts_wqeq->cmd_cmpl = lpfc_nvmet_xmt_ls_abort_cmp;
++ abts_wqeq->cmd_flag |= LPFC_IO_NVME_LS;
+ rc = lpfc_sli4_issue_wqe(phba, ctxp->hdwq, abts_wqeq);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+ if (rc == WQE_SUCCESS) {
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index ea93b7e07b7e..765849643aed 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -362,7 +362,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
+ kfree(psb);
+ break;
+ }
+- psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
++ psb->cur_iocbq.cmd_flag |= LPFC_IO_FCP;
+
+ psb->fcp_cmnd = psb->data;
+ psb->fcp_rsp = psb->data + sizeof(struct fcp_cmnd);
+@@ -468,7 +468,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
+ spin_lock(&qp->abts_io_buf_list_lock);
+ list_for_each_entry_safe(psb, next_psb,
+ &qp->lpfc_abts_io_buf_list, list) {
+- if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME)
++ if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME)
+ continue;
+
+ if (psb->rdata && psb->rdata->pnode &&
+@@ -524,7 +524,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ list_del_init(&psb->list);
+ psb->flags &= ~LPFC_SBUF_XBUSY;
+ psb->status = IOSTAT_SUCCESS;
+- if (psb->cur_iocbq.iocb_flag & LPFC_IO_NVME) {
++ if (psb->cur_iocbq.cmd_flag & LPFC_IO_NVME) {
+ qp->abts_nvme_io_bufs--;
+ spin_unlock(&qp->abts_io_buf_list_lock);
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+@@ -571,7 +571,7 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ * for command completion wake up the thread.
+ */
+ spin_lock_irqsave(&psb->buf_lock, iflag);
+- psb->cur_iocbq.iocb_flag &=
++ psb->cur_iocbq.cmd_flag &=
+ ~LPFC_DRIVER_ABORTED;
+ if (psb->waitq)
+ wake_up(psb->waitq);
+@@ -593,8 +593,8 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
+ for (i = 1; i <= phba->sli.last_iotag; i++) {
+ iocbq = phba->sli.iocbq_lookup[i];
+
+- if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
+- (iocbq->iocb_flag & LPFC_IO_LIBDFC))
++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) ||
++ (iocbq->cmd_flag & LPFC_IO_LIBDFC))
+ continue;
+ if (iocbq->sli4_xritag != xri)
+ continue;
+@@ -695,7 +695,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ /* Setup key fields in buffer that may have been changed
+ * if other protocols used this buffer.
+ */
+- lpfc_cmd->cur_iocbq.iocb_flag = LPFC_IO_FCP;
++ lpfc_cmd->cur_iocbq.cmd_flag = LPFC_IO_FCP;
+ lpfc_cmd->prot_seg_cnt = 0;
+ lpfc_cmd->seg_cnt = 0;
+ lpfc_cmd->timeout = 0;
+@@ -783,7 +783,7 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb)
+
+ spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag);
+ psb->pCmd = NULL;
+- psb->cur_iocbq.iocb_flag = LPFC_IO_FCP;
++ psb->cur_iocbq.cmd_flag = LPFC_IO_FCP;
+ list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put);
+ spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag);
+ }
+@@ -931,7 +931,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+ physaddr = sg_dma_address(sgel);
+ if (phba->sli_rev == 3 &&
+ !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
+- !(iocbq->iocb_flag & DSS_SECURITY_OP) &&
++ !(iocbq->cmd_flag & DSS_SECURITY_OP) &&
+ nseg <= LPFC_EXT_DATA_BDE_COUNT) {
+ data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+ data_bde->tus.f.bdeSize = sg_dma_len(sgel);
+@@ -959,7 +959,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+ */
+ if (phba->sli_rev == 3 &&
+ !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) &&
+- !(iocbq->iocb_flag & DSS_SECURITY_OP)) {
++ !(iocbq->cmd_flag & DSS_SECURITY_OP)) {
+ if (num_bde > LPFC_EXT_DATA_BDE_COUNT) {
+ /*
+ * The extended IOCB format can only fit 3 BDE or a BPL.
+@@ -3434,7 +3434,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+ */
+ if ((phba->cfg_fof) && ((struct lpfc_device_data *)
+ scsi_cmnd->device->hostdata)->oas_enabled) {
+- lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
++ lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
+ lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *)
+ scsi_cmnd->device->hostdata)->priority;
+
+@@ -3591,15 +3591,15 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
+ switch (scsi_get_prot_op(scsi_cmnd)) {
+ case SCSI_PROT_WRITE_STRIP:
+ case SCSI_PROT_READ_STRIP:
+- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_STRIP;
++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_STRIP;
+ break;
+ case SCSI_PROT_WRITE_INSERT:
+ case SCSI_PROT_READ_INSERT:
+- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_INSERT;
++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_INSERT;
+ break;
+ case SCSI_PROT_WRITE_PASS:
+ case SCSI_PROT_READ_PASS:
+- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_DIF_PASS;
++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_DIF_PASS;
+ break;
+ }
+
+@@ -3630,7 +3630,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
+ */
+ if ((phba->cfg_fof) && ((struct lpfc_device_data *)
+ scsi_cmnd->device->hostdata)->oas_enabled) {
+- lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
++ lpfc_cmd->cur_iocbq.cmd_flag |= (LPFC_IO_OAS | LPFC_IO_FOF);
+
+ /* Word 10 */
+ bf_set(wqe_oas, &wqe->generic.wqe_com, 1);
+@@ -3640,14 +3640,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
+ }
+
+ /* Word 7. DIF Flags */
+- if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_PASS)
++ if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_PASS)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU);
+- else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_STRIP)
++ else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_STRIP)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP);
+- else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_INSERT)
++ else if (lpfc_cmd->cur_iocbq.cmd_flag & LPFC_IO_DIF_INSERT)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
+
+- lpfc_cmd->cur_iocbq.iocb_flag &= ~(LPFC_IO_DIF_PASS |
++ lpfc_cmd->cur_iocbq.cmd_flag &= ~(LPFC_IO_DIF_PASS |
+ LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT);
+
+ return 0;
+@@ -4172,7 +4172,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
+ * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO
+ * @phba: The hba for which this call is being executed.
+ * @pwqeIn: The command WQE for the scsi cmnd.
+- * @wcqe: Pointer to driver response CQE object.
++ * @pwqeOut: Pointer to driver response WQE object.
+ *
+ * This routine assigns scsi command result by looking into response WQE
+ * status field appropriately. This routine handles QUEUE FULL condition as
+@@ -4180,10 +4180,11 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
+ **/
+ static void
+ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+- struct lpfc_wcqe_complete *wcqe)
++ struct lpfc_iocbq *pwqeOut)
+ {
+ struct lpfc_io_buf *lpfc_cmd =
+ (struct lpfc_io_buf *)pwqeIn->context1;
++ struct lpfc_wcqe_complete *wcqe = &pwqeOut->wcqe_cmpl;
+ struct lpfc_vport *vport = pwqeIn->vport;
+ struct lpfc_rport_data *rdata;
+ struct lpfc_nodelist *ndlp;
+@@ -4216,7 +4217,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ * This needs to be done outside buf_lock
+ */
+ spin_lock_irqsave(&phba->hbalock, iflags);
+- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY;
++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_EXCHANGE_BUSY;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ }
+
+@@ -4507,7 +4508,7 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ * wake up the thread.
+ */
+ spin_lock(&lpfc_cmd->buf_lock);
+- lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED;
++ lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED;
+ if (lpfc_cmd->waitq)
+ wake_up(lpfc_cmd->waitq);
+ spin_unlock(&lpfc_cmd->buf_lock);
+@@ -4567,7 +4568,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
+ /* pick up SLI4 exchange busy status from HBA */
+ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
+- if (pIocbOut->iocb_flag & LPFC_EXCHANGE_BUSY)
++ if (pIocbOut->cmd_flag & LPFC_EXCHANGE_BUSY)
+ lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
+
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+@@ -4776,7 +4777,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
+ * wake up the thread.
+ */
+ spin_lock(&lpfc_cmd->buf_lock);
+- lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED;
++ lpfc_cmd->cur_iocbq.cmd_flag &= ~LPFC_DRIVER_ABORTED;
+ if (lpfc_cmd->waitq)
+ wake_up(lpfc_cmd->waitq);
+ spin_unlock(&lpfc_cmd->buf_lock);
+@@ -4854,8 +4855,8 @@ static int lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport *vport,
+
+ piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
+ piocbq->context1 = lpfc_cmd;
+- if (!piocbq->iocb_cmpl)
+- piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl;
++ if (!piocbq->cmd_cmpl)
++ piocbq->cmd_cmpl = lpfc_scsi_cmd_iocb_cmpl;
+ piocbq->iocb.ulpTimeout = tmo;
+ piocbq->vport = vport;
+ return 0;
+@@ -4968,7 +4969,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
+ pwqeq->vport = vport;
+ pwqeq->context1 = lpfc_cmd;
+ pwqeq->hba_wqidx = lpfc_cmd->hdwq_no;
+- pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl;
++ pwqeq->cmd_cmpl = lpfc_fcp_io_cmd_wqe_cmpl;
+
+ return 0;
+ }
+@@ -5690,7 +5691,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ lpfc_cmd->pCmd = cmnd;
+ lpfc_cmd->rdata = rdata;
+ lpfc_cmd->ndlp = ndlp;
+- lpfc_cmd->cur_iocbq.iocb_cmpl = NULL;
++ lpfc_cmd->cur_iocbq.cmd_cmpl = NULL;
+ cmnd->host_scribble = (unsigned char *)lpfc_cmd;
+
+ err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
+@@ -5747,7 +5748,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ (union lpfc_vmid_io_tag *)
+ &lpfc_cmd->cur_iocbq.vmid_tag);
+ if (!err)
+- lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_IO_VMID;
++ lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID;
+ }
+ }
+
+@@ -5935,7 +5936,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ spin_lock(&pring_s4->ring_lock);
+ }
+ /* the command is in process of being cancelled */
+- if (!(iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
++ if (!(iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ)) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3169 SCSI Layer abort requested I/O has been "
+ "cancelled by LLD.\n");
+@@ -5958,7 +5959,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+ BUG_ON(iocb->context1 != lpfc_cmd);
+
+ /* abort issued in recovery is still in progress */
+- if (iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
++ if (iocb->cmd_flag & LPFC_DRIVER_ABORTED) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
+ "3389 SCSI Layer I/O Abort Request is pending\n");
+ if (phba->sli_rev == LPFC_SLI_REV4)
+@@ -5999,7 +6000,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
+
+ wait_for_cmpl:
+ /*
+- * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait
++ * cmd_flag is set to LPFC_DRIVER_ABORTED before we wait
+ * for abort to complete.
+ */
+ wait_event_timeout(waitq,
+@@ -6187,14 +6188,14 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+ return FAILED;
+ }
+- iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
++ iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ "0702 Issue %s to TGT %d LUN %llu "
+ "rpi x%x nlp_flag x%x Data: x%x x%x\n",
+ lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id,
+ pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag,
+- iocbq->iocb_flag);
++ iocbq->cmd_flag);
+
+ status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
+ iocbq, iocbqrsp, lpfc_cmd->timeout);
+@@ -6204,12 +6205,12 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR)
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0727 TMF %s to TGT %d LUN %llu "
+- "failed (%d, %d) iocb_flag x%x\n",
++ "failed (%d, %d) cmd_flag x%x\n",
+ lpfc_taskmgmt_name(task_mgmt_cmd),
+ tgt_id, lun_id,
+ iocbqrsp->iocb.ulpStatus,
+ iocbqrsp->iocb.un.ulpWord[4],
+- iocbq->iocb_flag);
++ iocbq->cmd_flag);
+ /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
+ if (status == IOCB_SUCCESS) {
+ if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index e905a246a2d6..413824fc9533 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -1254,21 +1254,21 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
+ struct lpfc_sli_ring *pring = NULL;
+ int found = 0;
+
+- if (piocbq->iocb_flag & LPFC_IO_NVME_LS)
++ if (piocbq->cmd_flag & LPFC_IO_NVME_LS)
+ pring = phba->sli4_hba.nvmels_wq->pring;
+ else
+ pring = lpfc_phba_elsring(phba);
+
+ lockdep_assert_held(&pring->ring_lock);
+
+- if (piocbq->iocb_flag & LPFC_IO_FCP) {
++ if (piocbq->cmd_flag & LPFC_IO_FCP) {
+ lpfc_cmd = (struct lpfc_io_buf *) piocbq->context1;
+ ndlp = lpfc_cmd->rdata->pnode;
+ } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) &&
+- !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) {
++ !(piocbq->cmd_flag & LPFC_IO_LIBDFC)) {
+ ndlp = piocbq->context_un.ndlp;
+- } else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) {
+- if (piocbq->iocb_flag & LPFC_IO_LOOPBACK)
++ } else if (piocbq->cmd_flag & LPFC_IO_LIBDFC) {
++ if (piocbq->cmd_flag & LPFC_IO_LOOPBACK)
+ ndlp = NULL;
+ else
+ ndlp = piocbq->context_un.ndlp;
+@@ -1391,7 +1391,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+
+
+ if (sglq) {
+- if (iocbq->iocb_flag & LPFC_IO_NVMET) {
++ if (iocbq->cmd_flag & LPFC_IO_NVMET) {
+ spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock,
+ iflag);
+ sglq->state = SGL_FREED;
+@@ -1403,7 +1403,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+ goto out;
+ }
+
+- if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
++ if ((iocbq->cmd_flag & LPFC_EXCHANGE_BUSY) &&
+ (!(unlikely(pci_channel_offline(phba->pcidev)))) &&
+ sglq->state != SGL_XRI_ABORTED) {
+ spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock,
+@@ -1440,7 +1440,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
+ memset((char *)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean);
+ iocbq->sli4_lxritag = NO_XRI;
+ iocbq->sli4_xritag = NO_XRI;
+- iocbq->iocb_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF |
++ iocbq->cmd_flag &= ~(LPFC_IO_NVME | LPFC_IO_NVMET | LPFC_IO_CMF |
+ LPFC_IO_NVME_LS);
+ list_add_tail(&iocbq->list, &phba->lpfc_iocb_list);
+ }
+@@ -1530,17 +1530,17 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
+
+ while (!list_empty(iocblist)) {
+ list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
+- if (piocb->wqe_cmpl) {
+- if (piocb->iocb_flag & LPFC_IO_NVME)
++ if (piocb->cmd_cmpl) {
++ if (piocb->cmd_flag & LPFC_IO_NVME)
+ lpfc_nvme_cancel_iocb(phba, piocb,
+ ulpstatus, ulpWord4);
+ else
+ lpfc_sli_release_iocbq(phba, piocb);
+
+- } else if (piocb->iocb_cmpl) {
++ } else if (piocb->cmd_cmpl) {
+ piocb->iocb.ulpStatus = ulpstatus;
+ piocb->iocb.un.ulpWord[4] = ulpWord4;
+- (piocb->iocb_cmpl) (phba, piocb, piocb);
++ (piocb->cmd_cmpl) (phba, piocb, piocb);
+ } else {
+ lpfc_sli_release_iocbq(phba, piocb);
+ }
+@@ -1732,7 +1732,7 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ BUG_ON(!piocb);
+
+ list_add_tail(&piocb->list, &pring->txcmplq);
+- piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ;
++ piocb->cmd_flag |= LPFC_IO_ON_TXCMPLQ;
+ pring->txcmplq_cnt++;
+
+ if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
+@@ -1773,7 +1773,7 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ * lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl
+ * @phba: Pointer to HBA context object.
+ * @cmdiocb: Pointer to driver command iocb object.
+- * @cmf_cmpl: Pointer to completed WCQE.
++ * @rspiocb: Pointer to driver response iocb object.
+ *
+ * This routine will inform the driver of any BW adjustments we need
+ * to make. These changes will be picked up during the next CMF
+@@ -1782,10 +1782,11 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
+ **/
+ static void
+ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+- struct lpfc_wcqe_complete *cmf_cmpl)
++ struct lpfc_iocbq *rspiocb)
+ {
+ union lpfc_wqe128 *wqe;
+ uint32_t status, info;
++ struct lpfc_wcqe_complete *wcqe = &rspiocb->wcqe_cmpl;
+ uint64_t bw, bwdif, slop;
+ uint64_t pcent, bwpcent;
+ int asig, afpin, sigcnt, fpincnt;
+@@ -1793,22 +1794,22 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ char *s;
+
+ /* First check for error */
+- status = bf_get(lpfc_wcqe_c_status, cmf_cmpl);
++ status = bf_get(lpfc_wcqe_c_status, wcqe);
+ if (status) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6211 CMF_SYNC_WQE Error "
+ "req_tag x%x status x%x hwstatus x%x "
+ "tdatap x%x parm x%x\n",
+- bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl),
+- bf_get(lpfc_wcqe_c_status, cmf_cmpl),
+- bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl),
+- cmf_cmpl->total_data_placed,
+- cmf_cmpl->parameter);
++ bf_get(lpfc_wcqe_c_request_tag, wcqe),
++ bf_get(lpfc_wcqe_c_status, wcqe),
++ bf_get(lpfc_wcqe_c_hw_status, wcqe),
++ wcqe->total_data_placed,
++ wcqe->parameter);
+ goto out;
+ }
+
+ /* Gather congestion information on a successful cmpl */
+- info = cmf_cmpl->parameter;
++ info = wcqe->parameter;
+ phba->cmf_active_info = info;
+
+ /* See if firmware info count is valid or has changed */
+@@ -1817,15 +1818,15 @@ lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ else
+ phba->cmf_info_per_interval = info;
+
+- tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl);
+- cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl);
++ tdp = bf_get(lpfc_wcqe_c_cmf_bw, wcqe);
++ cg = bf_get(lpfc_wcqe_c_cmf_cg, wcqe);
+
+ /* Get BW requirement from firmware */
+ bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE;
+ if (!bw) {
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+ "6212 CMF_SYNC_WQE x%x: NULL bw\n",
+- bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl));
++ bf_get(lpfc_wcqe_c_request_tag, wcqe));
+ goto out;
+ }
+
+@@ -1999,14 +2000,13 @@ lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
+ bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT);
+
+ sync_buf->vport = phba->pport;
+- sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl;
+- sync_buf->iocb_cmpl = NULL;
++ sync_buf->cmd_cmpl = lpfc_cmf_sync_cmpl;
+ sync_buf->context1 = NULL;
+ sync_buf->context2 = NULL;
+ sync_buf->context3 = NULL;
+ sync_buf->sli4_xritag = NO_XRI;
+
+- sync_buf->iocb_flag |= LPFC_IO_CMF;
++ sync_buf->cmd_flag |= LPFC_IO_CMF;
+ ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf);
+ if (ret_val)
+ lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+@@ -2173,7 +2173,7 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ /*
+ * Set up an iotag
+ */
+- nextiocb->iocb.ulpIoTag = (nextiocb->iocb_cmpl) ? nextiocb->iotag : 0;
++ nextiocb->iocb.ulpIoTag = (nextiocb->cmd_cmpl) ? nextiocb->iotag : 0;
+
+
+ if (pring->ringno == LPFC_ELS_RING) {
+@@ -2194,9 +2194,9 @@ lpfc_sli_submit_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ /*
+ * If there is no completion routine to call, we can release the
+ * IOCB buffer back right now. For IOCBs, like QUE_RING_BUF,
+- * that have no rsp ring completion, iocb_cmpl MUST be NULL.
++ * that have no rsp ring completion, cmd_cmpl MUST be NULL.
+ */
+- if (nextiocb->iocb_cmpl)
++ if (nextiocb->cmd_cmpl)
+ lpfc_sli_ringtxcmpl_put(phba, pring, nextiocb);
+ else
+ __lpfc_sli_release_iocbq(phba, nextiocb);
+@@ -3564,10 +3564,10 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba,
+
+ if (iotag != 0 && iotag <= phba->sli.last_iotag) {
+ cmd_iocb = phba->sli.iocbq_lookup[iotag];
+- if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
++ if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) {
+ /* remove from txcmpl queue list */
+ list_del_init(&cmd_iocb->list);
+- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
++ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ pring->txcmplq_cnt--;
+ spin_unlock_irqrestore(temp_lock, iflag);
+ return cmd_iocb;
+@@ -3611,10 +3611,10 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
+ spin_lock_irqsave(temp_lock, iflag);
+ if (iotag != 0 && iotag <= phba->sli.last_iotag) {
+ cmd_iocb = phba->sli.iocbq_lookup[iotag];
+- if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
++ if (cmd_iocb->cmd_flag & LPFC_IO_ON_TXCMPLQ) {
+ /* remove from txcmpl queue list */
+ list_del_init(&cmd_iocb->list);
+- cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
++ cmd_iocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ pring->txcmplq_cnt--;
+ spin_unlock_irqrestore(temp_lock, iflag);
+ return cmd_iocb;
+@@ -3624,9 +3624,9 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
+ spin_unlock_irqrestore(temp_lock, iflag);
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "0372 iotag x%x lookup error: max iotag (x%x) "
+- "iocb_flag x%x\n",
++ "cmd_flag x%x\n",
+ iotag, phba->sli.last_iotag,
+- cmd_iocb ? cmd_iocb->iocb_flag : 0xffff);
++ cmd_iocb ? cmd_iocb->cmd_flag : 0xffff);
+ return NULL;
+ }
+
+@@ -3657,7 +3657,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+
+ cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
+ if (cmdiocbp) {
+- if (cmdiocbp->iocb_cmpl) {
++ if (cmdiocbp->cmd_cmpl) {
+ /*
+ * If an ELS command failed send an event to mgmt
+ * application.
+@@ -3675,11 +3675,11 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ */
+ if (pring->ringno == LPFC_ELS_RING) {
+ if ((phba->sli_rev < LPFC_SLI_REV4) &&
+- (cmdiocbp->iocb_flag &
++ (cmdiocbp->cmd_flag &
+ LPFC_DRIVER_ABORTED)) {
+ spin_lock_irqsave(&phba->hbalock,
+ iflag);
+- cmdiocbp->iocb_flag &=
++ cmdiocbp->cmd_flag &=
+ ~LPFC_DRIVER_ABORTED;
+ spin_unlock_irqrestore(&phba->hbalock,
+ iflag);
+@@ -3694,12 +3694,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ */
+ spin_lock_irqsave(&phba->hbalock,
+ iflag);
+- saveq->iocb_flag |= LPFC_DELAY_MEM_FREE;
++ saveq->cmd_flag |= LPFC_DELAY_MEM_FREE;
+ spin_unlock_irqrestore(&phba->hbalock,
+ iflag);
+ }
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+- if (saveq->iocb_flag &
++ if (saveq->cmd_flag &
+ LPFC_EXCHANGE_BUSY) {
+ /* Set cmdiocb flag for the
+ * exchange busy so sgl (xri)
+@@ -3709,12 +3709,12 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ */
+ spin_lock_irqsave(
+ &phba->hbalock, iflag);
+- cmdiocbp->iocb_flag |=
++ cmdiocbp->cmd_flag |=
+ LPFC_EXCHANGE_BUSY;
+ spin_unlock_irqrestore(
+ &phba->hbalock, iflag);
+ }
+- if (cmdiocbp->iocb_flag &
++ if (cmdiocbp->cmd_flag &
+ LPFC_DRIVER_ABORTED) {
+ /*
+ * Clear LPFC_DRIVER_ABORTED
+@@ -3723,7 +3723,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ */
+ spin_lock_irqsave(
+ &phba->hbalock, iflag);
+- cmdiocbp->iocb_flag &=
++ cmdiocbp->cmd_flag &=
+ ~LPFC_DRIVER_ABORTED;
+ spin_unlock_irqrestore(
+ &phba->hbalock, iflag);
+@@ -3743,14 +3743,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ IOERR_SLI_ABORTED;
+ spin_lock_irqsave(
+ &phba->hbalock, iflag);
+- saveq->iocb_flag |=
++ saveq->cmd_flag |=
+ LPFC_DELAY_MEM_FREE;
+ spin_unlock_irqrestore(
+ &phba->hbalock, iflag);
+ }
+ }
+ }
+- (cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
++ (cmdiocbp->cmd_cmpl) (phba, cmdiocbp, saveq);
+ } else
+ lpfc_sli_release_iocbq(phba, cmdiocbp);
+ } else {
+@@ -3992,11 +3992,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba,
+ spin_lock_irqsave(&phba->hbalock, iflag);
+ if (unlikely(!cmdiocbq))
+ break;
+- if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED)
+- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED;
+- if (cmdiocbq->iocb_cmpl) {
++ if (cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED)
++ cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED;
++ if (cmdiocbq->cmd_cmpl) {
+ spin_unlock_irqrestore(&phba->hbalock, iflag);
+- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
++ (cmdiocbq->cmd_cmpl)(phba, cmdiocbq,
+ &rspiocbq);
+ spin_lock_irqsave(&phba->hbalock, iflag);
+ }
+@@ -4191,10 +4191,10 @@ lpfc_sli_sp_handle_rspiocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ }
+ if (cmdiocbp) {
+ /* Call the specified completion routine */
+- if (cmdiocbp->iocb_cmpl) {
++ if (cmdiocbp->cmd_cmpl) {
+ spin_unlock_irqrestore(&phba->hbalock,
+ iflag);
+- (cmdiocbp->iocb_cmpl)(phba, cmdiocbp,
++ (cmdiocbp->cmd_cmpl)(phba, cmdiocbp,
+ saveq);
+ spin_lock_irqsave(&phba->hbalock,
+ iflag);
+@@ -4573,7 +4573,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
+ list_splice_init(&pring->txq, &txq);
+ list_for_each_entry_safe(piocb, next_iocb,
+ &pring->txcmplq, list)
+- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ /* Retrieve everything on the txcmplq */
+ list_splice_init(&pring->txcmplq, &txcmplq);
+ pring->txq_cnt = 0;
+@@ -4599,7 +4599,7 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
+ list_splice_init(&pring->txq, &txq);
+ list_for_each_entry_safe(piocb, next_iocb,
+ &pring->txcmplq, list)
+- piocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
++ piocb->cmd_flag &= ~LPFC_IO_ON_TXCMPLQ;
+ /* Retrieve everything on the txcmplq */
+ list_splice_init(&pring->txcmplq, &txcmplq);
+ pring->txq_cnt = 0;
+@@ -10115,7 +10115,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
+
+ lockdep_assert_held(&phba->hbalock);
+
+- if (piocb->iocb_cmpl && (!piocb->vport) &&
++ if (piocb->cmd_cmpl && (!piocb->vport) &&
+ (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
+ (piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN)) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+@@ -10167,10 +10167,10 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number,
+ case CMD_QUE_RING_BUF64_CN:
+ /*
+ * For IOCBs, like QUE_RING_BUF, that have no rsp ring
+- * completion, iocb_cmpl MUST be 0.
++ * completion, cmd_cmpl MUST be 0.
+ */
+- if (piocb->iocb_cmpl)
+- piocb->iocb_cmpl = NULL;
++ if (piocb->cmd_cmpl)
++ piocb->cmd_cmpl = NULL;
+ fallthrough;
+ case CMD_CREATE_XRI_CR:
+ case CMD_CLOSE_XRI_CN:
+@@ -10361,9 +10361,9 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+
+ fip = phba->hba_flag & HBA_FIP_SUPPORT;
+ /* The fcp commands will set command type */
+- if (iocbq->iocb_flag & LPFC_IO_FCP)
++ if (iocbq->cmd_flag & LPFC_IO_FCP)
+ command_type = FCP_COMMAND;
+- else if (fip && (iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK))
++ else if (fip && (iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK))
+ command_type = ELS_COMMAND_FIP;
+ else
+ command_type = ELS_COMMAND_NON_FIP;
+@@ -10408,7 +10408,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+
+ switch (iocbq->iocb.ulpCommand) {
+ case CMD_ELS_REQUEST64_CR:
+- if (iocbq->iocb_flag & LPFC_IO_LIBDFC)
++ if (iocbq->cmd_flag & LPFC_IO_LIBDFC)
+ ndlp = iocbq->context_un.ndlp;
+ else
+ ndlp = (struct lpfc_nodelist *)iocbq->context1;
+@@ -10435,7 +10435,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ bf_set(wqe_pu, &wqe->els_req.wqe_com, 0);
+ /* CCP CCPE PV PRI in word10 were set in the memcpy */
+ if (command_type == ELS_COMMAND_FIP)
+- els_id = ((iocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK)
++ els_id = ((iocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK)
+ >> LPFC_FIP_ELS_ID_SHIFT);
+ pcmd = (uint32_t *) (((struct lpfc_dmabuf *)
+ iocbq->context2)->virt);
+@@ -10537,7 +10537,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ LPFC_WQE_LENLOC_WORD4);
+ bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, iocbq->iocb.ulpPU);
+ bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 1);
+- if (iocbq->iocb_flag & LPFC_IO_OAS) {
++ if (iocbq->cmd_flag & LPFC_IO_OAS) {
+ bf_set(wqe_oas, &wqe->fcp_iwrite.wqe_com, 1);
+ bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
+ if (iocbq->priority) {
+@@ -10601,7 +10601,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ LPFC_WQE_LENLOC_WORD4);
+ bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, iocbq->iocb.ulpPU);
+ bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 1);
+- if (iocbq->iocb_flag & LPFC_IO_OAS) {
++ if (iocbq->cmd_flag & LPFC_IO_OAS) {
+ bf_set(wqe_oas, &wqe->fcp_iread.wqe_com, 1);
+ bf_set(wqe_ccpe, &wqe->fcp_iread.wqe_com, 1);
+ if (iocbq->priority) {
+@@ -10664,7 +10664,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ LPFC_WQE_LENLOC_NONE);
+ bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com,
+ iocbq->iocb.ulpFCP2Rcvy);
+- if (iocbq->iocb_flag & LPFC_IO_OAS) {
++ if (iocbq->cmd_flag & LPFC_IO_OAS) {
+ bf_set(wqe_oas, &wqe->fcp_icmd.wqe_com, 1);
+ bf_set(wqe_ccpe, &wqe->fcp_icmd.wqe_com, 1);
+ if (iocbq->priority) {
+@@ -10798,7 +10798,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ abrt_iotag = iocbq->iocb.un.acxri.abortContextTag;
+ if (abrt_iotag != 0 && abrt_iotag <= phba->sli.last_iotag) {
+ abrtiocbq = phba->sli.iocbq_lookup[abrt_iotag];
+- fip = abrtiocbq->iocb_flag & LPFC_FIP_ELS_ID_MASK;
++ fip = abrtiocbq->cmd_flag & LPFC_FIP_ELS_ID_MASK;
+ } else
+ fip = 0;
+
+@@ -10907,13 +10907,13 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
+ return IOCB_ERROR;
+ }
+
+- if (iocbq->iocb_flag & LPFC_IO_DIF_PASS)
++ if (iocbq->cmd_flag & LPFC_IO_DIF_PASS)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU);
+- else if (iocbq->iocb_flag & LPFC_IO_DIF_STRIP)
++ else if (iocbq->cmd_flag & LPFC_IO_DIF_STRIP)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP);
+- else if (iocbq->iocb_flag & LPFC_IO_DIF_INSERT)
++ else if (iocbq->cmd_flag & LPFC_IO_DIF_INSERT)
+ bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT);
+- iocbq->iocb_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP |
++ iocbq->cmd_flag &= ~(LPFC_IO_DIF_PASS | LPFC_IO_DIF_STRIP |
+ LPFC_IO_DIF_INSERT);
+ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, xritag);
+ bf_set(wqe_reqtag, &wqe->generic.wqe_com, iocbq->iotag);
+@@ -11012,7 +11012,7 @@ __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ }
+
+ /* add the VMID tags as per switch response */
+- if (unlikely(piocb->iocb_flag & LPFC_IO_VMID)) {
++ if (unlikely(piocb->cmd_flag & LPFC_IO_VMID)) {
+ if (phba->pport->vmid_priority_tagging) {
+ bf_set(wqe_ccpe, &wqe->fcp_iwrite.wqe_com, 1);
+ bf_set(wqe_ccp, &wqe->fcp_iwrite.wqe_com,
+@@ -11051,8 +11051,8 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ struct lpfc_sli_ring *pring;
+
+ /* Get the WQ */
+- if ((piocb->iocb_flag & LPFC_IO_FCP) ||
+- (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
++ if ((piocb->cmd_flag & LPFC_IO_FCP) ||
++ (piocb->cmd_flag & LPFC_USE_FCPWQIDX)) {
+ wq = phba->sli4_hba.hdwq[piocb->hba_wqidx].io_wq;
+ } else {
+ wq = phba->sli4_hba.els_wq;
+@@ -11093,7 +11093,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
+ }
+ }
+ }
+- } else if (piocb->iocb_flag & LPFC_IO_FCP) {
++ } else if (piocb->cmd_flag & LPFC_IO_FCP) {
+ /* These IO's already have an XRI and a mapped sgl. */
+ sglq = NULL;
+ }
+@@ -11210,14 +11210,14 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
+ {
+ struct lpfc_io_buf *lpfc_cmd;
+
+- if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) {
++ if (piocb->cmd_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) {
+ if (unlikely(!phba->sli4_hba.hdwq))
+ return NULL;
+ /*
+ * for abort iocb hba_wqidx should already
+ * be setup based on what work queue we used.
+ */
+- if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
++ if (!(piocb->cmd_flag & LPFC_USE_FCPWQIDX)) {
+ lpfc_cmd = (struct lpfc_io_buf *)piocb->context1;
+ piocb->hba_wqidx = lpfc_cmd->hdwq_no;
+ }
+@@ -12359,14 +12359,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ icmd = &cmdiocb->iocb;
+ if (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
+ icmd->ulpCommand == CMD_CLOSE_XRI_CN ||
+- cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED)
++ cmdiocb->cmd_flag & LPFC_DRIVER_ABORTED)
+ return IOCB_ABORTING;
+
+ if (!pring) {
+- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
+- cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC)
++ cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl;
+ else
+- cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
++ cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl;
+ return retval;
+ }
+
+@@ -12376,10 +12376,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ */
+ if ((vport->load_flag & FC_UNLOADING) &&
+ pring->ringno == LPFC_ELS_RING) {
+- if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
+- cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
++ if (cmdiocb->cmd_flag & LPFC_IO_FABRIC)
++ cmdiocb->fabric_cmd_cmpl = lpfc_ignore_els_cmpl;
+ else
+- cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
++ cmdiocb->cmd_cmpl = lpfc_ignore_els_cmpl;
+ return retval;
+ }
+
+@@ -12391,7 +12391,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ /* This signals the response to set the correct status
+ * before calling the completion handler
+ */
+- cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
++ cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED;
+
+ iabt = &abtsiocbp->iocb;
+ iabt->un.acxri.abortType = ABORT_TYPE_ABTS;
+@@ -12412,10 +12412,10 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+
+ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+ abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx;
+- if (cmdiocb->iocb_flag & LPFC_IO_FCP)
+- abtsiocbp->iocb_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX);
+- if (cmdiocb->iocb_flag & LPFC_IO_FOF)
+- abtsiocbp->iocb_flag |= LPFC_IO_FOF;
++ if (cmdiocb->cmd_flag & LPFC_IO_FCP)
++ abtsiocbp->cmd_flag |= (LPFC_IO_FCP | LPFC_USE_FCPWQIDX);
++ if (cmdiocb->cmd_flag & LPFC_IO_FOF)
++ abtsiocbp->cmd_flag |= LPFC_IO_FOF;
+
+ if (phba->link_state < LPFC_LINK_UP ||
+ (phba->sli_rev == LPFC_SLI_REV4 &&
+@@ -12425,9 +12425,9 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ iabt->ulpCommand = CMD_ABORT_XRI_CN;
+
+ if (cmpl)
+- abtsiocbp->iocb_cmpl = cmpl;
++ abtsiocbp->cmd_cmpl = cmpl;
+ else
+- abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
++ abtsiocbp->cmd_cmpl = lpfc_sli_abort_els_cmpl;
+ abtsiocbp->vport = vport;
+
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+@@ -12454,7 +12454,7 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
+ abtsiocbp->iotag, retval);
+
+ if (retval) {
+- cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
++ cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED;
+ __lpfc_sli_release_iocbq(phba, abtsiocbp);
+ }
+
+@@ -12522,9 +12522,9 @@ lpfc_sli_validate_fcp_iocb_for_abort(struct lpfc_iocbq *iocbq,
+ * can't be premarked as driver aborted, nor be an ABORT iocb itself
+ */
+ icmd = &iocbq->iocb;
+- if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
+- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) ||
+- (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) ||
++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) ||
++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ) ||
++ (iocbq->cmd_flag & LPFC_DRIVER_ABORTED) ||
+ (icmd->ulpCommand == CMD_ABORT_XRI_CN ||
+ icmd->ulpCommand == CMD_CLOSE_XRI_CN))
+ return -EINVAL;
+@@ -12628,8 +12628,8 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id,
+
+ if (!iocbq || iocbq->vport != vport)
+ continue;
+- if (!(iocbq->iocb_flag & LPFC_IO_FCP) ||
+- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ))
++ if (!(iocbq->cmd_flag & LPFC_IO_FCP) ||
++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ))
+ continue;
+
+ /* Include counting outstanding aborts */
+@@ -12855,8 +12855,8 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
+ * If the iocbq is already being aborted, don't take a second
+ * action, but do count it.
+ */
+- if ((iocbq->iocb_flag & LPFC_DRIVER_ABORTED) ||
+- !(iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ)) {
++ if ((iocbq->cmd_flag & LPFC_DRIVER_ABORTED) ||
++ !(iocbq->cmd_flag & LPFC_IO_ON_TXCMPLQ)) {
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ spin_unlock(&pring_s4->ring_lock);
+ spin_unlock(&lpfc_cmd->buf_lock);
+@@ -12886,10 +12886,10 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
+
+ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+ abtsiocbq->hba_wqidx = iocbq->hba_wqidx;
+- if (iocbq->iocb_flag & LPFC_IO_FCP)
+- abtsiocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
+- if (iocbq->iocb_flag & LPFC_IO_FOF)
+- abtsiocbq->iocb_flag |= LPFC_IO_FOF;
++ if (iocbq->cmd_flag & LPFC_IO_FCP)
++ abtsiocbq->cmd_flag |= LPFC_USE_FCPWQIDX;
++ if (iocbq->cmd_flag & LPFC_IO_FOF)
++ abtsiocbq->cmd_flag |= LPFC_IO_FOF;
+
+ ndlp = lpfc_cmd->rdata->pnode;
+
+@@ -12900,13 +12900,13 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
+ abtsiocbq->iocb.ulpCommand = CMD_CLOSE_XRI_CN;
+
+ /* Setup callback routine and issue the command. */
+- abtsiocbq->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
++ abtsiocbq->cmd_cmpl = lpfc_sli_abort_fcp_cmpl;
+
+ /*
+ * Indicate the IO is being aborted by the driver and set
+ * the caller's flag into the aborted IO.
+ */
+- iocbq->iocb_flag |= LPFC_DRIVER_ABORTED;
++ iocbq->cmd_flag |= LPFC_DRIVER_ABORTED;
+
+ if (phba->sli_rev == LPFC_SLI_REV4) {
+ ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
+@@ -12955,7 +12955,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
+ struct lpfc_io_buf *lpfc_cmd;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+- if (cmdiocbq->iocb_flag & LPFC_IO_WAKE_TMO) {
++ if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) {
+
+ /*
+ * A time out has occurred for the iocb. If a time out
+@@ -12964,26 +12964,26 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
+ */
+
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+- cmdiocbq->iocb_cmpl = cmdiocbq->wait_iocb_cmpl;
+- cmdiocbq->wait_iocb_cmpl = NULL;
+- if (cmdiocbq->iocb_cmpl)
+- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, NULL);
++ cmdiocbq->cmd_cmpl = cmdiocbq->wait_cmd_cmpl;
++ cmdiocbq->wait_cmd_cmpl = NULL;
++ if (cmdiocbq->cmd_cmpl)
++ (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, NULL);
+ else
+ lpfc_sli_release_iocbq(phba, cmdiocbq);
+ return;
+ }
+
+- cmdiocbq->iocb_flag |= LPFC_IO_WAKE;
++ cmdiocbq->cmd_flag |= LPFC_IO_WAKE;
+ if (cmdiocbq->context2 && rspiocbq)
+ memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
+ &rspiocbq->iocb, sizeof(IOCB_t));
+
+ /* Set the exchange busy flag for task management commands */
+- if ((cmdiocbq->iocb_flag & LPFC_IO_FCP) &&
+- !(cmdiocbq->iocb_flag & LPFC_IO_LIBDFC)) {
++ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) &&
++ !(cmdiocbq->cmd_flag & LPFC_IO_LIBDFC)) {
+ lpfc_cmd = container_of(cmdiocbq, struct lpfc_io_buf,
+ cur_iocbq);
+- if (rspiocbq && (rspiocbq->iocb_flag & LPFC_EXCHANGE_BUSY))
++ if (rspiocbq && (rspiocbq->cmd_flag & LPFC_EXCHANGE_BUSY))
+ lpfc_cmd->flags |= LPFC_SBUF_XBUSY;
+ else
+ lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY;
+@@ -13002,7 +13002,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
+ * @piocbq: Pointer to command iocb.
+ * @flag: Flag to test.
+ *
+- * This routine grabs the hbalock and then test the iocb_flag to
++ * This routine grabs the hbalock and then test the cmd_flag to
+ * see if the passed in flag is set.
+ * Returns:
+ * 1 if flag is set.
+@@ -13016,7 +13016,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba,
+ int ret;
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+- ret = piocbq->iocb_flag & flag;
++ ret = piocbq->cmd_flag & flag;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return ret;
+
+@@ -13031,14 +13031,14 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba,
+ * @timeout: Timeout in number of seconds.
+ *
+ * This function issues the iocb to firmware and waits for the
+- * iocb to complete. The iocb_cmpl field of the shall be used
++ * iocb to complete. The cmd_cmpl field of the shall be used
+ * to handle iocbs which time out. If the field is NULL, the
+ * function shall free the iocbq structure. If more clean up is
+ * needed, the caller is expected to provide a completion function
+ * that will provide the needed clean up. If the iocb command is
+ * not completed within timeout seconds, the function will either
+- * free the iocbq structure (if iocb_cmpl == NULL) or execute the
+- * completion function set in the iocb_cmpl field and then return
++ * free the iocbq structure (if cmd_cmpl == NULL) or execute the
++ * completion function set in the cmd_cmpl field and then return
+ * a status of IOCB_TIMEDOUT. The caller should not free the iocb
+ * resources if this function returns IOCB_TIMEDOUT.
+ * The function waits for the iocb completion using an
+@@ -13050,7 +13050,7 @@ lpfc_chk_iocb_flg(struct lpfc_hba *phba,
+ * This function assumes that the iocb completions occur while
+ * this function sleep. So, this function cannot be called from
+ * the thread which process iocb completion for this ring.
+- * This function clears the iocb_flag of the iocb object before
++ * This function clears the cmd_flag of the iocb object before
+ * issuing the iocb and the iocb completion handler sets this
+ * flag and wakes this thread when the iocb completes.
+ * The contents of the response iocb will be copied to prspiocbq
+@@ -13090,10 +13090,10 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+ piocb->context2 = prspiocbq;
+ }
+
+- piocb->wait_iocb_cmpl = piocb->iocb_cmpl;
+- piocb->iocb_cmpl = lpfc_sli_wake_iocb_wait;
++ piocb->wait_cmd_cmpl = piocb->cmd_cmpl;
++ piocb->cmd_cmpl = lpfc_sli_wake_iocb_wait;
+ piocb->context_un.wait_queue = &done_q;
+- piocb->iocb_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO);
++ piocb->cmd_flag &= ~(LPFC_IO_WAKE | LPFC_IO_WAKE_TMO);
+
+ if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
+ if (lpfc_readl(phba->HCregaddr, &creg_val))
+@@ -13111,7 +13111,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+ lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE),
+ timeout_req);
+ spin_lock_irqsave(&phba->hbalock, iflags);
+- if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
++ if (!(piocb->cmd_flag & LPFC_IO_WAKE)) {
+
+ /*
+ * IOCB timed out. Inform the wake iocb wait
+@@ -13119,7 +13119,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+ */
+
+ iocb_completed = false;
+- piocb->iocb_flag |= LPFC_IO_WAKE_TMO;
++ piocb->cmd_flag |= LPFC_IO_WAKE_TMO;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (iocb_completed) {
+@@ -13174,7 +13174,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
+ piocb->context2 = NULL;
+
+ piocb->context_un.wait_queue = NULL;
+- piocb->iocb_cmpl = NULL;
++ piocb->cmd_cmpl = NULL;
+ return retval;
+ }
+
+@@ -14143,7 +14143,7 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
+ /* Map WCQE parameters into irspiocb parameters */
+ status = bf_get(lpfc_wcqe_c_status, wcqe);
+ pIocbIn->iocb.ulpStatus = (status & LPFC_IOCB_STATUS_MASK);
+- if (pIocbOut->iocb_flag & LPFC_IO_FCP)
++ if (pIocbOut->cmd_flag & LPFC_IO_FCP)
+ if (pIocbIn->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
+ pIocbIn->iocb.un.fcpi.fcpi_parm =
+ pIocbOut->iocb.un.fcpi.fcpi_parm -
+@@ -14225,7 +14225,7 @@ lpfc_sli4_iocb_param_transfer(struct lpfc_hba *phba,
+ /* Pick up HBA exchange busy condition */
+ if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
+ spin_lock_irqsave(&phba->hbalock, iflags);
+- pIocbIn->iocb_flag |= LPFC_EXCHANGE_BUSY;
++ pIocbIn->cmd_flag |= LPFC_EXCHANGE_BUSY;
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ }
+ }
+@@ -15076,7 +15076,6 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
+ {
+ struct lpfc_sli_ring *pring = cq->pring;
+ struct lpfc_iocbq *cmdiocbq;
+- struct lpfc_iocbq irspiocbq;
+ unsigned long iflags;
+
+ /* Check for response status */
+@@ -15115,39 +15114,31 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ cmdiocbq->isr_timestamp = cq->isr_timestamp;
+ #endif
+- if (cmdiocbq->iocb_cmpl == NULL) {
+- if (cmdiocbq->wqe_cmpl) {
+- /* For FCP the flag is cleared in wqe_cmpl */
+- if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) &&
+- cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
+- spin_lock_irqsave(&phba->hbalock, iflags);
+- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED;
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+- }
++ if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
++ spin_lock_irqsave(&phba->hbalock, iflags);
++ cmdiocbq->cmd_flag |= LPFC_EXCHANGE_BUSY;
++ spin_unlock_irqrestore(&phba->hbalock, iflags);
++ }
+
+- /* Pass the cmd_iocb and the wcqe to the upper layer */
+- (cmdiocbq->wqe_cmpl)(phba, cmdiocbq, wcqe);
+- return;
++ if (cmdiocbq->cmd_cmpl) {
++ /* For FCP the flag is cleared in cmd_cmpl */
++ if (!(cmdiocbq->cmd_flag & LPFC_IO_FCP) &&
++ cmdiocbq->cmd_flag & LPFC_DRIVER_ABORTED) {
++ spin_lock_irqsave(&phba->hbalock, iflags);
++ cmdiocbq->cmd_flag &= ~LPFC_DRIVER_ABORTED;
++ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ }
++
++ /* Pass the cmd_iocb and the wcqe to the upper layer */
++ memcpy(&cmdiocbq->wcqe_cmpl, wcqe,
++ sizeof(struct lpfc_wcqe_complete));
++ (cmdiocbq->cmd_cmpl)(phba, cmdiocbq, cmdiocbq);
++ } else {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+ "0375 FCP cmdiocb not callback function "
+ "iotag: (%d)\n",
+ bf_get(lpfc_wcqe_c_request_tag, wcqe));
+- return;
+- }
+-
+- /* Only SLI4 non-IO commands stil use IOCB */
+- /* Fake the irspiocb and copy necessary response information */
+- lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe);
+-
+- if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) {
+- spin_lock_irqsave(&phba->hbalock, iflags);
+- cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED;
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ }
+-
+- /* Pass the cmd_iocb and the rsp state to the upper layer */
+- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq, &irspiocbq);
+ }
+
+ /**
+@@ -18969,7 +18960,7 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport,
+ }
+
+ ctiocb->vport = phba->pport;
+- ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl;
++ ctiocb->cmd_cmpl = lpfc_sli4_seq_abort_rsp_cmpl;
+ ctiocb->sli4_lxritag = NO_XRI;
+ ctiocb->sli4_xritag = NO_XRI;
+
+@@ -19372,8 +19363,8 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+
+ iocbq->context2 = pcmd;
+ iocbq->vport = vport;
+- iocbq->iocb_flag &= ~LPFC_FIP_ELS_ID_MASK;
+- iocbq->iocb_flag |= LPFC_USE_FCPWQIDX;
++ iocbq->cmd_flag &= ~LPFC_FIP_ELS_ID_MASK;
++ iocbq->cmd_flag |= LPFC_USE_FCPWQIDX;
+
+ /*
+ * Setup rest of the iocb as though it were a WQE
+@@ -19391,7 +19382,7 @@ lpfc_sli4_handle_mds_loopback(struct lpfc_vport *vport,
+
+ iocbq->iocb.ulpCommand = CMD_SEND_FRAME;
+ iocbq->iocb.ulpLe = 1;
+- iocbq->iocb_cmpl = lpfc_sli4_mds_loopback_cmpl;
++ iocbq->cmd_cmpl = lpfc_sli4_mds_loopback_cmpl;
+ rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, iocbq, 0);
+ if (rc == IOCB_ERROR)
+ goto exit;
+@@ -21233,7 +21224,7 @@ lpfc_wqe_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeq,
+ cmd = bf_get(wqe_cmnd, &wqe->generic.wqe_com);
+ if (cmd == CMD_XMIT_BLS_RSP64_WQE)
+ return sglq->sli4_xritag;
+- numBdes = pwqeq->rsvd2;
++ numBdes = pwqeq->num_bdes;
+ if (numBdes) {
+ /* The addrHigh and addrLow fields within the WQE
+ * have not been byteswapped yet so there is no
+@@ -21334,7 +21325,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
+ uint32_t ret = 0;
+
+ /* NVME_LS and NVME_LS ABTS requests. */
+- if (pwqe->iocb_flag & LPFC_IO_NVME_LS) {
++ if (pwqe->cmd_flag & LPFC_IO_NVME_LS) {
+ pring = phba->sli4_hba.nvmels_wq->pring;
+ lpfc_qp_spin_lock_irqsave(&pring->ring_lock, iflags,
+ qp, wq_access);
+@@ -21365,7 +21356,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
+ }
+
+ /* NVME_FCREQ and NVME_ABTS requests */
+- if (pwqe->iocb_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) {
++ if (pwqe->cmd_flag & (LPFC_IO_NVME | LPFC_IO_FCP | LPFC_IO_CMF)) {
+ /* Get the IO distribution (hba_wqidx) for WQ assignment. */
+ wq = qp->io_wq;
+ pring = wq->pring;
+@@ -21387,7 +21378,7 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp,
+ }
+
+ /* NVMET requests */
+- if (pwqe->iocb_flag & LPFC_IO_NVMET) {
++ if (pwqe->cmd_flag & LPFC_IO_NVMET) {
+ /* Get the IO distribution (hba_wqidx) for WQ assignment. */
+ wq = qp->io_wq;
+ pring = wq->pring;
+@@ -21453,7 +21444,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ return WQE_NORESOURCE;
+
+ /* Indicate the IO is being aborted by the driver. */
+- cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
++ cmdiocb->cmd_flag |= LPFC_DRIVER_ABORTED;
+
+ abtswqe = &abtsiocb->wqe;
+ memset(abtswqe, 0, sizeof(*abtswqe));
+@@ -21472,15 +21463,15 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+
+ /* ABTS WQE must go to the same WQ as the WQE to be aborted */
+ abtsiocb->hba_wqidx = cmdiocb->hba_wqidx;
+- abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX;
+- if (cmdiocb->iocb_flag & LPFC_IO_FCP)
+- abtsiocb->iocb_flag |= LPFC_IO_FCP;
+- if (cmdiocb->iocb_flag & LPFC_IO_NVME)
+- abtsiocb->iocb_flag |= LPFC_IO_NVME;
+- if (cmdiocb->iocb_flag & LPFC_IO_FOF)
+- abtsiocb->iocb_flag |= LPFC_IO_FOF;
++ abtsiocb->cmd_flag |= LPFC_USE_FCPWQIDX;
++ if (cmdiocb->cmd_flag & LPFC_IO_FCP)
++ abtsiocb->cmd_flag |= LPFC_IO_FCP;
++ if (cmdiocb->cmd_flag & LPFC_IO_NVME)
++ abtsiocb->cmd_flag |= LPFC_IO_NVME;
++ if (cmdiocb->cmd_flag & LPFC_IO_FOF)
++ abtsiocb->cmd_flag |= LPFC_IO_FOF;
+ abtsiocb->vport = vport;
+- abtsiocb->wqe_cmpl = cmpl;
++ abtsiocb->cmd_cmpl = cmpl;
+
+ lpfc_cmd = container_of(cmdiocb, struct lpfc_io_buf, cur_iocbq);
+ retval = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, abtsiocb);
+@@ -21491,7 +21482,7 @@ lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+ xritag, cmdiocb->iotag, abtsiocb->iotag, retval);
+
+ if (retval) {
+- cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED;
++ cmdiocb->cmd_flag &= ~LPFC_DRIVER_ABORTED;
+ __lpfc_sli_release_iocbq(phba, abtsiocb);
+ }
+
+@@ -21853,8 +21844,7 @@ void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd,
+
+ /* MUST zero fields if buffer is reused by another protocol */
+ lpfc_ncmd->nvmeCmd = NULL;
+- lpfc_ncmd->cur_iocbq.wqe_cmpl = NULL;
+- lpfc_ncmd->cur_iocbq.iocb_cmpl = NULL;
++ lpfc_ncmd->cur_iocbq.cmd_cmpl = NULL;
+
+ if (phba->cfg_xpsgl && !phba->nvmet_support &&
+ !list_empty(&lpfc_ncmd->dma_sgl_xtra_list))
+diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
+index 5161ccacea3e..968c83182643 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.h
++++ b/drivers/scsi/lpfc/lpfc_sli.h
+@@ -35,7 +35,7 @@ typedef enum _lpfc_ctx_cmd {
+ LPFC_CTX_HOST
+ } lpfc_ctx_cmd;
+
+-union lpfc_vmid_iocb_tag {
++union lpfc_vmid_tag {
+ uint32_t app_id;
+ uint8_t cs_ctl_vmid;
+ struct lpfc_vmid_context *vmid_context; /* UVEM context information */
+@@ -69,16 +69,16 @@ struct lpfc_iocbq {
+ uint16_t sli4_xritag; /* pre-assigned XRI, (OXID) tag. */
+ uint16_t hba_wqidx; /* index to HBA work queue */
+ struct lpfc_cq_event cq_event;
+- struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
+ uint64_t isr_timestamp;
+
+ union lpfc_wqe128 wqe; /* SLI-4 */
+ IOCB_t iocb; /* SLI-3 */
++ struct lpfc_wcqe_complete wcqe_cmpl; /* WQE cmpl */
+
+- uint8_t rsvd2;
++ uint8_t num_bdes;
+ uint8_t priority; /* OAS priority */
+ uint8_t retry; /* retry counter for IOCB cmd - if needed */
+- uint32_t iocb_flag;
++ u32 cmd_flag;
+ #define LPFC_IO_LIBDFC 1 /* libdfc iocb */
+ #define LPFC_IO_WAKE 2 /* Synchronous I/O completed */
+ #define LPFC_IO_WAKE_TMO LPFC_IO_WAKE /* Synchronous I/O timed out */
+@@ -123,15 +123,13 @@ struct lpfc_iocbq {
+ struct lpfc_node_rrq *rrq;
+ } context_un;
+
+- union lpfc_vmid_iocb_tag vmid_tag;
+- void (*fabric_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
+- struct lpfc_iocbq *);
+- void (*wait_iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
+- struct lpfc_iocbq *);
+- void (*iocb_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
+- struct lpfc_iocbq *);
+- void (*wqe_cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
+- struct lpfc_wcqe_complete *);
++ union lpfc_vmid_tag vmid_tag;
++ void (*fabric_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
++ struct lpfc_iocbq *rsp);
++ void (*wait_cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
++ struct lpfc_iocbq *rsp);
++ void (*cmd_cmpl)(struct lpfc_hba *phba, struct lpfc_iocbq *cmd,
++ struct lpfc_iocbq *rsp);
+ };
+
+ #define SLI_IOCB_RET_IOCB 1 /* Return IOCB if cmd ring full */
+--
+2.35.1
+
--- /dev/null
+From 96a3e1903dcbece9c658a09376f9b5e602dbf44b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Feb 2022 18:23:04 -0800
+Subject: scsi: lpfc: SLI path split: Refactor SCSI paths
+
+From: James Smart <jsmart2021@gmail.com>
+
+[ Upstream commit 3512ac0942938d6977e7999ee69765d948d2faf1 ]
+
+This patch refactors the SCSI paths to use SLI-4 as the primary interface.
+
+ - Conversion away from using SLI-3 iocb structures to set/access fields in
+ common routines. Use the new generic get/set routines that were added.
+ This move changes code from indirect structure references to using local
+ variables with the generic routines.
+
+ - Refactor routines when setting non-generic fields, to have both SLI3 and
+ SLI4 specific sections. This replaces the set-as-SLI3 then translate to
+ SLI4 behavior of the past.
+
+Link: https://lore.kernel.org/r/20220225022308.16486-14-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc.h | 4 +
+ drivers/scsi/lpfc/lpfc_scsi.c | 374 +++++++++++++++-------------------
+ drivers/scsi/lpfc/lpfc_sli.c | 6 +-
+ 3 files changed, 174 insertions(+), 210 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 266d980667b8..f3bcb56e9ef2 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -920,6 +920,10 @@ struct lpfc_hba {
+ (struct lpfc_vport *vport,
+ struct lpfc_io_buf *lpfc_cmd,
+ uint8_t tmo);
++ int (*lpfc_scsi_prep_task_mgmt_cmd)
++ (struct lpfc_vport *vport,
++ struct lpfc_io_buf *lpfc_cmd,
++ u64 lun, u8 task_mgmt_cmd);
+
+ /* IOCB interface function jump table entries */
+ int (*__lpfc_sli_issue_iocb)
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index 765849643aed..b43dfcb81185 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -2942,154 +2942,58 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
+ * -1 - Internal error (bad profile, ...etc)
+ */
+ static int
+-lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
+- struct lpfc_wcqe_complete *wcqe)
++lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
++ struct lpfc_iocbq *pIocbOut)
+ {
+ struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
++ struct sli3_bg_fields *bgf;
+ int ret = 0;
+- u32 status = bf_get(lpfc_wcqe_c_status, wcqe);
++ struct lpfc_wcqe_complete *wcqe;
++ u32 status;
+ u32 bghm = 0;
+ u32 bgstat = 0;
+ u64 failing_sector = 0;
+
+- if (status == CQE_STATUS_DI_ERROR) {
+- if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */
+- bgstat |= BGS_GUARD_ERR_MASK;
+- if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */
+- bgstat |= BGS_APPTAG_ERR_MASK;
+- if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */
+- bgstat |= BGS_REFTAG_ERR_MASK;
+-
+- /* Check to see if there was any good data before the error */
+- if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
+- bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK;
+- bghm = wcqe->total_data_placed;
+- }
+-
+- /*
+- * Set ALL the error bits to indicate we don't know what
+- * type of error it is.
+- */
+- if (!bgstat)
+- bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK |
+- BGS_GUARD_ERR_MASK);
+- }
+-
+- if (lpfc_bgs_get_guard_err(bgstat)) {
+- ret = 1;
+-
+- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
+- set_host_byte(cmd, DID_ABORT);
+- phba->bg_guard_err_cnt++;
+- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+- "9059 BLKGRD: Guard Tag error in cmd"
+- " 0x%x lba 0x%llx blk cnt 0x%x "
+- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+- (unsigned long long)scsi_get_lba(cmd),
+- scsi_logical_block_count(cmd), bgstat, bghm);
+- }
+-
+- if (lpfc_bgs_get_reftag_err(bgstat)) {
+- ret = 1;
+-
+- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
+- set_host_byte(cmd, DID_ABORT);
+-
+- phba->bg_reftag_err_cnt++;
+- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+- "9060 BLKGRD: Ref Tag error in cmd"
+- " 0x%x lba 0x%llx blk cnt 0x%x "
+- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+- (unsigned long long)scsi_get_lba(cmd),
+- scsi_logical_block_count(cmd), bgstat, bghm);
+- }
++ if (phba->sli_rev == LPFC_SLI_REV4) {
++ wcqe = &pIocbOut->wcqe_cmpl;
++ status = bf_get(lpfc_wcqe_c_status, wcqe);
+
+- if (lpfc_bgs_get_apptag_err(bgstat)) {
+- ret = 1;
++ if (status == CQE_STATUS_DI_ERROR) {
++ /* Guard Check failed */
++ if (bf_get(lpfc_wcqe_c_bg_ge, wcqe))
++ bgstat |= BGS_GUARD_ERR_MASK;
+
+- scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
+- set_host_byte(cmd, DID_ABORT);
++ /* AppTag Check failed */
++ if (bf_get(lpfc_wcqe_c_bg_ae, wcqe))
++ bgstat |= BGS_APPTAG_ERR_MASK;
+
+- phba->bg_apptag_err_cnt++;
+- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+- "9062 BLKGRD: App Tag error in cmd"
+- " 0x%x lba 0x%llx blk cnt 0x%x "
+- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+- (unsigned long long)scsi_get_lba(cmd),
+- scsi_logical_block_count(cmd), bgstat, bghm);
+- }
++ /* RefTag Check failed */
++ if (bf_get(lpfc_wcqe_c_bg_re, wcqe))
++ bgstat |= BGS_REFTAG_ERR_MASK;
+
+- if (lpfc_bgs_get_hi_water_mark_present(bgstat)) {
+- /*
+- * setup sense data descriptor 0 per SPC-4 as an information
+- * field, and put the failing LBA in it.
+- * This code assumes there was also a guard/app/ref tag error
+- * indication.
+- */
+- cmd->sense_buffer[7] = 0xc; /* Additional sense length */
+- cmd->sense_buffer[8] = 0; /* Information descriptor type */
+- cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */
+- cmd->sense_buffer[10] = 0x80; /* Validity bit */
++ /* Check to see if there was any good data before the
++ * error
++ */
++ if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) {
++ bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK;
++ bghm = wcqe->total_data_placed;
++ }
+
+- /* bghm is a "on the wire" FC frame based count */
+- switch (scsi_get_prot_op(cmd)) {
+- case SCSI_PROT_READ_INSERT:
+- case SCSI_PROT_WRITE_STRIP:
+- bghm /= cmd->device->sector_size;
+- break;
+- case SCSI_PROT_READ_STRIP:
+- case SCSI_PROT_WRITE_INSERT:
+- case SCSI_PROT_READ_PASS:
+- case SCSI_PROT_WRITE_PASS:
+- bghm /= (cmd->device->sector_size +
+- sizeof(struct scsi_dif_tuple));
+- break;
++ /*
++ * Set ALL the error bits to indicate we don't know what
++ * type of error it is.
++ */
++ if (!bgstat)
++ bgstat |= (BGS_REFTAG_ERR_MASK |
++ BGS_APPTAG_ERR_MASK |
++ BGS_GUARD_ERR_MASK);
+ }
+
+- failing_sector = scsi_get_lba(cmd);
+- failing_sector += bghm;
+-
+- /* Descriptor Information */
+- put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]);
+- }
+-
+- if (!ret) {
+- /* No error was reported - problem in FW? */
+- lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+- "9068 BLKGRD: Unknown error in cmd"
+- " 0x%x lba 0x%llx blk cnt 0x%x "
+- "bgstat=x%x bghm=x%x\n", cmd->cmnd[0],
+- (unsigned long long)scsi_get_lba(cmd),
+- scsi_logical_block_count(cmd), bgstat, bghm);
+-
+- /* Calculate what type of error it was */
+- lpfc_calc_bg_err(phba, lpfc_cmd);
++ } else {
++ bgf = &pIocbOut->iocb.unsli3.sli3_bg;
++ bghm = bgf->bghm;
++ bgstat = bgf->bgstat;
+ }
+- return ret;
+-}
+-
+-/*
+- * This function checks for BlockGuard errors detected by
+- * the HBA. In case of errors, the ASC/ASCQ fields in the
+- * sense buffer will be set accordingly, paired with
+- * ILLEGAL_REQUEST to signal to the kernel that the HBA
+- * detected corruption.
+- *
+- * Returns:
+- * 0 - No error found
+- * 1 - BlockGuard error found
+- * -1 - Internal error (bad profile, ...etc)
+- */
+-static int
+-lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
+- struct lpfc_iocbq *pIocbOut)
+-{
+- struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
+- struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg;
+- int ret = 0;
+- uint32_t bghm = bgf->bghm;
+- uint32_t bgstat = bgf->bgstat;
+- uint64_t failing_sector = 0;
+
+ if (lpfc_bgs_get_invalid_prof(bgstat)) {
+ cmd->result = DID_ERROR << 16;
+@@ -3117,7 +3021,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
+
+ if (lpfc_bgs_get_guard_err(bgstat)) {
+ ret = 1;
+-
+ scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x1);
+ set_host_byte(cmd, DID_ABORT);
+ phba->bg_guard_err_cnt++;
+@@ -3131,10 +3034,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
+
+ if (lpfc_bgs_get_reftag_err(bgstat)) {
+ ret = 1;
+-
+ scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x3);
+ set_host_byte(cmd, DID_ABORT);
+-
+ phba->bg_reftag_err_cnt++;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9056 BLKGRD: Ref Tag error in cmd "
+@@ -3146,10 +3047,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd,
+
+ if (lpfc_bgs_get_apptag_err(bgstat)) {
+ ret = 1;
+-
+ scsi_build_sense(cmd, 1, ILLEGAL_REQUEST, 0x10, 0x2);
+ set_host_byte(cmd, DID_ABORT);
+-
+ phba->bg_apptag_err_cnt++;
+ lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG,
+ "9061 BLKGRD: App Tag error in cmd "
+@@ -4194,7 +4093,6 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ struct Scsi_Host *shost;
+ u32 logit = LOG_FCP;
+ u32 status, idx;
+- unsigned long iflags = 0;
+ u32 lat;
+ u8 wait_xb_clr = 0;
+
+@@ -4209,30 +4107,16 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ rdata = lpfc_cmd->rdata;
+ ndlp = rdata->pnode;
+
+- if (bf_get(lpfc_wcqe_c_xb, wcqe)) {
+- /* TOREMOVE - currently this flag is checked during
+- * the release of lpfc_iocbq. Remove once we move
+- * to lpfc_wqe_job construct.
+- *
+- * This needs to be done outside buf_lock
+- */
+- spin_lock_irqsave(&phba->hbalock, iflags);
+- lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_EXCHANGE_BUSY;
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+- }
+-
+- /* Guard against abort handler being called at same time */
+- spin_lock(&lpfc_cmd->buf_lock);
+-
+ /* Sanity check on return of outstanding command */
+ cmd = lpfc_cmd->pCmd;
+ if (!cmd) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "9042 I/O completion: Not an active IO\n");
+- spin_unlock(&lpfc_cmd->buf_lock);
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+ return;
+ }
++ /* Guard against abort handler being called at same time */
++ spin_lock(&lpfc_cmd->buf_lock);
+ idx = lpfc_cmd->cur_iocbq.hba_wqidx;
+ if (phba->sli4_hba.hdwq)
+ phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++;
+@@ -4406,12 +4290,14 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
+ * This is a response for a BG enabled
+ * cmd. Parse BG error
+ */
+- lpfc_sli4_parse_bg_err(phba, lpfc_cmd,
+- wcqe);
++ lpfc_parse_bg_err(phba, lpfc_cmd, pwqeOut);
+ break;
++ } else {
++ lpfc_printf_vlog(vport, KERN_WARNING,
++ LOG_BG,
++ "9040 non-zero BGSTAT "
++ "on unprotected cmd\n");
+ }
+- lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG,
+- "9040 non-zero BGSTAT on unprotected cmd\n");
+ }
+ lpfc_printf_vlog(vport, KERN_WARNING, logit,
+ "9036 Local Reject FCP cmd x%x failed"
+@@ -5016,7 +4902,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
+ }
+
+ /**
+- * lpfc_scsi_prep_task_mgmt_cmd - Convert SLI3 scsi TM cmd to FCP info unit
++ * lpfc_scsi_prep_task_mgmt_cmd_s3 - Convert SLI3 scsi TM cmd to FCP info unit
+ * @vport: The virtual port for which this call is being executed.
+ * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
+ * @lun: Logical unit number.
+@@ -5030,10 +4916,9 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
+ * 1 - Success
+ **/
+ static int
+-lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
+- struct lpfc_io_buf *lpfc_cmd,
+- uint64_t lun,
+- uint8_t task_mgmt_cmd)
++lpfc_scsi_prep_task_mgmt_cmd_s3(struct lpfc_vport *vport,
++ struct lpfc_io_buf *lpfc_cmd,
++ u64 lun, u8 task_mgmt_cmd)
+ {
+ struct lpfc_iocbq *piocbq;
+ IOCB_t *piocb;
+@@ -5054,15 +4939,10 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
+ memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+ int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
+ fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
+- if (vport->phba->sli_rev == 3 &&
+- !(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED))
++ if (!(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED))
+ lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd);
+ piocb->ulpCommand = CMD_FCP_ICMND64_CR;
+ piocb->ulpContext = ndlp->nlp_rpi;
+- if (vport->phba->sli_rev == LPFC_SLI_REV4) {
+- piocb->ulpContext =
+- vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
+- }
+ piocb->ulpFCP2Rcvy = (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0;
+ piocb->ulpClass = (ndlp->nlp_fcp_info & 0x0f);
+ piocb->ulpPU = 0;
+@@ -5078,8 +4958,79 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport,
+ } else
+ piocb->ulpTimeout = lpfc_cmd->timeout;
+
+- if (vport->phba->sli_rev == LPFC_SLI_REV4)
+- lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
++ return 1;
++}
++
++/**
++ * lpfc_scsi_prep_task_mgmt_cmd_s4 - Convert SLI4 scsi TM cmd to FCP info unit
++ * @vport: The virtual port for which this call is being executed.
++ * @lpfc_cmd: Pointer to lpfc_io_buf data structure.
++ * @lun: Logical unit number.
++ * @task_mgmt_cmd: SCSI task management command.
++ *
++ * This routine creates FCP information unit corresponding to @task_mgmt_cmd
++ * for device with SLI-4 interface spec.
++ *
++ * Return codes:
++ * 0 - Error
++ * 1 - Success
++ **/
++static int
++lpfc_scsi_prep_task_mgmt_cmd_s4(struct lpfc_vport *vport,
++ struct lpfc_io_buf *lpfc_cmd,
++ u64 lun, u8 task_mgmt_cmd)
++{
++ struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq;
++ union lpfc_wqe128 *wqe = &pwqeq->wqe;
++ struct fcp_cmnd *fcp_cmnd;
++ struct lpfc_rport_data *rdata = lpfc_cmd->rdata;
++ struct lpfc_nodelist *ndlp = rdata->pnode;
++
++ if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE)
++ return 0;
++
++ pwqeq->vport = vport;
++ /* Initialize 64 bytes only */
++ memset(wqe, 0, sizeof(union lpfc_wqe128));
++
++ /* From the icmnd template, initialize words 4 - 11 */
++ memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
++ sizeof(uint32_t) * 8);
++
++ fcp_cmnd = lpfc_cmd->fcp_cmnd;
++ /* Clear out any old data in the FCP command area */
++ memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
++ int_to_scsilun(lun, &fcp_cmnd->fcp_lun);
++ fcp_cmnd->fcpCntl3 = 0;
++ fcp_cmnd->fcpCntl2 = task_mgmt_cmd;
++
++ bf_set(payload_offset_len, &wqe->fcp_icmd,
++ sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
++ bf_set(cmd_buff_len, &wqe->fcp_icmd, 0);
++ bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, /* ulpContext */
++ vport->phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]);
++ bf_set(wqe_erp, &wqe->fcp_icmd.wqe_com,
++ ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) ? 1 : 0));
++ bf_set(wqe_class, &wqe->fcp_icmd.wqe_com,
++ (ndlp->nlp_fcp_info & 0x0f));
++
++ /* ulpTimeout is only one byte */
++ if (lpfc_cmd->timeout > 0xff) {
++ /*
++ * Do not timeout the command at the firmware level.
++ * The driver will provide the timeout mechanism.
++ */
++ bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, 0);
++ } else {
++ bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, lpfc_cmd->timeout);
++ }
++
++ lpfc_prep_embed_io(vport->phba, lpfc_cmd);
++ bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag);
++ wqe->generic.wqe_com.abort_tag = pwqeq->iotag;
++ bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag);
++
++ lpfc_sli4_set_rsp_sgl_last(vport->phba, lpfc_cmd);
+
+ return 1;
+ }
+@@ -5106,6 +5057,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
+ phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3;
+ phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3;
+ phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3;
++ phba->lpfc_scsi_prep_task_mgmt_cmd =
++ lpfc_scsi_prep_task_mgmt_cmd_s3;
+ break;
+ case LPFC_PCI_DEV_OC:
+ phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4;
+@@ -5113,6 +5066,8 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
+ phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4;
+ phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4;
+ phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4;
++ phba->lpfc_scsi_prep_task_mgmt_cmd =
++ lpfc_scsi_prep_task_mgmt_cmd_s4;
+ break;
+ default:
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+@@ -5591,6 +5546,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ {
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
++ struct lpfc_iocbq *cur_iocbq = NULL;
+ struct lpfc_rport_data *rdata;
+ struct lpfc_nodelist *ndlp;
+ struct lpfc_io_buf *lpfc_cmd;
+@@ -5684,6 +5640,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ }
+ lpfc_cmd->rx_cmd_start = start;
+
++ cur_iocbq = &lpfc_cmd->cur_iocbq;
+ /*
+ * Store the midlayer's command structure for the completion phase
+ * and complete the command initialization.
+@@ -5691,7 +5648,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ lpfc_cmd->pCmd = cmnd;
+ lpfc_cmd->rdata = rdata;
+ lpfc_cmd->ndlp = ndlp;
+- lpfc_cmd->cur_iocbq.cmd_cmpl = NULL;
++ cur_iocbq->cmd_cmpl = NULL;
+ cmnd->host_scribble = (unsigned char *)lpfc_cmd;
+
+ err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
+@@ -5733,7 +5690,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ goto out_host_busy_free_buf;
+ }
+
+-
+ /* check the necessary and sufficient condition to support VMID */
+ if (lpfc_is_vmid_enabled(phba) &&
+ (ndlp->vmid_support ||
+@@ -5746,20 +5702,19 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ if (uuid) {
+ err = lpfc_vmid_get_appid(vport, uuid, cmnd,
+ (union lpfc_vmid_io_tag *)
+- &lpfc_cmd->cur_iocbq.vmid_tag);
++ &cur_iocbq->vmid_tag);
+ if (!err)
+- lpfc_cmd->cur_iocbq.cmd_flag |= LPFC_IO_VMID;
++ cur_iocbq->cmd_flag |= LPFC_IO_VMID;
+ }
+ }
+-
+ atomic_inc(&ndlp->cmd_pending);
++
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO))
+ this_cpu_inc(phba->sli4_hba.c_stat->xmt_io);
+ #endif
+ /* Issue I/O to adapter */
+- err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING,
+- &lpfc_cmd->cur_iocbq,
++ err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, cur_iocbq,
+ SLI_IOCB_RET_IOCB);
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+ if (start) {
+@@ -5772,25 +5727,25 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
+ #endif
+ if (err) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+- "3376 FCP could not issue IOCB err %x "
+- "FCP cmd x%x <%d/%llu> "
+- "sid: x%x did: x%x oxid: x%x "
+- "Data: x%x x%x x%x x%x\n",
+- err, cmnd->cmnd[0],
+- cmnd->device ? cmnd->device->id : 0xffff,
+- cmnd->device ? cmnd->device->lun : (u64)-1,
+- vport->fc_myDID, ndlp->nlp_DID,
+- phba->sli_rev == LPFC_SLI_REV4 ?
+- lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff,
+- phba->sli_rev == LPFC_SLI_REV4 ?
+- phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] :
+- lpfc_cmd->cur_iocbq.iocb.ulpContext,
+- lpfc_cmd->cur_iocbq.iotag,
+- phba->sli_rev == LPFC_SLI_REV4 ?
+- bf_get(wqe_tmo,
+- &lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) :
+- lpfc_cmd->cur_iocbq.iocb.ulpTimeout,
+- (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
++ "3376 FCP could not issue iocb err %x "
++ "FCP cmd x%x <%d/%llu> "
++ "sid: x%x did: x%x oxid: x%x "
++ "Data: x%x x%x x%x x%x\n",
++ err, cmnd->cmnd[0],
++ cmnd->device ? cmnd->device->id : 0xffff,
++ cmnd->device ? cmnd->device->lun : (u64)-1,
++ vport->fc_myDID, ndlp->nlp_DID,
++ phba->sli_rev == LPFC_SLI_REV4 ?
++ cur_iocbq->sli4_xritag : 0xffff,
++ phba->sli_rev == LPFC_SLI_REV4 ?
++ phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] :
++ cur_iocbq->iocb.ulpContext,
++ cur_iocbq->iotag,
++ phba->sli_rev == LPFC_SLI_REV4 ?
++ bf_get(wqe_tmo,
++ &cur_iocbq->wqe.generic.wqe_com) :
++ cur_iocbq->iocb.ulpTimeout,
++ (uint32_t)(scsi_cmd_to_rq(cmnd)->timeout / 1000));
+
+ goto out_host_busy_free_buf;
+ }
+@@ -6167,7 +6122,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ return FAILED;
+ pnode = rdata->pnode;
+
+- lpfc_cmd = lpfc_get_scsi_buf(phba, pnode, NULL);
++ lpfc_cmd = lpfc_get_scsi_buf(phba, rdata->pnode, NULL);
+ if (lpfc_cmd == NULL)
+ return FAILED;
+ lpfc_cmd->timeout = phba->cfg_task_mgmt_tmo;
+@@ -6175,8 +6130,8 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ lpfc_cmd->pCmd = cmnd;
+ lpfc_cmd->ndlp = pnode;
+
+- status = lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
+- task_mgmt_cmd);
++ status = phba->lpfc_scsi_prep_task_mgmt_cmd(vport, lpfc_cmd, lun_id,
++ task_mgmt_cmd);
+ if (!status) {
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+ return FAILED;
+@@ -6189,6 +6144,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ return FAILED;
+ }
+ iocbq->cmd_cmpl = lpfc_tskmgmt_def_cmpl;
++ iocbq->vport = vport;
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
+ "0702 Issue %s to TGT %d LUN %llu "
+@@ -6200,26 +6156,28 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+ status = lpfc_sli_issue_iocb_wait(phba, LPFC_FCP_RING,
+ iocbq, iocbqrsp, lpfc_cmd->timeout);
+ if ((status != IOCB_SUCCESS) ||
+- (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) {
++ (get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_SUCCESS)) {
+ if (status != IOCB_SUCCESS ||
+- iocbqrsp->iocb.ulpStatus != IOSTAT_FCP_RSP_ERROR)
++ get_job_ulpstatus(phba, iocbqrsp) != IOSTAT_FCP_RSP_ERROR)
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+ "0727 TMF %s to TGT %d LUN %llu "
+ "failed (%d, %d) cmd_flag x%x\n",
+ lpfc_taskmgmt_name(task_mgmt_cmd),
+ tgt_id, lun_id,
+- iocbqrsp->iocb.ulpStatus,
+- iocbqrsp->iocb.un.ulpWord[4],
++ get_job_ulpstatus(phba, iocbqrsp),
++ get_job_word4(phba, iocbqrsp),
+ iocbq->cmd_flag);
+ /* if ulpStatus != IOCB_SUCCESS, then status == IOCB_SUCCESS */
+ if (status == IOCB_SUCCESS) {
+- if (iocbqrsp->iocb.ulpStatus == IOSTAT_FCP_RSP_ERROR)
++ if (get_job_ulpstatus(phba, iocbqrsp) ==
++ IOSTAT_FCP_RSP_ERROR)
+ /* Something in the FCP_RSP was invalid.
+ * Check conditions */
+ ret = lpfc_check_fcp_rsp(vport, lpfc_cmd);
+ else
+ ret = FAILED;
+- } else if (status == IOCB_TIMEDOUT) {
++ } else if ((status == IOCB_TIMEDOUT) ||
++ (status == IOCB_ABORTED)) {
+ ret = TIMEOUT_ERROR;
+ } else {
+ ret = FAILED;
+@@ -6229,7 +6187,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd,
+
+ lpfc_sli_release_iocbq(phba, iocbqrsp);
+
+- if (ret != TIMEOUT_ERROR)
++ if (status != IOCB_TIMEDOUT)
+ lpfc_release_scsi_buf(phba, lpfc_cmd);
+
+ return ret;
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 464a251bcc88..972251dd35a9 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -12968,6 +12968,7 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
+ wait_queue_head_t *pdone_q;
+ unsigned long iflags;
+ struct lpfc_io_buf *lpfc_cmd;
++ size_t offset = offsetof(struct lpfc_iocbq, wqe);
+
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ if (cmdiocbq->cmd_flag & LPFC_IO_WAKE_TMO) {
+@@ -12988,10 +12989,11 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba,
+ return;
+ }
+
++ /* Copy the contents of the local rspiocb into the caller's buffer. */
+ cmdiocbq->cmd_flag |= LPFC_IO_WAKE;
+ if (cmdiocbq->context2 && rspiocbq)
+- memcpy(&((struct lpfc_iocbq *)cmdiocbq->context2)->iocb,
+- &rspiocbq->iocb, sizeof(IOCB_t));
++ memcpy((char *)cmdiocbq->context2 + offset,
++ (char *)rspiocbq + offset, sizeof(*rspiocbq) - offset);
+
+ /* Set the exchange busy flag for task management commands */
+ if ((cmdiocbq->cmd_flag & LPFC_IO_FCP) &&
+--
+2.35.1
+
--- /dev/null
+From ce3eabf3448d5c7b76e15c2aab5be386774cf6fc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:40 -0700
+Subject: scsi: qla2xxx: edif: Fix dropped IKE message
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit c019cd656e717349ff22d0c41d6fbfc773f48c52 ]
+
+This patch fixes IKE message being dropped due to error in processing Purex
+IOCB and Continuation IOCBs.
+
+Link: https://lore.kernel.org/r/20220713052045.10683-6-njavali@marvell.com
+Fixes: fac2807946c1 ("scsi: qla2xxx: edif: Add extraction of auth_els from the wire")
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_isr.c | 54 +++++++++++++++-------------------
+ 1 file changed, 24 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index ecbc0a5ffb3f..59f5918dca95 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -3707,12 +3707,11 @@ void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *vha,
+ * Return: 0 all iocbs has arrived, xx- all iocbs have not arrived.
+ */
+ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
+- struct rsp_que *rsp, response_t *pkt)
++ struct rsp_que *rsp, response_t *pkt, u32 rsp_q_in)
+ {
+- int start_pkt_ring_index, end_pkt_ring_index, n_ring_index;
+- response_t *end_pkt;
++ int start_pkt_ring_index;
++ u32 iocb_cnt = 0;
+ int rc = 0;
+- u32 rsp_q_in;
+
+ if (pkt->entry_count == 1)
+ return rc;
+@@ -3723,34 +3722,18 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha,
+ else
+ start_pkt_ring_index = rsp->ring_index - 1;
+
+- if ((start_pkt_ring_index + pkt->entry_count) >= rsp->length)
+- end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count -
+- rsp->length - 1;
++ if (rsp_q_in < start_pkt_ring_index)
++ /* q in ptr is wrapped */
++ iocb_cnt = rsp->length - start_pkt_ring_index + rsp_q_in;
+ else
+- end_pkt_ring_index = start_pkt_ring_index + pkt->entry_count - 1;
++ iocb_cnt = rsp_q_in - start_pkt_ring_index;
+
+- end_pkt = rsp->ring + end_pkt_ring_index;
+-
+- /* next pkt = end_pkt + 1 */
+- n_ring_index = end_pkt_ring_index + 1;
+- if (n_ring_index >= rsp->length)
+- n_ring_index = 0;
+-
+- rsp_q_in = rsp->qpair->use_shadow_reg ? *rsp->in_ptr :
+- rd_reg_dword(rsp->rsp_q_in);
+-
+- /* rsp_q_in is either wrapped or pointing beyond endpkt */
+- if ((rsp_q_in < start_pkt_ring_index && rsp_q_in < n_ring_index) ||
+- rsp_q_in >= n_ring_index)
+- /* all IOCBs arrived. */
+- rc = 0;
+- else
++ if (iocb_cnt < pkt->entry_count)
+ rc = -EIO;
+
+- ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x5091,
+- "%s - ring %p pkt %p end pkt %p entry count %#x rsp_q_in %d rc %d\n",
+- __func__, rsp->ring, pkt, end_pkt, pkt->entry_count,
+- rsp_q_in, rc);
++ ql_dbg(ql_dbg_init, vha, 0x5091,
++ "%s - ring %p pkt %p entry count %d iocb_cnt %d rsp_q_in %d rc %d\n",
++ __func__, rsp->ring, pkt, pkt->entry_count, iocb_cnt, rsp_q_in, rc);
+
+ return rc;
+ }
+@@ -3767,7 +3750,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ struct qla_hw_data *ha = vha->hw;
+ struct purex_entry_24xx *purex_entry;
+ struct purex_item *pure_item;
+- u16 rsp_in = 0;
++ u16 rsp_in = 0, cur_ring_index;
+ int follow_inptr, is_shadow_hba;
+
+ if (!ha->flags.fw_started)
+@@ -3798,6 +3781,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ (!follow_inptr &&
+ rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
+ pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
++ cur_ring_index = rsp->ring_index;
+
+ rsp->ring_index++;
+ if (rsp->ring_index == rsp->length) {
+@@ -3918,7 +3902,17 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ break;
+
+ case ELS_AUTH_ELS:
+- if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt)) {
++ if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) {
++ /*
++ * ring_ptr and ring_index were
++ * pre-incremented above. Reset them
++ * back to current. Wait for next
++ * interrupt with all IOCBs to arrive
++ * and re-process.
++ */
++ rsp->ring_ptr = (response_t *)pkt;
++ rsp->ring_index = cur_ring_index;
++
+ ql_dbg(ql_dbg_init, vha, 0x5091,
+ "Defer processing ELS opcode %#x...\n",
+ purex_entry->els_frame_payload[3]);
+--
+2.35.1
+
--- /dev/null
+From 5022d7f75a959f35a10caa156f7872f76f101346 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:02 -0700
+Subject: scsi: qla2xxx: Fix crash due to stale SRB access around I/O timeouts
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit c39587bc0abaf16593f7abcdf8aeec3c038c7d52 ]
+
+Ensure SRB is returned during I/O timeout error escalation. If that is not
+possible fail the escalation path.
+
+Following crash stack was seen:
+
+BUG: unable to handle kernel paging request at 0000002f56aa90f8
+IP: qla_chk_edif_rx_sa_delete_pending+0x14/0x30 [qla2xxx]
+Call Trace:
+ ? qla2x00_status_entry+0x19f/0x1c50 [qla2xxx]
+ ? qla2x00_start_sp+0x116/0x1170 [qla2xxx]
+ ? dma_pool_alloc+0x1d6/0x210
+ ? mempool_alloc+0x54/0x130
+ ? qla24xx_process_response_queue+0x548/0x12b0 [qla2xxx]
+ ? qla_do_work+0x2d/0x40 [qla2xxx]
+ ? process_one_work+0x14c/0x390
+
+Link: https://lore.kernel.org/r/20220616053508.27186-6-njavali@marvell.com
+Fixes: d74595278f4a ("scsi: qla2xxx: Add multiple queue pair functionality.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_os.c | 43 +++++++++++++++++++++++++----------
+ 1 file changed, 31 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index eca622f3e8c1..6542a258cb75 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -1338,21 +1338,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
+ /*
+ * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
+ */
+-int
+-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
+- uint64_t l, enum nexus_wait_type type)
++static int
++__qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
++ uint64_t l, enum nexus_wait_type type)
+ {
+ int cnt, match, status;
+ unsigned long flags;
+- struct qla_hw_data *ha = vha->hw;
+- struct req_que *req;
++ scsi_qla_host_t *vha = qpair->vha;
++ struct req_que *req = qpair->req;
+ srb_t *sp;
+ struct scsi_cmnd *cmd;
+
+ status = QLA_SUCCESS;
+
+- spin_lock_irqsave(&ha->hardware_lock, flags);
+- req = vha->req;
++ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ for (cnt = 1; status == QLA_SUCCESS &&
+ cnt < req->num_outstanding_cmds; cnt++) {
+ sp = req->outstanding_cmds[cnt];
+@@ -1379,12 +1378,32 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
+ if (!match)
+ continue;
+
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+ status = qla2x00_eh_wait_on_command(cmd);
+- spin_lock_irqsave(&ha->hardware_lock, flags);
++ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ }
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
++ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
++
++ return status;
++}
++
++int
++qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
++ uint64_t l, enum nexus_wait_type type)
++{
++ struct qla_qpair *qpair;
++ struct qla_hw_data *ha = vha->hw;
++ int i, status = QLA_SUCCESS;
+
++ status = __qla2x00_eh_wait_for_pending_commands(ha->base_qpair, t, l,
++ type);
++ for (i = 0; status == QLA_SUCCESS && i < ha->max_qpairs; i++) {
++ qpair = ha->queue_pair_map[i];
++ if (!qpair)
++ continue;
++ status = __qla2x00_eh_wait_for_pending_commands(qpair, t, l,
++ type);
++ }
+ return status;
+ }
+
+@@ -1421,7 +1440,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
+ return err;
+
+ if (fcport->deleted)
+- return SUCCESS;
++ return FAILED;
+
+ ql_log(ql_log_info, vha, 0x8009,
+ "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no,
+@@ -1489,7 +1508,7 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd)
+ return err;
+
+ if (fcport->deleted)
+- return SUCCESS;
++ return FAILED;
+
+ ql_log(ql_log_info, vha, 0x8009,
+ "TARGET RESET ISSUED nexus=%ld:%d cmd=%p.\n", vha->host_no,
+--
+2.35.1
+
--- /dev/null
+From 0b4b66987bf3e1b6dc2f81496653d7ff9b38b5ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:42 -0700
+Subject: scsi: qla2xxx: Fix discovery issues in FC-AL topology
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 47ccb113cead905bdc236571bf8ac6fed90321b3 ]
+
+A direct attach tape device, when gets swapped with another, was not
+discovered. Fix this by looking at loop map and reinitialize link if there
+are devices present.
+
+Link: https://lore.kernel.org/linux-scsi/baef87c3-5dad-3b47-44c1-6914bfc90108@cybernetics.com/
+Link: https://lore.kernel.org/r/20220713052045.10683-8-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reported-by: Tony Battersby <tonyb@cybernetics.com>
+Tested-by: Tony Battersby <tonyb@cybernetics.com>
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_gbl.h | 3 ++-
+ drivers/scsi/qla2xxx/qla_init.c | 29 +++++++++++++++++++++++++++++
+ drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++-
+ 3 files changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index db6ccdda740e..f82e4a348330 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -435,7 +435,8 @@ extern int
+ qla2x00_get_resource_cnts(scsi_qla_host_t *);
+
+ extern int
+-qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
++qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map,
++ u8 *num_entries);
+
+ extern int
+ qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index b61a56e1b9a7..b81797a3ab61 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -5521,6 +5521,22 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
+ return QLA_FUNCTION_FAILED;
+ }
+
++static void
++qla_reinitialize_link(scsi_qla_host_t *vha)
++{
++ int rval;
++
++ atomic_set(&vha->loop_state, LOOP_DOWN);
++ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
++ rval = qla2x00_full_login_lip(vha);
++ if (rval == QLA_SUCCESS) {
++ ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n");
++ } else {
++ ql_dbg(ql_dbg_disc, vha, 0xd051,
++ "Link reinitialization failed (%d)\n", rval);
++ }
++}
++
+ /*
+ * qla2x00_configure_local_loop
+ * Updates Fibre Channel Device Database with local loop devices.
+@@ -5572,6 +5588,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+ if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
++ u8 loop_map_entries = 0;
++ int rc;
++
++ rc = qla2x00_get_fcal_position_map(vha, NULL,
++ &loop_map_entries);
++ if (rc == QLA_SUCCESS && loop_map_entries > 1) {
++ /*
++ * There are devices that are still not logged
++ * in. Reinitialize to give them a chance.
++ */
++ qla_reinitialize_link(vha);
++ return QLA_FUNCTION_FAILED;
++ }
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index 951f90035449..5bcb8da4360f 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -3062,7 +3062,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
+ * Kernel context.
+ */
+ int
+-qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
++qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
++ u8 *num_entries)
+ {
+ int rval;
+ mbx_cmd_t mc;
+@@ -3102,6 +3103,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
+
+ if (pos_map)
+ memcpy(pos_map, pmap, FCAL_MAP_SIZE);
++ if (num_entries)
++ *num_entries = pmap[0];
+ }
+ dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
+
+--
+2.35.1
+
--- /dev/null
+From e6f07ae0f8b10d076fd632535cf706e64a4b06f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:07 -0700
+Subject: scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error
+ injection
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit f260694e6463b63ae550aad25ddefe94cb1904da ]
+
+Clear wait for mailbox interrupt flag to prevent stale mailbox:
+
+Feb 22 05:22:56 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-500a:4: LOOP UP detected (16 Gbps).
+Feb 22 05:22:59 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-d04c:4: MBX Command timeout for cmd 69, ...
+
+To fix the issue, driver needs to clear the MBX_INTR_WAIT flag on purging
+the mailbox. When the stale mailbox completion does arrive, it will be
+dropped.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-11-njavali@marvell.com
+Fixes: b6faaaf796d7 ("scsi: qla2xxx: Serialize mailbox request")
+Cc: Naresh Bannoth <nbannoth@in.ibm.com>
+Cc: Kyle Mahlkuch <Kyle.Mahlkuch@ibm.com>
+Cc: stable@vger.kernel.org
+Reported-by: Naresh Bannoth <nbannoth@in.ibm.com>
+Tested-by: Naresh Bannoth <nbannoth@in.ibm.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_mbx.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index 5f2594d3d4f9..951f90035449 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -276,6 +276,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
+ atomic_inc(&ha->num_pend_mbx_stage3);
+ if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
+ mcp->tov * HZ)) {
++ ql_dbg(ql_dbg_mbx, vha, 0x117a,
++ "cmd=%x Timeout.\n", command);
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
+ if (chip_reset != ha->chip_reset) {
+ eeh_delay = ha->flags.eeh_busy ? 1 : 0;
+
+@@ -288,12 +294,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
+ rval = QLA_ABORTED;
+ goto premature_exit;
+ }
+- ql_dbg(ql_dbg_mbx, vha, 0x117a,
+- "cmd=%x Timeout.\n", command);
+- spin_lock_irqsave(&ha->hardware_lock, flags);
+- clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-
+ } else if (ha->flags.purge_mbox ||
+ chip_reset != ha->chip_reset) {
+ eeh_delay = ha->flags.eeh_busy ? 1 : 0;
+--
+2.35.1
+
--- /dev/null
+From e0e9abd03bd5742d62ac45c7517382dc7d2267f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:34:58 -0700
+Subject: scsi: qla2xxx: Fix excessive I/O error messages by default
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit bff4873c709085e09d0ffae0c25b8e65256e3205 ]
+
+Disable printing I/O error messages by default. The messages will be
+printed only when logging was enabled.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-2-njavali@marvell.com
+Fixes: 8e2d81c6b5be ("scsi: qla2xxx: Fix excessive messages during device logout")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_isr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index c41a965eb4a7..6c71e0fd4942 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -2633,7 +2633,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
+ }
+
+ if (unlikely(logit))
+- ql_log(ql_dbg_io, fcport->vha, 0x5060,
++ ql_dbg(ql_dbg_io, fcport->vha, 0x5060,
+ "NVME-%s ERR Handling - hdl=%x status(%x) tr_len:%x resid=%x ox_id=%x\n",
+ sp->name, sp->handle, comp_status,
+ fd->transferred_length, le32_to_cpu(sts->residual_len),
+@@ -3491,7 +3491,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
+
+ out:
+ if (logit)
+- ql_log(ql_dbg_io, fcport->vha, 0x3022,
++ ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
+ "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
+ comp_status, scsi_status, res, vha->host_no,
+ cp->device->id, cp->device->lun, fcport->d_id.b.domain,
+--
+2.35.1
+
--- /dev/null
+From 2d6af9bb8469e163a0afa2552f0e5edb03b41a1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:41 -0700
+Subject: scsi: qla2xxx: Fix imbalance vha->vref_count
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit 63fa7f2644b4b48e1913af33092c044bf48e9321 ]
+
+vref_count took an extra decrement in the task management path. Add an
+extra ref count to compensate the imbalance.
+
+Link: https://lore.kernel.org/r/20220713052045.10683-7-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index ab08ab206abc..b61a56e1b9a7 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -168,6 +168,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+ struct srb_iocb *abt_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
++ uint8_t bail;
+
+ /* ref: INIT for ABTS command */
+ sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
+@@ -175,6 +176,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+ if (!sp)
+ return QLA_MEMORY_ALLOC_FAILED;
+
++ QLA_VHA_MARK_BUSY(vha, bail);
+ abt_iocb = &sp->u.iocb_cmd;
+ sp->type = SRB_ABT_CMD;
+ sp->name = "abort";
+@@ -2020,12 +2022,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
+ struct srb_iocb *tm_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
++ uint8_t bail;
+
+ /* ref: INIT */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp)
+ goto done;
+
++ QLA_VHA_MARK_BUSY(vha, bail);
+ sp->type = SRB_TM_CMD;
+ sp->name = "tmf";
+ qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha),
+--
+2.35.1
+
--- /dev/null
+From 1a1e0916c6e933835567aa7c8daaca4a0b066e06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:03 -0700
+Subject: scsi: qla2xxx: Fix losing FCP-2 targets during port perturbation
+ tests
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 58d1c124cd79ea686b512043c5bd515590b2ed95 ]
+
+When a mix of FCP-2 (tape) and non-FCP-2 targets are present, FCP-2 target
+state was incorrectly transitioned when both of the targets were gone. Fix
+this by ignoring state transition for FCP-2 targets.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-7-njavali@marvell.com
+Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_gs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index 2c49f12078ac..d3742a83d2fd 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -3628,7 +3628,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
+ do_delete) {
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+ if (fcport->flags & FCF_FCP2_DEVICE)
+- fcport->logout_on_delete = 0;
++ continue;
+
+ ql_log(ql_log_warn, vha, 0x20f0,
+ "%s %d %8phC post del sess\n",
+--
+2.35.1
+
--- /dev/null
+From 2eba983f6446ec2ca5460d266c2e0b6b8fd70b2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:06 -0700
+Subject: scsi: qla2xxx: Fix losing FCP-2 targets on long port disable with
+ I/Os
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 2416ccd3815ba1613e10a6da0a24ef21acfe5633 ]
+
+FCP-2 devices were not coming back online once they were lost, login
+retries exhausted, and then came back up. Fix this by accepting RSCN when
+the device is not online.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-10-njavali@marvell.com
+Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 2f1fba2a014a..ab08ab206abc 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1834,7 +1834,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ case RSCN_PORT_ADDR:
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (fcport) {
+- if (fcport->flags & FCF_FCP2_DEVICE) {
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_disc, vha, 0x2115,
+ "Delaying session delete for FCP2 portid=%06x %8phC ",
+ fcport->d_id.b24, fcport->port_name);
+@@ -1866,7 +1867,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ break;
+ case RSCN_AREA_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) {
+@@ -1877,7 +1879,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ break;
+ case RSCN_DOM_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) {
+@@ -1889,7 +1892,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ case RSCN_FAB_ADDR:
+ default:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ fcport->scan_needed = 1;
+--
+2.35.1
+
--- /dev/null
+From f716ebbcca6fd9461d2fea1b920aa18c48915ca1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:04 -0700
+Subject: scsi: qla2xxx: Fix losing target when it reappears during delete
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 118b0c863c8f5629cc5271fc24d72d926e0715d9 ]
+
+FC target disappeared during port perturbation tests due to a race that
+tramples target state. Fix the issue by adding state checks before
+proceeding.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-8-njavali@marvell.com
+Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_attr.c | 24 +++++++++++++++++-------
+ 1 file changed, 17 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index bd4ebc1b5c1e..a302ed8b610f 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -2705,17 +2705,24 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
+ if (!fcport)
+ return;
+
+- /* Now that the rport has been deleted, set the fcport state to
+- FCS_DEVICE_DEAD */
+- qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
++
++ /*
++ * Now that the rport has been deleted, set the fcport state to
++ * FCS_DEVICE_DEAD, if the fcport is still lost.
++ */
++ if (fcport->scan_state != QLA_FCPORT_FOUND)
++ qla2x00_set_fcport_state(fcport, FCS_DEVICE_DEAD);
+
+ /*
+ * Transport has effectively 'deleted' the rport, clear
+ * all local references.
+ */
+ spin_lock_irqsave(host->host_lock, flags);
+- fcport->rport = fcport->drport = NULL;
+- *((fc_port_t **)rport->dd_data) = NULL;
++ /* Confirm port has not reappeared before clearing pointers. */
++ if (rport->port_state != FC_PORTSTATE_ONLINE) {
++ fcport->rport = fcport->drport = NULL;
++ *((fc_port_t **)rport->dd_data) = NULL;
++ }
+ spin_unlock_irqrestore(host->host_lock, flags);
+
+ if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
+@@ -2748,9 +2755,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
+ /*
+ * At this point all fcport's software-states are cleared. Perform any
+ * final cleanup of firmware resources (PCBs and XCBs).
++ *
++ * Attempt to cleanup only lost devices.
+ */
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+- if (IS_FWI2_CAPABLE(fcport->vha->hw)) {
++ if (IS_FWI2_CAPABLE(fcport->vha->hw) &&
++ fcport->scan_state != QLA_FCPORT_FOUND) {
+ if (fcport->loop_id != FC_NO_LOOP_ID)
+ fcport->logout_on_delete = 1;
+
+@@ -2760,7 +2770,7 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
+ __LINE__);
+ qlt_schedule_sess_for_deletion(fcport);
+ }
+- } else {
++ } else if (!IS_FWI2_CAPABLE(fcport->vha->hw)) {
+ qla2x00_port_logout(fcport->vha, fcport);
+ }
+ }
+--
+2.35.1
+
--- /dev/null
+From b85888be1f0e34cb530cdf984eedaf5f9ca2f63f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:39 -0700
+Subject: scsi: qla2xxx: Fix response queue handler reading stale packets
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit b1f707146923335849fb70237eec27d4d1ae7d62 ]
+
+On some platforms, the current logic of relying on finding new packet
+solely based on signature pattern can lead to driver reading stale
+packets. Though this is a bug in those platforms, reduce such exposures by
+limiting reading packets until the IN pointer.
+
+Two module parameters are introduced:
+
+ ql2xrspq_follow_inptr:
+
+ When set, on newer adapters that has queue pointer shadowing, look for
+ response packets only until response queue in pointer.
+
+ When reset, response packets are read based on a signature pattern
+ logic (old way).
+
+ ql2xrspq_follow_inptr_legacy:
+
+ Like ql2xrspq_follow_inptr, but for those adapters where there is no
+ queue pointer shadowing.
+
+Link: https://lore.kernel.org/r/20220713052045.10683-5-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_gbl.h | 2 ++
+ drivers/scsi/qla2xxx/qla_isr.c | 24 +++++++++++++++++++++++-
+ drivers/scsi/qla2xxx/qla_os.c | 10 ++++++++++
+ 3 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index 2f6afdbd2dfa..db6ccdda740e 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -192,6 +192,8 @@ extern int ql2xfulldump_on_mpifail;
+ extern int ql2xsecenable;
+ extern int ql2xenforce_iocb_limit;
+ extern int ql2xabts_wait_nvme;
++extern int ql2xrspq_follow_inptr;
++extern int ql2xrspq_follow_inptr_legacy;
+
+ extern int qla2x00_loop_reset(scsi_qla_host_t *);
+ extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index b218f9739619..ecbc0a5ffb3f 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -3767,6 +3767,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ struct qla_hw_data *ha = vha->hw;
+ struct purex_entry_24xx *purex_entry;
+ struct purex_item *pure_item;
++ u16 rsp_in = 0;
++ int follow_inptr, is_shadow_hba;
+
+ if (!ha->flags.fw_started)
+ return;
+@@ -3776,7 +3778,25 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ qla_cpu_update(rsp->qpair, smp_processor_id());
+ }
+
+- while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) {
++#define __update_rsp_in(_update, _is_shadow_hba, _rsp, _rsp_in) \
++ do { \
++ if (_update) { \
++ _rsp_in = _is_shadow_hba ? *(_rsp)->in_ptr : \
++ rd_reg_dword_relaxed((_rsp)->rsp_q_in); \
++ } \
++ } while (0)
++
++ is_shadow_hba = IS_SHADOW_REG_CAPABLE(ha);
++ follow_inptr = is_shadow_hba ? ql2xrspq_follow_inptr :
++ ql2xrspq_follow_inptr_legacy;
++
++ __update_rsp_in(follow_inptr, is_shadow_hba, rsp, rsp_in);
++
++ while ((likely(follow_inptr &&
++ rsp->ring_index != rsp_in &&
++ rsp->ring_ptr->signature != RESPONSE_PROCESSED)) ||
++ (!follow_inptr &&
++ rsp->ring_ptr->signature != RESPONSE_PROCESSED)) {
+ pkt = (struct sts_entry_24xx *)rsp->ring_ptr;
+
+ rsp->ring_index++;
+@@ -3889,6 +3909,8 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
+ }
+ pure_item = qla27xx_copy_fpin_pkt(vha,
+ (void **)&pkt, &rsp);
++ __update_rsp_in(follow_inptr, is_shadow_hba,
++ rsp, rsp_in);
+ if (!pure_item)
+ break;
+ qla24xx_queue_purex_item(vha, pure_item,
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index 6542a258cb75..00e97f0a07eb 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -338,6 +338,16 @@ module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
+ MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
+ "Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
+
++int ql2xrspq_follow_inptr = 1;
++module_param(ql2xrspq_follow_inptr, int, 0644);
++MODULE_PARM_DESC(ql2xrspq_follow_inptr,
++ "Follow RSP IN pointer for RSP updates for HBAs 27xx and newer (default: 1).");
++
++int ql2xrspq_follow_inptr_legacy = 1;
++module_param(ql2xrspq_follow_inptr_legacy, int, 0644);
++MODULE_PARM_DESC(ql2xrspq_follow_inptr_legacy,
++ "Follow RSP IN pointer for RSP updates for HBAs older than 27XX. (default: 1).");
++
+ static void qla2x00_clear_drv_active(struct qla_hw_data *);
+ static void qla2x00_free_device(scsi_qla_host_t *);
+ static int qla2xxx_map_queues(struct Scsi_Host *shost);
+--
+2.35.1
+
--- /dev/null
+From a5fefe072ff838eb38ad9905a6c9eeeb513a6f02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:01 -0700
+Subject: scsi: qla2xxx: Turn off multi-queue for 8G adapters
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit 5304673bdb1635e27555bd636fd5d6956f1cd552 ]
+
+For 8G adapters, multi-queue was enabled accidentally. Make sure
+multi-queue is not enabled.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-5-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 4 ++--
+ drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++----------
+ 2 files changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 5e74c451bf4e..51c7ce5f9792 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -4265,8 +4265,8 @@ struct qla_hw_data {
+ #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001)
+ #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
+ #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED)
+-#define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \
+- IS_QLA27XX(ha) || IS_QLA28XX(ha))
++#define IS_MQUE_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
++ IS_QLA28XX(ha))
+ #define IS_BIDI_CAPABLE(ha) \
+ (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ /* Bit 21 of fw_attributes decides the MCTP capabilities */
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index 6c71e0fd4942..b218f9739619 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -4415,16 +4415,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
+ }
+
+ /* Enable MSI-X vector for response queue update for queue 0 */
+- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+- if (ha->msixbase && ha->mqiobase &&
+- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
+- ql2xmqsupport))
+- ha->mqenable = 1;
+- } else
+- if (ha->mqiobase &&
+- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
+- ql2xmqsupport))
+- ha->mqenable = 1;
++ if (IS_MQUE_CAPABLE(ha) &&
++ (ha->msixbase && ha->mqiobase && ha->max_qpairs))
++ ha->mqenable = 1;
++ else
++ ha->mqenable = 0;
++
+ ql_dbg(ql_dbg_multiq, vha, 0xc005,
+ "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+ ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
+--
+2.35.1
+
--- /dev/null
+From 318142b652409d6495f685168c5d8ef1539dbd9e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:44 -0700
+Subject: scsi: qla2xxx: Update manufacturer details
+
+From: Bikash Hazarika <bhazarika@marvell.com>
+
+[ Upstream commit 1ccad27716ecad1fd58c35e579bedb81fa5e1ad5 ]
+
+Update manufacturer details to indicate Marvell Semiconductors.
+
+Link: https://lore.kernel.org/r/20220713052045.10683-10-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 2 +-
+ drivers/scsi/qla2xxx/qla_gs.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 51c7ce5f9792..c906b45ff76a 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -78,7 +78,7 @@ typedef union {
+ #include "qla_nvme.h"
+ #define QLA2XXX_DRIVER_NAME "qla2xxx"
+ #define QLA2XXX_APIDEV "ql2xapidev"
+-#define QLA2XXX_MANUFACTURER "QLogic Corporation"
++#define QLA2XXX_MANUFACTURER "Marvell Semiconductor, Inc."
+
+ /*
+ * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index d3742a83d2fd..b0f3bf42c340 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -1615,7 +1615,7 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
+ eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
+ alen = scnprintf(
+ eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
+- "%s", "QLogic Corporation");
++ "%s", QLA2XXX_MANUFACTURER);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+--
+2.35.1
+
--- /dev/null
+From f2fbb80e0df228b61cec2944fe21ed09e396ecdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:00 -0700
+Subject: scsi: qla2xxx: Wind down adapter after PCIe error
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit d3117c83ba316b3200d9f2fe900f2b9a5525a25c ]
+
+Put adapter into a wind down state if OS does not make any attempt to
+recover the adapter after PCIe error.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-4-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_bsg.c | 10 ++++++-
+ drivers/scsi/qla2xxx/qla_def.h | 4 +++
+ drivers/scsi/qla2xxx/qla_init.c | 20 ++++++++++++++
+ drivers/scsi/qla2xxx/qla_os.c | 48 +++++++++++++++++++++++++++++++++
+ 4 files changed, 81 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
+index c636165be52b..3650f16cab6c 100644
+--- a/drivers/scsi/qla2xxx/qla_bsg.c
++++ b/drivers/scsi/qla2xxx/qla_bsg.c
+@@ -2972,6 +2972,13 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
+
+ ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
+ __func__, bsg_job);
++
++ if (qla2x00_isp_reg_stat(ha)) {
++ ql_log(ql_log_info, vha, 0x9007,
++ "PCI/Register disconnect.\n");
++ qla_pci_set_eeh_busy(vha);
++ }
++
+ /* find the bsg job from the active list of commands */
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ for (que = 0; que < ha->max_req_queues; que++) {
+@@ -2989,7 +2996,8 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
+ sp->u.bsg_job == bsg_job) {
+ req->outstanding_cmds[cnt] = NULL;
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+- if (ha->isp_ops->abort_command(sp)) {
++
++ if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
+ ql_log(ql_log_warn, vha, 0x7089,
+ "mbx abort_command failed.\n");
+ bsg_reply->result = -EIO;
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 4fc289815ccb..5e74c451bf4e 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -4045,6 +4045,9 @@ struct qla_hw_data {
+ uint32_t n2n_fw_acc_sec:1;
+ uint32_t plogi_template_valid:1;
+ uint32_t port_isolated:1;
++ uint32_t eeh_flush:2;
++#define EEH_FLUSH_RDY 1
++#define EEH_FLUSH_DONE 2
+ } flags;
+
+ uint16_t max_exchg;
+@@ -4079,6 +4082,7 @@ struct qla_hw_data {
+ uint32_t rsp_que_len;
+ uint32_t req_que_off;
+ uint32_t rsp_que_off;
++ unsigned long eeh_jif;
+
+ /* Multi queue data structs */
+ device_reg_t *mqiobase;
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index edc29d6ebb28..2f1fba2a014a 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -47,6 +47,7 @@ qla2x00_sp_timeout(struct timer_list *t)
+ {
+ srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer);
+ struct srb_iocb *iocb;
++ scsi_qla_host_t *vha = sp->vha;
+
+ WARN_ON(irqs_disabled());
+ iocb = &sp->u.iocb_cmd;
+@@ -54,6 +55,12 @@ qla2x00_sp_timeout(struct timer_list *t)
+
+ /* ref: TMR */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
++
++ if (vha && qla2x00_isp_reg_stat(vha->hw)) {
++ ql_log(ql_log_info, vha, 0x9008,
++ "PCI/Register disconnect.\n");
++ qla_pci_set_eeh_busy(vha);
++ }
+ }
+
+ void qla2x00_sp_free(srb_t *sp)
+@@ -9698,6 +9705,12 @@ int qla2xxx_disable_port(struct Scsi_Host *host)
+
+ vha->hw->flags.port_isolated = 1;
+
++ if (qla2x00_isp_reg_stat(vha->hw)) {
++ ql_log(ql_log_info, vha, 0x9006,
++ "PCI/Register disconnect, exiting.\n");
++ qla_pci_set_eeh_busy(vha);
++ return FAILED;
++ }
+ if (qla2x00_chip_is_down(vha))
+ return 0;
+
+@@ -9713,6 +9726,13 @@ int qla2xxx_enable_port(struct Scsi_Host *host)
+ {
+ scsi_qla_host_t *vha = shost_priv(host);
+
++ if (qla2x00_isp_reg_stat(vha->hw)) {
++ ql_log(ql_log_info, vha, 0x9001,
++ "PCI/Register disconnect, exiting.\n");
++ qla_pci_set_eeh_busy(vha);
++ return FAILED;
++ }
++
+ vha->hw->flags.port_isolated = 0;
+ /* Set the flag to 1, so that isp_abort can proceed */
+ vha->flags.online = 1;
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index e87ad7e0dc94..eca622f3e8c1 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -333,6 +333,11 @@ MODULE_PARM_DESC(ql2xabts_wait_nvme,
+ "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
+
+
++u32 ql2xdelay_before_pci_error_handling = 5;
++module_param(ql2xdelay_before_pci_error_handling, uint, 0644);
++MODULE_PARM_DESC(ql2xdelay_before_pci_error_handling,
++ "Number of seconds delayed before qla begin PCI error self-handling (default: 5).\n");
++
+ static void qla2x00_clear_drv_active(struct qla_hw_data *);
+ static void qla2x00_free_device(scsi_qla_host_t *);
+ static int qla2xxx_map_queues(struct Scsi_Host *shost);
+@@ -7232,6 +7237,44 @@ static void qla_heart_beat(struct scsi_qla_host *vha, u16 dpc_started)
+ }
+ }
+
++static void qla_wind_down_chip(scsi_qla_host_t *vha)
++{
++ struct qla_hw_data *ha = vha->hw;
++
++ if (!ha->flags.eeh_busy)
++ return;
++ if (ha->pci_error_state)
++ /* system is trying to recover */
++ return;
++
++ /*
++ * Current system is not handling PCIE error. At this point, this is
++ * best effort to wind down the adapter.
++ */
++ if (time_after_eq(jiffies, ha->eeh_jif + ql2xdelay_before_pci_error_handling * HZ) &&
++ !ha->flags.eeh_flush) {
++ ql_log(ql_log_info, vha, 0x9009,
++ "PCI Error detected, attempting to reset hardware.\n");
++
++ ha->isp_ops->reset_chip(vha);
++ ha->isp_ops->disable_intrs(ha);
++
++ ha->flags.eeh_flush = EEH_FLUSH_RDY;
++ ha->eeh_jif = jiffies;
++
++ } else if (ha->flags.eeh_flush == EEH_FLUSH_RDY &&
++ time_after_eq(jiffies, ha->eeh_jif + 5 * HZ)) {
++ pci_clear_master(ha->pdev);
++
++ /* flush all command */
++ qla2x00_abort_isp_cleanup(vha);
++ ha->flags.eeh_flush = EEH_FLUSH_DONE;
++
++ ql_log(ql_log_info, vha, 0x900a,
++ "PCI Error handling complete, all IOs aborted.\n");
++ }
++}
++
+ /**************************************************************************
+ * qla2x00_timer
+ *
+@@ -7255,6 +7298,8 @@ qla2x00_timer(struct timer_list *t)
+ fc_port_t *fcport = NULL;
+
+ if (ha->flags.eeh_busy) {
++ qla_wind_down_chip(vha);
++
+ ql_dbg(ql_dbg_timer, vha, 0x6000,
+ "EEH = %d, restarting timer.\n",
+ ha->flags.eeh_busy);
+@@ -7835,6 +7880,9 @@ void qla_pci_set_eeh_busy(struct scsi_qla_host *vha)
+
+ spin_lock_irqsave(&base_vha->work_lock, flags);
+ if (!ha->flags.eeh_busy) {
++ ha->eeh_jif = jiffies;
++ ha->flags.eeh_flush = 0;
++
+ ha->flags.eeh_busy = 1;
+ do_cleanup = true;
+ }
+--
+2.35.1
+
--- /dev/null
+From 2440da0db53103791d3d98b6593db82ffcd684c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Apr 2022 16:27:33 +0100
+Subject: serial: 8250: Add proper clock handling for OxSemi PCIe devices
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+[ Upstream commit 366f6c955d4d1a5125ffcd6875ead26a3c7a2a1c ]
+
+Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven
+by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock.
+
+We currently drive the device using its default oversampling rate of 16
+and the clock prescaler disabled, consequently yielding the baud base of
+3906250. This base is inadequate for some of the high-speed baud rates
+such as 460800bps, for which the closest rate possible can be obtained
+by dividing the baud base by 8, yielding the baud rate of 488281.25bps,
+which is off by 5.9638%. This is enough for data communication to break
+with the remote end talking actual 460800bps, where missed stop bits
+have been observed.
+
+We can do better however, by taking advantage of a reduced oversampling
+rate, which can be set to any integer value from 4 to 16 inclusive by
+programming the TCR register, and by using the clock prescaler, which
+can be set to any value from 1 to 63.875 in increments of 0.125 in the
+CPR/CPR2 register pair. The prescaler has to be explicitly enabled
+though by setting bit 7 in the MCR or otherwise it is bypassed (in the
+enhanced mode that we enable) as if the value of 1 was used.
+
+Make use of these features then as follows:
+
+- Set the baud base to 15625000, reflecting the minimum oversampling
+ rate of 4 with the clock prescaler and divisor both set to 1.
+
+- Override the `set_mctrl' and set the MCR shadow there so as to have
+ MCR[7] always set and have the 8250 core propagate these settings.
+
+- Override the `get_divisor' handler and determine a good combination of
+ parameters by using a lookup table with predetermined value pairs of
+ the oversampling rate and the clock prescaler and finding a pair that
+ divides the input clock such that the quotient, when rounded to the
+ nearest integer, deviates the least from the exact result. Calculate
+ the clock divisor accordingly.
+
+ Scale the resulting oversampling rate (only by powers of two) if
+ possible so as to maximise it, reducing the divisor accordingly, and
+ avoid a divisor overflow for very low baud rates by scaling the
+ oversampling rate and/or the prescaler even if that causes some
+ accuracy loss.
+
+ Also handle the historic spd_cust feature so as to allow one to set
+ all the three parameters manually to arbitrary values, by keeping the
+ low 16 bits for the divisor and then putting TCR in bits 19:16 and
+ CPR/CPR2 in bits 28:20, sanitising the bit pattern supplied such as
+ to clamp CPR/CPR2 values between 0.000 and 0.875 inclusive to 33.875.
+ This preserves compatibility with any existing setups, that is where
+ requesting a custom divisor that only has any bits set among the low
+ 16 the oversampling rate of 16 and the clock prescaler of 33.875 will
+ be used as with the original 8250.
+
+ Finally abuse the `frac' argument to store the determined bit patterns
+ for the TCR, CPR and CPR2 registers.
+
+- Override the `set_divisor' handler so as to set the TCR, CPR and CPR2
+ registers from the `frac' value supplied. Set the divisor as usual.
+
+With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
+limitation imposed by `serial8250_get_baud_rate' standard baud rates
+below 300bps become unavailable in the regular way, e.g. the rate of
+200bps requires the baud base to be divided by 78125 and that is beyond
+the unsigned 16-bit range. The historic spd_cust feature can still be
+used to obtain such rates if so required.
+
+See Documentation/tty/device_drivers/oxsemi-tornado.rst for more details.
+
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181519450.9383@angie.orcam.me.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../tty/device_drivers/oxsemi-tornado.rst | 129 +++++++
+ drivers/tty/serial/8250/8250_pci.c | 339 ++++++++++++++----
+ 2 files changed, 400 insertions(+), 68 deletions(-)
+ create mode 100644 Documentation/tty/device_drivers/oxsemi-tornado.rst
+
+diff --git a/Documentation/tty/device_drivers/oxsemi-tornado.rst b/Documentation/tty/device_drivers/oxsemi-tornado.rst
+new file mode 100644
+index 000000000000..0180d8bb0881
+--- /dev/null
++++ b/Documentation/tty/device_drivers/oxsemi-tornado.rst
+@@ -0,0 +1,129 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++====================================================================
++Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices
++====================================================================
++
++Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven
++by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock.
++
++The baud rate produced by the baud generator is obtained from this input
++frequency by dividing it by the clock prescaler, which can be set to any
++value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit
++divisor is used as with the original 8250, to divide the frequency by a
++value from 1 to 65535. Finally a programmable oversampling rate is used
++that can take any value from 4 to 16 to divide the frequency further and
++determine the actual baud rate used. Baud rates from 15625000bps down
++to 0.933bps can be obtained this way.
++
++By default the oversampling rate is set to 16 and the clock prescaler is
++set to 33.875, meaning that the frequency to be used as the reference
++for the usual 16-bit divisor is 115313.653, which is close enough to the
++frequency of 115200 used by the original 8250 for the same values to be
++used for the divisor to obtain the requested baud rates by software that
++is unaware of the extra clock controls available.
++
++The oversampling rate is programmed with the TCR register and the clock
++prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4].
++To switch away from the default value of 33.875 for the prescaler the
++the enhanced mode has to be explicitly enabled though, by setting bit 4
++of the EFR. In that mode setting bit 7 in the MCR enables the prescaler
++or otherwise it is bypassed as if the value of 1 was used. Additionally
++writing any value to CPR clears CPR2 for compatibility with old software
++written for older conventional PCI Oxford Semiconductor devices that do
++not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register
++pair has to be programmed in the right order.
++
++By using these parameters rates from 15625000bps down to 1bps can be
++obtained, with either exact or highly-accurate actual bit rates for
++standard and many non-standard rates.
++
++Here are the figures for the standard and some non-standard baud rates
++(including those quoted in Oxford Semiconductor documentation), giving
++the requested rate (r), the actual rate yielded (a) and its deviation
++from the requested rate (d), and the values of the oversampling rate
++(tcr), the clock prescaler (cpr) and the divisor (div) produced by the
++new `get_divisor' handler:
++
++r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1
++r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1
++r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1
++r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1
++r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1
++r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1
++r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1
++r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1
++r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1
++r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1
++r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1
++r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1
++r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1
++r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1
++r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2
++r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2
++r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5
++r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5
++r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31
++r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35
++r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30
++r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105
++r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643
++r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647
++r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286
++r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294
++r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215
++r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625
++r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245
++r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153
++r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348
++r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461
++r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500
++r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500
++r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828
++r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828
++r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154
++
++With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX
++limitation imposed by `serial8250_get_baud_rate' standard baud rates
++below 300bps become unavailable in the regular way, e.g. the rate of
++200bps requires the baud base to be divided by 78125 and that is beyond
++the unsigned 16-bit range. The historic spd_cust feature can still be
++used by encoding the values for, the prescaler, the oversampling rate
++and the clock divisor (DLM/DLL) as follows to obtain such rates if so
++required:
++
++ 31 29 28 20 19 16 15 0
+++-----+-----------------+-------+-------------------------------+
++|0 0 0| CPR2:CPR | TCR | DLM:DLL |
+++-----+-----------------+-------+-------------------------------+
++
++Use a value such encoded for the `custom_divisor' field along with the
++ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct'
++passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8)
++utility and its `divisor' and `spd_cust' parameters, and the select
++the baud rate of 38400bps. Note that the value of 0 in TCR sets the
++oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are
++clamped by the driver to 1.
++
++For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL
++respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value,
++the oversampling rate and the clock divisor of 62.500, 16 and 1250
++respectively. These parameters will set the baud rate for the serial
++port to 62500000 / 62.500 / 1250 / 16 = 50bps.
++
++References:
++
++[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor,
++ Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65
++
++[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port",
++ Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode",
++ p. 20
++
++[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford
++ Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20
++
++[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford
++ Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20
++
++Maciej W. Rozycki <macro@orcam.me.uk>
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 20ce812a069c..1860fc969433 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -11,6 +11,7 @@
+ #include <linux/pci.h>
+ #include <linux/string.h>
+ #include <linux/kernel.h>
++#include <linux/math.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/tty.h>
+@@ -1044,6 +1045,208 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ return number_uarts;
+ }
+
++/* Tornado-specific constants for the TCR and CPR registers; see below. */
++#define OXSEMI_TORNADO_TCR_MASK 0xf
++#define OXSEMI_TORNADO_CPR_MASK 0x1ff
++#define OXSEMI_TORNADO_CPR_MIN 0x008
++#define OXSEMI_TORNADO_CPR_DEF 0x10f
++
++/*
++ * Determine the oversampling rate, the clock prescaler, and the clock
++ * divisor for the requested baud rate. The clock rate is 62.5 MHz,
++ * which is four times the baud base, and the prescaler increments in
++ * steps of 1/8. Therefore to make calculations on integers we need
++ * to use a scaled clock rate, which is the baud base multiplied by 32
++ * (or our assumed UART clock rate multiplied by 2).
++ *
++ * The allowed oversampling rates are from 4 up to 16 inclusive (values
++ * from 0 to 3 inclusive map to 16). Likewise the clock prescaler allows
++ * values between 1.000 and 63.875 inclusive (operation for values from
++ * 0.000 to 0.875 has not been specified). The clock divisor is the usual
++ * unsigned 16-bit integer.
++ *
++ * For the most accurate baud rate we use a table of predetermined
++ * oversampling rates and clock prescalers that records all possible
++ * products of the two parameters in the range from 4 up to 255 inclusive,
++ * and additionally 335 for the 1500000bps rate, with the prescaler scaled
++ * by 8. The table is sorted by the decreasing value of the oversampling
++ * rate and ties are resolved by sorting by the decreasing value of the
++ * product. This way preference is given to higher oversampling rates.
++ *
++ * We iterate over the table and choose the product of an oversampling
++ * rate and a clock prescaler that gives the lowest integer division
++ * result deviation, or if an exact integer divider is found we stop
++ * looking for it right away. We do some fixup if the resulting clock
++ * divisor required would be out of its unsigned 16-bit integer range.
++ *
++ * Finally we abuse the supposed fractional part returned to encode the
++ * 4-bit value of the oversampling rate and the 9-bit value of the clock
++ * prescaler which will end up in the TCR and CPR/CPR2 registers.
++ */
++static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port,
++ unsigned int baud,
++ unsigned int *frac)
++{
++ static u8 p[][2] = {
++ { 16, 14, }, { 16, 13, }, { 16, 12, }, { 16, 11, },
++ { 16, 10, }, { 16, 9, }, { 16, 8, }, { 15, 17, },
++ { 15, 16, }, { 15, 15, }, { 15, 14, }, { 15, 13, },
++ { 15, 12, }, { 15, 11, }, { 15, 10, }, { 15, 9, },
++ { 15, 8, }, { 14, 18, }, { 14, 17, }, { 14, 14, },
++ { 14, 13, }, { 14, 12, }, { 14, 11, }, { 14, 10, },
++ { 14, 9, }, { 14, 8, }, { 13, 19, }, { 13, 18, },
++ { 13, 17, }, { 13, 13, }, { 13, 12, }, { 13, 11, },
++ { 13, 10, }, { 13, 9, }, { 13, 8, }, { 12, 19, },
++ { 12, 18, }, { 12, 17, }, { 12, 11, }, { 12, 9, },
++ { 12, 8, }, { 11, 23, }, { 11, 22, }, { 11, 21, },
++ { 11, 20, }, { 11, 19, }, { 11, 18, }, { 11, 17, },
++ { 11, 11, }, { 11, 10, }, { 11, 9, }, { 11, 8, },
++ { 10, 25, }, { 10, 23, }, { 10, 20, }, { 10, 19, },
++ { 10, 17, }, { 10, 10, }, { 10, 9, }, { 10, 8, },
++ { 9, 27, }, { 9, 23, }, { 9, 21, }, { 9, 19, },
++ { 9, 18, }, { 9, 17, }, { 9, 9, }, { 9, 8, },
++ { 8, 31, }, { 8, 29, }, { 8, 23, }, { 8, 19, },
++ { 8, 17, }, { 8, 8, }, { 7, 35, }, { 7, 31, },
++ { 7, 29, }, { 7, 25, }, { 7, 23, }, { 7, 21, },
++ { 7, 19, }, { 7, 17, }, { 7, 15, }, { 7, 14, },
++ { 7, 13, }, { 7, 12, }, { 7, 11, }, { 7, 10, },
++ { 7, 9, }, { 7, 8, }, { 6, 41, }, { 6, 37, },
++ { 6, 31, }, { 6, 29, }, { 6, 23, }, { 6, 19, },
++ { 6, 17, }, { 6, 13, }, { 6, 11, }, { 6, 10, },
++ { 6, 9, }, { 6, 8, }, { 5, 67, }, { 5, 47, },
++ { 5, 43, }, { 5, 41, }, { 5, 37, }, { 5, 31, },
++ { 5, 29, }, { 5, 25, }, { 5, 23, }, { 5, 19, },
++ { 5, 17, }, { 5, 15, }, { 5, 13, }, { 5, 11, },
++ { 5, 10, }, { 5, 9, }, { 5, 8, }, { 4, 61, },
++ { 4, 59, }, { 4, 53, }, { 4, 47, }, { 4, 43, },
++ { 4, 41, }, { 4, 37, }, { 4, 31, }, { 4, 29, },
++ { 4, 23, }, { 4, 19, }, { 4, 17, }, { 4, 13, },
++ { 4, 9, }, { 4, 8, },
++ };
++ /* Scale the quotient for comparison to get the fractional part. */
++ const unsigned int quot_scale = 65536;
++ unsigned int sclk = port->uartclk * 2;
++ unsigned int sdiv = DIV_ROUND_CLOSEST(sclk, baud);
++ unsigned int best_squot;
++ unsigned int squot;
++ unsigned int quot;
++ u16 cpr;
++ u8 tcr;
++ int i;
++
++ /* Old custom speed handling. */
++ if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
++ unsigned int cust_div = port->custom_divisor;
++
++ quot = cust_div & UART_DIV_MAX;
++ tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK;
++ cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK;
++ if (cpr < OXSEMI_TORNADO_CPR_MIN)
++ cpr = OXSEMI_TORNADO_CPR_DEF;
++ } else {
++ best_squot = quot_scale;
++ for (i = 0; i < ARRAY_SIZE(p); i++) {
++ unsigned int spre;
++ unsigned int srem;
++ u8 cp;
++ u8 tc;
++
++ tc = p[i][0];
++ cp = p[i][1];
++ spre = tc * cp;
++
++ srem = sdiv % spre;
++ if (srem > spre / 2)
++ srem = spre - srem;
++ squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre);
++
++ if (srem == 0) {
++ tcr = tc;
++ cpr = cp;
++ quot = sdiv / spre;
++ break;
++ } else if (squot < best_squot) {
++ best_squot = squot;
++ tcr = tc;
++ cpr = cp;
++ quot = DIV_ROUND_CLOSEST(sdiv, spre);
++ }
++ }
++ while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 &&
++ quot % 2 == 0) {
++ quot >>= 1;
++ tcr <<= 1;
++ }
++ while (quot > UART_DIV_MAX) {
++ if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) {
++ quot >>= 1;
++ tcr <<= 1;
++ } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) {
++ quot >>= 1;
++ cpr <<= 1;
++ } else {
++ quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK;
++ cpr = OXSEMI_TORNADO_CPR_MASK;
++ }
++ }
++ }
++
++ *frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK);
++ return quot;
++}
++
++/*
++ * Set the oversampling rate in the transmitter clock cycle register (TCR),
++ * the clock prescaler in the clock prescaler register (CPR and CPR2), and
++ * the clock divisor in the divisor latch (DLL and DLM). Note that for
++ * backwards compatibility any write to CPR clears CPR2 and therefore CPR
++ * has to be written first, followed by CPR2, which occupies the location
++ * of CKS used with earlier UART designs.
++ */
++static void pci_oxsemi_tornado_set_divisor(struct uart_port *port,
++ unsigned int baud,
++ unsigned int quot,
++ unsigned int quot_frac)
++{
++ struct uart_8250_port *up = up_to_u8250p(port);
++ u8 cpr2 = quot_frac >> 16;
++ u8 cpr = quot_frac >> 8;
++ u8 tcr = quot_frac;
++
++ serial_icr_write(up, UART_TCR, tcr);
++ serial_icr_write(up, UART_CPR, cpr);
++ serial_icr_write(up, UART_CKS, cpr2);
++ serial8250_do_set_divisor(port, baud, quot, 0);
++}
++
++/*
++ * For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate
++ * generator prescaler (CPR and CPR2). Otherwise no prescaler would be used.
++ */
++static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port,
++ unsigned int mctrl)
++{
++ struct uart_8250_port *up = up_to_u8250p(port);
++
++ up->mcr |= UART_MCR_CLKSEL;
++ serial8250_do_set_mctrl(port, mctrl);
++}
++
++static int pci_oxsemi_tornado_setup(struct serial_private *priv,
++ const struct pciserial_board *board,
++ struct uart_8250_port *up, int idx)
++{
++ struct pci_dev *dev = priv->dev;
++
++ if (pci_oxsemi_tornado_p(dev)) {
++ up->port.get_divisor = pci_oxsemi_tornado_get_divisor;
++ up->port.set_divisor = pci_oxsemi_tornado_set_divisor;
++ up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl;
++ }
++
++ return pci_default_setup(priv, board, up, idx);
++}
++
+ static int pci_asix_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_8250_port *port, int idx)
+@@ -2507,7 +2710,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+- .setup = pci_default_setup,
++ .setup = pci_oxsemi_tornado_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_MAINPINE,
+@@ -2515,7 +2718,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+- .setup = pci_default_setup,
++ .setup = pci_oxsemi_tornado_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_DIGI,
+@@ -2523,7 +2726,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
+ .subvendor = PCI_SUBVENDOR_ID_IBM,
+ .subdevice = PCI_ANY_ID,
+ .init = pci_oxsemi_tornado_init,
+- .setup = pci_default_setup,
++ .setup = pci_oxsemi_tornado_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+@@ -2840,7 +3043,7 @@ enum pci_board_num_t {
+ pbn_b0_2_1843200,
+ pbn_b0_4_1843200,
+
+- pbn_b0_1_3906250,
++ pbn_b0_1_15625000,
+
+ pbn_b0_bt_1_115200,
+ pbn_b0_bt_2_115200,
+@@ -2919,10 +3122,10 @@ enum pci_board_num_t {
+ pbn_panacom4,
+ pbn_plx_romulus,
+ pbn_oxsemi,
+- pbn_oxsemi_1_3906250,
+- pbn_oxsemi_2_3906250,
+- pbn_oxsemi_4_3906250,
+- pbn_oxsemi_8_3906250,
++ pbn_oxsemi_1_15625000,
++ pbn_oxsemi_2_15625000,
++ pbn_oxsemi_4_15625000,
++ pbn_oxsemi_8_15625000,
+ pbn_intel_i960,
+ pbn_sgi_ioc3,
+ pbn_computone_4,
+@@ -3069,10 +3272,10 @@ static struct pciserial_board pci_boards[] = {
+ .uart_offset = 8,
+ },
+
+- [pbn_b0_1_3906250] = {
++ [pbn_b0_1_15625000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+- .base_baud = 3906250,
++ .base_baud = 15625000,
+ .uart_offset = 8,
+ },
+
+@@ -3453,31 +3656,31 @@ static struct pciserial_board pci_boards[] = {
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+- [pbn_oxsemi_1_3906250] = {
++ [pbn_oxsemi_1_15625000] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+- .base_baud = 3906250,
++ .base_baud = 15625000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_2_3906250] = {
++ [pbn_oxsemi_2_15625000] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+- .base_baud = 3906250,
++ .base_baud = 15625000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_4_3906250] = {
++ [pbn_oxsemi_4_15625000] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+- .base_baud = 3906250,
++ .base_baud = 15625000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_8_3906250] = {
++ [pbn_oxsemi_8_15625000] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+- .base_baud = 3906250,
++ .base_baud = 15625000,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+@@ -4483,165 +4686,165 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ */
+ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_3906250 },
++ pbn_b0_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_3906250 },
++ pbn_oxsemi_2_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_3906250 },
++ pbn_oxsemi_2_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_4_3906250 },
++ pbn_oxsemi_4_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_4_3906250 },
++ pbn_oxsemi_4_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_8_3906250 },
++ pbn_oxsemi_8_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_8_3906250 },
++ pbn_oxsemi_8_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ /*
+ * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
+- pbn_oxsemi_1_3906250 },
++ pbn_oxsemi_1_15625000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
+- pbn_oxsemi_2_3906250 },
++ pbn_oxsemi_2_15625000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
+- pbn_oxsemi_4_3906250 },
++ pbn_oxsemi_4_15625000 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
+- pbn_oxsemi_8_3906250 },
++ pbn_oxsemi_8_15625000 },
+
+ /*
+ * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_3906250 },
++ pbn_oxsemi_2_15625000 },
+ /*
+ * EndRun Technologies. PCI express device range.
+ * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952.
+ */
+ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_3906250 },
++ pbn_oxsemi_2_15625000 },
+
+ /*
+ * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+--
+2.35.1
+
--- /dev/null
+From aa5d7246d233d1983175ca21ac6b0682e3e28515 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Apr 2022 16:27:22 +0100
+Subject: serial: 8250: Fold EndRun device support into OxSemi Tornado code
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+[ Upstream commit 1f32c65bad24b9787d3e52843de375430e3df822 ]
+
+The EndRun PTP/1588 dual serial port device is based on the Oxford
+Semiconductor OXPCIe952 UART device with the PCI vendor:device ID set
+for EndRun Technologies and uses the same sequence to determine the
+number of ports available. Despite that we have duplicate code
+specific to the EndRun device.
+
+Remove redundant code then and factor out OxSemi Tornado device
+detection.
+
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181516220.9383@angie.orcam.me.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 76 ++++++++++--------------------
+ 1 file changed, 25 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 1994d2db213c..20ce812a069c 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -994,41 +994,29 @@ static void pci_ite887x_exit(struct pci_dev *dev)
+ }
+
+ /*
+- * EndRun Technologies.
+- * Determine the number of ports available on the device.
++ * Oxford Semiconductor Inc.
++ * Check if an OxSemi device is part of the Tornado range of devices.
+ */
+ #define PCI_VENDOR_ID_ENDRUN 0x7401
+ #define PCI_DEVICE_ID_ENDRUN_1588 0xe100
+
+-static int pci_endrun_init(struct pci_dev *dev)
++static bool pci_oxsemi_tornado_p(struct pci_dev *dev)
+ {
+- u8 __iomem *p;
+- unsigned long deviceID;
+- unsigned int number_uarts = 0;
++ /* OxSemi Tornado devices are all 0xCxxx */
++ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
++ (dev->device & 0xf000) != 0xc000)
++ return false;
+
+- /* EndRun device is all 0xexxx */
++ /* EndRun devices are all 0xExxx */
+ if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
+- (dev->device & 0xf000) != 0xe000)
+- return 0;
+-
+- p = pci_iomap(dev, 0, 5);
+- if (p == NULL)
+- return -ENOMEM;
++ (dev->device & 0xf000) != 0xe000)
++ return false;
+
+- deviceID = ioread32(p);
+- /* EndRun device */
+- if (deviceID == 0x07000200) {
+- number_uarts = ioread8(p + 4);
+- pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
+- }
+- pci_iounmap(dev, p);
+- return number_uarts;
++ return true;
+ }
+
+ /*
+- * Oxford Semiconductor Inc.
+- * Check that device is part of the Tornado range of devices, then determine
+- * the number of ports available on the device.
++ * Determine the number of ports available on a Tornado device.
+ */
+ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ {
+@@ -1036,9 +1024,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ unsigned long deviceID;
+ unsigned int number_uarts = 0;
+
+- /* OxSemi Tornado devices are all 0xCxxx */
+- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+- (dev->device & 0xF000) != 0xC000)
++ if (!pci_oxsemi_tornado_p(dev))
+ return 0;
+
+ p = pci_iomap(dev, 0, 5);
+@@ -1049,7 +1035,10 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
++ pci_dbg(dev, "%d ports detected on %s PCI Express device\n",
++ number_uarts,
++ dev->vendor == PCI_VENDOR_ID_ENDRUN ?
++ "EndRun" : "Oxford");
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -2506,7 +2495,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+- .init = pci_endrun_init,
++ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ /*
+@@ -2929,7 +2918,6 @@ enum pci_board_num_t {
+ pbn_panacom2,
+ pbn_panacom4,
+ pbn_plx_romulus,
+- pbn_endrun_2_3906250,
+ pbn_oxsemi,
+ pbn_oxsemi_1_3906250,
+ pbn_oxsemi_2_3906250,
+@@ -3455,20 +3443,6 @@ static struct pciserial_board pci_boards[] = {
+ .first_offset = 0x03,
+ },
+
+- /*
+- * EndRun Technologies
+- * Uses the size of PCI Base region 0 to
+- * signal now many ports are available
+- * 2 port 952 Uart support
+- */
+- [pbn_endrun_2_3906250] = {
+- .flags = FL_BASE0,
+- .num_ports = 2,
+- .base_baud = 3906250,
+- .uart_offset = 0x200,
+- .first_offset = 0x1000,
+- },
+-
+ /*
+ * This board uses the size of PCI Base region 0 to
+ * signal now many ports are available
+@@ -4400,13 +4374,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
+ 0x10b5, 0x106a, 0, 0,
+ pbn_plx_romulus },
+- /*
+- * EndRun Technologies. PCI express device range.
+- * EndRun PTP/1588 has 2 Native UARTs.
+- */
+- { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
+- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_endrun_2_3906250 },
+ /*
+ * Quatech cards. These actually have configurable clocks but for
+ * now we just use the default.
+@@ -4668,6 +4635,13 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_3906250 },
++ /*
++ * EndRun Technologies. PCI express device range.
++ * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952.
++ */
++ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ pbn_oxsemi_2_3906250 },
+
+ /*
+ * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+--
+2.35.1
+
--- /dev/null
+From 6805c901d96c34706c924c1422585a22738742d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Oct 2021 16:51:45 +0300
+Subject: serial: 8250_pci: Refactor the loop in pci_ite887x_init()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 35b4f17231923e2f64521bdf7a2793ce2c3c74a6 ]
+
+The loop can be refactored by using ARRAY_SIZE() instead of NULL terminator.
+This reduces code base and makes it easier to read and understand.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Jiri Slaby <jslaby@kernel.org>
+Link: https://lore.kernel.org/r/20211022135147.70965-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index e7b9805903f4..ef44e5320bef 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -897,18 +897,16 @@ static int pci_netmos_init(struct pci_dev *dev)
+ /* enable IO_Space bit */
+ #define ITE_887x_POSIO_ENABLE (1 << 31)
+
++/* inta_addr are the configuration addresses of the ITE */
++static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 };
+ static int pci_ite887x_init(struct pci_dev *dev)
+ {
+- /* inta_addr are the configuration addresses of the ITE */
+- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
+- 0x200, 0x280, 0 };
+ int ret, i, type;
+ struct resource *iobase = NULL;
+ u32 miscr, uartbar, ioport;
+
+ /* search for the base-ioport */
+- i = 0;
+- while (inta_addr[i] && iobase == NULL) {
++ for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
+ iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
+ "ite887x");
+ if (iobase != NULL) {
+@@ -925,12 +923,10 @@ static int pci_ite887x_init(struct pci_dev *dev)
+ break;
+ }
+ release_region(iobase->start, ITE_887x_IOSIZE);
+- iobase = NULL;
+ }
+- i++;
+ }
+
+- if (!inta_addr[i]) {
++ if (i == ARRAY_SIZE(inta_addr)) {
+ dev_err(&dev->dev, "ite887x: could not find iobase\n");
+ return -ENODEV;
+ }
+--
+2.35.1
+
--- /dev/null
+From b265a9249a3f39a92164e0cc1b62fed5b45140cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Oct 2021 16:51:47 +0300
+Subject: serial: 8250_pci: Replace dev_*() by pci_*() macros
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 1177384179416c7136e1348f07609e0da1ae6b91 ]
+
+PCI subsystem provides convenient shortcut macros for message printing.
+Use those macros instead of dev_*().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Jiri Slaby <jslaby@kernel.org>
+Link: https://lore.kernel.org/r/20211022135147.70965-3-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 52 +++++++++++++-----------------
+ 1 file changed, 22 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index ef44e5320bef..1994d2db213c 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -75,13 +75,12 @@ static int pci_default_setup(struct serial_private*,
+
+ static void moan_device(const char *str, struct pci_dev *dev)
+ {
+- dev_err(&dev->dev,
+- "%s: %s\n"
++ pci_err(dev, "%s\n"
+ "Please send the output of lspci -vv, this\n"
+ "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+ "manufacturer and name of serial board or\n"
+ "modem board to <linux-serial@vger.kernel.org>.\n",
+- pci_name(dev), str, dev->vendor, dev->device,
++ str, dev->vendor, dev->device,
+ dev->subsystem_vendor, dev->subsystem_device);
+ }
+
+@@ -238,7 +237,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev)
+ /* is firmware started? */
+ pci_read_config_dword(dev, 0x44, &oldval);
+ if (oldval == 0x00001000L) { /* RESET value */
+- dev_dbg(&dev->dev, "Local i960 firmware missing\n");
++ pci_dbg(dev, "Local i960 firmware missing\n");
+ return -ENODEV;
+ }
+ return 0;
+@@ -588,9 +587,8 @@ static int pci_timedia_probe(struct pci_dev *dev)
+ * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
+ */
+ if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+- dev_info(&dev->dev,
+- "ignoring Timedia subdevice %04x for parport_serial\n",
+- dev->subsystem_device);
++ pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n",
++ dev->subsystem_device);
+ return -ENODEV;
+ }
+
+@@ -827,8 +825,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
+ if (sub_serports > 0)
+ return sub_serports;
+
+- dev_err(&dev->dev,
+- "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
++ pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+ return 0;
+ }
+
+@@ -927,7 +924,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
+ }
+
+ if (i == ARRAY_SIZE(inta_addr)) {
+- dev_err(&dev->dev, "ite887x: could not find iobase\n");
++ pci_err(dev, "could not find iobase\n");
+ return -ENODEV;
+ }
+
+@@ -1022,9 +1019,7 @@ static int pci_endrun_init(struct pci_dev *dev)
+ /* EndRun device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- dev_dbg(&dev->dev,
+- "%d ports detected on EndRun PCI Express device\n",
+- number_uarts);
++ pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -1054,9 +1049,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- dev_dbg(&dev->dev,
+- "%d ports detected on Oxford PCI Express device\n",
+- number_uarts);
++ pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -1116,15 +1109,15 @@ static struct quatech_feature quatech_cards[] = {
+ { 0, }
+ };
+
+-static int pci_quatech_amcc(u16 devid)
++static int pci_quatech_amcc(struct pci_dev *dev)
+ {
+ struct quatech_feature *qf = &quatech_cards[0];
+ while (qf->devid) {
+- if (qf->devid == devid)
++ if (qf->devid == dev->device)
+ return qf->amcc;
+ qf++;
+ }
+- pr_err("quatech: unknown port type '0x%04X'.\n", devid);
++ pci_err(dev, "unknown port type '0x%04X'.\n", dev->device);
+ return 0;
+ };
+
+@@ -1287,7 +1280,7 @@ static int pci_quatech_rs422(struct uart_8250_port *port)
+
+ static int pci_quatech_init(struct pci_dev *dev)
+ {
+- if (pci_quatech_amcc(dev->device)) {
++ if (pci_quatech_amcc(dev)) {
+ unsigned long base = pci_resource_start(dev, 0);
+ if (base) {
+ u32 tmp;
+@@ -1311,7 +1304,7 @@ static int pci_quatech_setup(struct serial_private *priv,
+ port->port.uartclk = pci_quatech_clock(port);
+ /* For now just warn about RS422 */
+ if (pci_quatech_rs422(port))
+- pr_warn("quatech: software control of RS422 features not currently supported.\n");
++ pci_warn(priv->dev, "software control of RS422 features not currently supported.\n");
+ return pci_default_setup(priv, board, port, idx);
+ }
+
+@@ -1525,7 +1518,7 @@ static int pci_fintek_setup(struct serial_private *priv,
+ /* Get the io address from configuration space */
+ pci_read_config_word(pdev, config_base + 4, &iobase);
+
+- dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase);
++ pci_dbg(pdev, "idx=%d iobase=0x%x", idx, iobase);
+
+ port->port.iotype = UPIO_PORT;
+ port->port.iobase = iobase;
+@@ -1689,7 +1682,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
+ struct uart_8250_port *port, int idx)
+ {
+ port->port.quirks |= UPQ_NO_TXEN_TEST;
+- dev_dbg(&priv->dev->dev,
++ pci_dbg(priv->dev,
+ "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ priv->dev->vendor, priv->dev->device,
+ priv->dev->subsystem_vendor, priv->dev->subsystem_device);
+@@ -4007,12 +4000,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+ uart.port.irq = 0;
+ } else {
+ if (pci_match_id(pci_use_msi, dev)) {
+- dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
++ pci_dbg(dev, "Using MSI(-X) interrupts\n");
+ pci_set_master(dev);
+ uart.port.flags &= ~UPF_SHARE_IRQ;
+ rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
+ } else {
+- dev_dbg(&dev->dev, "Using legacy interrupts\n");
++ pci_dbg(dev, "Using legacy interrupts\n");
+ rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
+ }
+ if (rc < 0) {
+@@ -4030,12 +4023,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+ if (quirk->setup(priv, board, &uart, i))
+ break;
+
+- dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
++ pci_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
+
+ priv->line[i] = serial8250_register_8250_port(&uart);
+ if (priv->line[i] < 0) {
+- dev_err(&dev->dev,
++ pci_err(dev,
+ "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
+ uart.port.iobase, uart.port.irq,
+ uart.port.iotype, priv->line[i]);
+@@ -4131,8 +4124,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ }
+
+ if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+- dev_err(&dev->dev, "invalid driver_data: %ld\n",
+- ent->driver_data);
++ pci_err(dev, "invalid driver_data: %ld\n", ent->driver_data);
+ return -EINVAL;
+ }
+
+@@ -4215,7 +4207,7 @@ static int pciserial_resume_one(struct device *dev)
+ err = pci_enable_device(pdev);
+ /* FIXME: We cannot simply error out here */
+ if (err)
+- dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
++ pci_err(pdev, "Unable to re-enable ports, trying to continue.\n");
+ pciserial_resume_ports(priv);
+ }
+ return 0;
+--
+2.35.1
+
input-gscps2-check-return-value-of-ioremap-in-gscps2_probe.patch
__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch
spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch
+drm-mediatek-allow-commands-to-be-sent-during-video-.patch
+drm-mediatek-keep-dsi-as-lp00-before-dcs-cmds-transf.patch
+crypto-blake2s-remove-shash-module.patch
+drm-dp-mst-read-the-extended-dpcd-capabilities-durin.patch
+scsi-qla2xxx-fix-excessive-i-o-error-messages-by-def.patch
+scsi-qla2xxx-wind-down-adapter-after-pcie-error.patch-6065
+scsi-qla2xxx-turn-off-multi-queue-for-8g-adapters.patch-24759
+scsi-qla2xxx-fix-crash-due-to-stale-srb-access-aroun.patch
+scsi-qla2xxx-fix-losing-fcp-2-targets-during-port-pe.patch
+scsi-qla2xxx-fix-losing-target-when-it-reappears-dur.patch
+scsi-qla2xxx-fix-losing-fcp-2-targets-on-long-port-d.patch
+scsi-qla2xxx-fix-erroneous-mailbox-timeout-after-pci.patch
+drm-vc4-drv-adopt-the-dma-configuration-from-the-hvs.patch
+usbnet-smsc95xx-don-t-clear-read-only-phy-interrupt.patch
+usbnet-smsc95xx-avoid-link-settings-race-on-interrup.patch
+usbnet-smsc95xx-forward-phy-interrupts-to-phy-driver.patch
+usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch
+firmware-arm_scpi-ensure-scpi_info-is-not-assigned-i.patch
+__follow_mount_rcu-verify-that-mount_lock-remains-un.patch
+scsi-lpfc-fix-eeh-support-for-nvme-i-o.patch
+scsi-lpfc-sli-path-split-refactor-lpfc_iocbq.patch
+scsi-lpfc-sli-path-split-refactor-fast-and-slow-path.patch
+scsi-lpfc-sli-path-split-refactor-scsi-paths.patch
+scsi-lpfc-remove-extra-atomic_inc-on-cmd_pending-in-.patch
+intel_th-pci-add-meteor-lake-p-support.patch
+intel_th-pci-add-raptor-lake-s-pch-support.patch
+intel_th-pci-add-raptor-lake-s-cpu-support.patch
+kvm-set_msr_mce-permit-guests-to-ignore-single-bit-e.patch
+kvm-x86-signal-gp-not-eperm-on-bad-wrmsr-mci_ctl-sta.patch
+iommu-vt-d-avoid-invalid-memory-access-via-node_onli.patch
+pci-aer-iterate-over-error-counters-instead-of-error.patch
+pci-qcom-power-on-phy-before-ipq8074-dbi-register-ac.patch
+serial-8250_pci-refactor-the-loop-in-pci_ite887x_ini.patch
+serial-8250_pci-replace-dev_-by-pci_-macros.patch
+serial-8250-fold-endrun-device-support-into-oxsemi-t.patch
+serial-8250-add-proper-clock-handling-for-oxsemi-pci.patch
+tty-8250-add-support-for-brainboxes-px-cards.patch
+dm-writecache-set-a-default-max_writeback_jobs.patch
+x86-olpc-fix-logical-not-is-only-applied-to-the-left.patch
+topology-represent-clusters-of-cpus-within-a-die.patch
+topology-sysfs-export-die-attributes-only-if-an-arch.patch
+topology-sysfs-export-cluster-attributes-only-if-an-.patch
+drivers-base-fix-userspace-break-from-using-bin_attr.patch
+kexec-keys-s390-make-use-of-built-in-and-secondary-k.patch
+dm-thin-fix-use-after-free-crash-in-dm_sm_register_t.patch
+net-9p-initialize-the-iounit-field-during-fid-creati.patch
+arm-remove-some-dead-code.patch
+timekeeping-contribute-wall-clock-to-rng-on-time-cha.patch
+scsi-qla2xxx-fix-response-queue-handler-reading-stal.patch
+scsi-qla2xxx-edif-fix-dropped-ike-message.patch
+scsi-qla2xxx-fix-imbalance-vha-vref_count.patch-21291
+scsi-qla2xxx-fix-discovery-issues-in-fc-al-topology.patch-12842
+scsi-qla2xxx-update-manufacturer-details.patch
+locking-csd_lock-change-csdlock_debug-from-early_par.patch
+block-remove-the-struct-blk_queue_ctx-forward-declar.patch
+block-don-t-allow-the-same-type-rq_qos-add-more-than.patch
+spmi-trace-fix-stack-out-of-bound-access-in-spmi-tra.patch
+btrfs-ensure-pages-are-unlocked-on-cow_file_range-fa.patch
+btrfs-reset-block-group-chunk-force-if-we-have-to-wa.patch
+btrfs-properly-flag-filesystem-with-btrfs_feature_in.patch
+acpi-cppc-do-not-prevent-cppc-from-working-in-the-fu.patch
+powerpc-powernv-kvm-use-darn-for-h_random-on-power9.patch
+kvm-x86-pmu-introduce-the-ctrl_mask-value-for-fixed-.patch
+kvm-vmx-mark-all-perf_global_-ovf-_ctrl-bits-reserve.patch
+kvm-x86-pmu-ignore-pmu-global_ctrl-check-if-vpmu-doe.patch
+kvm-vmx-add-helper-to-check-if-the-guest-pmu-has-per.patch
+kvm-nvmx-attempt-to-load-perf_global_ctrl-on-nvmx-xf.patch
+dm-raid-fix-address-sanitizer-warning-in-raid_status.patch
+dm-raid-fix-address-sanitizer-warning-in-raid_resume.patch
+ftrace-x86-add-back-ftrace_expected-assignment.patch-22490
+tracing-add-__rel_loc-using-trace-event-macros.patch
+tracing-avoid-warray-bounds-warning-for-__rel_loc-ma.patch
+input-gscps2-check-return-value-of-ioremap-in-gscps2.patch
+x86-kprobes-update-kcb-status-flag-after-singlestepp.patch
+ext4-update-s_overhead_clusters-in-the-superblock-du.patch
+ext4-fix-extent-status-tree-race-in-writeback-error-.patch
+ext4-add-ext4_inode_has_xattr_space-macro-in-xattr.h.patch
+ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch
+ext4-correct-max_inline_xattr_value_size-computing.patch
+ext4-correct-the-misjudgment-in-ext4_iget_extra_inod.patch
+ext4-fix-warning-in-ext4_iomap_begin-as-race-between.patch
+ext4-check-if-directory-block-is-within-i_size.patch
+ext4-make-sure-ext4_append-always-allocates-new-bloc.patch
+ext4-remove-ea-inode-entry-from-mbcache-on-inode-evi.patch
+ext4-use-kmemdup-to-replace-kmalloc-memcpy.patch
+ext4-unindent-codeblock-in-ext4_xattr_block_set.patch
+ext4-fix-race-when-reusing-xattr-blocks.patch
+keys-asymmetric-enforce-sm2-signature-use-pkey-algo.patch
+tpm-eventlog-fix-section-mismatch-for-debug_section_.patch
--- /dev/null
+From 2164f615c64d6f8549823f48cde9c7450e5e84d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 16:55:12 -0700
+Subject: spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
+
+From: David Collins <quic_collinsd@quicinc.com>
+
+[ Upstream commit 2af28b241eea816e6f7668d1954f15894b45d7e3 ]
+
+trace_spmi_write_begin() and trace_spmi_read_end() both call
+memcpy() with a length of "len + 1". This leads to one extra
+byte being read beyond the end of the specified buffer. Fix
+this out-of-bound memory access by using a length of "len"
+instead.
+
+Here is a KASAN log showing the issue:
+
+BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_spmi_read_end+0x1d0/0x234
+Read of size 2 at addr ffffffc0265b7540 by task thermal@2.0-ser/1314
+...
+Call trace:
+ dump_backtrace+0x0/0x3e8
+ show_stack+0x2c/0x3c
+ dump_stack_lvl+0xdc/0x11c
+ print_address_description+0x74/0x384
+ kasan_report+0x188/0x268
+ kasan_check_range+0x270/0x2b0
+ memcpy+0x90/0xe8
+ trace_event_raw_event_spmi_read_end+0x1d0/0x234
+ spmi_read_cmd+0x294/0x3ac
+ spmi_ext_register_readl+0x84/0x9c
+ regmap_spmi_ext_read+0x144/0x1b0 [regmap_spmi]
+ _regmap_raw_read+0x40c/0x754
+ regmap_raw_read+0x3a0/0x514
+ regmap_bulk_read+0x418/0x494
+ adc5_gen3_poll_wait_hs+0xe8/0x1e0 [qcom_spmi_adc5_gen3]
+ ...
+ __arm64_sys_read+0x4c/0x60
+ invoke_syscall+0x80/0x218
+ el0_svc_common+0xec/0x1c8
+ ...
+
+addr ffffffc0265b7540 is located in stack of task thermal@2.0-ser/1314 at offset 32 in frame:
+ adc5_gen3_poll_wait_hs+0x0/0x1e0 [qcom_spmi_adc5_gen3]
+
+this frame has 1 object:
+ [32, 33) 'status'
+
+Memory state around the buggy address:
+ ffffffc0265b7400: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
+ ffffffc0265b7480: 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
+>ffffffc0265b7500: 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3 00 00 00 00
+ ^
+ ffffffc0265b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffffffc0265b7600: f1 f1 f1 f1 01 f2 07 f2 f2 f2 01 f3 00 00 00 00
+==================================================================
+
+Fixes: a9fce374815d ("spmi: add command tracepoints for SPMI")
+Cc: stable@vger.kernel.org
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: David Collins <quic_collinsd@quicinc.com>
+Link: https://lore.kernel.org/r/20220627235512.2272783-1-quic_collinsd@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/spmi.h | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h
+index 8b60efe18ba6..a6819fd85cdf 100644
+--- a/include/trace/events/spmi.h
++++ b/include/trace/events/spmi.h
+@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin,
+ __field ( u8, sid )
+ __field ( u16, addr )
+ __field ( u8, len )
+- __dynamic_array ( u8, buf, len + 1 )
++ __dynamic_array ( u8, buf, len )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+- __entry->len = len + 1;
+- memcpy(__get_dynamic_array(buf), buf, len + 1);
++ __entry->len = len;
++ memcpy(__get_dynamic_array(buf), buf, len);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]",
+@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end,
+ __field ( u16, addr )
+ __field ( int, ret )
+ __field ( u8, len )
+- __dynamic_array ( u8, buf, len + 1 )
++ __dynamic_array ( u8, buf, len )
+ ),
+
+ TP_fast_assign(
+@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end,
+ __entry->sid = sid;
+ __entry->addr = addr;
+ __entry->ret = ret;
+- __entry->len = len + 1;
+- memcpy(__get_dynamic_array(buf), buf, len + 1);
++ __entry->len = len;
++ memcpy(__get_dynamic_array(buf), buf, len);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",
+--
+2.35.1
+
--- /dev/null
+From cd57e246465d84fac3e0eb2b338b665c889a0319 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Jul 2022 23:53:34 +0200
+Subject: timekeeping: contribute wall clock to rng on time change
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit b8ac29b40183a6038919768b5d189c9bd91ce9b4 ]
+
+The rng's random_init() function contributes the real time to the rng at
+boot time, so that events can at least start in relation to something
+particular in the real world. But this clock might not yet be set that
+point in boot, so nothing is contributed. In addition, the relation
+between minor clock changes from, say, NTP, and the cycle counter is
+potentially useful entropic data.
+
+This commit addresses this by mixing in a time stamp on calls to
+settimeofday and adjtimex. No entropy is credited in doing so, so it
+doesn't make initialization faster, but it is still useful input to
+have.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/timekeeping.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index 871c912860ed..d6a0ff68df41 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -23,6 +23,7 @@
+ #include <linux/pvclock_gtod.h>
+ #include <linux/compiler.h>
+ #include <linux/audit.h>
++#include <linux/random.h>
+
+ #include "tick-internal.h"
+ #include "ntp_internal.h"
+@@ -1326,8 +1327,10 @@ int do_settimeofday64(const struct timespec64 *ts)
+ /* Signal hrtimers about time change */
+ clock_was_set(CLOCK_SET_WALL);
+
+- if (!ret)
++ if (!ret) {
+ audit_tk_injoffset(ts_delta);
++ add_device_randomness(ts, sizeof(*ts));
++ }
+
+ return ret;
+ }
+@@ -2413,6 +2416,7 @@ int do_adjtimex(struct __kernel_timex *txc)
+ ret = timekeeping_validate_timex(txc);
+ if (ret)
+ return ret;
++ add_device_randomness(txc, sizeof(*txc));
+
+ if (txc->modes & ADJ_SETOFFSET) {
+ struct timespec64 delta;
+@@ -2430,6 +2434,7 @@ int do_adjtimex(struct __kernel_timex *txc)
+ audit_ntp_init(&ad);
+
+ ktime_get_real_ts64(&ts);
++ add_device_randomness(&ts, sizeof(ts));
+
+ raw_spin_lock_irqsave(&timekeeper_lock, flags);
+ write_seqcount_begin(&tk_core.seq);
+--
+2.35.1
+
--- /dev/null
+From 384461141ad56b514a9d7c6b3aa4f8ae5c27daff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Sep 2021 20:51:02 +1200
+Subject: topology: Represent clusters of CPUs within a die
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit c5e22feffdd736cb02b98b0f5b375c8ebc858dd4 ]
+
+Both ACPI and DT provide the ability to describe additional layers of
+topology between that of individual cores and higher level constructs
+such as the level at which the last level cache is shared.
+In ACPI this can be represented in PPTT as a Processor Hierarchy
+Node Structure [1] that is the parent of the CPU cores and in turn
+has a parent Processor Hierarchy Nodes Structure representing
+a higher level of topology.
+
+For example Kunpeng 920 has 6 or 8 clusters in each NUMA node, and each
+cluster has 4 cpus. All clusters share L3 cache data, but each cluster
+has local L3 tag. On the other hand, each clusters will share some
+internal system bus.
+
++-----------------------------------+ +---------+
+| +------+ +------+ +--------------------------+ |
+| | CPU0 | | cpu1 | | +-----------+ | |
+| +------+ +------+ | | | | |
+| +----+ L3 | | |
+| +------+ +------+ cluster | | tag | | |
+| | CPU2 | | CPU3 | | | | | |
+| +------+ +------+ | +-----------+ | |
+| | | |
++-----------------------------------+ | |
++-----------------------------------+ | |
+| +------+ +------+ +--------------------------+ |
+| | | | | | +-----------+ | |
+| +------+ +------+ | | | | |
+| | | L3 | | |
+| +------+ +------+ +----+ tag | | |
+| | | | | | | | | |
+| +------+ +------+ | +-----------+ | |
+| | | |
++-----------------------------------+ | L3 |
+ | data |
++-----------------------------------+ | |
+| +------+ +------+ | +-----------+ | |
+| | | | | | | | | |
+| +------+ +------+ +----+ L3 | | |
+| | | tag | | |
+| +------+ +------+ | | | | |
+| | | | | | +-----------+ | |
+| +------+ +------+ +--------------------------+ |
++-----------------------------------| | |
++-----------------------------------| | |
+| +------+ +------+ +--------------------------+ |
+| | | | | | +-----------+ | |
+| +------+ +------+ | | | | |
+| +----+ L3 | | |
+| +------+ +------+ | | tag | | |
+| | | | | | | | | |
+| +------+ +------+ | +-----------+ | |
+| | | |
++-----------------------------------+ | |
++-----------------------------------+ | |
+| +------+ +------+ +--------------------------+ |
+| | | | | | +-----------+ | |
+| +------+ +------+ | | | | |
+| | | L3 | | |
+| +------+ +------+ +---+ tag | | |
+| | | | | | | | | |
+| +------+ +------+ | +-----------+ | |
+| | | |
++-----------------------------------+ | |
++-----------------------------------+ | |
+| +------+ +------+ +--------------------------+ |
+| | | | | | +-----------+ | |
+| +------+ +------+ | | | | |
+| | | L3 | | |
+| +------+ +------+ +--+ tag | | |
+| | | | | | | | | |
+| +------+ +------+ | +-----------+ | |
+| | +---------+
++-----------------------------------+
+
+That means spreading tasks among clusters will bring more bandwidth
+while packing tasks within one cluster will lead to smaller cache
+synchronization latency. So both kernel and userspace will have
+a chance to leverage this topology to deploy tasks accordingly to
+achieve either smaller cache latency within one cluster or an even
+distribution of load among clusters for higher throughput.
+
+This patch exposes cluster topology to both kernel and userspace.
+Libraried like hwloc will know cluster by cluster_cpus and related
+sysfs attributes. PoC of HWLOC support at [2].
+
+Note this patch only handle the ACPI case.
+
+Special consideration is needed for SMT processors, where it is
+necessary to move 2 levels up the hierarchy from the leaf nodes
+(thus skipping the processor core level).
+
+Note that arm64 / ACPI does not provide any means of identifying
+a die level in the topology but that may be unrelate to the cluster
+level.
+
+[1] ACPI Specification 6.3 - section 5.2.29.1 processor hierarchy node
+ structure (Type 0)
+[2] https://github.com/hisilicon/hwloc/tree/linux-cluster
+
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
+Signed-off-by: Barry Song <song.bao.hua@hisilicon.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20210924085104.44806-2-21cnbao@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ABI/stable/sysfs-devices-system-cpu | 15 +++++
+ Documentation/admin-guide/cputopology.rst | 12 ++--
+ arch/arm64/kernel/topology.c | 2 +
+ drivers/acpi/pptt.c | 67 +++++++++++++++++++
+ drivers/base/arch_topology.c | 15 +++++
+ drivers/base/topology.c | 10 +++
+ include/linux/acpi.h | 5 ++
+ include/linux/arch_topology.h | 5 ++
+ include/linux/topology.h | 6 ++
+ 9 files changed, 133 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/ABI/stable/sysfs-devices-system-cpu b/Documentation/ABI/stable/sysfs-devices-system-cpu
+index 516dafea03eb..3965ce504484 100644
+--- a/Documentation/ABI/stable/sysfs-devices-system-cpu
++++ b/Documentation/ABI/stable/sysfs-devices-system-cpu
+@@ -42,6 +42,12 @@ Description: the CPU core ID of cpuX. Typically it is the hardware platform's
+ architecture and platform dependent.
+ Values: integer
+
++What: /sys/devices/system/cpu/cpuX/topology/cluster_id
++Description: the cluster ID of cpuX. Typically it is the hardware platform's
++ identifier (rather than the kernel's). The actual value is
++ architecture and platform dependent.
++Values: integer
++
+ What: /sys/devices/system/cpu/cpuX/topology/book_id
+ Description: the book ID of cpuX. Typically it is the hardware platform's
+ identifier (rather than the kernel's). The actual value is
+@@ -85,6 +91,15 @@ Description: human-readable list of CPUs within the same die.
+ The format is like 0-3, 8-11, 14,17.
+ Values: decimal list.
+
++What: /sys/devices/system/cpu/cpuX/topology/cluster_cpus
++Description: internal kernel map of CPUs within the same cluster.
++Values: hexadecimal bitmask.
++
++What: /sys/devices/system/cpu/cpuX/topology/cluster_cpus_list
++Description: human-readable list of CPUs within the same cluster.
++ The format is like 0-3, 8-11, 14,17.
++Values: decimal list.
++
+ What: /sys/devices/system/cpu/cpuX/topology/book_siblings
+ Description: internal kernel map of cpuX's hardware threads within the same
+ book_id. it's only used on s390.
+diff --git a/Documentation/admin-guide/cputopology.rst b/Documentation/admin-guide/cputopology.rst
+index b085dbac60a5..6b62e182baf4 100644
+--- a/Documentation/admin-guide/cputopology.rst
++++ b/Documentation/admin-guide/cputopology.rst
+@@ -19,11 +19,13 @@ these macros in include/asm-XXX/topology.h::
+
+ #define topology_physical_package_id(cpu)
+ #define topology_die_id(cpu)
++ #define topology_cluster_id(cpu)
+ #define topology_core_id(cpu)
+ #define topology_book_id(cpu)
+ #define topology_drawer_id(cpu)
+ #define topology_sibling_cpumask(cpu)
+ #define topology_core_cpumask(cpu)
++ #define topology_cluster_cpumask(cpu)
+ #define topology_die_cpumask(cpu)
+ #define topology_book_cpumask(cpu)
+ #define topology_drawer_cpumask(cpu)
+@@ -39,10 +41,12 @@ not defined by include/asm-XXX/topology.h:
+
+ 1) topology_physical_package_id: -1
+ 2) topology_die_id: -1
+-3) topology_core_id: 0
+-4) topology_sibling_cpumask: just the given CPU
+-5) topology_core_cpumask: just the given CPU
+-6) topology_die_cpumask: just the given CPU
++3) topology_cluster_id: -1
++4) topology_core_id: 0
++5) topology_sibling_cpumask: just the given CPU
++6) topology_core_cpumask: just the given CPU
++7) topology_cluster_cpumask: just the given CPU
++8) topology_die_cpumask: just the given CPU
+
+ For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
+ default definitions for topology_book_id() and topology_book_cpumask().
+diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
+index 4dd14a6620c1..9ab78ad826e2 100644
+--- a/arch/arm64/kernel/topology.c
++++ b/arch/arm64/kernel/topology.c
+@@ -103,6 +103,8 @@ int __init parse_acpi_topology(void)
+ cpu_topology[cpu].thread_id = -1;
+ cpu_topology[cpu].core_id = topology_id;
+ }
++ topology_id = find_acpi_cpu_topology_cluster(cpu);
++ cpu_topology[cpu].cluster_id = topology_id;
+ topology_id = find_acpi_cpu_topology_package(cpu);
+ cpu_topology[cpu].package_id = topology_id;
+
+diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
+index fe69dc518f31..701f61c01359 100644
+--- a/drivers/acpi/pptt.c
++++ b/drivers/acpi/pptt.c
+@@ -746,6 +746,73 @@ int find_acpi_cpu_topology_package(unsigned int cpu)
+ ACPI_PPTT_PHYSICAL_PACKAGE);
+ }
+
++/**
++ * find_acpi_cpu_topology_cluster() - Determine a unique CPU cluster value
++ * @cpu: Kernel logical CPU number
++ *
++ * Determine a topology unique cluster ID for the given CPU/thread.
++ * This ID can then be used to group peers, which will have matching ids.
++ *
++ * The cluster, if present is the level of topology above CPUs. In a
++ * multi-thread CPU, it will be the level above the CPU, not the thread.
++ * It may not exist in single CPU systems. In simple multi-CPU systems,
++ * it may be equal to the package topology level.
++ *
++ * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found
++ * or there is no toplogy level above the CPU..
++ * Otherwise returns a value which represents the package for this CPU.
++ */
++
++int find_acpi_cpu_topology_cluster(unsigned int cpu)
++{
++ struct acpi_table_header *table;
++ acpi_status status;
++ struct acpi_pptt_processor *cpu_node, *cluster_node;
++ u32 acpi_cpu_id;
++ int retval;
++ int is_thread;
++
++ status = acpi_get_table(ACPI_SIG_PPTT, 0, &table);
++ if (ACPI_FAILURE(status)) {
++ acpi_pptt_warn_missing();
++ return -ENOENT;
++ }
++
++ acpi_cpu_id = get_acpi_id_for_cpu(cpu);
++ cpu_node = acpi_find_processor_node(table, acpi_cpu_id);
++ if (cpu_node == NULL || !cpu_node->parent) {
++ retval = -ENOENT;
++ goto put_table;
++ }
++
++ is_thread = cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD;
++ cluster_node = fetch_pptt_node(table, cpu_node->parent);
++ if (cluster_node == NULL) {
++ retval = -ENOENT;
++ goto put_table;
++ }
++ if (is_thread) {
++ if (!cluster_node->parent) {
++ retval = -ENOENT;
++ goto put_table;
++ }
++ cluster_node = fetch_pptt_node(table, cluster_node->parent);
++ if (cluster_node == NULL) {
++ retval = -ENOENT;
++ goto put_table;
++ }
++ }
++ if (cluster_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID)
++ retval = cluster_node->acpi_processor_id;
++ else
++ retval = ACPI_PTR_DIFF(cluster_node, table);
++
++put_table:
++ acpi_put_table(table);
++
++ return retval;
++}
++
+ /**
+ * find_acpi_cpu_topology_hetero_id() - Get a core architecture tag
+ * @cpu: Kernel logical CPU number
+diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
+index ef4fc89f085d..3d6df911bcb3 100644
+--- a/drivers/base/arch_topology.c
++++ b/drivers/base/arch_topology.c
+@@ -600,6 +600,11 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
+ return core_mask;
+ }
+
++const struct cpumask *cpu_clustergroup_mask(int cpu)
++{
++ return &cpu_topology[cpu].cluster_sibling;
++}
++
+ void update_siblings_masks(unsigned int cpuid)
+ {
+ struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
+@@ -617,6 +622,12 @@ void update_siblings_masks(unsigned int cpuid)
+ if (cpuid_topo->package_id != cpu_topo->package_id)
+ continue;
+
++ if (cpuid_topo->cluster_id == cpu_topo->cluster_id &&
++ cpuid_topo->cluster_id != -1) {
++ cpumask_set_cpu(cpu, &cpuid_topo->cluster_sibling);
++ cpumask_set_cpu(cpuid, &cpu_topo->cluster_sibling);
++ }
++
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+ cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
+
+@@ -635,6 +646,9 @@ static void clear_cpu_topology(int cpu)
+ cpumask_clear(&cpu_topo->llc_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
+
++ cpumask_clear(&cpu_topo->cluster_sibling);
++ cpumask_set_cpu(cpu, &cpu_topo->cluster_sibling);
++
+ cpumask_clear(&cpu_topo->core_sibling);
+ cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
+ cpumask_clear(&cpu_topo->thread_sibling);
+@@ -650,6 +664,7 @@ void __init reset_cpu_topology(void)
+
+ cpu_topo->thread_id = -1;
+ cpu_topo->core_id = -1;
++ cpu_topo->cluster_id = -1;
+ cpu_topo->package_id = -1;
+ cpu_topo->llc_id = -1;
+
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index 43c0940643f5..8f2b641d0b8c 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -48,6 +48,9 @@ static DEVICE_ATTR_RO(physical_package_id);
+ define_id_show_func(die_id);
+ static DEVICE_ATTR_RO(die_id);
+
++define_id_show_func(cluster_id);
++static DEVICE_ATTR_RO(cluster_id);
++
+ define_id_show_func(core_id);
+ static DEVICE_ATTR_RO(core_id);
+
+@@ -63,6 +66,10 @@ define_siblings_read_func(core_siblings, core_cpumask);
+ static BIN_ATTR_RO(core_siblings, 0);
+ static BIN_ATTR_RO(core_siblings_list, 0);
+
++define_siblings_read_func(cluster_cpus, cluster_cpumask);
++static BIN_ATTR_RO(cluster_cpus, 0);
++static BIN_ATTR_RO(cluster_cpus_list, 0);
++
+ define_siblings_read_func(die_cpus, die_cpumask);
+ static BIN_ATTR_RO(die_cpus, 0);
+ static BIN_ATTR_RO(die_cpus_list, 0);
+@@ -94,6 +101,8 @@ static struct bin_attribute *bin_attrs[] = {
+ &bin_attr_thread_siblings_list,
+ &bin_attr_core_siblings,
+ &bin_attr_core_siblings_list,
++ &bin_attr_cluster_cpus,
++ &bin_attr_cluster_cpus_list,
+ &bin_attr_die_cpus,
+ &bin_attr_die_cpus_list,
+ &bin_attr_package_cpus,
+@@ -112,6 +121,7 @@ static struct bin_attribute *bin_attrs[] = {
+ static struct attribute *default_attrs[] = {
+ &dev_attr_physical_package_id.attr,
+ &dev_attr_die_id.attr,
++ &dev_attr_cluster_id.attr,
+ &dev_attr_core_id.attr,
+ #ifdef CONFIG_SCHED_BOOK
+ &dev_attr_book_id.attr,
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 6224b1e32681..878a62266304 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -1362,6 +1362,7 @@ static inline int lpit_read_residency_count_address(u64 *address)
+ #ifdef CONFIG_ACPI_PPTT
+ int acpi_pptt_cpu_is_thread(unsigned int cpu);
+ int find_acpi_cpu_topology(unsigned int cpu, int level);
++int find_acpi_cpu_topology_cluster(unsigned int cpu);
+ int find_acpi_cpu_topology_package(unsigned int cpu);
+ int find_acpi_cpu_topology_hetero_id(unsigned int cpu);
+ int find_acpi_cpu_cache_topology(unsigned int cpu, int level);
+@@ -1374,6 +1375,10 @@ static inline int find_acpi_cpu_topology(unsigned int cpu, int level)
+ {
+ return -EINVAL;
+ }
++static inline int find_acpi_cpu_topology_cluster(unsigned int cpu)
++{
++ return -EINVAL;
++}
+ static inline int find_acpi_cpu_topology_package(unsigned int cpu)
+ {
+ return -EINVAL;
+diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h
+index f180240dc95f..b97cea83b25e 100644
+--- a/include/linux/arch_topology.h
++++ b/include/linux/arch_topology.h
+@@ -62,10 +62,12 @@ void topology_set_thermal_pressure(const struct cpumask *cpus,
+ struct cpu_topology {
+ int thread_id;
+ int core_id;
++ int cluster_id;
+ int package_id;
+ int llc_id;
+ cpumask_t thread_sibling;
+ cpumask_t core_sibling;
++ cpumask_t cluster_sibling;
+ cpumask_t llc_sibling;
+ };
+
+@@ -73,13 +75,16 @@ struct cpu_topology {
+ extern struct cpu_topology cpu_topology[NR_CPUS];
+
+ #define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id)
++#define topology_cluster_id(cpu) (cpu_topology[cpu].cluster_id)
+ #define topology_core_id(cpu) (cpu_topology[cpu].core_id)
+ #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
+ #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
++#define topology_cluster_cpumask(cpu) (&cpu_topology[cpu].cluster_sibling)
+ #define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling)
+ void init_cpu_topology(void);
+ void store_cpu_topology(unsigned int cpuid);
+ const struct cpumask *cpu_coregroup_mask(int cpu);
++const struct cpumask *cpu_clustergroup_mask(int cpu);
+ void update_siblings_masks(unsigned int cpu);
+ void remove_cpu_topology(unsigned int cpuid);
+ void reset_cpu_topology(void);
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index 7634cd737061..80d27d717631 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -186,6 +186,9 @@ static inline int cpu_to_mem(int cpu)
+ #ifndef topology_die_id
+ #define topology_die_id(cpu) ((void)(cpu), -1)
+ #endif
++#ifndef topology_cluster_id
++#define topology_cluster_id(cpu) ((void)(cpu), -1)
++#endif
+ #ifndef topology_core_id
+ #define topology_core_id(cpu) ((void)(cpu), 0)
+ #endif
+@@ -195,6 +198,9 @@ static inline int cpu_to_mem(int cpu)
+ #ifndef topology_core_cpumask
+ #define topology_core_cpumask(cpu) cpumask_of(cpu)
+ #endif
++#ifndef topology_cluster_cpumask
++#define topology_cluster_cpumask(cpu) cpumask_of(cpu)
++#endif
+ #ifndef topology_die_cpumask
+ #define topology_die_cpumask(cpu) cpumask_of(cpu)
+ #endif
+--
+2.35.1
+
--- /dev/null
+From e4d3e0f541c6884ea3a9d67839e74293c4cd8512 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Nov 2021 14:03:08 +0100
+Subject: topology/sysfs: export cluster attributes only if an architectures
+ has support
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit e795707703b32fecdd7467afcc33ff1e92416c05 ]
+
+The cluster_id and cluster_cpus topology sysfs attributes have been
+added with commit c5e22feffdd7 ("topology: Represent clusters of CPUs
+within a die").
+
+They are currently only used for x86, arm64, and riscv (via generic
+arch topology), however they are still present with bogus default
+values for all other architectures. Instead of enforcing such new
+sysfs attributes to all architectures, make them only optional visible
+if an architecture opts in by defining both the topology_cluster_id
+and topology_cluster_cpumask attributes.
+
+This is similar to what was done when the book and drawer topology
+levels were introduced: avoid useless and therefore confusing sysfs
+attributes for architectures which cannot make use of them.
+
+This should not break any existing applications, since this is a
+new interface introduced with the v5.16 merge window.
+
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Link: https://lore.kernel.org/r/20211129130309.3256168-3-hca@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/admin-guide/cputopology.rst | 4 ++--
+ drivers/base/topology.c | 8 ++++++++
+ include/linux/topology.h | 3 +++
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/admin-guide/cputopology.rst b/Documentation/admin-guide/cputopology.rst
+index c68d07533c45..ad2238b41439 100644
+--- a/Documentation/admin-guide/cputopology.rst
++++ b/Documentation/admin-guide/cputopology.rst
+@@ -11,8 +11,8 @@ Architecture-neutral, drivers/base/topology.c, exports these attributes.
+ However, the book and drawer related sysfs files will only be created if
+ CONFIG_SCHED_BOOK and CONFIG_SCHED_DRAWER are selected, respectively.
+
+-The die hierarchy related sysfs files will only be created if an architecture
+-provides the related macros as described below.
++The die and cluster hierarchy related sysfs files will only be created if an
++architecture provides the related macros as described below.
+
+ CONFIG_SCHED_BOOK and CONFIG_SCHED_DRAWER are currently only used on s390,
+ where they reflect the cpu and cache hierarchy.
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index f079a55793ec..9d049724e4b4 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -50,8 +50,10 @@ define_id_show_func(die_id);
+ static DEVICE_ATTR_RO(die_id);
+ #endif
+
++#ifdef TOPOLOGY_CLUSTER_SYSFS
+ define_id_show_func(cluster_id);
+ static DEVICE_ATTR_RO(cluster_id);
++#endif
+
+ define_id_show_func(core_id);
+ static DEVICE_ATTR_RO(core_id);
+@@ -68,9 +70,11 @@ define_siblings_read_func(core_siblings, core_cpumask);
+ static BIN_ATTR_RO(core_siblings, 0);
+ static BIN_ATTR_RO(core_siblings_list, 0);
+
++#ifdef TOPOLOGY_CLUSTER_SYSFS
+ define_siblings_read_func(cluster_cpus, cluster_cpumask);
+ static BIN_ATTR_RO(cluster_cpus, 0);
+ static BIN_ATTR_RO(cluster_cpus_list, 0);
++#endif
+
+ #ifdef TOPOLOGY_DIE_SYSFS
+ define_siblings_read_func(die_cpus, die_cpumask);
+@@ -105,8 +109,10 @@ static struct bin_attribute *bin_attrs[] = {
+ &bin_attr_thread_siblings_list,
+ &bin_attr_core_siblings,
+ &bin_attr_core_siblings_list,
++#ifdef TOPOLOGY_CLUSTER_SYSFS
+ &bin_attr_cluster_cpus,
+ &bin_attr_cluster_cpus_list,
++#endif
+ #ifdef TOPOLOGY_DIE_SYSFS
+ &bin_attr_die_cpus,
+ &bin_attr_die_cpus_list,
+@@ -129,7 +135,9 @@ static struct attribute *default_attrs[] = {
+ #ifdef TOPOLOGY_DIE_SYSFS
+ &dev_attr_die_id.attr,
+ #endif
++#ifdef TOPOLOGY_CLUSTER_SYSFS
+ &dev_attr_cluster_id.attr,
++#endif
+ &dev_attr_core_id.attr,
+ #ifdef CONFIG_SCHED_BOOK
+ &dev_attr_book_id.attr,
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index 9ec418f58804..6f6f9cdc5274 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -183,6 +183,9 @@ static inline int cpu_to_mem(int cpu)
+ #if defined(topology_die_id) && defined(topology_die_cpumask)
+ #define TOPOLOGY_DIE_SYSFS
+ #endif
++#if defined(topology_cluster_id) && defined(topology_cluster_cpumask)
++#define TOPOLOGY_CLUSTER_SYSFS
++#endif
+
+ #ifndef topology_physical_package_id
+ #define topology_physical_package_id(cpu) ((void)(cpu), -1)
+--
+2.35.1
+
--- /dev/null
+From c7a2cd6e4e942bd7271d652f8f40aafab20e69c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 Nov 2021 14:03:07 +0100
+Subject: topology/sysfs: export die attributes only if an architectures has
+ support
+
+From: Heiko Carstens <hca@linux.ibm.com>
+
+[ Upstream commit 2c4dcd7fd57b20a21b65da04d89c38a7217d79cf ]
+
+The die_id and die_cpus topology sysfs attributes have been added with
+commit 0e344d8c709f ("cpu/topology: Export die_id") and commit
+2e4c54dac7b3 ("topology: Create core_cpus and die_cpus sysfs attributes").
+
+While they are currently only used and useful for x86 they are still
+present with bogus default values for all architectures. Instead of
+enforcing such new sysfs attributes to all architectures, make them
+only optional visible if an architecture opts in by defining both the
+topology_die_id and topology_die_cpumask attributes.
+
+This is similar to what was done when the book and drawer topology
+levels were introduced: avoid useless and therefore confusing sysfs
+attributes for architectures which cannot make use of them.
+
+This should not break any existing applications, since this is a
+rather new interface and applications should be able to handle also
+older kernel versions without such attributes - besides that they
+contain only useful information for x86.
+
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Link: https://lore.kernel.org/r/20211129130309.3256168-2-hca@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/admin-guide/cputopology.rst | 3 +++
+ drivers/base/topology.c | 8 ++++++++
+ include/linux/topology.h | 4 ++++
+ 3 files changed, 15 insertions(+)
+
+diff --git a/Documentation/admin-guide/cputopology.rst b/Documentation/admin-guide/cputopology.rst
+index 6b62e182baf4..c68d07533c45 100644
+--- a/Documentation/admin-guide/cputopology.rst
++++ b/Documentation/admin-guide/cputopology.rst
+@@ -11,6 +11,9 @@ Architecture-neutral, drivers/base/topology.c, exports these attributes.
+ However, the book and drawer related sysfs files will only be created if
+ CONFIG_SCHED_BOOK and CONFIG_SCHED_DRAWER are selected, respectively.
+
++The die hierarchy related sysfs files will only be created if an architecture
++provides the related macros as described below.
++
+ CONFIG_SCHED_BOOK and CONFIG_SCHED_DRAWER are currently only used on s390,
+ where they reflect the cpu and cache hierarchy.
+
+diff --git a/drivers/base/topology.c b/drivers/base/topology.c
+index 8f2b641d0b8c..f079a55793ec 100644
+--- a/drivers/base/topology.c
++++ b/drivers/base/topology.c
+@@ -45,8 +45,10 @@ static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
+ define_id_show_func(physical_package_id);
+ static DEVICE_ATTR_RO(physical_package_id);
+
++#ifdef TOPOLOGY_DIE_SYSFS
+ define_id_show_func(die_id);
+ static DEVICE_ATTR_RO(die_id);
++#endif
+
+ define_id_show_func(cluster_id);
+ static DEVICE_ATTR_RO(cluster_id);
+@@ -70,9 +72,11 @@ define_siblings_read_func(cluster_cpus, cluster_cpumask);
+ static BIN_ATTR_RO(cluster_cpus, 0);
+ static BIN_ATTR_RO(cluster_cpus_list, 0);
+
++#ifdef TOPOLOGY_DIE_SYSFS
+ define_siblings_read_func(die_cpus, die_cpumask);
+ static BIN_ATTR_RO(die_cpus, 0);
+ static BIN_ATTR_RO(die_cpus_list, 0);
++#endif
+
+ define_siblings_read_func(package_cpus, core_cpumask);
+ static BIN_ATTR_RO(package_cpus, 0);
+@@ -103,8 +107,10 @@ static struct bin_attribute *bin_attrs[] = {
+ &bin_attr_core_siblings_list,
+ &bin_attr_cluster_cpus,
+ &bin_attr_cluster_cpus_list,
++#ifdef TOPOLOGY_DIE_SYSFS
+ &bin_attr_die_cpus,
+ &bin_attr_die_cpus_list,
++#endif
+ &bin_attr_package_cpus,
+ &bin_attr_package_cpus_list,
+ #ifdef CONFIG_SCHED_BOOK
+@@ -120,7 +126,9 @@ static struct bin_attribute *bin_attrs[] = {
+
+ static struct attribute *default_attrs[] = {
+ &dev_attr_physical_package_id.attr,
++#ifdef TOPOLOGY_DIE_SYSFS
+ &dev_attr_die_id.attr,
++#endif
+ &dev_attr_cluster_id.attr,
+ &dev_attr_core_id.attr,
+ #ifdef CONFIG_SCHED_BOOK
+diff --git a/include/linux/topology.h b/include/linux/topology.h
+index 80d27d717631..9ec418f58804 100644
+--- a/include/linux/topology.h
++++ b/include/linux/topology.h
+@@ -180,6 +180,10 @@ static inline int cpu_to_mem(int cpu)
+
+ #endif /* [!]CONFIG_HAVE_MEMORYLESS_NODES */
+
++#if defined(topology_die_id) && defined(topology_die_cpumask)
++#define TOPOLOGY_DIE_SYSFS
++#endif
++
+ #ifndef topology_physical_package_id
+ #define topology_physical_package_id(cpu) ((void)(cpu), -1)
+ #endif
+--
+2.35.1
+
--- /dev/null
+From 81aa50dc324598e59926aba99bd7147036869229 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Jul 2022 09:17:38 +0800
+Subject: tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH
+
+From: Huacai Chen <chenhuacai@loongson.cn>
+
+[ Upstream commit bed4593645366ad7362a3aa7bc0d100d8d8236a8 ]
+
+If DEBUG_SECTION_MISMATCH enabled, __calc_tpm2_event_size() will not be
+inlined, this cause section mismatch like this:
+
+WARNING: modpost: vmlinux.o(.text.unlikely+0xe30c): Section mismatch in reference from the variable L0 to the function .init.text:early_ioremap()
+The function L0() references
+the function __init early_memremap().
+This is often because L0 lacks a __init
+annotation or the annotation of early_ioremap is wrong.
+
+Fix it by using __always_inline instead of inline for the called-once
+function __calc_tpm2_event_size().
+
+Fixes: 44038bc514a2 ("tpm: Abstract crypto agile event size calculations")
+Cc: stable@vger.kernel.org # v5.3
+Reported-by: WANG Xuerui <git@xen0n.name>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/tpm_eventlog.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
+index 739ba9a03ec1..20c0ff54b7a0 100644
+--- a/include/linux/tpm_eventlog.h
++++ b/include/linux/tpm_eventlog.h
+@@ -157,7 +157,7 @@ struct tcg_algorithm_info {
+ * Return: size of the event on success, 0 on failure
+ */
+
+-static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
++static __always_inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
+ struct tcg_pcr_event *event_header,
+ bool do_mapping)
+ {
+--
+2.35.1
+
--- /dev/null
+From 53c30a8233056bf70160e6cf69d51ea176cdead1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Nov 2021 18:30:21 +0900
+Subject: tracing: Add '__rel_loc' using trace event macros
+
+From: Masami Hiramatsu <mhiramat@kernel.org>
+
+[ Upstream commit 55de2c0b5610cba5a5a93c0788031133c457e689 ]
+
+Add '__rel_loc' using trace event macros. These macros are usually
+not used in the kernel, except for testing purpose.
+This also add "rel_" variant of macros for dynamic_array string,
+and bitmask.
+
+Link: https://lkml.kernel.org/r/163757342119.510314.816029622439099016.stgit@devnote2
+
+Cc: Beau Belgrave <beaub@linux.microsoft.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Tom Zanussi <zanussi@kernel.org>
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/bpf_probe.h | 16 +++++
+ include/trace/perf.h | 16 +++++
+ include/trace/trace_events.h | 120 ++++++++++++++++++++++++++++++++++-
+ kernel/trace/trace.h | 3 +
+ 4 files changed, 153 insertions(+), 2 deletions(-)
+
+diff --git a/include/trace/bpf_probe.h b/include/trace/bpf_probe.h
+index a23be89119aa..04939b2d2f19 100644
+--- a/include/trace/bpf_probe.h
++++ b/include/trace/bpf_probe.h
+@@ -21,6 +21,22 @@
+ #undef __get_bitmask
+ #define __get_bitmask(field) (char *)__get_dynamic_array(field)
+
++#undef __get_rel_dynamic_array
++#define __get_rel_dynamic_array(field) \
++ ((void *)(&__entry->__rel_loc_##field) + \
++ sizeof(__entry->__rel_loc_##field) + \
++ (__entry->__rel_loc_##field & 0xffff))
++
++#undef __get_rel_dynamic_array_len
++#define __get_rel_dynamic_array_len(field) \
++ ((__entry->__rel_loc_##field >> 16) & 0xffff)
++
++#undef __get_rel_str
++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field))
++
++#undef __get_rel_bitmask
++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
++
+ #undef __perf_count
+ #define __perf_count(c) (c)
+
+diff --git a/include/trace/perf.h b/include/trace/perf.h
+index dbc6c74defc3..ea4405de175a 100644
+--- a/include/trace/perf.h
++++ b/include/trace/perf.h
+@@ -21,6 +21,22 @@
+ #undef __get_bitmask
+ #define __get_bitmask(field) (char *)__get_dynamic_array(field)
+
++#undef __get_rel_dynamic_array
++#define __get_rel_dynamic_array(field) \
++ ((void *)(&__entry->__rel_loc_##field) + \
++ sizeof(__entry->__rel_loc_##field) + \
++ (__entry->__rel_loc_##field & 0xffff))
++
++#undef __get_rel_dynamic_array_len
++#define __get_rel_dynamic_array_len(field) \
++ ((__entry->__rel_loc_##field >> 16) & 0xffff)
++
++#undef __get_rel_str
++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field))
++
++#undef __get_rel_bitmask
++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
++
+ #undef __perf_count
+ #define __perf_count(c) (__count = (c))
+
+diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
+index 08810a463880..8c6f7c433518 100644
+--- a/include/trace/trace_events.h
++++ b/include/trace/trace_events.h
+@@ -108,6 +108,18 @@ TRACE_MAKE_SYSTEM_STR();
+ #undef __bitmask
+ #define __bitmask(item, nr_bits) __dynamic_array(char, item, -1)
+
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(type, item, len) u32 __rel_loc_##item;
++
++#undef __rel_string
++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_string_len
++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_bitmask
++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(char, item, -1)
++
+ #undef TP_STRUCT__entry
+ #define TP_STRUCT__entry(args...) args
+
+@@ -200,11 +212,23 @@ TRACE_MAKE_SYSTEM_STR();
+ #undef __string
+ #define __string(item, src) __dynamic_array(char, item, -1)
+
++#undef __bitmask
++#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)
++
+ #undef __string_len
+ #define __string_len(item, src, len) __dynamic_array(char, item, -1)
+
+-#undef __bitmask
+-#define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(type, item, len) u32 item;
++
++#undef __rel_string
++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_string_len
++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_bitmask
++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1)
+
+ #undef DECLARE_EVENT_CLASS
+ #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
+@@ -293,6 +317,19 @@ TRACE_MAKE_SYSTEM_STR();
+ #undef __get_str
+ #define __get_str(field) ((char *)__get_dynamic_array(field))
+
++#undef __get_rel_dynamic_array
++#define __get_rel_dynamic_array(field) \
++ ((void *)(&__entry->__rel_loc_##field) + \
++ sizeof(__entry->__rel_loc_##field) + \
++ (__entry->__rel_loc_##field & 0xffff))
++
++#undef __get_rel_dynamic_array_len
++#define __get_rel_dynamic_array_len(field) \
++ ((__entry->__rel_loc_##field >> 16) & 0xffff)
++
++#undef __get_rel_str
++#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field))
++
+ #undef __get_bitmask
+ #define __get_bitmask(field) \
+ ({ \
+@@ -302,6 +339,15 @@ TRACE_MAKE_SYSTEM_STR();
+ trace_print_bitmask_seq(p, __bitmask, __bitmask_size); \
+ })
+
++#undef __get_rel_bitmask
++#define __get_rel_bitmask(field) \
++ ({ \
++ void *__bitmask = __get_rel_dynamic_array(field); \
++ unsigned int __bitmask_size; \
++ __bitmask_size = __get_rel_dynamic_array_len(field); \
++ trace_print_bitmask_seq(p, __bitmask, __bitmask_size); \
++ })
++
+ #undef __print_flags
+ #define __print_flags(flag, delim, flag_array...) \
+ ({ \
+@@ -471,6 +517,21 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \
+ #undef __bitmask
+ #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)
+
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(_type, _item, _len) { \
++ .type = "__rel_loc " #_type "[]", .name = #_item, \
++ .size = 4, .align = 4, \
++ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER },
++
++#undef __rel_string
++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_string_len
++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_bitmask
++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1)
++
+ #undef DECLARE_EVENT_CLASS
+ #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
+ static struct trace_event_fields trace_event_fields_##call[] = { \
+@@ -519,6 +580,22 @@ static struct trace_event_fields trace_event_fields_##call[] = { \
+ #undef __string_len
+ #define __string_len(item, src, len) __dynamic_array(char, item, (len) + 1)
+
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(type, item, len) \
++ __item_length = (len) * sizeof(type); \
++ __data_offsets->item = __data_size + \
++ offsetof(typeof(*entry), __data) - \
++ offsetof(typeof(*entry), __rel_loc_##item) - \
++ sizeof(u32); \
++ __data_offsets->item |= __item_length << 16; \
++ __data_size += __item_length;
++
++#undef __rel_string
++#define __rel_string(item, src) __rel_dynamic_array(char, item, \
++ strlen((src) ? (const char *)(src) : "(null)") + 1)
++
++#undef __rel_string_len
++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, (len) + 1)
+ /*
+ * __bitmask_size_in_bytes_raw is the number of bytes needed to hold
+ * num_possible_cpus().
+@@ -542,6 +619,10 @@ static struct trace_event_fields trace_event_fields_##call[] = { \
+ #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, \
+ __bitmask_size_in_longs(nr_bits))
+
++#undef __rel_bitmask
++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, \
++ __bitmask_size_in_longs(nr_bits))
++
+ #undef DECLARE_EVENT_CLASS
+ #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
+ static inline notrace int trace_event_get_offsets_##call( \
+@@ -706,6 +787,37 @@ static inline notrace int trace_event_get_offsets_##call( \
+ #define __assign_bitmask(dst, src, nr_bits) \
+ memcpy(__get_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits))
+
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(type, item, len) \
++ __entry->__rel_loc_##item = __data_offsets.item;
++
++#undef __rel_string
++#define __rel_string(item, src) __rel_dynamic_array(char, item, -1)
++
++#undef __rel_string_len
++#define __rel_string_len(item, src, len) __rel_dynamic_array(char, item, -1)
++
++#undef __assign_rel_str
++#define __assign_rel_str(dst, src) \
++ strcpy(__get_rel_str(dst), (src) ? (const char *)(src) : "(null)");
++
++#undef __assign_rel_str_len
++#define __assign_rel_str_len(dst, src, len) \
++ do { \
++ memcpy(__get_rel_str(dst), (src), (len)); \
++ __get_rel_str(dst)[len] = '\0'; \
++ } while (0)
++
++#undef __rel_bitmask
++#define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1)
++
++#undef __get_rel_bitmask
++#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
++
++#undef __assign_rel_bitmask
++#define __assign_rel_bitmask(dst, src, nr_bits) \
++ memcpy(__get_rel_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits))
++
+ #undef TP_fast_assign
+ #define TP_fast_assign(args...) args
+
+@@ -770,6 +882,10 @@ static inline void ftrace_test_probe_##call(void) \
+ #undef __get_dynamic_array_len
+ #undef __get_str
+ #undef __get_bitmask
++#undef __get_rel_dynamic_array
++#undef __get_rel_dynamic_array_len
++#undef __get_rel_str
++#undef __get_rel_bitmask
+ #undef __print_array
+ #undef __print_hex_dump
+
+diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
+index d6763366a320..28ea6c0be495 100644
+--- a/kernel/trace/trace.h
++++ b/kernel/trace/trace.h
+@@ -83,6 +83,9 @@ enum trace_type {
+ #undef __dynamic_array
+ #define __dynamic_array(type, item) type item[];
+
++#undef __rel_dynamic_array
++#define __rel_dynamic_array(type, item) type item[];
++
+ #undef F_STRUCT
+ #define F_STRUCT(args...) args
+
+--
+2.35.1
+
--- /dev/null
+From eddd09b8d3ad6134db6d0034a8254c45da0587c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jan 2022 23:19:30 +0900
+Subject: tracing: Avoid -Warray-bounds warning for __rel_loc macro
+
+From: Masami Hiramatsu <mhiramat@kernel.org>
+
+[ Upstream commit 58c5724ec2cdd72b22107ec5de00d90cc4797796 ]
+
+Since -Warray-bounds checks the destination size from the type of given
+pointer, __assign_rel_str() macro gets warned because it passes the
+pointer to the 'u32' field instead of 'trace_event_raw_*' data structure.
+Pass the data address calculated from the 'trace_event_raw_*' instead of
+'u32' __rel_loc field.
+
+Link: https://lkml.kernel.org/r/20220125233154.dac280ed36944c0c2fe6f3ac@kernel.org
+
+Cc: Stephen Rothwell <sfr@canb.auug.org.au>
+Cc: Kees Cook <keescook@chromium.org>
+Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
+[ This did not fix the warning, but is still a nice clean up ]
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/trace_events.h | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
+index 8c6f7c433518..65d927e059d3 100644
+--- a/include/trace/trace_events.h
++++ b/include/trace/trace_events.h
+@@ -318,9 +318,10 @@ TRACE_MAKE_SYSTEM_STR();
+ #define __get_str(field) ((char *)__get_dynamic_array(field))
+
+ #undef __get_rel_dynamic_array
+-#define __get_rel_dynamic_array(field) \
+- ((void *)(&__entry->__rel_loc_##field) + \
+- sizeof(__entry->__rel_loc_##field) + \
++#define __get_rel_dynamic_array(field) \
++ ((void *)__entry + \
++ offsetof(typeof(*__entry), __rel_loc_##field) + \
++ sizeof(__entry->__rel_loc_##field) + \
+ (__entry->__rel_loc_##field & 0xffff))
+
+ #undef __get_rel_dynamic_array_len
+--
+2.35.1
+
--- /dev/null
+From 2b7d45020f0fd554a1ec008305f07d8fe4964340 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Jul 2022 16:35:10 +0100
+Subject: tty: 8250: Add support for Brainboxes PX cards.
+
+From: Cameron Williams <cang1@live.co.uk>
+
+[ Upstream commit ef5a03a26c87a760bc3d86b5af7b773e82f8b1b7 ]
+
+Add support for some of the Brainboxes PCIe (PX) range of
+serial cards, including the PX-101, PX-235/PX-246,
+PX-203/PX-257, PX-260/PX-701, PX-310, PX-313,
+PX-320/PX-324/PX-376/PX-387, PX-335/PX-346, PX-368, PX-420,
+PX-803 and PX-846.
+
+Signed-off-by: Cameron Williams <cang1@live.co.uk>
+Cc: stable <stable@kernel.org>
+Link: https://lore.kernel.org/r/AM5PR0202MB2564669252BDC59BF55A6E87C4879@AM5PR0202MB2564.eurprd02.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 109 +++++++++++++++++++++++++++++
+ 1 file changed, 109 insertions(+)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 1860fc969433..a16743856fc7 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -5475,6 +5475,115 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0,
+ pbn_b2_4_115200 },
++ /*
++ * Brainboxes PX-101
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4005,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_2_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x4019,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_2_15625000 },
++ /*
++ * Brainboxes PX-235/246
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4004,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_1_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x4016,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_1_15625000 },
++ /*
++ * Brainboxes PX-203/PX-257
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4006,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_2_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x4015,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_4_15625000 },
++ /*
++ * Brainboxes PX-260/PX-701
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x400A,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_4_15625000 },
++ /*
++ * Brainboxes PX-310
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x400E,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_2_15625000 },
++ /*
++ * Brainboxes PX-313
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x400C,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_2_15625000 },
++ /*
++ * Brainboxes PX-320/324/PX-376/PX-387
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x400B,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_1_15625000 },
++ /*
++ * Brainboxes PX-335/346
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x400F,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_4_15625000 },
++ /*
++ * Brainboxes PX-368
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4010,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_4_15625000 },
++ /*
++ * Brainboxes PX-420
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4000,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_4_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x4011,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_4_15625000 },
++ /*
++ * Brainboxes PX-803
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4009,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_1_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x401E,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_1_15625000 },
++ /*
++ * Brainboxes PX-846
++ */
++ { PCI_VENDOR_ID_INTASHIELD, 0x4008,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_b0_1_115200 },
++ { PCI_VENDOR_ID_INTASHIELD, 0x4017,
++ PCI_ANY_ID, PCI_ANY_ID,
++ 0, 0,
++ pbn_oxsemi_1_15625000 },
++
+ /*
+ * Perle PCI-RAS cards
+ */
+--
+2.35.1
+
--- /dev/null
+From 0d558f5af530b7f58eaba9633342640ab602cec7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 10:42:04 +0200
+Subject: usbnet: smsc95xx: Avoid link settings race on interrupt reception
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 8960f878e39fadc03d74292a6731f1e914cf2019 ]
+
+When a PHY interrupt is signaled, the SMSC LAN95xx driver updates the
+MAC full duplex mode and PHY flow control registers based on cached data
+in struct phy_device:
+
+ smsc95xx_status() # raises EVENT_LINK_RESET
+ usbnet_deferred_kevent()
+ smsc95xx_link_reset() # uses cached data in phydev
+
+Simultaneously, phylib polls link status once per second and updates
+that cached data:
+
+ phy_state_machine()
+ phy_check_link_status()
+ phy_read_status()
+ lan87xx_read_status()
+ genphy_read_status() # updates cached data in phydev
+
+If smsc95xx_link_reset() wins the race against genphy_read_status(),
+the registers may be updated based on stale data.
+
+E.g. if the link was previously down, phydev->duplex is set to
+DUPLEX_UNKNOWN and that's what smsc95xx_link_reset() will use, even
+though genphy_read_status() may update it to DUPLEX_FULL afterwards.
+
+PHY interrupts are currently only enabled on suspend to trigger wakeup,
+so the impact of the race is limited, but we're about to enable them
+perpetually.
+
+Avoid the race by delaying execution of smsc95xx_link_reset() until
+phy_state_machine() has done its job and calls back via
+smsc95xx_handle_link_change().
+
+Signaling EVENT_LINK_RESET on wakeup is not necessary because phylib
+picks up link status changes through polling. So drop the declaration
+of a ->link_reset() callback.
+
+Note that the semicolon on a line by itself added in smsc95xx_status()
+is a placeholder for a function call which will be added in a subsequent
+commit. That function call will actually handle the INT_ENP_PHY_INT_
+interrupt.
+
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
+Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index c33089168880..7cf9206638c3 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -564,7 +564,7 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev)
+ return smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
+ }
+
+-static int smsc95xx_link_reset(struct usbnet *dev)
++static void smsc95xx_mac_update_fullduplex(struct usbnet *dev)
+ {
+ struct smsc95xx_priv *pdata = dev->driver_priv;
+ unsigned long flags;
+@@ -581,14 +581,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+- if (ret < 0)
+- return ret;
++ if (ret < 0) {
++ if (ret != -ENODEV)
++ netdev_warn(dev->net,
++ "Error updating MAC full duplex mode\n");
++ return;
++ }
+
+ ret = smsc95xx_phy_update_flowcontrol(dev);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error updating PHY flow control\n");
+-
+- return ret;
+ }
+
+ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+@@ -605,7 +607,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+ netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
+
+ if (intdata & INT_ENP_PHY_INT_)
+- usbnet_defer_kevent(dev, EVENT_LINK_RESET);
++ ;
+ else
+ netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+ intdata);
+@@ -1062,6 +1064,7 @@ static void smsc95xx_handle_link_change(struct net_device *net)
+ struct usbnet *dev = netdev_priv(net);
+
+ phy_print_status(net->phydev);
++ smsc95xx_mac_update_fullduplex(dev);
+ usbnet_defer_kevent(dev, EVENT_LINK_CHANGE);
+ }
+
+@@ -1967,7 +1970,6 @@ static const struct driver_info smsc95xx_info = {
+ .description = "smsc95xx USB 2.0 Ethernet",
+ .bind = smsc95xx_bind,
+ .unbind = smsc95xx_unbind,
+- .link_reset = smsc95xx_link_reset,
+ .reset = smsc95xx_reset,
+ .check_connect = smsc95xx_start_phy,
+ .stop = smsc95xx_stop,
+--
+2.35.1
+
--- /dev/null
+From 2c1c3a1806ffa081e67dd98bd100544ea82439ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 10:42:02 +0200
+Subject: usbnet: smsc95xx: Don't clear read-only PHY interrupt
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 3108871f19221372b251f7da1ac38736928b5b3a ]
+
+Upon receiving data from the Interrupt Endpoint, the SMSC LAN95xx driver
+attempts to clear the signaled interrupts by writing "all ones" to the
+Interrupt Status Register.
+
+However the driver only ever enables a single type of interrupt, namely
+the PHY Interrupt. And according to page 119 of the LAN950x datasheet,
+its bit in the Interrupt Status Register is read-only. There's no other
+way to clear it than in a separate PHY register:
+
+https://www.microchip.com/content/dam/mchp/documents/UNG/ProductDocuments/DataSheets/LAN950x-Data-Sheet-DS00001875D.pdf
+
+Consequently, writing "all ones" to the Interrupt Status Register is
+pointless and can be dropped.
+
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
+Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index 4e39e4345084..c33089168880 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -570,10 +570,6 @@ static int smsc95xx_link_reset(struct usbnet *dev)
+ unsigned long flags;
+ int ret;
+
+- ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
+- if (ret < 0)
+- return ret;
+-
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+ if (pdata->phydev->duplex != DUPLEX_FULL) {
+ pdata->mac_cr &= ~MAC_CR_FDPX_;
+--
+2.35.1
+
--- /dev/null
+From 378ef3e9c6baae3d46143011f3a9a07f0e2e845c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Jul 2022 22:47:51 +0200
+Subject: usbnet: smsc95xx: Fix deadlock on runtime resume
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 7b960c967f2aa01ab8f45c5a0bd78e754cffdeee ]
+
+Commit 05b35e7eb9a1 ("smsc95xx: add phylib support") amended
+smsc95xx_resume() to call phy_init_hw(). That function waits for the
+device to runtime resume even though it is placed in the runtime resume
+path, causing a deadlock.
+
+The problem is that phy_init_hw() calls down to smsc95xx_mdiobus_read(),
+which never uses the _nopm variant of usbnet_read_cmd().
+
+Commit b4df480f68ae ("usbnet: smsc95xx: add reset_resume function with
+reset operation") causes a similar deadlock on resume if the device was
+already runtime suspended when entering system sleep:
+
+That's because the commit introduced smsc95xx_reset_resume(), which
+calls down to smsc95xx_reset(), which neglects to use _nopm accessors.
+
+Fix by auto-detecting whether a device access is performed by the
+suspend/resume task_struct and use the _nopm variant if so. This works
+because the PM core guarantees that suspend/resume callbacks are run in
+task context.
+
+Stacktrace for posterity:
+
+ INFO: task kworker/2:1:49 blocked for more than 122 seconds.
+ Workqueue: usb_hub_wq hub_event
+ schedule
+ rpm_resume
+ __pm_runtime_resume
+ usb_autopm_get_interface
+ usbnet_read_cmd
+ __smsc95xx_read_reg
+ __smsc95xx_phy_wait_not_busy
+ __smsc95xx_mdio_read
+ smsc95xx_mdiobus_read
+ __mdiobus_read
+ mdiobus_read
+ smsc_phy_reset
+ phy_init_hw
+ smsc95xx_resume
+ usb_resume_interface
+ usb_resume_both
+ usb_runtime_resume
+ __rpm_callback
+ rpm_callback
+ rpm_resume
+ __pm_runtime_resume
+ usb_autoresume_device
+ hub_event
+ process_one_work
+
+Fixes: b4df480f68ae ("usbnet: smsc95xx: add reset_resume function with reset operation")
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org # v3.16+
+Cc: Andre Edich <andre.edich@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 26 ++++++++++++++++++++------
+ 1 file changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index 3eb62197c2f5..460e90eb528f 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -69,6 +69,7 @@ struct smsc95xx_priv {
+ struct fwnode_handle *irqfwnode;
+ struct mii_bus *mdiobus;
+ struct phy_device *phydev;
++ struct task_struct *pm_task;
+ };
+
+ static bool turbo_mode = true;
+@@ -78,13 +79,14 @@ MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ u32 *data, int in_pm)
+ {
++ struct smsc95xx_priv *pdata = dev->driver_priv;
+ u32 buf;
+ int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
+
+ BUG_ON(!dev);
+
+- if (!in_pm)
++ if (current != pdata->pm_task)
+ fn = usbnet_read_cmd;
+ else
+ fn = usbnet_read_cmd_nopm;
+@@ -108,13 +110,14 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+ static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
+ u32 data, int in_pm)
+ {
++ struct smsc95xx_priv *pdata = dev->driver_priv;
+ u32 buf;
+ int ret;
+ int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
+
+ BUG_ON(!dev);
+
+- if (!in_pm)
++ if (current != pdata->pm_task)
+ fn = usbnet_write_cmd;
+ else
+ fn = usbnet_write_cmd_nopm;
+@@ -1482,9 +1485,12 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
+ u32 val, link_up;
+ int ret;
+
++ pdata->pm_task = current;
++
+ ret = usbnet_suspend(intf, message);
+ if (ret < 0) {
+ netdev_warn(dev->net, "usbnet_suspend error\n");
++ pdata->pm_task = NULL;
+ return ret;
+ }
+
+@@ -1724,6 +1730,7 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
+ if (ret && PMSG_IS_AUTO(message))
+ usbnet_resume(intf);
+
++ pdata->pm_task = NULL;
+ return ret;
+ }
+
+@@ -1744,29 +1751,31 @@ static int smsc95xx_resume(struct usb_interface *intf)
+ /* do this first to ensure it's cleared even in error case */
+ pdata->suspend_flags = 0;
+
++ pdata->pm_task = current;
++
+ if (suspend_flags & SUSPEND_ALLMODES) {
+ /* clear wake-up sources */
+ ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+ if (ret < 0)
+- return ret;
++ goto done;
+
+ val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
+
+ ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+ if (ret < 0)
+- return ret;
++ goto done;
+
+ /* clear wake-up status */
+ ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+ if (ret < 0)
+- return ret;
++ goto done;
+
+ val &= ~PM_CTL_WOL_EN_;
+ val |= PM_CTL_WUPS_;
+
+ ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+ if (ret < 0)
+- return ret;
++ goto done;
+ }
+
+ phy_init_hw(pdata->phydev);
+@@ -1775,15 +1784,20 @@ static int smsc95xx_resume(struct usb_interface *intf)
+ if (ret < 0)
+ netdev_warn(dev->net, "usbnet_resume error\n");
+
++done:
++ pdata->pm_task = NULL;
+ return ret;
+ }
+
+ static int smsc95xx_reset_resume(struct usb_interface *intf)
+ {
+ struct usbnet *dev = usb_get_intfdata(intf);
++ struct smsc95xx_priv *pdata = dev->driver_priv;
+ int ret;
+
++ pdata->pm_task = current;
+ ret = smsc95xx_reset(dev);
++ pdata->pm_task = NULL;
+ if (ret < 0)
+ return ret;
+
+--
+2.35.1
+
--- /dev/null
+From 9818677dafd6898fab24700a0ce03c086b7d4010 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 10:42:05 +0200
+Subject: usbnet: smsc95xx: Forward PHY interrupts to PHY driver to avoid
+ polling
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 1ce8b37241ed291af56f7a49bbdbf20c08728e88 ]
+
+Link status of SMSC LAN95xx chips is polled once per second, even though
+they're capable of signaling PHY interrupts through the MAC layer.
+
+Forward those interrupts to the PHY driver to avoid polling. Benefits
+are reduced bus traffic, reduced CPU overhead and quicker interface
+bringup.
+
+Polling was introduced in 2016 by commit d69d16949346 ("usbnet:
+smsc95xx: fix link detection for disabled autonegotiation").
+Back then, the LAN95xx driver neglected to enable the ENERGYON interrupt,
+hence couldn't detect link-up events when auto-negotiation was disabled.
+The proper solution would have been to enable the ENERGYON interrupt
+instead of polling.
+
+Since then, PHY handling was moved from the LAN95xx driver to the SMSC
+PHY driver with commit 05b35e7eb9a1 ("smsc95xx: add phylib support").
+That PHY driver is capable of link detection with auto-negotiation
+disabled because it enables the ENERGYON interrupt.
+
+Note that signaling interrupts through the MAC layer not only works with
+the integrated PHY, but also with an external PHY, provided its
+interrupt pin is attached to LAN95xx's nPHY_INT pin.
+
+In the unlikely event that the interrupt pin of an external PHY is
+attached to a GPIO of the SoC (or not connected at all), the driver can
+be amended to retrieve the irq from the PHY's of_node.
+
+To forward PHY interrupts to phylib, it is not sufficient to call
+phy_mac_interrupt(). Instead, the PHY's interrupt handler needs to run
+so that PHY interrupts are cleared. That's because according to page
+119 of the LAN950x datasheet, "The source of this interrupt is a level.
+The interrupt persists until it is cleared in the PHY."
+
+https://www.microchip.com/content/dam/mchp/documents/UNG/ProductDocuments/DataSheets/LAN950x-Data-Sheet-DS00001875D.pdf
+
+Therefore, create an IRQ domain with a single IRQ for the PHY. In the
+future, the IRQ domain may be extended to support the 11 GPIOs on the
+LAN95xx.
+
+Normally the PHY interrupt should be masked until the PHY driver has
+cleared it. However masking requires a (sleeping) USB transaction and
+interrupts are received in (non-sleepable) softirq context. I decided
+not to mask the interrupt at all (by using the dummy_irq_chip's noop
+->irq_mask() callback): The USB interrupt endpoint is polled in 1 msec
+intervals and normally that's sufficient to wake the PHY driver's IRQ
+thread and have it clear the interrupt. If it does take longer, worst
+thing that can happen is the IRQ thread is woken again. No big deal.
+
+Because PHY interrupts are now perpetually enabled, there's no need to
+selectively enable them on suspend. So remove all invocations of
+smsc95xx_enable_phy_wakeup_interrupts().
+
+In smsc95xx_resume(), move the call of phy_init_hw() before
+usbnet_resume() (which restarts the status URB) to ensure that the PHY
+is fully initialized when an interrupt is handled.
+
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
+Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch> # from a PHY perspective
+Cc: Andre Edich <andre.edich@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 113 ++++++++++++++++++++-----------------
+ 1 file changed, 61 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index 7cf9206638c3..3eb62197c2f5 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -18,6 +18,8 @@
+ #include <linux/usb/usbnet.h>
+ #include <linux/slab.h>
+ #include <linux/of_net.h>
++#include <linux/irq.h>
++#include <linux/irqdomain.h>
+ #include <linux/mdio.h>
+ #include <linux/phy.h>
+ #include "smsc95xx.h"
+@@ -51,6 +53,9 @@
+ #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+ SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
+
++#define SMSC95XX_NR_IRQS (1) /* raise to 12 for GPIOs */
++#define PHY_HWIRQ (SMSC95XX_NR_IRQS - 1)
++
+ struct smsc95xx_priv {
+ u32 mac_cr;
+ u32 hash_hi;
+@@ -59,6 +64,9 @@ struct smsc95xx_priv {
+ spinlock_t mac_cr_lock;
+ u8 features;
+ u8 suspend_flags;
++ struct irq_chip irqchip;
++ struct irq_domain *irqdomain;
++ struct fwnode_handle *irqfwnode;
+ struct mii_bus *mdiobus;
+ struct phy_device *phydev;
+ };
+@@ -595,6 +603,8 @@ static void smsc95xx_mac_update_fullduplex(struct usbnet *dev)
+
+ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+ {
++ struct smsc95xx_priv *pdata = dev->driver_priv;
++ unsigned long flags;
+ u32 intdata;
+
+ if (urb->actual_length != 4) {
+@@ -606,11 +616,15 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+ intdata = get_unaligned_le32(urb->transfer_buffer);
+ netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
+
++ local_irq_save(flags);
++
+ if (intdata & INT_ENP_PHY_INT_)
+- ;
++ generic_handle_domain_irq(pdata->irqdomain, PHY_HWIRQ);
+ else
+ netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+ intdata);
++
++ local_irq_restore(flags);
+ }
+
+ /* Enable or disable Tx & Rx checksum offload engines */
+@@ -1072,8 +1086,9 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+ {
+ struct smsc95xx_priv *pdata;
+ bool is_internal_phy;
++ char usb_path[64];
++ int ret, phy_irq;
+ u32 val;
+- int ret;
+
+ printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
+
+@@ -1113,10 +1128,38 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+ if (ret)
+ goto free_pdata;
+
++ /* create irq domain for use by PHY driver and GPIO consumers */
++ usb_make_path(dev->udev, usb_path, sizeof(usb_path));
++ pdata->irqfwnode = irq_domain_alloc_named_fwnode(usb_path);
++ if (!pdata->irqfwnode) {
++ ret = -ENOMEM;
++ goto free_pdata;
++ }
++
++ pdata->irqdomain = irq_domain_create_linear(pdata->irqfwnode,
++ SMSC95XX_NR_IRQS,
++ &irq_domain_simple_ops,
++ pdata);
++ if (!pdata->irqdomain) {
++ ret = -ENOMEM;
++ goto free_irqfwnode;
++ }
++
++ phy_irq = irq_create_mapping(pdata->irqdomain, PHY_HWIRQ);
++ if (!phy_irq) {
++ ret = -ENOENT;
++ goto remove_irqdomain;
++ }
++
++ pdata->irqchip = dummy_irq_chip;
++ pdata->irqchip.name = SMSC_CHIPNAME;
++ irq_set_chip_and_handler_name(phy_irq, &pdata->irqchip,
++ handle_simple_irq, "phy");
++
+ pdata->mdiobus = mdiobus_alloc();
+ if (!pdata->mdiobus) {
+ ret = -ENOMEM;
+- goto free_pdata;
++ goto dispose_irq;
+ }
+
+ ret = smsc95xx_read_reg(dev, HW_CFG, &val);
+@@ -1149,6 +1192,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+ goto unregister_mdio;
+ }
+
++ pdata->phydev->irq = phy_irq;
+ pdata->phydev->is_internal = is_internal_phy;
+
+ /* detect device revision as different features may be available */
+@@ -1191,6 +1235,15 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
+ free_mdio:
+ mdiobus_free(pdata->mdiobus);
+
++dispose_irq:
++ irq_dispose_mapping(phy_irq);
++
++remove_irqdomain:
++ irq_domain_remove(pdata->irqdomain);
++
++free_irqfwnode:
++ irq_domain_free_fwnode(pdata->irqfwnode);
++
+ free_pdata:
+ kfree(pdata);
+ return ret;
+@@ -1203,6 +1256,9 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
+ phy_disconnect(dev->net->phydev);
+ mdiobus_unregister(pdata->mdiobus);
+ mdiobus_free(pdata->mdiobus);
++ irq_dispose_mapping(irq_find_mapping(pdata->irqdomain, PHY_HWIRQ));
++ irq_domain_remove(pdata->irqdomain);
++ irq_domain_free_fwnode(pdata->irqfwnode);
+ netif_dbg(dev, ifdown, dev->net, "free pdata\n");
+ kfree(pdata);
+ }
+@@ -1227,29 +1283,6 @@ static u32 smsc_crc(const u8 *buffer, size_t len, int filter)
+ return crc << ((filter % 2) * 16);
+ }
+
+-static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+-{
+- int ret;
+-
+- netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+-
+- /* read to clear */
+- ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_SRC);
+- if (ret < 0)
+- return ret;
+-
+- /* enable interrupt source */
+- ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_MASK);
+- if (ret < 0)
+- return ret;
+-
+- ret |= mask;
+-
+- smsc95xx_mdio_write_nopm(dev, PHY_INT_MASK, ret);
+-
+- return 0;
+-}
+-
+ static int smsc95xx_link_ok_nopm(struct usbnet *dev)
+ {
+ int ret;
+@@ -1416,7 +1449,6 @@ static int smsc95xx_enter_suspend3(struct usbnet *dev)
+ static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up)
+ {
+ struct smsc95xx_priv *pdata = dev->driver_priv;
+- int ret;
+
+ if (!netif_running(dev->net)) {
+ /* interface is ifconfig down so fully power down hw */
+@@ -1435,27 +1467,10 @@ static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up)
+ }
+
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+-
+- /* enable PHY wakeup events for if cable is attached */
+- ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+- PHY_INT_MASK_ANEG_COMP_);
+- if (ret < 0) {
+- netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+- return ret;
+- }
+-
+ netdev_info(dev->net, "entering SUSPEND1 mode\n");
+ return smsc95xx_enter_suspend1(dev);
+ }
+
+- /* enable PHY wakeup events so we remote wakeup if cable is pulled */
+- ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+- PHY_INT_MASK_LINK_DOWN_);
+- if (ret < 0) {
+- netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+- return ret;
+- }
+-
+ netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+ return smsc95xx_enter_suspend3(dev);
+ }
+@@ -1521,13 +1536,6 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
+ }
+
+ if (pdata->wolopts & WAKE_PHY) {
+- ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+- (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
+- if (ret < 0) {
+- netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+- goto done;
+- }
+-
+ /* if link is down then configure EDPD and enter SUSPEND1,
+ * otherwise enter SUSPEND0 below
+ */
+@@ -1761,11 +1769,12 @@ static int smsc95xx_resume(struct usb_interface *intf)
+ return ret;
+ }
+
++ phy_init_hw(pdata->phydev);
++
+ ret = usbnet_resume(intf);
+ if (ret < 0)
+ netdev_warn(dev->net, "usbnet_resume error\n");
+
+- phy_init_hw(pdata->phydev);
+ return ret;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From f0226069b64d2032c220973bcfcacef9358446ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Aug 2022 15:04:16 +0900
+Subject: x86/kprobes: Update kcb status flag after singlestepping
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ Upstream commit dec8784c9088b131a1523f582c2194cfc8107dc0 ]
+
+Fix kprobes to update kcb (kprobes control block) status flag to
+KPROBE_HIT_SSDONE even if the kp->post_handler is not set.
+
+This bug may cause a kernel panic if another INT3 user runs right
+after kprobes because kprobe_int3_handler() misunderstands the
+INT3 is kprobe's single stepping INT3.
+
+Fixes: 6256e668b7af ("x86/kprobes: Use int3 instead of debug trap for single-step")
+Reported-by: Daniel Müller <deso@posteo.net>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Tested-by: Daniel Müller <deso@posteo.net>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/all/20220727210136.jjgc3lpqeq42yr3m@muellerd-fedora-PC2BDTX9
+Link: https://lore.kernel.org/r/165942025658.342061.12452378391879093249.stgit@devnote2
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/kprobes/core.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
+index f6727c67ae02..7a7f671c60b4 100644
+--- a/arch/x86/kernel/kprobes/core.c
++++ b/arch/x86/kernel/kprobes/core.c
+@@ -816,16 +816,20 @@ NOKPROBE_SYMBOL(arch_prepare_kretprobe);
+ static void kprobe_post_process(struct kprobe *cur, struct pt_regs *regs,
+ struct kprobe_ctlblk *kcb)
+ {
+- if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+- kcb->kprobe_status = KPROBE_HIT_SSDONE;
+- cur->post_handler(cur, regs, 0);
+- }
+-
+ /* Restore back the original saved kprobes variables and continue. */
+- if (kcb->kprobe_status == KPROBE_REENTER)
++ if (kcb->kprobe_status == KPROBE_REENTER) {
++ /* This will restore both kcb and current_kprobe */
+ restore_previous_kprobe(kcb);
+- else
++ } else {
++ /*
++ * Always update the kcb status because
++ * reset_curent_kprobe() doesn't update kcb.
++ */
++ kcb->kprobe_status = KPROBE_HIT_SSDONE;
++ if (cur->post_handler)
++ cur->post_handler(cur, regs, 0);
+ reset_current_kprobe();
++ }
+ }
+ NOKPROBE_SYMBOL(kprobe_post_process);
+
+--
+2.35.1
+
--- /dev/null
+From 91089205ead74e301d3394fcc2dc38ba07f63541 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Jul 2022 17:15:36 +0200
+Subject: x86/olpc: fix 'logical not is only applied to the left hand side'
+
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+
+[ Upstream commit 3a2ba42cbd0b669ce3837ba400905f93dd06c79f ]
+
+The bitops compile-time optimization series revealed one more
+problem in olpc-xo1-sci.c:send_ebook_state(), resulted in GCC
+warnings:
+
+arch/x86/platform/olpc/olpc-xo1-sci.c: In function 'send_ebook_state':
+arch/x86/platform/olpc/olpc-xo1-sci.c:83:63: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses]
+ 83 | if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
+ | ^~
+arch/x86/platform/olpc/olpc-xo1-sci.c:83:13: note: add parentheses around left hand side expression to silence this warning
+
+Despite this code working as intended, this redundant double
+negation of boolean value, together with comparing to `char`
+with no explicit conversion to bool, makes compilers think
+the author made some unintentional logical mistakes here.
+Make it the other way around and negate the char instead
+to silence the warnings.
+
+Fixes: d2aa37411b8e ("x86/olpc/xo1/sci: Produce wakeup events for buttons and switches")
+Cc: stable@vger.kernel.org # 3.5+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Reported-by: kernel test robot <lkp@intel.com>
+Reviewed-and-tested-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com>
+Signed-off-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/olpc/olpc-xo1-sci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
+index f03a6883dcc6..89f25af4b3c3 100644
+--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
++++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
+@@ -80,7 +80,7 @@ static void send_ebook_state(void)
+ return;
+ }
+
+- if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
++ if (test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == !!state)
+ return; /* Nothing new to report. */
+
+ input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
+--
+2.35.1
+