From: Sasha Levin Date: Mon, 15 Aug 2022 05:56:01 +0000 (-0400) Subject: Fixes for 5.15 X-Git-Tag: v5.15.61~98 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d1889208954bc949e3cc964d47d7c29c151d4ef;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/__follow_mount_rcu-verify-that-mount_lock-remains-un.patch b/queue-5.15/__follow_mount_rcu-verify-that-mount_lock-remains-un.patch new file mode 100644 index 00000000000..eeb8af4d647 --- /dev/null +++ b/queue-5.15/__follow_mount_rcu-verify-that-mount_lock-remains-un.patch @@ -0,0 +1,51 @@ +From e40d0d60d2c1e1cf43d222db49ed94322e32d6f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 17:26:29 -0400 +Subject: __follow_mount_rcu(): verify that mount_lock remains unchanged + +From: Al Viro + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/acpi-cppc-do-not-prevent-cppc-from-working-in-the-fu.patch b/queue-5.15/acpi-cppc-do-not-prevent-cppc-from-working-in-the-fu.patch new file mode 100644 index 00000000000..106ba6fbc19 --- /dev/null +++ b/queue-5.15/acpi-cppc-do-not-prevent-cppc-from-working-in-the-fu.patch @@ -0,0 +1,131 @@ +From 17cafc5c8190f0164683e76dd6d0bc673a2679af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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+ # 4.18+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + 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 + #include + +-/* 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 + diff --git a/queue-5.15/arm-remove-some-dead-code.patch b/queue-5.15/arm-remove-some-dead-code.patch new file mode 100644 index 00000000000..860788d1d1e --- /dev/null +++ b/queue-5.15/arm-remove-some-dead-code.patch @@ -0,0 +1,92 @@ +From c31c587677dced7d7175db5a9f0873480eb388fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Oct 2021 09:15:34 +0200 +Subject: ARM: remove some dead code + +From: Ard Biesheuvel + +[ Upstream commit 08572cd41955166e387d9b4984294d37f8f7526c ] + +This code appears to be no longer used so let's get rid of it. + +Signed-off-by: Ard Biesheuvel +Reviewed-by: Arnd Bergmann +Acked-by: Linus Walleij +Tested-by: Keith Packard +Tested-by: Marc Zyngier +Tested-by: Vladimir Murzin # ARMv7M +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/block-don-t-allow-the-same-type-rq_qos-add-more-than.patch b/queue-5.15/block-don-t-allow-the-same-type-rq_qos-add-more-than.patch new file mode 100644 index 00000000000..ec03fe05797 --- /dev/null +++ b/queue-5.15/block-don-t-allow-the-same-type-rq_qos-add-more-than.patch @@ -0,0 +1,199 @@ +From ef0f2fd061fc2f3fe75df0dc806453625cc94a6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Muchun Song +Acked-by: Tejun Heo +Cc: +Link: https://lore.kernel.org/r/20220720093616.70584-1-hanjinke.666@bytedance.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/block-remove-the-struct-blk_queue_ctx-forward-declar.patch b/queue-5.15/block-remove-the-struct-blk_queue_ctx-forward-declar.patch new file mode 100644 index 00000000000..4b5d86ef4e8 --- /dev/null +++ b/queue-5.15/block-remove-the-struct-blk_queue_ctx-forward-declar.patch @@ -0,0 +1,36 @@ +From 5f5103d02c0fcb8444d03ad19e6686db42d157de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Sep 2021 14:33:22 +0200 +Subject: block: remove the struct blk_queue_ctx forward declaration + +From: Christoph Hellwig + +[ Upstream commit 9778ac77c2027827ffdbb33d3e936b3a0ae9f0f9 ] + +This type doesn't exist at all, so no need to forward declare it. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/20210920123328.1399408-12-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + 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 + +-struct blk_queue_ctx; +- + struct bio_vec; + + enum blk_eh_timer_return { +-- +2.35.1 + diff --git a/queue-5.15/btrfs-ensure-pages-are-unlocked-on-cow_file_range-fa.patch b/queue-5.15/btrfs-ensure-pages-are-unlocked-on-cow_file_range-fa.patch new file mode 100644 index 00000000000..c8fec997b7e --- /dev/null +++ b/queue-5.15/btrfs-ensure-pages-are-unlocked-on-cow_file_range-fa.patch @@ -0,0 +1,196 @@ +From a4558e5dece194a423b115a2dbd28ff7850f6208 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 15:40:59 +0900 +Subject: btrfs: ensure pages are unlocked on cow_file_range() failure + +From: Naohiro Aota + +[ 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] + [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] + +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 +Signed-off-by: Naohiro Aota +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/btrfs-properly-flag-filesystem-with-btrfs_feature_in.patch b/queue-5.15/btrfs-properly-flag-filesystem-with-btrfs_feature_in.patch new file mode 100644 index 00000000000..0f5bdfd6b1d --- /dev/null +++ b/queue-5.15/btrfs-properly-flag-filesystem-with-btrfs_feature_in.patch @@ -0,0 +1,72 @@ +From 6b607f1c8790fef2b56dd25d1d5caaff57970c9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 10:55:47 +0300 +Subject: btrfs: properly flag filesystem with + BTRFS_FEATURE_INCOMPAT_BIG_METADATA + +From: Nikolay Borisov + +[ 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 +Signed-off-by: Nikolay Borisov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/btrfs-reset-block-group-chunk-force-if-we-have-to-wa.patch b/queue-5.15/btrfs-reset-block-group-chunk-force-if-we-have-to-wa.patch new file mode 100644 index 00000000000..36f3d19122c --- /dev/null +++ b/queue-5.15/btrfs-reset-block-group-chunk-force-if-we-have-to-wa.patch @@ -0,0 +1,42 @@ +From 0775fc483ddd36d1168678ec927a972779daa0cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jun 2022 18:31:17 -0400 +Subject: btrfs: reset block group chunk force if we have to wait + +From: Josef Bacik + +[ 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 +CC: stable@vger.kernel.org # 5.4+ +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/crypto-blake2s-remove-shash-module.patch b/queue-5.15/crypto-blake2s-remove-shash-module.patch new file mode 100644 index 00000000000..3af3f267547 --- /dev/null +++ b/queue-5.15/crypto-blake2s-remove-shash-module.patch @@ -0,0 +1,957 @@ +From c8305bb9801b29944fcf91a8e2a7690b48bcf387 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 28 May 2022 21:44:07 +0200 +Subject: crypto: blake2s - remove shash module + +From: Jason A. Donenfeld + +[ 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 +Cc: Eric Biggers +Cc: Ard Biesheuvel +Cc: stable@vger.kernel.org +Fixes: 6048fdcc5f26 ("lib/crypto: blake2s: include as built-in") +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + 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 +-#include +- +-#include +- +-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 "); +-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 +-#include + + #include + #include +@@ -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 . All Rights Reserved. +- */ +- +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-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 . All Rights Reserved. +- */ +- +-#include +-#include +- +-#include +-#include +-#include +- +-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 +-#include + #include + + 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 ++#include ++#include + #include + + /* +@@ -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 + #include + ++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 "); +-- +2.35.1 + diff --git a/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_resume.patch b/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_resume.patch new file mode 100644 index 00000000000..30d1d51bae7 --- /dev/null +++ b/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_resume.patch @@ -0,0 +1,38 @@ +From eb5c27f4c1e650acfdefdba676b5ddc2591cd52a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 14:33:52 -0400 +Subject: dm raid: fix address sanitizer warning in raid_resume + +From: Mikulas Patocka + +[ 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 +Signed-off-by: Mike Snitzer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_status.patch b/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_status.patch new file mode 100644 index 00000000000..db057e7ee08 --- /dev/null +++ b/queue-5.15/dm-raid-fix-address-sanitizer-warning-in-raid_status.patch @@ -0,0 +1,68 @@ +From 7cb190fc09a2445aa081c2713c06ecbd2a93b3fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 14:31:35 -0400 +Subject: dm raid: fix address sanitizer warning in raid_status + +From: Mikulas Patocka + +[ 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. #1 +Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 +Call Trace: + + 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 +Signed-off-by: Mike Snitzer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dm-thin-fix-use-after-free-crash-in-dm_sm_register_t.patch b/queue-5.15/dm-thin-fix-use-after-free-crash-in-dm_sm_register_t.patch new file mode 100644 index 00000000000..7aa69d84c7b --- /dev/null +++ b/queue-5.15/dm-thin-fix-use-after-free-crash-in-dm_sm_register_t.patch @@ -0,0 +1,96 @@ +From 875865ffbe115bafceb09867b999cfe17a0dc5df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 +Signed-off-by: Luo Meng +Signed-off-by: Mike Snitzer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/dm-writecache-set-a-default-max_writeback_jobs.patch b/queue-5.15/dm-writecache-set-a-default-max_writeback_jobs.patch new file mode 100644 index 00000000000..6fa3b091c6b --- /dev/null +++ b/queue-5.15/dm-writecache-set-a-default-max_writeback_jobs.patch @@ -0,0 +1,41 @@ +From 6ded3ae94fbe69ecdb10b7b5e2c8aa48e7400731 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Jul 2022 07:09:04 -0400 +Subject: dm writecache: set a default MAX_WRITEBACK_JOBS + +From: Mikulas Patocka + +[ 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 +Signed-off-by: Mike Snitzer +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drivers-base-fix-userspace-break-from-using-bin_attr.patch b/queue-5.15/drivers-base-fix-userspace-break-from-using-bin_attr.patch new file mode 100644 index 00000000000..5350be56185 --- /dev/null +++ b/queue-5.15/drivers-base-fix-userspace-break-from-using-bin_attr.patch @@ -0,0 +1,188 @@ +From 40c1b27ca3a22ee15423a5f6e890084576809c2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: "Rafael J. Wysocki" +Cc: Yury Norov +Cc: stable@vger.kernel.org +Acked-by: Yury Norov (for include/linux/cpumask.h) +Signed-off-by: Phil Auld +Link: https://lore.kernel.org/r/20220715134924.3466194-1-pauld@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-dp-mst-read-the-extended-dpcd-capabilities-durin.patch b/queue-5.15/drm-dp-mst-read-the-extended-dpcd-capabilities-durin.patch new file mode 100644 index 00000000000..760f00347dc --- /dev/null +++ b/queue-5.15/drm-dp-mst-read-the-extended-dpcd-capabilities-durin.patch @@ -0,0 +1,57 @@ +From 8694527edadbe03effe336ee4e9544b1cbf0ec56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jun 2022 12:45:37 +0300 +Subject: drm/dp/mst: Read the extended DPCD capabilities during system resume + +From: Imre Deak + +[ 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 +Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5292 +Signed-off-by: Imre Deak +Reviewed-by: Jani Nikula +Cc: # v5.14+ +Reviewed-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20220614094537.885472-1-imre.deak@intel.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mediatek-allow-commands-to-be-sent-during-video-.patch b/queue-5.15/drm-mediatek-allow-commands-to-be-sent-during-video-.patch new file mode 100644 index 00000000000..2d31af01826 --- /dev/null +++ b/queue-5.15/drm-mediatek-allow-commands-to-be-sent-during-video-.patch @@ -0,0 +1,93 @@ +From 243864f2df3daf5d6cb0e245ad8c0e5e86095300 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Feb 2022 10:27:42 +0100 +Subject: drm/mediatek: Allow commands to be sent during video mode + +From: Julien STEPHAN + +[ 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 +Signed-off-by: Mattijs Korpershoek +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-mediatek-keep-dsi-as-lp00-before-dcs-cmds-transf.patch b/queue-5.15/drm-mediatek-keep-dsi-as-lp00-before-dcs-cmds-transf.patch new file mode 100644 index 00000000000..91d217492fa --- /dev/null +++ b/queue-5.15/drm-mediatek-keep-dsi-as-lp00-before-dcs-cmds-transf.patch @@ -0,0 +1,116 @@ +From 7f86de396d1dab9dcb0538a562495d2c6afc5d70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 May 2022 10:00:06 +0800 +Subject: drm/mediatek: Keep dsi as LP00 before dcs cmds transfer + +From: Jitao Shi + +[ 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: # 5.10.x: 7f6335c6a258: drm/mediatek: Modify dsi funcs to atomic operations +Cc: # 5.10.x: cde7e2e35c28: drm/mediatek: Separate poweron/poweroff from enable/disable and define new funcs +Cc: # 5.10.x +Signed-off-by: Jitao Shi +Signed-off-by: Xinlei Lee +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Rex-BC Chen +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/drm-vc4-drv-adopt-the-dma-configuration-from-the-hvs.patch b/queue-5.15/drm-vc4-drv-adopt-the-dma-configuration-from-the-hvs.patch new file mode 100644 index 00000000000..a47fea1bcd8 --- /dev/null +++ b/queue-5.15/drm-vc4-drv-adopt-the-dma-configuration-from-the-hvs.patch @@ -0,0 +1,68 @@ +From 06208ff69009db66d711791450761f83b1a35f35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: +Signed-off-by: Dave Stevenson +Link: https://lore.kernel.org/r/20220613144800.326124-2-maxime@cerno.tech +Signed-off-by: Maxime Ripard +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-add-ext4_inode_has_xattr_space-macro-in-xattr.h.patch b/queue-5.15/ext4-add-ext4_inode_has_xattr_space-macro-in-xattr.h.patch new file mode 100644 index 00000000000..182663c18c4 --- /dev/null +++ b/queue-5.15/ext4-add-ext4_inode_has_xattr_space-macro-in-xattr.h.patch @@ -0,0 +1,50 @@ +From 7e2b828c174bb92b4832b3e238d8d2c193d1a45d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 10:13:55 +0800 +Subject: ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h + +From: Baokun Li + +[ 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 +Reviewed-by: Jan Kara +Reviewed-by: Ritesh Harjani (IBM) +Link: https://lore.kernel.org/r/20220616021358.2504451-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-check-if-directory-block-is-within-i_size.patch b/queue-5.15/ext4-check-if-directory-block-is-within-i_size.patch new file mode 100644 index 00000000000..8174d8e41e9 --- /dev/null +++ b/queue-5.15/ext4-check-if-directory-block-is-within-i_size.patch @@ -0,0 +1,56 @@ +From 57e37b1671dd15766e9431707d0ba164f9cf767d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 16:27:20 +0200 +Subject: ext4: check if directory block is within i_size + +From: Lukas Czerner + +[ 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 +Cc: stable@vger.kernel.org +Reviewed-by: Andreas Dilger +Link: https://lore.kernel.org/r/20220704142721.157985-1-lczerner@redhat.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-correct-max_inline_xattr_value_size-computing.patch b/queue-5.15/ext4-correct-max_inline_xattr_value_size-computing.patch new file mode 100644 index 00000000000..c8cc2673965 --- /dev/null +++ b/queue-5.15/ext4-correct-max_inline_xattr_value_size-computing.patch @@ -0,0 +1,41 @@ +From 304c7507b95cfd6985aaa2612801b08d28dc1708 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 10:13:57 +0800 +Subject: ext4: correct max_inline_xattr_value_size computing + +From: Baokun Li + +[ 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 +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220616021358.2504451-4-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-correct-the-misjudgment-in-ext4_iget_extra_inod.patch b/queue-5.15/ext4-correct-the-misjudgment-in-ext4_iget_extra_inod.patch new file mode 100644 index 00000000000..dcbb93c0d91 --- /dev/null +++ b/queue-5.15/ext4-correct-the-misjudgment-in-ext4_iget_extra_inod.patch @@ -0,0 +1,40 @@ +From d2b4d667e5d2a217a92cd61c2848c0c9a91def6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 10:13:58 +0800 +Subject: ext4: correct the misjudgment in ext4_iget_extra_inode + +From: Baokun Li + +[ 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 +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220616021358.2504451-5-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-fix-extent-status-tree-race-in-writeback-error-.patch b/queue-5.15/ext4-fix-extent-status-tree-race-in-writeback-error-.patch new file mode 100644 index 00000000000..9c6769da7d3 --- /dev/null +++ b/queue-5.15/ext4-fix-extent-status-tree-race-in-writeback-error-.patch @@ -0,0 +1,57 @@ +From 1264125b3b0d6dc51db48c6303bb8fb9bfdd88a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 12:05:30 -0400 +Subject: ext4: fix extent status tree race in writeback error recovery path + +From: Eric Whitney + +[ 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 +Signed-off-by: Eric Whitney +Link: https://lore.kernel.org/r/20220615160530.1928801-1-enwlinux@gmail.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-fix-race-when-reusing-xattr-blocks.patch b/queue-5.15/ext4-fix-race-when-reusing-xattr-blocks.patch new file mode 100644 index 00000000000..1eec51dc928 --- /dev/null +++ b/queue-5.15/ext4-fix-race-when-reusing-xattr-blocks.patch @@ -0,0 +1,179 @@ +From 17452bc7744e3011f61a29340e2e13848eff0020 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 12:54:24 +0200 +Subject: ext4: fix race when reusing xattr blocks + +From: Jan Kara + +[ 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 +CC: stable@vger.kernel.org +Fixes: 82939d7999df ("ext4: convert to mbcache2") +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20220712105436.32204-5-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch b/queue-5.15/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch new file mode 100644 index 00000000000..e4d50003762 --- /dev/null +++ b/queue-5.15/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch @@ -0,0 +1,128 @@ +From 19663aea6ffb8fceab2f77fdc15d6a9bb564cb8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 10:13:56 +0800 +Subject: ext4: fix use-after-free in ext4_xattr_set_entry + +From: Baokun Li + +[ 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 +Signed-off-by: Baokun Li +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220616021358.2504451-3-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-fix-warning-in-ext4_iomap_begin-as-race-between.patch b/queue-5.15/ext4-fix-warning-in-ext4_iomap_begin-as-race-between.patch new file mode 100644 index 00000000000..fd41509cb12 --- /dev/null +++ b/queue-5.15/ext4-fix-warning-in-ext4_iomap_begin-as-race-between.patch @@ -0,0 +1,103 @@ +From 86911a73bc1d6a5c206fb422230bb328b1df552f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20220617013935.397596-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-make-sure-ext4_append-always-allocates-new-bloc.patch b/queue-5.15/ext4-make-sure-ext4_append-always-allocates-new-bloc.patch new file mode 100644 index 00000000000..533cc7614f3 --- /dev/null +++ b/queue-5.15/ext4-make-sure-ext4_append-always-allocates-new-bloc.patch @@ -0,0 +1,63 @@ +From 67f725fbcb44ebec0e5c4353f5a468e6b93886a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 16:27:21 +0200 +Subject: ext4: make sure ext4_append() always allocates new block + +From: Lukas Czerner + +[ 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 +Reviewed-by: Andreas Dilger +Link: https://lore.kernel.org/r/20220704142721.157985-2-lczerner@redhat.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-remove-ea-inode-entry-from-mbcache-on-inode-evi.patch b/queue-5.15/ext4-remove-ea-inode-entry-from-mbcache-on-inode-evi.patch new file mode 100644 index 00000000000..11567f9d544 --- /dev/null +++ b/queue-5.15/ext4-remove-ea-inode-entry-from-mbcache-on-inode-evi.patch @@ -0,0 +1,116 @@ +From 723a7030c98ae1a3715d97105b34866cc9df4ec5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 12:54:22 +0200 +Subject: ext4: remove EA inode entry from mbcache on inode eviction + +From: Jan Kara + +[ 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 +Link: https://lore.kernel.org/r/20220712105436.32204-3-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-unindent-codeblock-in-ext4_xattr_block_set.patch b/queue-5.15/ext4-unindent-codeblock-in-ext4_xattr_block_set.patch new file mode 100644 index 00000000000..7ca84164206 --- /dev/null +++ b/queue-5.15/ext4-unindent-codeblock-in-ext4_xattr_block_set.patch @@ -0,0 +1,125 @@ +From 71871a22a9a65e84430055f0429a1b70b0f9286c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 12:54:23 +0200 +Subject: ext4: unindent codeblock in ext4_xattr_block_set() + +From: Jan Kara + +[ 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 +Link: https://lore.kernel.org/r/20220712105436.32204-4-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-update-s_overhead_clusters-in-the-superblock-du.patch b/queue-5.15/ext4-update-s_overhead_clusters-in-the-superblock-du.patch new file mode 100644 index 00000000000..fa3bf6894be --- /dev/null +++ b/queue-5.15/ext4-update-s_overhead_clusters-in-the-superblock-du.patch @@ -0,0 +1,51 @@ +From aaa919979d4732f24de785c56e839330351ba23c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: stable@kernel.org +Reviewed-by: Andreas Dilger +Link: https://lore.kernel.org/r/20220629040026.112371-1-tytso@mit.edu +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ext4-use-kmemdup-to-replace-kmalloc-memcpy.patch b/queue-5.15/ext4-use-kmemdup-to-replace-kmalloc-memcpy.patch new file mode 100644 index 00000000000..dc4953c2946 --- /dev/null +++ b/queue-5.15/ext4-use-kmemdup-to-replace-kmalloc-memcpy.patch @@ -0,0 +1,40 @@ +From 69601d26ae1f0f5fbd563f58131ba84784faa8f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 May 2022 11:01:20 +0800 +Subject: ext4: use kmemdup() to replace kmalloc + memcpy + +From: Shuqi Zhang + +[ Upstream commit 4efd9f0d120c55b08852ee5605dbb02a77089a5d ] + +Replace kmalloc + memcpy with kmemdup() + +Signed-off-by: Shuqi Zhang +Reviewed-by: Ritesh Harjani +Link: https://lore.kernel.org/r/20220525030120.803330-1-zhangshuqi3@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/firmware-arm_scpi-ensure-scpi_info-is-not-assigned-i.patch b/queue-5.15/firmware-arm_scpi-ensure-scpi_info-is-not-assigned-i.patch new file mode 100644 index 00000000000..9e5be653d1c --- /dev/null +++ b/queue-5.15/firmware-arm_scpi-ensure-scpi_info-is-not-assigned-i.patch @@ -0,0 +1,156 @@ +From 80c500ac7a77f89055f67bef3fcee94b3e07bbaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jackie Liu +Signed-off-by: Sudeep Holla +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/ftrace-x86-add-back-ftrace_expected-assignment.patch-22490 b/queue-5.15/ftrace-x86-add-back-ftrace_expected-assignment.patch-22490 new file mode 100644 index 00000000000..713ecf7aafb --- /dev/null +++ b/queue-5.15/ftrace-x86-add-back-ftrace_expected-assignment.patch-22490 @@ -0,0 +1,49 @@ +From 585d0f39ee37d8e804082139876ac4975e04209a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Jul 2022 10:18:51 -0400 +Subject: ftrace/x86: Add back ftrace_expected assignment + +From: Steven Rostedt (Google) + +[ 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" +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: "H. Peter Anvin" +Cc: Andrew Morton +Cc: stable@vger.kernel.org +Fixes: 768ae4406a5c ("x86/ftrace: Use text_poke()") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/input-gscps2-check-return-value-of-ioremap-in-gscps2.patch b/queue-5.15/input-gscps2-check-return-value-of-ioremap-in-gscps2.patch new file mode 100644 index 00000000000..04ef9baaca7 --- /dev/null +++ b/queue-5.15/input-gscps2-check-return-value-of-ioremap-in-gscps2.patch @@ -0,0 +1,40 @@ +From 3650b44badc32848799e20d0626bf23914a67b77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 15:20:33 +0800 +Subject: Input: gscps2 - check return value of ioremap() in gscps2_probe() + +From: Xie Shaowen + +[ 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: # v5.6+ +Reported-by: Hacash Robot +Signed-off-by: Xie Shaowen +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/intel_th-pci-add-meteor-lake-p-support.patch b/queue-5.15/intel_th-pci-add-meteor-lake-p-support.patch new file mode 100644 index 00000000000..0517ced6cf1 --- /dev/null +++ b/queue-5.15/intel_th-pci-add-meteor-lake-p-support.patch @@ -0,0 +1,40 @@ +From c785bd2648485518b65637389e9a44c9b0add3a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 11:26:35 +0300 +Subject: intel_th: pci: Add Meteor Lake-P support + +From: Alexander Shishkin + +[ Upstream commit 802a9a0b1d91274ef10d9fe429b4cc1e8c200aef ] + +Add support for the Trace Hub in Meteor Lake-P. + +Reviewed-by: Andy Shevchenko +Cc: stable +Signed-off-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20220705082637.59979-5-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/intel_th-pci-add-raptor-lake-s-cpu-support.patch b/queue-5.15/intel_th-pci-add-raptor-lake-s-cpu-support.patch new file mode 100644 index 00000000000..7af7661db9b --- /dev/null +++ b/queue-5.15/intel_th-pci-add-raptor-lake-s-cpu-support.patch @@ -0,0 +1,40 @@ +From c84e7921fd6e00cb04aca62790e5c688b9687267 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 11:26:37 +0300 +Subject: intel_th: pci: Add Raptor Lake-S CPU support + +From: Alexander Shishkin + +[ Upstream commit ff46a601afc5a66a81c3945b83d0a2caeb88e8bc ] + +Add support for the Trace Hub in Raptor Lake-S CPU. + +Reviewed-by: Andy Shevchenko +Cc: stable +Signed-off-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20220705082637.59979-7-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/intel_th-pci-add-raptor-lake-s-pch-support.patch b/queue-5.15/intel_th-pci-add-raptor-lake-s-pch-support.patch new file mode 100644 index 00000000000..34baa18613b --- /dev/null +++ b/queue-5.15/intel_th-pci-add-raptor-lake-s-pch-support.patch @@ -0,0 +1,40 @@ +From da8b11da15dd582cd0e1f0d9da07580ec5738564 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 11:26:36 +0300 +Subject: intel_th: pci: Add Raptor Lake-S PCH support + +From: Alexander Shishkin + +[ Upstream commit 23e2de5826e2fc4dd43e08bab3a2ea1a5338b063 ] + +Add support for the Trace Hub in Raptor Lake-S PCH. + +Reviewed-by: Andy Shevchenko +Cc: stable +Signed-off-by: Alexander Shishkin +Link: https://lore.kernel.org/r/20220705082637.59979-6-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/iommu-vt-d-avoid-invalid-memory-access-via-node_onli.patch b/queue-5.15/iommu-vt-d-avoid-invalid-memory-access-via-node_onli.patch new file mode 100644 index 00000000000..239d5157d65 --- /dev/null +++ b/queue-5.15/iommu-vt-d-avoid-invalid-memory-access-via-node_onli.patch @@ -0,0 +1,66 @@ +From 538e6fd1e59662975ef67b348de758020c8f31ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +[ 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 +Signed-off-by: Alexander Lobakin +Reviewed-by: Andy Shevchenko +Reviewed-by: Lu Baolu +Signed-off-by: Yury Norov +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kexec-keys-s390-make-use-of-built-in-and-secondary-k.patch b/queue-5.15/kexec-keys-s390-make-use-of-built-in-and-secondary-k.patch new file mode 100644 index 00000000000..164cc1d7a1e --- /dev/null +++ b/queue-5.15/kexec-keys-s390-make-use-of-built-in-and-secondary-k.patch @@ -0,0 +1,72 @@ +From 21898a1cb7606e9a5ce4befe24ac82f69647030c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: kexec@lists.infradead.org +Cc: keyrings@vger.kernel.org +Cc: linux-security-module@vger.kernel.org +Signed-off-by: Michal Suchanek +Reviewed-by: "Lee, Chun-Yi" +Acked-by: Baoquan He +Signed-off-by: Coiby Xu +Acked-by: Heiko Carstens +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/keys-asymmetric-enforce-sm2-signature-use-pkey-algo.patch b/queue-5.15/keys-asymmetric-enforce-sm2-signature-use-pkey-algo.patch new file mode 100644 index 00000000000..831b8d9c7fd --- /dev/null +++ b/queue-5.15/keys-asymmetric-enforce-sm2-signature-use-pkey-algo.patch @@ -0,0 +1,60 @@ +From 5de69edcf45f620aa93d523b42aa99b1a8a2a4e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 11:37:20 +0800 +Subject: KEYS: asymmetric: enforce SM2 signature use pkey algo + +From: Tianjia Zhang + +[ 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 +Cc: stable@vger.kernel.org # v5.10+ +Signed-off-by: Tianjia Zhang +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-nvmx-attempt-to-load-perf_global_ctrl-on-nvmx-xf.patch b/queue-5.15/kvm-nvmx-attempt-to-load-perf_global_ctrl-on-nvmx-xf.patch new file mode 100644 index 00000000000..f2faf885b50 --- /dev/null +++ b/queue-5.15/kvm-nvmx-attempt-to-load-perf_global_ctrl-on-nvmx-xf.patch @@ -0,0 +1,78 @@ +From 8a7edf17c3f5130188103fb95c52153b2badeabb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220722224409.1336532-5-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-set_msr_mce-permit-guests-to-ignore-single-bit-e.patch b/queue-5.15/kvm-set_msr_mce-permit-guests-to-ignore-single-bit-e.patch new file mode 100644 index 00000000000..1ba9ba195b1 --- /dev/null +++ b/queue-5.15/kvm-set_msr_mce-permit-guests-to-ignore-single-bit-e.patch @@ -0,0 +1,71 @@ +From 16198eef162b1958bc149d489bec46899d1da19b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220521081511.187388-1-lkujaw@member.fsf.org> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-vmx-add-helper-to-check-if-the-guest-pmu-has-per.patch b/queue-5.15/kvm-vmx-add-helper-to-check-if-the-guest-pmu-has-per.patch new file mode 100644 index 00000000000..bb946357dc9 --- /dev/null +++ b/queue-5.15/kvm-vmx-add-helper-to-check-if-the-guest-pmu-has-per.patch @@ -0,0 +1,73 @@ +From 7e6065df24b496053100812039a3a1e9c70517c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220722224409.1336532-4-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-vmx-mark-all-perf_global_-ovf-_ctrl-bits-reserve.patch b/queue-5.15/kvm-vmx-mark-all-perf_global_-ovf-_ctrl-bits-reserve.patch new file mode 100644 index 00000000000..b6d58398fa7 --- /dev/null +++ b/queue-5.15/kvm-vmx-mark-all-perf_global_-ovf-_ctrl-bits-reserve.patch @@ -0,0 +1,43 @@ +From 7b656117a1d2961bfbbdb1309cb6e5db3135efab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220722224409.1336532-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-pmu-ignore-pmu-global_ctrl-check-if-vpmu-doe.patch b/queue-5.15/kvm-x86-pmu-ignore-pmu-global_ctrl-check-if-vpmu-doe.patch new file mode 100644 index 00000000000..9ab2898aeb0 --- /dev/null +++ b/queue-5.15/kvm-x86-pmu-ignore-pmu-global_ctrl-check-if-vpmu-doe.patch @@ -0,0 +1,40 @@ +From f36e7bace71271b84f97a4f4868c7f52799579e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Message-Id: <20220509102204.62389-1-likexu@tencent.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-pmu-introduce-the-ctrl_mask-value-for-fixed-.patch b/queue-5.15/kvm-x86-pmu-introduce-the-ctrl_mask-value-for-fixed-.patch new file mode 100644 index 00000000000..0424306abbe --- /dev/null +++ b/queue-5.15/kvm-x86-pmu-introduce-the-ctrl_mask-value-for-fixed-.patch @@ -0,0 +1,79 @@ +From 93487041049f8add6f81d6e3b60db1e844507c08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Apr 2022 18:19:34 +0800 +Subject: KVM: x86/pmu: Introduce the ctrl_mask value for fixed counter + +From: Like Xu + +[ 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 +Signed-off-by: Luwei Kang +Signed-off-by: Like Xu +Acked-by: Peter Zijlstra (Intel) +Message-Id: <20220411101946.20262-6-likexu@tencent.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/kvm-x86-signal-gp-not-eperm-on-bad-wrmsr-mci_ctl-sta.patch b/queue-5.15/kvm-x86-signal-gp-not-eperm-on-bad-wrmsr-mci_ctl-sta.patch new file mode 100644 index 00000000000..4c63ebf4533 --- /dev/null +++ b/queue-5.15/kvm-x86-signal-gp-not-eperm-on-bad-wrmsr-mci_ctl-sta.patch @@ -0,0 +1,50 @@ +From 077cef63d8bd4e55745d198fd7cf2bec15c0c3e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Jim Mattson +Link: https://lore.kernel.org/r/20220512222716.4112548-2-seanjc@google.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/locking-csd_lock-change-csdlock_debug-from-early_par.patch b/queue-5.15/locking-csd_lock-change-csdlock_debug-from-early_par.patch new file mode 100644 index 00000000000..2fb9177138a --- /dev/null +++ b/queue-5.15/locking-csd_lock-change-csdlock_debug-from-early_par.patch @@ -0,0 +1,56 @@ +From 452c6339258b2e881f5d086964f3333a511f08fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 May 2022 17:46:39 +0800 +Subject: locking/csd_lock: Change csdlock_debug from early_param to __setup + +From: Chen Zhongjin + +[ 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 +Signed-off-by: Chen Zhongjin +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/net-9p-initialize-the-iounit-field-during-fid-creati.patch b/queue-5.15/net-9p-initialize-the-iounit-field-during-fid-creati.patch new file mode 100644 index 00000000000..d94985f1016 --- /dev/null +++ b/queue-5.15/net-9p-initialize-the-iounit-field-during-fid-creati.patch @@ -0,0 +1,68 @@ +From 8822529cea86104c1bbae6788949871a68c2d490 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 10 Jul 2022 09:14:02 -0500 +Subject: net/9p: Initialize the iounit field during fid creation + +From: Tyler Hicks + +[ 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 +Reviewed-by: Christian Schoenebeck +Signed-off-by: Dominique Martinet +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pci-aer-iterate-over-error-counters-instead-of-error.patch b/queue-5.15/pci-aer-iterate-over-error-counters-instead-of-error.patch new file mode 100644 index 00000000000..4d9dc448171 --- /dev/null +++ b/queue-5.15/pci-aer-iterate-over-error-counters-instead-of-error.patch @@ -0,0 +1,61 @@ +From f32962975fa337d30945cd15f1e428988d87822a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 9 May 2022 18:14:41 +0000 +Subject: PCI/AER: Iterate over error counters instead of error strings + +From: Mohamed Khalfella + +[ 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 +Signed-off-by: Mohamed Khalfella +Signed-off-by: Bjorn Helgaas +Reviewed-by: Meeta Saggi +Reviewed-by: Eric Badger +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/pci-qcom-power-on-phy-before-ipq8074-dbi-register-ac.patch b/queue-5.15/pci-qcom-power-on-phy-before-ipq8074-dbi-register-ac.patch new file mode 100644 index 00000000000..c6783b86a5e --- /dev/null +++ b/queue-5.15/pci-qcom-power-on-phy-before-ipq8074-dbi-register-ac.patch @@ -0,0 +1,111 @@ +From 5c50abf727e665c6674473b2c2e1016a534cee8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 17:50:03 +0200 +Subject: PCI: qcom: Power on PHY before IPQ8074 DBI register accesses + +From: Robert Marko + +[ 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 +Signed-off-by: Bjorn Helgaas +Reviewed-by: Dmitry Baryshkov +Cc: stable@vger.kernel.org # v5.11+ +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/powerpc-powernv-kvm-use-darn-for-h_random-on-power9.patch b/queue-5.15/powerpc-powernv-kvm-use-darn-for-h_random-on-power9.patch new file mode 100644 index 00000000000..ae7117c45ee --- /dev/null +++ b/queue-5.15/powerpc-powernv-kvm-use-darn-for-h_random-on-power9.patch @@ -0,0 +1,145 @@ +From a64d93aa22c776f0955f289745e4f34537de308a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 00:32:18 +1000 +Subject: powerpc/powernv/kvm: Use darn for H_RANDOM on Power9 + +From: Jason A. Donenfeld + +[ 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 +Tested-by: Sachin Sant +[mpe: Rebase on previous commit, update change log appropriately] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220727143219.2684192-2-mpe@ellerman.id.au +Signed-off-by: Sasha Levin +--- + 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 + #include + #include +-#include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-5.15/scsi-lpfc-fix-eeh-support-for-nvme-i-o.patch b/queue-5.15/scsi-lpfc-fix-eeh-support-for-nvme-i-o.patch new file mode 100644 index 00000000000..898ce52a255 --- /dev/null +++ b/queue-5.15/scsi-lpfc-fix-eeh-support-for-nvme-i-o.patch @@ -0,0 +1,527 @@ +From b1e40f182db9a716acfaa99902ceb83aff08c39b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Sep 2021 16:31:54 -0700 +Subject: scsi: lpfc: Fix EEH support for NVMe I/O + +From: James Smart + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-lpfc-remove-extra-atomic_inc-on-cmd_pending-in-.patch b/queue-5.15/scsi-lpfc-remove-extra-atomic_inc-on-cmd_pending-in-.patch new file mode 100644 index 00000000000..7d6443480a2 --- /dev/null +++ b/queue-5.15/scsi-lpfc-remove-extra-atomic_inc-on-cmd_pending-in-.patch @@ -0,0 +1,40 @@ +From 1b118d426a9477a697c4ec0251b0e68d20125365 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: # v5.14+ +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-lpfc-sli-path-split-refactor-fast-and-slow-path.patch b/queue-5.15/scsi-lpfc-sli-path-split-refactor-fast-and-slow-path.patch new file mode 100644 index 00000000000..345fd9b7bde --- /dev/null +++ b/queue-5.15/scsi-lpfc-sli-path-split-refactor-fast-and-slow-path.patch @@ -0,0 +1,889 @@ +From 3510446140fedf511836136d992afcfa9e506c3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 error: IOCB */ ++ if (ulp_status) { ++ /* Rsp ring 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 + diff --git a/queue-5.15/scsi-lpfc-sli-path-split-refactor-lpfc_iocbq.patch b/queue-5.15/scsi-lpfc-sli-path-split-refactor-lpfc_iocbq.patch new file mode 100644 index 00000000000..cc7cf6dfed5 --- /dev/null +++ b/queue-5.15/scsi-lpfc-sli-path-split-refactor-lpfc_iocbq.patch @@ -0,0 +1,2691 @@ +From 34168a969ca406c4f18c1610d38d777788f268d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 18:22:52 -0800 +Subject: scsi: lpfc: SLI path split: Refactor lpfc_iocbq + +From: James Smart + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 */ +- 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 */ + 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 + diff --git a/queue-5.15/scsi-lpfc-sli-path-split-refactor-scsi-paths.patch b/queue-5.15/scsi-lpfc-sli-path-split-refactor-scsi-paths.patch new file mode 100644 index 00000000000..362cbfa08ef --- /dev/null +++ b/queue-5.15/scsi-lpfc-sli-path-split-refactor-scsi-paths.patch @@ -0,0 +1,677 @@ +From 96a3e1903dcbece9c658a09376f9b5e602dbf44b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Feb 2022 18:23:04 -0800 +Subject: scsi: lpfc: SLI path split: Refactor SCSI paths + +From: James Smart + +[ 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 +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-edif-fix-dropped-ike-message.patch b/queue-5.15/scsi-qla2xxx-edif-fix-dropped-ike-message.patch new file mode 100644 index 00000000000..e322f305fea --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-edif-fix-dropped-ike-message.patch @@ -0,0 +1,126 @@ +From ce3eabf3448d5c7b76e15c2aab5be386774cf6fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 22:20:40 -0700 +Subject: scsi: qla2xxx: edif: Fix dropped IKE message + +From: Quinn Tran + +[ 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 +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-crash-due-to-stale-srb-access-aroun.patch b/queue-5.15/scsi-qla2xxx-fix-crash-due-to-stale-srb-access-aroun.patch new file mode 100644 index 00000000000..9d5b4a00b39 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-crash-due-to-stale-srb-access-aroun.patch @@ -0,0 +1,125 @@ +From 5022d7f75a959f35a10caa156f7872f76f101346 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-discovery-issues-in-fc-al-topology.patch-12842 b/queue-5.15/scsi-qla2xxx-fix-discovery-issues-in-fc-al-topology.patch-12842 new file mode 100644 index 00000000000..66b6f7be419 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-discovery-issues-in-fc-al-topology.patch-12842 @@ -0,0 +1,116 @@ +From 0b4b66987bf3e1b6dc2f81496653d7ff9b38b5ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 22:20:42 -0700 +Subject: scsi: qla2xxx: Fix discovery issues in FC-AL topology + +From: Arun Easi + +[ 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 +Tested-by: Tony Battersby +Reviewed-by: Himanshu Madhani +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-erroneous-mailbox-timeout-after-pci.patch b/queue-5.15/scsi-qla2xxx-fix-erroneous-mailbox-timeout-after-pci.patch new file mode 100644 index 00000000000..2f242a77838 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-erroneous-mailbox-timeout-after-pci.patch @@ -0,0 +1,67 @@ +From e6f07ae0f8b10d076fd632535cf706e64a4b06f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:07 -0700 +Subject: scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error + injection + +From: Quinn Tran + +[ 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 +Cc: Kyle Mahlkuch +Cc: stable@vger.kernel.org +Reported-by: Naresh Bannoth +Tested-by: Naresh Bannoth +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-excessive-i-o-error-messages-by-def.patch b/queue-5.15/scsi-qla2xxx-fix-excessive-i-o-error-messages-by-def.patch new file mode 100644 index 00000000000..937701c5e49 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-excessive-i-o-error-messages-by-def.patch @@ -0,0 +1,48 @@ +From e0e9abd03bd5742d62ac45c7517382dc7d2267f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:34:58 -0700 +Subject: scsi: qla2xxx: Fix excessive I/O error messages by default + +From: Arun Easi + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-imbalance-vha-vref_count.patch-21291 b/queue-5.15/scsi-qla2xxx-fix-imbalance-vha-vref_count.patch-21291 new file mode 100644 index 00000000000..46cf1e93528 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-imbalance-vha-vref_count.patch-21291 @@ -0,0 +1,61 @@ +From 2d6af9bb8469e163a0afa2552f0e5edb03b41a1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 22:20:41 -0700 +Subject: scsi: qla2xxx: Fix imbalance vha->vref_count + +From: Quinn Tran + +[ 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 +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-during-port-pe.patch b/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-during-port-pe.patch new file mode 100644 index 00000000000..10524c330b7 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-during-port-pe.patch @@ -0,0 +1,41 @@ +From 1a1e0916c6e933835567aa7c8daaca4a0b066e06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:03 -0700 +Subject: scsi: qla2xxx: Fix losing FCP-2 targets during port perturbation + tests + +From: Arun Easi + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-on-long-port-d.patch b/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-on-long-port-d.patch new file mode 100644 index 00000000000..4a6c1e80a48 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-losing-fcp-2-targets-on-long-port-d.patch @@ -0,0 +1,72 @@ +From 2eba983f6446ec2ca5460d266c2e0b6b8fd70b2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-losing-target-when-it-reappears-dur.patch b/queue-5.15/scsi-qla2xxx-fix-losing-target-when-it-reappears-dur.patch new file mode 100644 index 00000000000..d5982a9638f --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-losing-target-when-it-reappears-dur.patch @@ -0,0 +1,84 @@ +From f716ebbcca6fd9461d2fea1b920aa18c48915ca1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:04 -0700 +Subject: scsi: qla2xxx: Fix losing target when it reappears during delete + +From: Arun Easi + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-fix-response-queue-handler-reading-stal.patch b/queue-5.15/scsi-qla2xxx-fix-response-queue-handler-reading-stal.patch new file mode 100644 index 00000000000..d9a5eb39a00 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-response-queue-handler-reading-stal.patch @@ -0,0 +1,128 @@ +From b85888be1f0e34cb530cdf984eedaf5f9ca2f63f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 22:20:39 -0700 +Subject: scsi: qla2xxx: Fix response queue handler reading stale packets + +From: Arun Easi + +[ 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 +Signed-off-by: Arun Easi +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-turn-off-multi-queue-for-8g-adapters.patch-24759 b/queue-5.15/scsi-qla2xxx-turn-off-multi-queue-for-8g-adapters.patch-24759 new file mode 100644 index 00000000000..d794a399829 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-turn-off-multi-queue-for-8g-adapters.patch-24759 @@ -0,0 +1,68 @@ +From a5fefe072ff838eb38ad9905a6c9eeeb513a6f02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:01 -0700 +Subject: scsi: qla2xxx: Turn off multi-queue for 8G adapters + +From: Quinn Tran + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-update-manufacturer-details.patch b/queue-5.15/scsi-qla2xxx-update-manufacturer-details.patch new file mode 100644 index 00000000000..9984ebd6f09 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-update-manufacturer-details.patch @@ -0,0 +1,52 @@ +From 318142b652409d6495f685168c5d8ef1539dbd9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 22:20:44 -0700 +Subject: scsi: qla2xxx: Update manufacturer details + +From: Bikash Hazarika + +[ 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 +Signed-off-by: Bikash Hazarika +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/scsi-qla2xxx-wind-down-adapter-after-pcie-error.patch-6065 b/queue-5.15/scsi-qla2xxx-wind-down-adapter-after-pcie-error.patch-6065 new file mode 100644 index 00000000000..20124b567de --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-wind-down-adapter-after-pcie-error.patch-6065 @@ -0,0 +1,210 @@ +From f2fbb80e0df228b61cec2944fe21ed09e396ecdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 22:35:00 -0700 +Subject: scsi: qla2xxx: Wind down adapter after PCIe error + +From: Quinn Tran + +[ 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 +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/serial-8250-add-proper-clock-handling-for-oxsemi-pci.patch b/queue-5.15/serial-8250-add-proper-clock-handling-for-oxsemi-pci.patch new file mode 100644 index 00000000000..10b5505fdd2 --- /dev/null +++ b/queue-5.15/serial-8250-add-proper-clock-handling-for-oxsemi-pci.patch @@ -0,0 +1,764 @@ +From 2440da0db53103791d3d98b6593db82ffcd684c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Apr 2022 16:27:33 +0100 +Subject: serial: 8250: Add proper clock handling for OxSemi PCIe devices + +From: Maciej W. Rozycki + +[ 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 +Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181519450.9383@angie.orcam.me.uk +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + .../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 +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 + #include + #include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-5.15/serial-8250-fold-endrun-device-support-into-oxsemi-t.patch b/queue-5.15/serial-8250-fold-endrun-device-support-into-oxsemi-t.patch new file mode 100644 index 00000000000..df5c159035b --- /dev/null +++ b/queue-5.15/serial-8250-fold-endrun-device-support-into-oxsemi-t.patch @@ -0,0 +1,177 @@ +From aa5d7246d233d1983175ca21ac6b0682e3e28515 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Apr 2022 16:27:22 +0100 +Subject: serial: 8250: Fold EndRun device support into OxSemi Tornado code + +From: Maciej W. Rozycki + +[ 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 +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181516220.9383@angie.orcam.me.uk +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/serial-8250_pci-refactor-the-loop-in-pci_ite887x_ini.patch b/queue-5.15/serial-8250_pci-refactor-the-loop-in-pci_ite887x_ini.patch new file mode 100644 index 00000000000..88ac0af4364 --- /dev/null +++ b/queue-5.15/serial-8250_pci-refactor-the-loop-in-pci_ite887x_ini.patch @@ -0,0 +1,64 @@ +From 6805c901d96c34706c924c1422585a22738742d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Oct 2021 16:51:45 +0300 +Subject: serial: 8250_pci: Refactor the loop in pci_ite887x_init() + +From: Andy Shevchenko + +[ 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 +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/20211022135147.70965-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/serial-8250_pci-replace-dev_-by-pci_-macros.patch b/queue-5.15/serial-8250_pci-replace-dev_-by-pci_-macros.patch new file mode 100644 index 00000000000..2389e305806 --- /dev/null +++ b/queue-5.15/serial-8250_pci-replace-dev_-by-pci_-macros.patch @@ -0,0 +1,210 @@ +From b265a9249a3f39a92164e0cc1b62fed5b45140cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Oct 2021 16:51:47 +0300 +Subject: serial: 8250_pci: Replace dev_*() by pci_*() macros + +From: Andy Shevchenko + +[ Upstream commit 1177384179416c7136e1348f07609e0da1ae6b91 ] + +PCI subsystem provides convenient shortcut macros for message printing. +Use those macros instead of dev_*(). + +Signed-off-by: Andy Shevchenko +Reviewed-by: Jiri Slaby +Link: https://lore.kernel.org/r/20211022135147.70965-3-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 .\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 + diff --git a/queue-5.15/series b/queue-5.15/series index e93299aae03..e61cbfff3fc 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -690,3 +690,92 @@ posix-cpu-timers-cleanup-cpu-timers-before-freeing-them-during-exec.patch 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 diff --git a/queue-5.15/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tra.patch b/queue-5.15/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tra.patch new file mode 100644 index 00000000000..ed9d15d6dd7 --- /dev/null +++ b/queue-5.15/spmi-trace-fix-stack-out-of-bound-access-in-spmi-tra.patch @@ -0,0 +1,115 @@ +From 2164f615c64d6f8549823f48cde9c7450e5e84d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Steven Rostedt (Google) +Signed-off-by: David Collins +Link: https://lore.kernel.org/r/20220627235512.2272783-1-quic_collinsd@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/timekeeping-contribute-wall-clock-to-rng-on-time-cha.patch b/queue-5.15/timekeeping-contribute-wall-clock-to-rng-on-time-cha.patch new file mode 100644 index 00000000000..3bdac3984af --- /dev/null +++ b/queue-5.15/timekeeping-contribute-wall-clock-to-rng-on-time-cha.patch @@ -0,0 +1,74 @@ +From cd57e246465d84fac3e0eb2b338b665c889a0319 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Jul 2022 23:53:34 +0200 +Subject: timekeeping: contribute wall clock to rng on time change + +From: Jason A. Donenfeld + +[ 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 +Reviewed-by: Eric Biggers +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + + #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 + diff --git a/queue-5.15/topology-represent-clusters-of-cpus-within-a-die.patch b/queue-5.15/topology-represent-clusters-of-cpus-within-a-die.patch new file mode 100644 index 00000000000..ccf01006605 --- /dev/null +++ b/queue-5.15/topology-represent-clusters-of-cpus-within-a-die.patch @@ -0,0 +1,458 @@ +From 384461141ad56b514a9d7c6b3aa4f8ae5c27daff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Sep 2021 20:51:02 +1200 +Subject: topology: Represent clusters of CPUs within a die + +From: Jonathan Cameron + +[ 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 +Signed-off-by: Tian Tao +Signed-off-by: Barry Song +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20210924085104.44806-2-21cnbao@gmail.com +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.15/topology-sysfs-export-cluster-attributes-only-if-an-.patch b/queue-5.15/topology-sysfs-export-cluster-attributes-only-if-an-.patch new file mode 100644 index 00000000000..ca696e02291 --- /dev/null +++ b/queue-5.15/topology-sysfs-export-cluster-attributes-only-if-an-.patch @@ -0,0 +1,119 @@ +From e4d3e0f541c6884ea3a9d67839e74293c4cd8512 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Nov 2021 14:03:08 +0100 +Subject: topology/sysfs: export cluster attributes only if an architectures + has support + +From: Heiko Carstens + +[ 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) +Signed-off-by: Heiko Carstens +Link: https://lore.kernel.org/r/20211129130309.3256168-3-hca@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/topology-sysfs-export-die-attributes-only-if-an-arch.patch b/queue-5.15/topology-sysfs-export-die-attributes-only-if-an-arch.patch new file mode 100644 index 00000000000..5823a7194bb --- /dev/null +++ b/queue-5.15/topology-sysfs-export-die-attributes-only-if-an-arch.patch @@ -0,0 +1,120 @@ +From c7a2cd6e4e942bd7271d652f8f40aafab20e69c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Nov 2021 14:03:07 +0100 +Subject: topology/sysfs: export die attributes only if an architectures has + support + +From: Heiko Carstens + +[ 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) +Signed-off-by: Heiko Carstens +Link: https://lore.kernel.org/r/20211129130309.3256168-2-hca@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tpm-eventlog-fix-section-mismatch-for-debug_section_.patch b/queue-5.15/tpm-eventlog-fix-section-mismatch-for-debug_section_.patch new file mode 100644 index 00000000000..1725ec34c90 --- /dev/null +++ b/queue-5.15/tpm-eventlog-fix-section-mismatch-for-debug_section_.patch @@ -0,0 +1,47 @@ +From 81aa50dc324598e59926aba99bd7147036869229 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Jul 2022 09:17:38 +0800 +Subject: tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH + +From: Huacai Chen + +[ 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 +Signed-off-by: Huacai Chen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tracing-add-__rel_loc-using-trace-event-macros.patch b/queue-5.15/tracing-add-__rel_loc-using-trace-event-macros.patch new file mode 100644 index 00000000000..ed6e28400fc --- /dev/null +++ b/queue-5.15/tracing-add-__rel_loc-using-trace-event-macros.patch @@ -0,0 +1,290 @@ +From 53c30a8233056bf70160e6cf69d51ea176cdead1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Nov 2021 18:30:21 +0900 +Subject: tracing: Add '__rel_loc' using trace event macros + +From: Masami Hiramatsu + +[ 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 +Cc: Namhyung Kim +Cc: Tom Zanussi +Signed-off-by: Masami Hiramatsu +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tracing-avoid-warray-bounds-warning-for-__rel_loc-ma.patch b/queue-5.15/tracing-avoid-warray-bounds-warning-for-__rel_loc-ma.patch new file mode 100644 index 00000000000..cf10437f7cf --- /dev/null +++ b/queue-5.15/tracing-avoid-warray-bounds-warning-for-__rel_loc-ma.patch @@ -0,0 +1,48 @@ +From eddd09b8d3ad6134db6d0034a8254c45da0587c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jan 2022 23:19:30 +0900 +Subject: tracing: Avoid -Warray-bounds warning for __rel_loc macro + +From: Masami Hiramatsu + +[ 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 +Cc: Kees Cook +Signed-off-by: Masami Hiramatsu +[ This did not fix the warning, but is still a nice clean up ] +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/tty-8250-add-support-for-brainboxes-px-cards.patch b/queue-5.15/tty-8250-add-support-for-brainboxes-px-cards.patch new file mode 100644 index 00000000000..19e7f2a337f --- /dev/null +++ b/queue-5.15/tty-8250-add-support-for-brainboxes-px-cards.patch @@ -0,0 +1,147 @@ +From 2b7d45020f0fd554a1ec008305f07d8fe4964340 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Jul 2022 16:35:10 +0100 +Subject: tty: 8250: Add support for Brainboxes PX cards. + +From: Cameron Williams + +[ 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 +Cc: stable +Link: https://lore.kernel.org/r/AM5PR0202MB2564669252BDC59BF55A6E87C4879@AM5PR0202MB2564.eurprd02.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usbnet-smsc95xx-avoid-link-settings-race-on-interrup.patch b/queue-5.15/usbnet-smsc95xx-avoid-link-settings-race-on-interrup.patch new file mode 100644 index 00000000000..7d561932c49 --- /dev/null +++ b/queue-5.15/usbnet-smsc95xx-avoid-link-settings-race-on-interrup.patch @@ -0,0 +1,122 @@ +From 0d558f5af530b7f58eaba9633342640ab602cec7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 May 2022 10:42:04 +0200 +Subject: usbnet: smsc95xx: Avoid link settings race on interrupt reception + +From: Lukas Wunner + +[ 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 # LAN9514/9512/9500 +Tested-by: Ferry Toth # LAN9514 +Signed-off-by: Lukas Wunner +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usbnet-smsc95xx-don-t-clear-read-only-phy-interrupt.patch b/queue-5.15/usbnet-smsc95xx-don-t-clear-read-only-phy-interrupt.patch new file mode 100644 index 00000000000..ea9ed0684b7 --- /dev/null +++ b/queue-5.15/usbnet-smsc95xx-don-t-clear-read-only-phy-interrupt.patch @@ -0,0 +1,51 @@ +From 2c1c3a1806ffa081e67dd98bd100544ea82439ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 May 2022 10:42:02 +0200 +Subject: usbnet: smsc95xx: Don't clear read-only PHY interrupt + +From: Lukas Wunner + +[ 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 # LAN9514/9512/9500 +Tested-by: Ferry Toth # LAN9514 +Signed-off-by: Lukas Wunner +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch b/queue-5.15/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch new file mode 100644 index 00000000000..4c2ea4e9b94 --- /dev/null +++ b/queue-5.15/usbnet-smsc95xx-fix-deadlock-on-runtime-resume.patch @@ -0,0 +1,193 @@ +From 378ef3e9c6baae3d46143011f3a9a07f0e2e845c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Jul 2022 22:47:51 +0200 +Subject: usbnet: smsc95xx: Fix deadlock on runtime resume + +From: Lukas Wunner + +[ 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 +Cc: stable@vger.kernel.org # v3.16+ +Cc: Andre Edich +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/usbnet-smsc95xx-forward-phy-interrupts-to-phy-driver.patch b/queue-5.15/usbnet-smsc95xx-forward-phy-interrupts-to-phy-driver.patch new file mode 100644 index 00000000000..13d70267a91 --- /dev/null +++ b/queue-5.15/usbnet-smsc95xx-forward-phy-interrupts-to-phy-driver.patch @@ -0,0 +1,318 @@ +From 9818677dafd6898fab24700a0ce03c086b7d4010 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 May 2022 10:42:05 +0200 +Subject: usbnet: smsc95xx: Forward PHY interrupts to PHY driver to avoid + polling + +From: Lukas Wunner + +[ 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 # LAN9514/9512/9500 +Tested-by: Ferry Toth # LAN9514 +Signed-off-by: Lukas Wunner +Reviewed-by: Andrew Lunn # from a PHY perspective +Cc: Andre Edich +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include ++#include + #include + #include + #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 + diff --git a/queue-5.15/x86-kprobes-update-kcb-status-flag-after-singlestepp.patch b/queue-5.15/x86-kprobes-update-kcb-status-flag-after-singlestepp.patch new file mode 100644 index 00000000000..69d4b684180 --- /dev/null +++ b/queue-5.15/x86-kprobes-update-kcb-status-flag-after-singlestepp.patch @@ -0,0 +1,67 @@ +From f0226069b64d2032c220973bcfcacef9358446ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Ingo Molnar +Tested-by: Daniel Müller +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 +--- + 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 + diff --git a/queue-5.15/x86-olpc-fix-logical-not-is-only-applied-to-the-left.patch b/queue-5.15/x86-olpc-fix-logical-not-is-only-applied-to-the-left.patch new file mode 100644 index 00000000000..fa1a644f3d2 --- /dev/null +++ b/queue-5.15/x86-olpc-fix-logical-not-is-only-applied-to-the-left.patch @@ -0,0 +1,54 @@ +From 91089205ead74e301d3394fcc2dc38ba07f63541 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: kernel test robot +Reviewed-and-tested-by: Guenter Roeck +Signed-off-by: Alexander Lobakin +Signed-off-by: Yury Norov +Signed-off-by: Sasha Levin +--- + 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 +