From 7d1afe8a99206da5040d8d6496e6855852fe5553 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 10 May 2023 11:51:52 +0300 Subject: [PATCH 01/93] qla2x00t-32gbit: Drop redundant pci_enable_pcie_error_reporting() pci_enable_pcie_error_reporting() enables the device to send ERR_* Messages. Since commit f26e58bf6f54 ("PCI/AER: Enable error reporting when AER is native"), the PCI core does this for all devices during enumeration, so the driver doesn't need to do it itself. Remove the redundant pci_enable_pcie_error_reporting() call from the driver. Also remove the corresponding pci_disable_pcie_error_reporting() from the driver .remove() path. Note that this only controls ERR_* Messages from the device. An ERR_* Message may cause the Root Port to generate an interrupt, depending on the AER Root Error Command register managed by the AER service driver. Signed-off-by: Bjorn Helgaas Link: https://lore.kernel.org/r/20230307182842.870378-10-helgaas@kernel.org Cc: Nilesh Javali Cc: GR-QLogic-Storage-Upstream@marvell.com Signed-off-by: Martin K. Petersen [ commit c5c440bbff86 upstream ] --- qla2x00t-32gbit/qla_def.h | 1 - qla2x00t-32gbit/qla_os.c | 6 ------ 2 files changed, 7 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index e25f8ea2b..437200a46 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 4b4b19fe9..fc071dfbb 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3010,9 +3010,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql2xallocfwdump = 0; } - /* This may fail but that's ok */ - pci_enable_pcie_error_reporting(pdev); - ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, @@ -4022,8 +4019,6 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); } @@ -6899,7 +6894,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) qla2x00_unmap_iobases(ha); pci_release_selected_regions(ha->pdev, ha->bars); - pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); /* From 596800ce2d75ea9dd01e68c8a14b5baa0e6bd6e5 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 10 May 2023 11:09:00 +0300 Subject: [PATCH 02/93] qla2x00t-32gbit: Backport to older kernel versions Backport the change from a previous commit to kernel versions prior to v6.0, where commit f26e58bf6f54 ("PCI/AER: Enable error reporting when AER is native") hasn't been introduced. --- qla2x00t-32gbit/qla_def.h | 6 ++++++ qla2x00t-32gbit/qla_os.c | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 437200a46..b403107b6 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -6,6 +6,9 @@ #ifndef __QLA_DEF_H #define __QLA_DEF_H +#ifndef INSIDE_KERNEL_TREE +#include +#endif #include #include #include @@ -22,6 +25,9 @@ #include #include #include +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) +#include +#endif #include #include #include diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index fc071dfbb..490568ee4 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3010,6 +3010,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ql2xallocfwdump = 0; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) + /* This may fail but that's ok */ + pci_enable_pcie_error_reporting(pdev); +#endif + ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { ql_log_pci(ql_log_fatal, pdev, 0x0009, @@ -4019,6 +4024,10 @@ qla2x00_remove_one(struct pci_dev *pdev) pci_release_selected_regions(ha->pdev, ha->bars); kfree(ha); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) + pci_disable_pcie_error_reporting(pdev); +#endif + pci_disable_device(pdev); } @@ -6894,6 +6903,9 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work) qla2x00_unmap_iobases(ha); pci_release_selected_regions(ha->pdev, ha->bars); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) + pci_disable_pcie_error_reporting(pdev); +#endif pci_disable_device(pdev); /* From 1a4ecab818f3d54b131655d5d604bc49d5648662 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 11 May 2023 12:12:52 +0300 Subject: [PATCH 03/93] qla2x00t-32gbit: Fix NULL pointer dereference in target mode When target mode is enabled, the pci_irq_get_affinity() function may return a NULL value in qla_mapq_init_qp_cpu_map() due to the qla24xx_enable_msix() code that handles IRQ settings for target mode. This leads to a crash due to a NULL pointer dereference. This patch fixes the issue by adding a check for the NULL value returned by pci_irq_get_affinity() and introducing a 'cpu_mapped' boolean flag to the qla_qpair structure, ensuring that the qpair's CPU affinity is updated when it has not been mapped to a CPU. Fixes: 1d201c81d4cc ("scsi: qla2xxx: Select qpair depending on which CPU post_cmd() gets called") Signed-off-by: Gleb Chesnokov Link: https://lore.kernel.org/r/56b416f2-4e0f-b6cf-d6d5-b7c372e3c6a2@scst.dev Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit d54820b22e40 upstream ] Fixes: https://github.com/SCST-project/scst/issues/156 --- qla2x00t-32gbit/qla_def.h | 1 + qla2x00t-32gbit/qla_init.c | 9 +++------ qla2x00t-32gbit/qla_inline.h | 3 +++ qla2x00t-32gbit/qla_isr.c | 11 ++++------- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index b403107b6..d4f7c4dea 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3848,6 +3848,7 @@ struct qla_qpair { uint64_t retry_term_jiff; struct qla_tgt_counters tgt_counters; uint16_t cpuid; + bool cpu_mapped; struct qla_fw_resources fwres ____cacheline_aligned; struct qla_buf_pool buf_pool; u32 cmd_cnt; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 8dc879c01..b86f9af22 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -9428,12 +9428,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->req = ha->req_q_map[req_id]; qpair->rsp->req = qpair->req; qpair->rsp->qpair = qpair; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) && \ - (!defined(RHEL_RELEASE_CODE) || \ - RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(7, 5)) - /* init qpair to this cpu. Will adjust at run time. */ - qla_cpu_update(qpair, raw_smp_processor_id()); -#endif + + if (!qpair->cpu_mapped) + qla_cpu_update(qpair, raw_smp_processor_id()); if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index c3f1b3b7f..b1bf22d79 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -550,11 +550,14 @@ qla_mapq_init_qp_cpu_map(struct qla_hw_data *ha, if (!ha->qp_cpu_map) return; mask = pci_irq_get_affinity(ha->pdev, msix->vector_base0); + if (!mask) + return; qpair->cpuid = cpumask_first(mask); for_each_cpu(cpu, mask) { ha->qp_cpu_map[cpu] = qpair; } msix->cpuid = qpair->cpuid; + qpair->cpu_mapped = true; #endif } diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 9a57920f2..646a4ebe8 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -3791,14 +3791,11 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, if (!ha->flags.fw_started) return; - if (rsp->qpair->cpuid != raw_smp_processor_id() || - !rsp->qpair->rcv_intr) { + if (rsp->qpair->cpuid != raw_smp_processor_id() || !rsp->qpair->rcv_intr) { rsp->qpair->rcv_intr = 1; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) && \ - (!defined(RHEL_RELEASE_CODE) || \ - RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(7, 5)) - qla_cpu_update(rsp->qpair, raw_smp_processor_id()); -#endif + + if (!rsp->qpair->cpu_mapped) + qla_cpu_update(rsp->qpair, raw_smp_processor_id()); } #define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in) \ From e2a6774a2e28c389a69a3525e9c653688fd31951 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 24 Apr 2023 18:08:13 +0300 Subject: [PATCH 04/93] scstadmin.spec: Replace custom Requires line with package names The scstadmin.spec.in file contained a custom Requires line that generated dependencies based on the full paths of the killall and rm commands. This approach is unconventional and could cause issues with dependency resolution. This patch replaces the custom Requires line with the package names providing the required commands, namely 'psmisc' for killall and 'coreutils' for rm. This change ensures proper dependency resolution and adheres to recommended practices for specifying dependencies in spec files. Fixes: https://github.com/SCST-project/scst/issues/152 --- scstadmin/scstadmin.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scstadmin/scstadmin.spec.in b/scstadmin/scstadmin.spec.in index 853c0631a..201652018 100644 --- a/scstadmin/scstadmin.spec.in +++ b/scstadmin/scstadmin.spec.in @@ -16,7 +16,7 @@ URL: http://scst.sourceforge.net/ Source: %{name}-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build AutoReqProv: yes -Requires: %{expand:%%(for c in killall rm; do echo -n "$(which $c) "; done)} +Requires: psmisc, coreutils %description A tool for configuring SCST via the SCST sysfs interface. Allows to save, From 1756a54367c3a46fa058618023f950abe0c6b7c9 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 9 Jun 2023 14:23:04 +0300 Subject: [PATCH 05/93] scst.spec.in, scst-dkms.spec.in: Unbreak the CentOS Stream 9 build Fixes: https://github.com/SCST-project/scst/issues/167 --- scst-dkms.spec.in | 5 +++++ scst.spec.in | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/scst-dkms.spec.in b/scst-dkms.spec.in index 848a3ea7a..ab43bb12b 100644 --- a/scst-dkms.spec.in +++ b/scst-dkms.spec.in @@ -46,6 +46,10 @@ # Fedora %define kernel_devel_rpm kernel-devel %else +%if %([ %{kernel_rpm} = kernel-modules-core ]; echo $((1-$?))) +# CentOS Stream 9 +%define kernel_devel_rpm kernel-devel +%else %if %([ %{kernel_rpm} = kernel-uek-core ]; echo $((1-$?))) # UEK 7 %define kernel_devel_rpm kernel-uek-devel @@ -56,6 +60,7 @@ %endif %endif %endif +%endif %{echo:kernel_devel_rpm=%{kernel_devel_rpm} } %endif diff --git a/scst.spec.in b/scst.spec.in index b99bcb2c0..ba4f40d75 100644 --- a/scst.spec.in +++ b/scst.spec.in @@ -51,6 +51,10 @@ # Fedora %define kernel_devel_rpm kernel-devel %else +%if %([ %{kernel_rpm} = kernel-modules-core ]; echo $((1-$?))) +# CentOS Stream 9 +%define kernel_devel_rpm kernel-devel +%else %if %([ %{kernel_rpm} = kernel-uek-core ]; echo $((1-$?))) # UEK 7 %define kernel_devel_rpm kernel-uek-devel @@ -61,6 +65,7 @@ %endif %endif %endif +%endif %{echo:kernel_devel_rpm=%{kernel_devel_rpm} } %endif From 3b0ab93c93b94d880f60fba76c8e9458cbf83ee1 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 13 Jun 2023 17:38:26 +0300 Subject: [PATCH 06/93] scst/include/backport.h: Unbreak the RHEL 9.3 build Fixes: https://github.com/SCST-project/scst/issues/167 --- scst/include/backport.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index 66671bcd4..6d0fd876e 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -798,13 +798,15 @@ static inline void kvfree(void *addr) /* */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 3)) /* * See also commit e33c267ab70d ("mm: shrinkers: provide shrinkers with * names") # v6.0. */ -static inline -int register_shrinker_backport(struct shrinker *shrinker, const char *fmt, ...) +static inline int +register_shrinker_backport(struct shrinker *shrinker, const char *fmt, ...) { /* * See also commit 1d3d4437eae1 ("vmscan: per-node deferred work") # v3.12 From 85e8086a7e49428666df6b139d53f1364a979b51 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 13 Jun 2023 21:36:19 +0300 Subject: [PATCH 07/93] Makefile: Implement several improvements to SCST Makefiles 1. Correct a typo, changing `make release` to `make 2release`. 2. Add information about package-related targets to the help section. 3. Remove `dev_handler` directory during the uninstall process. 4. Eliminate the non-existent `tgt` target from the PHONY targets. 5. Introduce SCST_MOD_DIR and SCST_DH_MOD_DIR as helper variables. --- INSTALL.md | 2 +- Makefile | 7 +++++++ fcst/Makefile | 2 +- qla2x00t-32gbit/Makefile | 2 +- qla2x00t-32gbit/qla2x00-target/Makefile | 2 +- qla2x00t/Makefile | 2 +- qla2x00t/qla2x00-target/Makefile | 2 +- scst/src/Makefile | 15 +++++++++------ scst/src/dev_handlers/Makefile | 1 + scst_local/Makefile | 2 +- 10 files changed, 24 insertions(+), 13 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index ce7c6b272..80c3472e5 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -22,7 +22,7 @@ If the following packages have not yet been installed, install these now: The next step is to build and install SCST. How to do that depends on whether or not your Linux distribution supports a package manager: - make release + make 2release if rpm -q glibc >/dev/null 2>&1; then rm -rf {,scstadmin/}rpmbuilddir make rpm diff --git a/Makefile b/Makefile index e81abe212..bdcca8243 100644 --- a/Makefile +++ b/Makefile @@ -146,6 +146,13 @@ help: @echo " usr_install : usr target: install" @echo " usr_uninstall : usr target: uninstall" @echo "" + @echo " scst-rpm : make SCST RPM packages" + @echo " scst-dkms-rpm : make SCST DKMS RPM packages" + @echo " rpm : make both SCST and scstadmin RPM packages" + @echo " rpm-dkms : make both SCST DKMS and scstadmin RPM packages" + @echo "" + @echo " dpkg : make SCST dpkg packages" + @echo "" @echo " 2perf : changes debug state to full performance" @echo " 2release : changes debug state to release" @echo " 2debug : changes debug state to full debug" diff --git a/fcst/Makefile b/fcst/Makefile index 8c82d4a41..7c3904470 100644 --- a/fcst/Makefile +++ b/fcst/Makefile @@ -87,4 +87,4 @@ extraclean: clean release-archive: ../scripts/generate-release-archive fcst "$$(sed -n 's/^#define[[:blank:]]FT_VERSION[[:blank:]]*\"\([^\"]*\)\".*/\1/p' fcst.h)" -.PHONY: all tgt install uninstall clean extraclean release-archive +.PHONY: all install uninstall clean extraclean release-archive diff --git a/qla2x00t-32gbit/Makefile b/qla2x00t-32gbit/Makefile index ddcaafc56..cf4cea8cb 100644 --- a/qla2x00t-32gbit/Makefile +++ b/qla2x00t-32gbit/Makefile @@ -71,7 +71,7 @@ clean: extraclean: clean rm -f *.orig *.rej -.PHONY: all tgt install uninstall clean extraclean +.PHONY: all install uninstall clean extraclean endif diff --git a/qla2x00t-32gbit/qla2x00-target/Makefile b/qla2x00t-32gbit/qla2x00-target/Makefile index 886494dc5..574527e9a 100644 --- a/qla2x00t-32gbit/qla2x00-target/Makefile +++ b/qla2x00t-32gbit/qla2x00-target/Makefile @@ -102,4 +102,4 @@ endif extraclean: clean rm -f *.orig *.rej -.PHONY: all tgt install uninstall clean extraclean qla2xxx_scst +.PHONY: all install uninstall clean extraclean qla2xxx_scst diff --git a/qla2x00t/Makefile b/qla2x00t/Makefile index dfaa980ff..9806a81e5 100644 --- a/qla2x00t/Makefile +++ b/qla2x00t/Makefile @@ -69,7 +69,7 @@ clean: extraclean: clean rm -f *.orig *.rej -.PHONY: all tgt install uninstall clean extraclean +.PHONY: all install uninstall clean extraclean endif diff --git a/qla2x00t/qla2x00-target/Makefile b/qla2x00t/qla2x00-target/Makefile index b976e174c..0fe34e109 100644 --- a/qla2x00t/qla2x00-target/Makefile +++ b/qla2x00t/qla2x00-target/Makefile @@ -101,4 +101,4 @@ endif extraclean: clean rm -f *.orig *.rej -.PHONY: all tgt install uninstall clean extraclean qla2xxx_scst +.PHONY: all install uninstall clean extraclean qla2xxx_scst diff --git a/scst/src/Makefile b/scst/src/Makefile index 236d1d206..9975a1f94 100644 --- a/scst/src/Makefile +++ b/scst/src/Makefile @@ -35,6 +35,9 @@ SHELL=/bin/bash DEV_HANDLERS_DIR = dev_handlers +SCST_MOD_DIR := $(shell pwd) +SCST_DH_MOD_DIR := $(shell pwd)/$(DEV_HANDLERS_DIR) + ifeq ($(KVER),) ifeq ($(KDIR),) KVER := $(shell uname -r) @@ -73,13 +76,13 @@ $(SCST_INTF_VER_FILE): $(SCST_INC_DIR)/scst.h $(SCST_INC_DIR)/scst_const.h $(SCS all: $(SCST_INTF_VER_FILE) $(MAKE) -C certs KDIR=$(KDIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") - $(MAKE) -C $(KDIR) M=$(shell pwd) \ + $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") - $(MAKE) -C $(KDIR) M=$(shell pwd)/dev_handlers \ + $(MAKE) -C $(KDIR) M=$(SCST_DH_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") scst: - $(MAKE) -C $(KDIR) M=$(shell pwd) \ + $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") install: all @@ -89,12 +92,12 @@ install: all false; fi -rm -f $(INSTALL_DIR)/scsi_tgt.ko KDIR=$(KDIR) ../../scripts/sign-modules - $(MAKE) -C $(KDIR) M=$(shell pwd)/dev_handlers \ + $(MAKE) -C $(KDIR) M=$(SCST_DH_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ INSTALL_MOD_DIR=extra/dev_handlers \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install - $(MAKE) -C $(KDIR) M=$(shell pwd) \ + $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install @@ -135,7 +138,7 @@ INSTALL_DIR_H := $(DESTDIR)$(PREFIX)/include/scst clean: rm -f $(SCST_INTF_VER_FILE) - $(MAKE) -C $(KDIR) M=$(shell pwd) $@ + $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) $@ $(MAKE) -C $(DEV_HANDLERS_DIR) $@ extraclean: clean diff --git a/scst/src/dev_handlers/Makefile b/scst/src/dev_handlers/Makefile index 2be974b99..4ecbb5fdc 100644 --- a/scst/src/dev_handlers/Makefile +++ b/scst/src/dev_handlers/Makefile @@ -68,6 +68,7 @@ install: all uninstall: rm -f $(INSTALL_DIR)/dev_handlers/scst_*.ko + -rmdir $(INSTALL_DIR)/dev_handlers 2>/dev/null clean: $(MAKE) -C $(KDIR) M=$(shell pwd) $@ diff --git a/scst_local/Makefile b/scst_local/Makefile index 4e7626f6a..f53473c13 100644 --- a/scst_local/Makefile +++ b/scst_local/Makefile @@ -57,5 +57,5 @@ extraclean: clean release-archive: ../scripts/generate-release-archive scst_local "$$(sed -n 's/^#define[[:blank:]]SCST_LOCAL_VERSION[[:blank:]]*\"\([^\"]*\)\".*/\1/p' scst_local.c)" -.PHONY: all tgt install uninstall clean extraclean +.PHONY: all install uninstall clean extraclean From 6c2771baefc91d3a9219333b6bc994b8c6992bb4 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 14 Jun 2023 10:56:52 +0300 Subject: [PATCH 08/93] Makefile: Specify the installation directory for SCST modules explicitly This patch fixes the installation process for Linux kernels where the default value of INSTALL_MOD_DIR differs from `extra`. For instance, it unbreaks `make rpm` against Fedora's kernels, where INSTALL_MOD_DIR is set to `updates`. --- fcst/Makefile | 5 ++++- iscsi-scst/Makefile | 6 +++++- qla2x00t-32gbit/Makefile | 5 ++++- qla2x00t-32gbit/qla2x00-target/Makefile | 5 ++++- qla2x00t/Makefile | 5 ++++- qla2x00t/qla2x00-target/Makefile | 5 ++++- scst/src/Makefile | 11 +++++++---- scst/src/dev_handlers/Makefile | 9 ++++++--- scst_local/Makefile | 5 ++++- srpt/Makefile | 5 ++++- 10 files changed, 46 insertions(+), 15 deletions(-) diff --git a/fcst/Makefile b/fcst/Makefile index 7c3904470..497291bb2 100644 --- a/fcst/Makefile +++ b/fcst/Makefile @@ -55,7 +55,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) SCST_DIR := $(shell echo "$$PWD")/../scst/src @@ -67,6 +69,7 @@ install: all KDIR=$(KDIR) ../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/iscsi-scst/Makefile b/iscsi-scst/Makefile index 557088e98..f153e3522 100644 --- a/iscsi-scst/Makefile +++ b/iscsi-scst/Makefile @@ -43,7 +43,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) INFINIBAND_ENABLED = $(shell syms=$$(dirname "$(KDIR)")/modules.symbols; if [ -e "$$syms" ] && grep -wq 'ib_register_client' "$$syms" || grep -q "^CONFIG_INFINIBAND=[my]$$" "$(KDIR)/.config"; then echo true; else echo false; fi) all: progs mods @@ -166,6 +168,7 @@ install: all (cd $(KMOD) && KDIR=$(KDIR) ../../scripts/sign-modules) $(MAKE) -C $(KDIR) M=$(KMOD) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install echo "$@: INFINIBAND_ENABLED = $(INFINIBAND_ENABLED)" @@ -173,6 +176,7 @@ install: all (cd $(ISERTMOD) && KDIR=$(KDIR) ../../../scripts/sign-modules);\ $(MAKE) -C $(KDIR) M=$(ISERTMOD) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install; \ fi diff --git a/qla2x00t-32gbit/Makefile b/qla2x00t-32gbit/Makefile index cf4cea8cb..48dad4ff1 100644 --- a/qla2x00t-32gbit/Makefile +++ b/qla2x00t-32gbit/Makefile @@ -45,7 +45,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) all: $(MAKE) -C $(KDIR) M=$(shell pwd) \ @@ -56,6 +58,7 @@ install: all KDIR=$(KDIR) ../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/qla2x00t-32gbit/qla2x00-target/Makefile b/qla2x00t-32gbit/qla2x00-target/Makefile index 574527e9a..4de10dc7a 100644 --- a/qla2x00t-32gbit/qla2x00-target/Makefile +++ b/qla2x00t-32gbit/qla2x00-target/Makefile @@ -62,7 +62,9 @@ ifndef PREFIX PREFIX=/usr/local endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) SCST_DIR := $(shell echo "$$PWD/../../scst/src") @@ -77,6 +79,7 @@ endif KDIR=$(KDIR) ../../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/qla2x00t/Makefile b/qla2x00t/Makefile index 9806a81e5..4bdb5fa1b 100644 --- a/qla2x00t/Makefile +++ b/qla2x00t/Makefile @@ -43,7 +43,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) all: $(MAKE) -C $(KDIR) M=$(shell pwd) \ @@ -54,6 +56,7 @@ install: all KDIR=$(KDIR) ../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) BUILD_INI=m \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/qla2x00t/qla2x00-target/Makefile b/qla2x00t/qla2x00-target/Makefile index 0fe34e109..5fdfcf878 100644 --- a/qla2x00t/qla2x00-target/Makefile +++ b/qla2x00t/qla2x00-target/Makefile @@ -61,7 +61,9 @@ ifndef PREFIX PREFIX=/usr/local endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) SCST_DIR := $(shell echo "$$PWD/../../scst/src") @@ -76,6 +78,7 @@ endif KDIR=$(KDIR) ../../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/scst/src/Makefile b/scst/src/Makefile index 9975a1f94..a4469bfcb 100644 --- a/scst/src/Makefile +++ b/scst/src/Makefile @@ -61,8 +61,13 @@ ifeq ($(SCST_INC_DIR),) SCST_INC_DIR := ../include endif +INSTALL_MOD_DIR=extra + SCST_INTF_VER_FILE := $(SCST_INC_DIR)/scst_itf_ver.h +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) +INSTALL_DIR_H := $(DESTDIR)$(PREFIX)/include/scst + $(SCST_INTF_VER_FILE): $(SCST_INC_DIR)/scst.h $(SCST_INC_DIR)/scst_const.h $(SCST_INC_DIR)/scst_user.h echo "/* Autogenerated, don't edit */" >$(SCST_INTF_VER_FILE) echo "" >>$(SCST_INTF_VER_FILE) @@ -94,11 +99,12 @@ install: all KDIR=$(KDIR) ../../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(SCST_DH_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ - INSTALL_MOD_DIR=extra/dev_handlers \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR)/dev_handlers \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install install -d $(INSTALL_DIR_H) @@ -133,9 +139,6 @@ uninstall: -/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER) rm -rf $(INSTALL_DIR_H) -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra -INSTALL_DIR_H := $(DESTDIR)$(PREFIX)/include/scst - clean: rm -f $(SCST_INTF_VER_FILE) $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) $@ diff --git a/scst/src/dev_handlers/Makefile b/scst/src/dev_handlers/Makefile index 4ecbb5fdc..8d5734d5e 100644 --- a/scst/src/dev_handlers/Makefile +++ b/scst/src/dev_handlers/Makefile @@ -48,7 +48,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra/dev_handlers + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) all: $(MAKE) -C $(KDIR) M=$(shell pwd) \ @@ -63,12 +65,13 @@ install: all KDIR=$(KDIR) ../../../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install uninstall: - rm -f $(INSTALL_DIR)/dev_handlers/scst_*.ko - -rmdir $(INSTALL_DIR)/dev_handlers 2>/dev/null + rm -f $(INSTALL_DIR)/scst_*.ko + -rmdir $(INSTALL_DIR) 2>/dev/null clean: $(MAKE) -C $(KDIR) M=$(shell pwd) $@ diff --git a/scst_local/Makefile b/scst_local/Makefile index f53473c13..05e2c4c4e 100644 --- a/scst_local/Makefile +++ b/scst_local/Makefile @@ -29,7 +29,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) SCST_DIR := $(shell echo "$$PWD")/../scst/src @@ -41,6 +43,7 @@ install: all KDIR=$(KDIR) ../scripts/sign-modules $(MAKE) -C $(KDIR) M=$(shell pwd) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install diff --git a/srpt/Makefile b/srpt/Makefile index 5f2a97a01..86ba92f53 100644 --- a/srpt/Makefile +++ b/srpt/Makefile @@ -31,7 +31,9 @@ ifeq ($(INSTALL_MOD_PATH),) export INSTALL_MOD_PATH := $(DESTDIR) endif -INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/extra +INSTALL_MOD_DIR=extra + +INSTALL_DIR := $(INSTALL_MOD_PATH)/lib/modules/$(KVER)/$(INSTALL_MOD_DIR) SRC_FILES=$(wildcard */*.[ch]) @@ -125,6 +127,7 @@ install: all $(MAKE) -C $(KDIR) M=$(shell pwd)/src \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ CONFTEST_CFLAGS="$(CONFTEST_CFLAGS)" \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install From a6e09670547ba6b62d36b6102f13b47fa4bdc140 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 14 Jun 2023 12:14:43 +0300 Subject: [PATCH 09/93] scst/src/Makefile: Fix depmod warnings during installation process This patch fixes the following warnings: /lib/.../scst_cdrom.ko needs unknown symbol scst_obtain_device_parameters /lib/.../scst_cdrom.ko needs unknown symbol scst_unregister_dev_driver ... These warnings were caused by an incorrect module installation order: the SCST module was being installed after the device handler modules on which they depend. This patch rectifies the issue by altering the order in which the modules are installed. Additionally, this patch fixes the missing signatures for the device handler modules. --- scst/src/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scst/src/Makefile b/scst/src/Makefile index a4469bfcb..1d7914346 100644 --- a/scst/src/Makefile +++ b/scst/src/Makefile @@ -97,14 +97,15 @@ install: all false; fi -rm -f $(INSTALL_DIR)/scsi_tgt.ko KDIR=$(KDIR) ../../scripts/sign-modules - $(MAKE) -C $(KDIR) M=$(SCST_DH_MOD_DIR) \ + $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ - INSTALL_MOD_DIR=$(INSTALL_MOD_DIR)/dev_handlers \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install - $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) \ + (cd $(SCST_DH_MOD_DIR) && KDIR=$(KDIR) ../../../scripts/sign-modules) + $(MAKE) -C $(KDIR) M=$(SCST_DH_MOD_DIR) \ $(shell [ -n "$(PASS_CC_TO_MAKE)" ] && echo CC="$(CC)") \ - INSTALL_MOD_DIR=$(INSTALL_MOD_DIR) \ + INSTALL_MOD_DIR=$(INSTALL_MOD_DIR)/dev_handlers \ $$([ -n "$(DEPMOD)" ] && echo "DEPMOD=$(DEPMOD)") \ CONFIG_MODULE_SIG_ALL= modules_install install -d $(INSTALL_DIR_H) @@ -140,12 +141,11 @@ uninstall: rm -rf $(INSTALL_DIR_H) clean: + $(MAKE) -C $(DEV_HANDLERS_DIR) $@ rm -f $(SCST_INTF_VER_FILE) $(MAKE) -C $(KDIR) M=$(SCST_MOD_DIR) $@ - $(MAKE) -C $(DEV_HANDLERS_DIR) $@ extraclean: clean - rm -f $(SCST_INTF_VER_FILE) cd $(DEV_HANDLERS_DIR) && $(MAKE) $@ rm -f *.orig *.rej From 7881162b9b475e707b9c7e4a764272aa3ec22be8 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 16 Jun 2023 13:18:01 +0300 Subject: [PATCH 10/93] scst: Unbreak the non-DLM build Fix the following compiler error: ERROR: modpost: "scst_dlm_cluster_name" [...] undefined! The error occurs because the declaration of scst_dlm_cluster_name is located in the scst_dlm.c file, but it's used in the scst_sysfs.c file. As a result, when building without DLM, this variable lacks a declaration. To resolve this, the declaration is moved to the scst_main.c file, and the variable scst_dlm_cluster_name is renamed to scst_cluster_name. Fixes: 00f31004ab2b ("scst_sysfs: Add support for cluster_name") --- scst/src/scst_dlm.c | 2 -- scst/src/scst_main.c | 6 ++++-- scst/src/scst_priv.h | 4 ++-- scst/src/scst_sysfs.c | 17 ++++++++--------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/scst/src/scst_dlm.c b/scst/src/scst_dlm.c index c3fb41190..8afedb1f8 100644 --- a/scst/src/scst_dlm.c +++ b/scst/src/scst_dlm.c @@ -1831,6 +1831,4 @@ const struct scst_cl_ops scst_dlm_cl_ops = { .pr_reg_queue_rem_ua = scst_dlm_pr_reg_queue_rem_ua, }; -char *scst_dlm_cluster_name; - #endif diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 564488d74..11d26d336 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -93,6 +93,8 @@ struct kmem_cache *scst_sess_cachep; struct kmem_cache *scst_acgd_cachep; static struct kmem_cache *scst_thr_cachep; +char *scst_cluster_name; + unsigned int scst_setup_id; spinlock_t scst_init_lock; @@ -2599,7 +2601,6 @@ static void __exit exit_scst(void) scst_cm_exit(); - scst_stop_global_threads(); scst_deinit_threads(&scst_main_cmd_threads); @@ -2609,13 +2610,14 @@ static void __exit exit_scst(void) scsi_unregister_interface(&scst_interface); - scst_sgv_pools_deinit(); scst_tg_cleanup(); scst_sysfs_cleanup(); + kfree(scst_cluster_name); + scst_event_exit(); rcu_barrier(); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index c2e2cf727..c30af8e1d 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -176,7 +176,7 @@ extern wait_queue_head_t scst_dev_cmd_waitQ; extern const struct scst_cl_ops scst_no_dlm_cl_ops; extern const struct scst_cl_ops scst_dlm_cl_ops; -extern char *scst_dlm_cluster_name; +extern char *scst_cluster_name; extern unsigned int scst_setup_id; @@ -418,7 +418,7 @@ static inline int scst_dlm_new_lockspace(const char *name, int namelen, uint32_t flags, int lvblen) { - return dlm_new_lockspace(name, scst_dlm_cluster_name, flags, lvblen, + return dlm_new_lockspace(name, scst_cluster_name, flags, lvblen, NULL, NULL, NULL, lockspace); } diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 4fadd8605..110cd45b6 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -7701,8 +7701,8 @@ static ssize_t scst_cluster_name_show(struct kobject *kobj, TRACE_ENTRY(); - if (scst_dlm_cluster_name != NULL) - res = sprintf(buf, "%s\n%s", scst_dlm_cluster_name, + if (scst_cluster_name != NULL) + res = sprintf(buf, "%s\n%s", scst_cluster_name, SCST_SYSFS_KEY_MARK "\n"); TRACE_EXIT_RES(res); @@ -7726,8 +7726,8 @@ static ssize_t scst_cluster_name_store(struct kobject *kobj, len--; if (len == 0) { - kfree(scst_dlm_cluster_name); - scst_dlm_cluster_name = NULL; + kfree(scst_cluster_name); + scst_cluster_name = NULL; goto out_done; } @@ -7737,11 +7737,11 @@ static ssize_t scst_cluster_name_store(struct kobject *kobj, goto out; } - kfree(scst_dlm_cluster_name); - scst_dlm_cluster_name = kstrndup(buf, len, GFP_KERNEL); - if (!scst_dlm_cluster_name) { + kfree(scst_cluster_name); + scst_cluster_name = kstrndup(buf, len, GFP_KERNEL); + if (!scst_cluster_name) { PRINT_ERROR("Unable to alloc cluster_name string (len %d)", - len+1); + len + 1); res = -ENOMEM; goto out; } @@ -8097,7 +8097,6 @@ void scst_sysfs_cleanup(void) TRACE_ENTRY(); PRINT_INFO("%s", "Exiting SCST sysfs hierarchy..."); - kfree(scst_dlm_cluster_name); scst_del_put_sgv_kobj(); From 334d29c96ad338191fe6719ee86be04d22634228 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 15 Jun 2023 11:28:56 +0300 Subject: [PATCH 11/93] scst.h: Unify names in prepare_to_wait_exclusive_head() Use the standardized version of the name for wait_queue_head and wait_queue_entry variables. This patch doesn't change any functionality. --- scst/include/scst.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 0723d759b..1eb72137b 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -5382,21 +5382,23 @@ void scst_dev_inquiry_data_changed(struct scst_device *dev); */ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && \ !defined(CONFIG_SUSE_KERNEL) -static inline void prepare_to_wait_exclusive_head(wait_queue_head_t *q, - wait_queue_t *wait, int state) +static inline void +prepare_to_wait_exclusive_head(wait_queue_head_t *wq_head, + wait_queue_t *wq_entry, int state) { unsigned long flags; - wait->flags |= WQ_FLAG_EXCLUSIVE; - spin_lock_irqsave(&q->lock, flags); - if (list_empty(&wait->task_list)) - __add_wait_queue(q, wait); + wq_entry->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&wq_head->lock, flags); + if (list_empty(&wq_entry->task_list)) + __add_wait_queue(wq_head, wq_entry); set_current_state(state); - spin_unlock_irqrestore(&q->lock, flags); + spin_unlock_irqrestore(&wq_head->lock, flags); } #else -static inline void prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head, - struct wait_queue_entry *wq_entry, int state) +static inline void +prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head, + struct wait_queue_entry *wq_entry, int state) { unsigned long flags; From d8894cbd11573f688a22b199f18359a8075ebce6 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 15 Jun 2023 11:12:48 +0300 Subject: [PATCH 12/93] scst.h: Refactor wait_event_locked() to enhance usability and clarity 1. Set the default process state to TASK_UNINTERRUPTIBLE during sleep. This change is made because our current code does not check whether a process was interrupted by a signal. 2. Prefix all SCST wait_event-related macros with 'scst_'. This helps to distinguish SCST-specific macros from those provided by the Linux kernel itself. 3. Add the capability to return an error code when a process in a non-TASK_UNINTERRUPTIBLE state is interrupted by a signal. 4. Divide the wait_event_locked function based on each lock type, resulting in the following new functions: scst_wait_event_lock(), scst_wait_event_lock_bh(), and scst_wait_event_lock_irq(). --- iscsi-scst/kernel/nthread.c | 6 +- scst/include/scst.h | 150 +++++++++++++++++++++++------- scst/src/dev_handlers/scst_user.c | 10 +- scst/src/scst_lib.c | 3 +- scst/src/scst_sysfs.c | 4 +- scst/src/scst_targ.c | 16 ++-- 6 files changed, 136 insertions(+), 53 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index e91a88541..fb4e93a36 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -960,8 +960,7 @@ int istrd(void *arg) spin_lock_bh(&p->rd_lock); while (!kthread_should_stop()) { - wait_event_locked(p->rd_waitQ, test_rd_list(p), lock_bh, - p->rd_lock); + scst_wait_event_lock_bh(p->rd_waitQ, test_rd_list(p), p->rd_lock); scst_do_job_rd(p); } spin_unlock_bh(&p->rd_lock); @@ -1613,8 +1612,7 @@ int istwr(void *arg) spin_lock_bh(&p->wr_lock); while (!kthread_should_stop()) { - wait_event_locked(p->wr_waitQ, test_wr_list(p), lock_bh, - p->wr_lock); + scst_wait_event_lock_bh(p->wr_waitQ, test_wr_list(p), p->wr_lock); scst_do_job_wr(p); } spin_unlock_bh(&p->wr_lock); diff --git a/scst/include/scst.h b/scst/include/scst.h index 1eb72137b..424ef0bf5 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -36,6 +36,9 @@ #endif #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include +#endif #include #include #include @@ -5382,59 +5385,142 @@ void scst_dev_inquiry_data_changed(struct scst_device *dev); */ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) && \ !defined(CONFIG_SUSE_KERNEL) -static inline void +static inline long prepare_to_wait_exclusive_head(wait_queue_head_t *wq_head, wait_queue_t *wq_entry, int state) { unsigned long flags; + long ret = 0; wq_entry->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&wq_head->lock, flags); - if (list_empty(&wq_entry->task_list)) - __add_wait_queue(wq_head, wq_entry); - set_current_state(state); + if (signal_pending_state(state, current)) { + /* + * Exclusive waiter must not fail if it was selected by wakeup, + * it should "consume" the condition we were waiting for. + * + * The caller will recheck the condition and return success if + * we were already woken up, we can not miss the event because + * wakeup locks/unlocks the same wq_head->lock. + * + * But we need to ensure that set-condition + wakeup after that + * can't see us, it should wake up another exclusive waiter if + * we fail. + */ + list_del_init(&wq_entry->task_list); + ret = -ERESTARTSYS; + } else { + if (list_empty(&wq_entry->task_list)) + __add_wait_queue(wq_head, wq_entry); + set_current_state(state); + } spin_unlock_irqrestore(&wq_head->lock, flags); + + return ret; } #else -static inline void +static inline long prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state) { unsigned long flags; + long ret = 0; wq_entry->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&wq_head->lock, flags); - if (list_empty(&wq_entry->entry)) - __add_wait_queue(wq_head, wq_entry); - set_current_state(state); + if (signal_pending_state(state, current)) { + /* + * Exclusive waiter must not fail if it was selected by wakeup, + * it should "consume" the condition we were waiting for. + * + * The caller will recheck the condition and return success if + * we were already woken up, we can not miss the event because + * wakeup locks/unlocks the same wq_head->lock. + * + * But we need to ensure that set-condition + wakeup after that + * can't see us, it should wake up another exclusive waiter if + * we fail. + */ + list_del_init(&wq_entry->entry); + ret = -ERESTARTSYS; + } else { + if (list_empty(&wq_entry->entry)) + __add_wait_queue(wq_head, wq_entry); + set_current_state(state); + } spin_unlock_irqrestore(&wq_head->lock, flags); + + return ret; } #endif -/** - * wait_event_locked() - Wait until a condition becomes true. - * @wq: Wait queue to wait on if @condition is false. - * @condition: Condition to wait for. Can be any C expression. - * @lock_type: One of lock, lock_bh or lock_irq. - * @lock: A spinlock. - * - * Caller must hold lock of type @lock_type on @lock. - */ -#define wait_event_locked(wq, condition, lock_type, lock) do { \ -if (!(condition)) { \ - DEFINE_WAIT(__wait); \ - \ - do { \ - prepare_to_wait_exclusive_head(&(wq), &__wait, \ - TASK_INTERRUPTIBLE); \ - if (condition) \ - break; \ - spin_un ## lock_type(&(lock)); \ - schedule(); \ - spin_ ## lock_type(&(lock)); \ - } while (!(condition)); \ - finish_wait(&(wq), &__wait); \ -} \ +#define ___scst_wait_is_interruptible(state) \ + (!__builtin_constant_p(state) || \ + (state & (TASK_INTERRUPTIBLE | TASK_WAKEKILL))) + +#define ___scst_wait_event(wq_head, condition, state, ret, cmd) \ +({ \ + __label__ __out; \ + DEFINE_WAIT(__wq_entry); \ + long __ret = ret; /* explicit shadow */ \ + \ + for (;;) { \ + long __int = prepare_to_wait_exclusive_head(&wq_head, &__wq_entry,\ + state); \ + \ + if (condition) \ + break; \ + \ + if (___scst_wait_is_interruptible(state) && __int) { \ + __ret = __int; \ + goto __out; \ + } \ + \ + cmd; \ + } \ + finish_wait(&wq_head, &__wq_entry); \ +__out: __ret; \ +}) + +#define __scst_wait_event_lock(wq_head, condition, lock) \ + (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ + spin_unlock(&lock); \ + schedule(); \ + spin_lock(&lock)) + +#define scst_wait_event_lock(wq_head, condition, lock) \ +do { \ + if (condition) \ + break; \ + __scst_wait_event_lock(wq_head, condition, lock); \ +} while (0) + +#define __scst_wait_event_lock_bh(wq_head, condition, lock) \ + (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ + spin_unlock_bh(&lock); \ + schedule(); \ + spin_lock_bh(&lock)) + +#define scst_wait_event_lock_bh(wq_head, condition, lock) \ +do { \ + if (condition) \ + break; \ + __scst_wait_event_lock_bh(wq_head, condition, lock); \ +} while (0) + +#define __scst_wait_event_lock_irq(wq_head, condition, lock) \ + (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ + spin_unlock_irq(&lock); \ + schedule(); \ + spin_lock_irq(&lock)) + +#define scst_wait_event_lock_irq(wq_head, condition, lock) \ +do { \ + if (condition) \ + break; \ + __scst_wait_event_lock_irq(wq_head, condition, lock); \ } while (0) #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index b995f85a0..e41b3bafc 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -2233,9 +2233,9 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, TRACE_ENTRY(); while (1) { - wait_event_locked(dev->udev_cmd_threads.cmd_list_waitQ, - test_cmd_threads(dev, can_block), lock_irq, - dev->udev_cmd_threads.cmd_list_lock); + scst_wait_event_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ, + test_cmd_threads(dev, can_block), + dev->udev_cmd_threads.cmd_list_lock); dev_user_process_scst_commands(dev); @@ -4053,8 +4053,8 @@ static int dev_user_cleanup_thread(void *arg) spin_lock(&cleanup_lock); while (!kthread_should_stop()) { - wait_event_locked(cleanup_list_waitQ, test_cleanup_list(), - lock, cleanup_lock); + scst_wait_event_lock(cleanup_list_waitQ, test_cleanup_list(), + cleanup_lock); /* * We have to poll devices, because commands can go from SCST diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 976dcc4c2..1026d2879 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -14978,8 +14978,7 @@ int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, b->ext_blocker_done_fn = scst_sync_ext_blocking_done; *((void **)&b->ext_blocker_data[0]) = &w; - wait_event_locked(w, (dev->on_dev_cmd_count == 0), - lock_bh, dev->dev_lock); + scst_wait_event_lock_bh(w, dev->on_dev_cmd_count == 0, dev->dev_lock); spin_unlock_bh(&dev->dev_lock); } else { diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 110cd45b6..874ef82db 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -470,8 +470,8 @@ static int sysfs_work_thread_fn(void *arg) while (!kthread_should_stop()) { if (one_time_only && !test_sysfs_work_list()) break; - wait_event_locked(sysfs_work_waitQ, test_sysfs_work_list(), - lock, sysfs_work_lock); + scst_wait_event_lock(sysfs_work_waitQ, test_sysfs_work_list(), + sysfs_work_lock); scst_process_sysfs_works(); } spin_unlock(&sysfs_work_lock); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index d69688326..2593cc07f 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4510,9 +4510,9 @@ int scst_init_thread(void *arg) spin_lock_irq(&scst_init_lock); while (!kthread_should_stop()) { - wait_event_locked(scst_init_cmd_list_waitQ, - test_init_cmd_list(), - lock_irq, scst_init_lock); + scst_wait_event_lock_irq(scst_init_cmd_list_waitQ, + test_init_cmd_list(), + scst_init_lock); scst_do_job_init(); } spin_unlock_irq(&scst_init_lock); @@ -6794,9 +6794,9 @@ int scst_tm_thread(void *arg) spin_lock_irq(&scst_mcmd_lock); while (!kthread_should_stop()) { - wait_event_locked(scst_mgmt_cmd_list_waitQ, - test_mgmt_cmd_list(), lock_irq, - scst_mcmd_lock); + scst_wait_event_lock_irq(scst_mgmt_cmd_list_waitQ, + test_mgmt_cmd_list(), + scst_mcmd_lock); while (!list_empty(&scst_active_mgmt_cmd_list)) { int rc; @@ -7610,8 +7610,8 @@ int scst_global_mgmt_thread(void *arg) spin_lock_irq(&scst_mgmt_lock); while (!kthread_should_stop()) { - wait_event_locked(scst_mgmt_waitQ, test_mgmt_list(), lock_irq, - scst_mgmt_lock); + scst_wait_event_lock_irq(scst_mgmt_waitQ, test_mgmt_list(), + scst_mgmt_lock); while (!list_empty(&scst_sess_init_list)) { sess = list_first_entry(&scst_sess_init_list, From b13b580d8b195dcb6d66dc041d70be32d3b439f9 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 15 Jun 2023 22:55:07 +0300 Subject: [PATCH 13/93] scst_lib: Split scst_ext_block_dev() for clarity and easier maintenance This patch divides the scst_ext_block_dev() function into two separate functions to improve code readability and simplify maintenance: 1. scst_sync_ext_block_dev() - This function is for synchronous blocking and serves as the equivalent of calling the old scst_ext_block_dev() function with the SCST_EXT_BLOCK_SYNC flag. 2. scst_ext_block_dev() - This function is for asynchronous blocking. Additionally, the patch introduces the helper function scst_dev_ext_block() to reduce code duplication between the scst_sync_ext_block_dev() and scst_ext_block_dev() functions. This patch doesn't change any functionality. --- scst/src/scst_lib.c | 140 ++++++++++++++++++++++++++---------------- scst/src/scst_priv.h | 5 +- scst/src/scst_sysfs.c | 4 +- scst/src/scst_tg.c | 3 +- 4 files changed, 92 insertions(+), 60 deletions(-) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 1026d2879..f160d0612 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -14918,30 +14918,12 @@ static void scst_sync_ext_blocking_done(struct scst_device *dev, return; } -int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, - const uint8_t *priv, int priv_len, int flags) +static void scst_dev_ext_block(struct scst_device *dev, bool block_stpg) { - int res; - struct scst_ext_blocker *b; + lockdep_assert_held(&dev->dev_lock); TRACE_ENTRY(); - if (flags & SCST_EXT_BLOCK_SYNC) - priv_len = sizeof(void *); - - b = kzalloc(sizeof(*b) + priv_len, GFP_KERNEL); - if (b == NULL) { - PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data " - "(size %zd)", sizeof(*b) + priv_len); - res = -ENOMEM; - goto out; - } - - TRACE_MGMT_DBG("New %d ext blocker %p for dev %s (flags %x)", - dev->ext_blocks_cnt+1, b, dev->virt_name, flags); - - spin_lock_bh(&dev->dev_lock); - if (dev->strictly_serialized_cmd_waiting) { /* * Avoid deadlock when this strictly serialized cmd @@ -14951,10 +14933,11 @@ int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, TRACE_DBG("Unstrictlyserialize dev %s", dev->virt_name); dev->strictly_serialized_cmd_waiting = 0; /* We will reuse blocking done by the strictly serialized cmd */ - } else + } else { scst_block_dev(dev); + } - if (flags & SCST_EXT_BLOCK_STPG) { + if (block_stpg) { WARN_ON(dev->stpg_ext_blocked); dev->stpg_ext_blocked = 1; } @@ -14962,52 +14945,103 @@ int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, dev->ext_blocks_cnt++; TRACE_DBG("ext_blocks_cnt %d", dev->ext_blocks_cnt); - if ((flags & SCST_EXT_BLOCK_SYNC) && (dev->on_dev_cmd_count == 0)) { + TRACE_EXIT(); +} + +int scst_sync_ext_block_dev(struct scst_device *dev) +{ + struct scst_ext_blocker *b; + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(w); + int res = 0; + + TRACE_ENTRY(); + + b = kzalloc(sizeof(*b) + sizeof(void *), GFP_KERNEL); + if (unlikely(!b)) { + PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data (size %zd)", + sizeof(*b) + sizeof(void *)); + res = -ENOMEM; + goto out; + } + + TRACE_MGMT_DBG("New %d sync ext blocker %p for dev %s", + dev->ext_blocks_cnt + 1, b, dev->virt_name); + + spin_lock_bh(&dev->dev_lock); + + scst_dev_ext_block(dev, false); + + if (dev->on_dev_cmd_count == 0) { TRACE_DBG("No commands to wait for sync blocking (dev %s)", - dev->virt_name); + dev->virt_name); spin_unlock_bh(&dev->dev_lock); - goto out_free_success; + goto out_free; } list_add_tail(&b->ext_blockers_list_entry, &dev->ext_blockers_list); dev->ext_blocking_pending = 1; - if (flags & SCST_EXT_BLOCK_SYNC) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(w); + b->ext_blocker_done_fn = scst_sync_ext_blocking_done; + *((void **)&b->ext_blocker_data[0]) = &w; - b->ext_blocker_done_fn = scst_sync_ext_blocking_done; - *((void **)&b->ext_blocker_data[0]) = &w; + scst_wait_event_lock_bh(w, dev->on_dev_cmd_count == 0, dev->dev_lock); - scst_wait_event_lock_bh(w, dev->on_dev_cmd_count == 0, dev->dev_lock); + spin_unlock_bh(&dev->dev_lock); - spin_unlock_bh(&dev->dev_lock); - } else { - b->ext_blocker_done_fn = done_fn; - if (priv_len > 0) { - b->ext_blocker_data_len = priv_len; - memcpy(b->ext_blocker_data, priv, priv_len); - } - if (dev->on_dev_cmd_count == 0) { - TRACE_DBG("No commands to wait for async blocking " - "(dev %s)", dev->virt_name); - if (!dev->ext_unblock_scheduled) - __scst_ext_blocking_done(dev); - spin_unlock_bh(&dev->dev_lock); - } else - spin_unlock_bh(&dev->dev_lock); +out: + TRACE_EXIT_RES(res); + return res; + +out_free: + kfree(b); + goto out; +} + +int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, + const void *priv, size_t priv_len, bool block_stpg) +{ + struct scst_ext_blocker *b; + int res = 0; + + TRACE_ENTRY(); + + b = kzalloc(sizeof(*b) + priv_len, GFP_KERNEL); + if (unlikely(!b)) { + PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data (size %zd)", + sizeof(*b) + priv_len); + res = -ENOMEM; + goto out; } -out_success: - res = 0; + TRACE_MGMT_DBG("New %d ext blocker %p for dev %s (block_stpg %d)", + dev->ext_blocks_cnt + 1, b, dev->virt_name, block_stpg); + + spin_lock_bh(&dev->dev_lock); + + scst_dev_ext_block(dev, block_stpg); + + list_add_tail(&b->ext_blockers_list_entry, &dev->ext_blockers_list); + dev->ext_blocking_pending = 1; + + b->ext_blocker_done_fn = done_fn; + if (priv_len > 0) { + b->ext_blocker_data_len = priv_len; + memcpy(b->ext_blocker_data, priv, priv_len); + } + + if (dev->on_dev_cmd_count == 0) { + TRACE_DBG("No commands to wait for async blocking (dev %s)", + dev->virt_name); + + if (!dev->ext_unblock_scheduled) + __scst_ext_blocking_done(dev); + } + + spin_unlock_bh(&dev->dev_lock); out: TRACE_EXIT_RES(res); return res; - -out_free_success: - sBUG_ON(!(flags & SCST_EXT_BLOCK_SYNC)); - kfree(b); - goto out_success; } void scst_ext_unblock_dev(struct scst_device *dev, bool stpg) @@ -15044,7 +15078,7 @@ void scst_ext_unblock_dev(struct scst_device *dev, bool stpg) spin_unlock_bh(&dev->dev_lock); TRACE_DBG("Ext unblock (dev %s): still pending...", dev->virt_name); - rc = scst_ext_block_dev(dev, NULL, NULL, 0, SCST_EXT_BLOCK_SYNC); + rc = scst_sync_ext_block_dev(dev); if (rc != 0) { /* Oops, have to poll */ PRINT_WARNING("scst_ext_block_dev(dev %s) failed, " diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index c30af8e1d..641ae5be3 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -611,10 +611,9 @@ bool __scst_check_blocked_dev(struct scst_cmd *cmd); void __scst_check_unblock_dev(struct scst_cmd *cmd); void scst_check_unblock_dev(struct scst_cmd *cmd); -#define SCST_EXT_BLOCK_SYNC 1 -#define SCST_EXT_BLOCK_STPG 2 +int scst_sync_ext_block_dev(struct scst_device *dev); int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, - const uint8_t *priv, int priv_len, int flags); + const void *priv, size_t priv_len, bool block_stpg); void scst_ext_unblock_dev(struct scst_device *dev, bool stpg); void __scst_ext_blocking_done(struct scst_device *dev); void scst_ext_blocking_done(struct scst_device *dev); diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 874ef82db..1ed72270f 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -3805,10 +3805,10 @@ static ssize_t scst_dev_block_store(struct kobject *kobj, "data_len %d)", dev->virt_name, sync, data_start, data_len); if (sync) - res = scst_ext_block_dev(dev, NULL, NULL, 0, SCST_EXT_BLOCK_SYNC); + res = scst_sync_ext_block_dev(dev); else res = scst_ext_block_dev(dev, scst_sysfs_ext_blocking_done, - data_start, data_len, 0); + data_start, data_len, false); if (res != 0) goto out; diff --git a/scst/src/scst_tg.c b/scst/src/scst_tg.c index 72feb671d..d03dda1d9 100644 --- a/scst/src/scst_tg.c +++ b/scst/src/scst_tg.c @@ -1820,8 +1820,7 @@ static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg, rc = scst_ext_block_dev(dgd->dev, scst_stpg_ext_blocking_done, - (uint8_t *)&wait, sizeof(wait), - SCST_EXT_BLOCK_STPG); + &wait, sizeof(wait), true); if (rc != 0) { TRACE_DBG("scst_ext_block_dev() failed " "with %d, reverting (cmd %p)", rc, cmd); From 2c5c12c017e7febdd2019217f99749f1516040a0 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 16 Jun 2023 09:55:16 +0300 Subject: [PATCH 14/93] scst_lib: Enable scst_sync_ext_block_dev() to handle signals This patch modifies scst_sync_ext_block_dev() to support INTERRUPTIBLE waiting and handle signal-induced waiting cancellation. To achieve this, the waitqueue head is moved from the stack and allocated with the blocker. Additionally, reference counting and its management are added to the blocker to handle memory freeing from multiple contexts. Fixes: https://github.com/SCST-project/scst/issues/164 --- scst/include/scst.h | 17 ++++++++++++ scst/src/scst_lib.c | 63 +++++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 424ef0bf5..91258d148 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -2716,6 +2716,7 @@ typedef void (*ext_blocker_done_fn_t) (struct scst_device *dev, struct scst_ext_blocker { struct list_head ext_blockers_list_entry; + struct kref refcount; ext_blocker_done_fn_t ext_blocker_done_fn; int ext_blocker_data_len; @@ -5510,6 +5511,22 @@ do { \ __scst_wait_event_lock_bh(wq_head, condition, lock); \ } while (0) +#define __scst_wait_event_interruptible_lock_bh(wq_head, condition, lock) \ + ___scst_wait_event(wq_head, condition, TASK_INTERRUPTIBLE, 0, \ + spin_unlock_bh(&lock); \ + schedule(); \ + spin_lock_bh(&lock)) + +#define scst_wait_event_interruptible_lock_bh(wq_head, condition, lock) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __ret = __scst_wait_event_interruptible_lock_bh(wq_head, \ + condition, lock);\ + __ret; \ +}) + + #define __scst_wait_event_lock_irq(wq_head, condition, lock) \ (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ spin_unlock_irq(&lock); \ diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index f160d0612..897d526de 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -14820,6 +14820,39 @@ int scst_restore_global_mode_pages(struct scst_device *dev, char *params, } EXPORT_SYMBOL_GPL(scst_restore_global_mode_pages); +static inline struct scst_ext_blocker *scst_ext_blocker_create(size_t size) +{ + struct scst_ext_blocker *b; + + b = kzalloc(size, GFP_KERNEL); + if (unlikely(!b)) { + PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data (size %zd)", + size); + return NULL; + } + + kref_init(&b->refcount); + + return b; +} + +static inline void scst_ext_blocker_get(struct scst_ext_blocker *b) +{ + kref_get(&b->refcount); +} + +static inline void scst_ext_blocker_release(struct kref *kref) +{ + struct scst_ext_blocker *b = container_of(kref, struct scst_ext_blocker, refcount); + + kfree(b); +} + +static inline void scst_ext_blocker_put(struct scst_ext_blocker *b) +{ + kref_put(&b->refcount, scst_ext_blocker_release); +} + /* Must be called under dev_lock and BHs off. Might release it, then reacquire. */ void __scst_ext_blocking_done(struct scst_device *dev) { @@ -14851,7 +14884,7 @@ void __scst_ext_blocking_done(struct scst_device *dev) b->ext_blocker_done_fn(dev, b->ext_blocker_data, b->ext_blocker_data_len); - kfree(b); + scst_ext_blocker_put(b); spin_lock_bh(&dev->dev_lock); } @@ -14911,7 +14944,7 @@ static void scst_sync_ext_blocking_done(struct scst_device *dev, TRACE_ENTRY(); - w = (void *)*((unsigned long *)data); + w = (void *) data; wake_up_all(w); TRACE_EXIT(); @@ -14951,19 +14984,20 @@ static void scst_dev_ext_block(struct scst_device *dev, bool block_stpg) int scst_sync_ext_block_dev(struct scst_device *dev) { struct scst_ext_blocker *b; - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(w); + wait_queue_head_t *w; int res = 0; TRACE_ENTRY(); - b = kzalloc(sizeof(*b) + sizeof(void *), GFP_KERNEL); + b = scst_ext_blocker_create(sizeof(*b) + sizeof(wait_queue_head_t)); if (unlikely(!b)) { - PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data (size %zd)", - sizeof(*b) + sizeof(void *)); res = -ENOMEM; goto out; } + w = (void *)b->ext_blocker_data; + init_waitqueue_head(w); + TRACE_MGMT_DBG("New %d sync ext blocker %p for dev %s", dev->ext_blocks_cnt + 1, b, dev->virt_name); @@ -14975,26 +15009,25 @@ int scst_sync_ext_block_dev(struct scst_device *dev) TRACE_DBG("No commands to wait for sync blocking (dev %s)", dev->virt_name); spin_unlock_bh(&dev->dev_lock); - goto out_free; + goto put_blocker; } list_add_tail(&b->ext_blockers_list_entry, &dev->ext_blockers_list); dev->ext_blocking_pending = 1; b->ext_blocker_done_fn = scst_sync_ext_blocking_done; - *((void **)&b->ext_blocker_data[0]) = &w; + scst_ext_blocker_get(b); - scst_wait_event_lock_bh(w, dev->on_dev_cmd_count == 0, dev->dev_lock); + res = scst_wait_event_interruptible_lock_bh(*w, dev->on_dev_cmd_count == 0, dev->dev_lock); spin_unlock_bh(&dev->dev_lock); +put_blocker: + scst_ext_blocker_put(b); + out: TRACE_EXIT_RES(res); return res; - -out_free: - kfree(b); - goto out; } int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, @@ -15005,10 +15038,8 @@ int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, TRACE_ENTRY(); - b = kzalloc(sizeof(*b) + priv_len, GFP_KERNEL); + b = scst_ext_blocker_create(sizeof(*b) + priv_len); if (unlikely(!b)) { - PRINT_ERROR("Unable to alloc struct scst_ext_blocker with data (size %zd)", - sizeof(*b) + priv_len); res = -ENOMEM; goto out; } From be1574d80e0ff51c74bb05f4a1996e1316df78b5 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 19 Jun 2023 20:21:44 +0300 Subject: [PATCH 15/93] scst_lib: Make __scst_ext_blocking_done() static Since __scst_ext_blocking_done() is only called from inside scst_lib.c, declare that function static. This patch doesn't change any functionality. --- scst/src/scst_lib.c | 13 ++++++++----- scst/src/scst_priv.h | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 897d526de..23149b624 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -14854,14 +14854,18 @@ static inline void scst_ext_blocker_put(struct scst_ext_blocker *b) } /* Must be called under dev_lock and BHs off. Might release it, then reacquire. */ -void __scst_ext_blocking_done(struct scst_device *dev) +static void __scst_ext_blocking_done(struct scst_device *dev) + __releases(&dev->dev_lock) + __acquires(&dev->dev_lock) { bool stop; TRACE_ENTRY(); + lockdep_assert_held(&dev->dev_lock); + TRACE_BLOCK("Notifying ext blockers for dev %s (ext_blocks_cnt %d)", - dev->virt_name, dev->ext_blocks_cnt); + dev->virt_name, dev->ext_blocks_cnt); stop = list_empty(&dev->ext_blockers_list); while (!stop) { @@ -14870,8 +14874,8 @@ void __scst_ext_blocking_done(struct scst_device *dev) b = list_first_entry(&dev->ext_blockers_list, typeof(*b), ext_blockers_list_entry); - TRACE_DBG("Notifying async ext blocker %p (cnt %d)", b, - dev->ext_blocks_cnt); + TRACE_DBG("Notifying async ext blocker %p (cnt %d)", + b, dev->ext_blocks_cnt); list_del(&b->ext_blockers_list_entry); @@ -14890,7 +14894,6 @@ void __scst_ext_blocking_done(struct scst_device *dev) } TRACE_EXIT(); - return; } static void scst_ext_blocking_done_fn(struct work_struct *work) diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index 641ae5be3..c9c0d3fb2 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -615,7 +615,6 @@ int scst_sync_ext_block_dev(struct scst_device *dev); int scst_ext_block_dev(struct scst_device *dev, ext_blocker_done_fn_t done_fn, const void *priv, size_t priv_len, bool block_stpg); void scst_ext_unblock_dev(struct scst_device *dev, bool stpg); -void __scst_ext_blocking_done(struct scst_device *dev); void scst_ext_blocking_done(struct scst_device *dev); int scst_get_suspend_count(void); From 1d6ab4aa72b666c62fc4cd851b6f5581f7d23d11 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 26 Jun 2023 14:04:11 +0300 Subject: [PATCH 16/93] nightly build: Update kernel versions Another kernel versions update following the 6.4 release. --- nightly/conf/nightly.conf | 51 +++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index dec343700..524607468 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,37 +3,38 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -6.3 \ -6.2.13-nc \ -6.1.26-nc \ +6.4 \ +6.3.9-nc \ +6.2.16-nc \ +6.1.35-nc \ 6.0.19-nc \ 5.19.17-nc \ 5.18.19-nc \ 5.17.15-nc \ 5.16.20-nc \ -5.15.109-nc \ +5.15.118-nc \ 5.14.21-nc \ 5.13.19-nc \ 5.12.19-nc \ 5.11.22-nc \ -5.10.179-nc \ +5.10.185-nc \ 5.9.16-nc \ 5.8.18-nc \ 5.7.19-nc \ 5.6.19-nc \ 5.5.19-nc \ -5.4.242-nc \ +5.4.248-nc \ 5.3.18-nc \ 5.2.21-nc \ 5.1.21-nc \ 5.0.21-nc \ 4.20.17-nc \ -4.19.282-nc \ +4.19.287-nc \ 4.18.20-nc \ 4.17.19-nc \ 4.16.18-nc \ 4.15.18-nc \ -4.14.314-nc \ +4.14.319-nc \ 4.13.16-nc \ 4.12.14-nc \ 4.11.12-nc \ @@ -58,8 +59,10 @@ ABT_KERNELS=" \ 3.12.74-nc \ 3.11.10-nc \ 3.10.108-nc \ +5.14.0-284.11.1.el9_2^AlmaLinux^9.2-nc \ 5.14.0-162.23.1.el9_1^AlmaLinux^9.1-nc \ 5.14.0-70.30.1.el9_0^AlmaLinux^9.0-nc \ +4.18.0-477.13.1.el8_8^AlmaLinux^8.8-nc \ 4.18.0-425.19.2.el8_7^AlmaLinux^8.7-nc \ 4.18.0-372.32.1.el8_6^AlmaLinux^8.6-nc \ 4.18.0-348.2.1.el8_5^CentOS^8.5.2111-nc \ @@ -68,20 +71,20 @@ ABT_KERNELS=" \ 4.18.0-193.28.1.el8_2^CentOS^8.2.2004-nc \ 4.18.0-147.8.1.el8_1^CentOS^8.1.1911-nc \ 4.18.0-80.11.2.el8_0^CentOS^8.0.1905-nc \ -3.10.0-1160.88.1.el7^CentOS^7.9.2009-nc \ -3.10.0-1127.19.1.el7^CentOS^7.8.2003-nc \ -3.10.0-1062.18.1.el7^CentOS^7.7.1908-nc \ -3.10.0-957.27.2.el7^CentOS^7.6.1810-nc \ -3.10.0-862.14.4.el7^CentOS^7.5.1804-nc \ -5.15.0-8.91.4.1.el9uek^UEK^9-nc \ -5.15.0-8.91.4.1.el8uek^UEK^8-nc \ -5.4.17-2136.318.7.1.el8uek^UEK^8-nc \ -5.4.17-2102.206.1.el8uek^UEK^8-nc \ -5.4.17-2036.104.5.el8uek^UEK^8-nc \ -5.4.17-2011.7.4.el8uek^UEK^8-nc \ -5.4.17-2136.318.7.1.el7uek^UEK^7-nc \ -5.4.17-2102.206.1.el7uek^UEK^7-nc \ -5.4.17-2036.104.5.el7uek^UEK^7-nc \ -5.4.17-2011.7.4.el7uek^UEK^7-nc \ -4.1.12-124.48.6.el6uek^UEK^6-nc \ +3.10.0-1160.90.1.el7^CentOS^7.9.2009-nc \ +3.10.0-1127.19.1.el7^CentOS^7.8.2003-nc \ +3.10.0-1062.18.1.el7^CentOS^7.7.1908-nc \ +3.10.0-957.27.2.el7^CentOS^7.6.1810-nc \ +3.10.0-862.14.4.el7^CentOS^7.5.1804-nc \ +5.15.0-102.110.5.1.el9uek^UEK^9-nc \ +5.15.0-102.110.5.1.el8uek^UEK^8-nc \ +5.4.17-2136.320.7.1.el8uek^UEK^8-nc \ +5.4.17-2102.206.1.el8uek^UEK^8-nc \ +5.4.17-2036.104.5.el8uek^UEK^8-nc \ +5.4.17-2011.7.4.el8uek^UEK^8-nc \ +5.4.17-2136.320.7.1.el7uek^UEK^7-nc \ +5.4.17-2102.206.1.el7uek^UEK^7-nc \ +5.4.17-2036.104.5.el7uek^UEK^7-nc \ +5.4.17-2011.7.4.el7uek^UEK^7-nc \ +4.1.12-124.48.6.el6uek^UEK^6-nc \ " From bdf867ffd18a8781ccf344f1ef39ebb29c412897 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 27 Jun 2023 16:10:12 +0300 Subject: [PATCH 17/93] scst: Use scst_wait_event_...() with INTERRUPTIBLE sleep This patch changes the processing threads to use INTERRUPTIBLE sleep states in the scst_wait_event_...() functions. This aims to avoid warnings from the hung task detection checker and to prevent unnecessary load counting. Fixes: d8894cbd1157 ("scst.h: Refactor wait_event_locked() to enhance usability and clarity") --- iscsi-scst/kernel/nthread.c | 4 +- scst/include/scst.h | 64 +++++++++++++------------------ scst/src/dev_handlers/scst_user.c | 10 ++--- scst/src/scst_sysfs.c | 4 +- scst/src/scst_targ.c | 16 ++++---- 5 files changed, 44 insertions(+), 54 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index fb4e93a36..593d7eeec 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -960,7 +960,7 @@ int istrd(void *arg) spin_lock_bh(&p->rd_lock); while (!kthread_should_stop()) { - scst_wait_event_lock_bh(p->rd_waitQ, test_rd_list(p), p->rd_lock); + scst_wait_event_interruptible_lock_bh(p->rd_waitQ, test_rd_list(p), p->rd_lock); scst_do_job_rd(p); } spin_unlock_bh(&p->rd_lock); @@ -1612,7 +1612,7 @@ int istwr(void *arg) spin_lock_bh(&p->wr_lock); while (!kthread_should_stop()) { - scst_wait_event_lock_bh(p->wr_waitQ, test_wr_list(p), p->wr_lock); + scst_wait_event_interruptible_lock_bh(p->wr_waitQ, test_wr_list(p), p->wr_lock); scst_do_job_wr(p); } spin_unlock_bh(&p->wr_lock); diff --git a/scst/include/scst.h b/scst/include/scst.h index 91258d148..781aabb21 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -5485,31 +5485,20 @@ prepare_to_wait_exclusive_head(struct wait_queue_head *wq_head, __out: __ret; \ }) -#define __scst_wait_event_lock(wq_head, condition, lock) \ - (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ - spin_unlock(&lock); \ - schedule(); \ - spin_lock(&lock)) - -#define scst_wait_event_lock(wq_head, condition, lock) \ -do { \ - if (condition) \ - break; \ - __scst_wait_event_lock(wq_head, condition, lock); \ -} while (0) - -#define __scst_wait_event_lock_bh(wq_head, condition, lock) \ - (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ - spin_unlock_bh(&lock); \ - schedule(); \ - spin_lock_bh(&lock)) - -#define scst_wait_event_lock_bh(wq_head, condition, lock) \ -do { \ - if (condition) \ - break; \ - __scst_wait_event_lock_bh(wq_head, condition, lock); \ -} while (0) +#define __scst_wait_event_interruptible_lock(wq_head, condition, lock) \ + ___scst_wait_event(wq_head, condition, TASK_INTERRUPTIBLE, 0, \ + spin_unlock(&lock); \ + schedule(); \ + spin_lock(&lock)) + +#define scst_wait_event_interruptible_lock(wq_head, condition, lock) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __ret = __scst_wait_event_interruptible_lock(wq_head, \ + condition, lock); \ + __ret; \ +}) #define __scst_wait_event_interruptible_lock_bh(wq_head, condition, lock) \ ___scst_wait_event(wq_head, condition, TASK_INTERRUPTIBLE, 0, \ @@ -5526,19 +5515,20 @@ do { \ __ret; \ }) +#define __scst_wait_event_interruptible_lock_irq(wq_head, condition, lock) \ + ___scst_wait_event(wq_head, condition, TASK_INTERRUPTIBLE, 0, \ + spin_unlock_irq(&lock); \ + schedule(); \ + spin_lock_irq(&lock)) -#define __scst_wait_event_lock_irq(wq_head, condition, lock) \ - (void)___scst_wait_event(wq_head, condition, TASK_UNINTERRUPTIBLE, 0, \ - spin_unlock_irq(&lock); \ - schedule(); \ - spin_lock_irq(&lock)) - -#define scst_wait_event_lock_irq(wq_head, condition, lock) \ -do { \ - if (condition) \ - break; \ - __scst_wait_event_lock_irq(wq_head, condition, lock); \ -} while (0) +#define scst_wait_event_interruptible_lock_irq(wq_head, condition, lock) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __ret = __scst_wait_event_interruptible_lock_irq(wq_head, \ + condition, lock);\ + __ret; \ +}) #if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) const char *scst_get_opcode_name(struct scst_cmd *cmd); diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index e41b3bafc..fcf2d90b8 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -2233,9 +2233,9 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, TRACE_ENTRY(); while (1) { - scst_wait_event_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ, - test_cmd_threads(dev, can_block), - dev->udev_cmd_threads.cmd_list_lock); + scst_wait_event_interruptible_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ, + test_cmd_threads(dev, can_block), + dev->udev_cmd_threads.cmd_list_lock); dev_user_process_scst_commands(dev); @@ -4053,8 +4053,8 @@ static int dev_user_cleanup_thread(void *arg) spin_lock(&cleanup_lock); while (!kthread_should_stop()) { - scst_wait_event_lock(cleanup_list_waitQ, test_cleanup_list(), - cleanup_lock); + scst_wait_event_interruptible_lock(cleanup_list_waitQ, test_cleanup_list(), + cleanup_lock); /* * We have to poll devices, because commands can go from SCST diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index 1ed72270f..f21362dc3 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -470,8 +470,8 @@ static int sysfs_work_thread_fn(void *arg) while (!kthread_should_stop()) { if (one_time_only && !test_sysfs_work_list()) break; - scst_wait_event_lock(sysfs_work_waitQ, test_sysfs_work_list(), - sysfs_work_lock); + scst_wait_event_interruptible_lock(sysfs_work_waitQ, test_sysfs_work_list(), + sysfs_work_lock); scst_process_sysfs_works(); } spin_unlock(&sysfs_work_lock); diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 2593cc07f..70e212e7e 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4510,9 +4510,9 @@ int scst_init_thread(void *arg) spin_lock_irq(&scst_init_lock); while (!kthread_should_stop()) { - scst_wait_event_lock_irq(scst_init_cmd_list_waitQ, - test_init_cmd_list(), - scst_init_lock); + scst_wait_event_interruptible_lock_irq(scst_init_cmd_list_waitQ, + test_init_cmd_list(), + scst_init_lock); scst_do_job_init(); } spin_unlock_irq(&scst_init_lock); @@ -6794,9 +6794,9 @@ int scst_tm_thread(void *arg) spin_lock_irq(&scst_mcmd_lock); while (!kthread_should_stop()) { - scst_wait_event_lock_irq(scst_mgmt_cmd_list_waitQ, - test_mgmt_cmd_list(), - scst_mcmd_lock); + scst_wait_event_interruptible_lock_irq(scst_mgmt_cmd_list_waitQ, + test_mgmt_cmd_list(), + scst_mcmd_lock); while (!list_empty(&scst_active_mgmt_cmd_list)) { int rc; @@ -7610,8 +7610,8 @@ int scst_global_mgmt_thread(void *arg) spin_lock_irq(&scst_mgmt_lock); while (!kthread_should_stop()) { - scst_wait_event_lock_irq(scst_mgmt_waitQ, test_mgmt_list(), - scst_mgmt_lock); + scst_wait_event_interruptible_lock_irq(scst_mgmt_waitQ, test_mgmt_list(), + scst_mgmt_lock); while (!list_empty(&scst_sess_init_list)) { sess = list_first_entry(&scst_sess_init_list, From 6a925490fd5447033aabb847ab3418a20aba4266 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 28 Jun 2023 15:29:22 +0300 Subject: [PATCH 18/93] scst: Confirm percpu refs has scheduled and switched to atomic This patch replaces percpu_ref_kill() with percpu_ref_kill_and_confirm() to guarantee safe usage of references in atomic mode immediately afterwards. This change ensures accurate checking of active commands following the initial reference killing. Reported-by: Lev Vainblat --- .github/workflows/checkpatch_pull.yml | 1 + .github/workflows/checkpatch_push.yml | 1 + scst/include/backport.h | 10 ++++++- scst/src/scst_main.c | 42 ++++++++++++++++++--------- scst/src/scst_priv.h | 1 - 5 files changed, 40 insertions(+), 15 deletions(-) diff --git a/.github/workflows/checkpatch_pull.yml b/.github/workflows/checkpatch_pull.yml index c231e64b5..dfee81f03 100644 --- a/.github/workflows/checkpatch_pull.yml +++ b/.github/workflows/checkpatch_pull.yml @@ -30,6 +30,7 @@ jobs: UNKNOWN_COMMIT_ID NO_AUTHOR_SIGN_OFF COMMIT_LOG_USE_LINK + BAD_REPORTED_BY_LINK FILE_PATH_CHANGES SPDX_LICENSE_TAG LINUX_VERSION_CODE diff --git a/.github/workflows/checkpatch_push.yml b/.github/workflows/checkpatch_push.yml index c5071f46f..e517ccc07 100644 --- a/.github/workflows/checkpatch_push.yml +++ b/.github/workflows/checkpatch_push.yml @@ -35,6 +35,7 @@ jobs: UNKNOWN_COMMIT_ID NO_AUTHOR_SIGN_OFF COMMIT_LOG_USE_LINK + BAD_REPORTED_BY_LINK FILE_PATH_CHANGES SPDX_LICENSE_TAG LINUX_VERSION_CODE diff --git a/scst/include/backport.h b/scst/include/backport.h index 6d0fd876e..d8e873afa 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -1098,13 +1098,21 @@ static inline void percpu_ref_put(struct percpu_ref *ref) ref->release(ref); } -static inline void percpu_ref_kill(struct percpu_ref *ref) +static inline void +percpu_ref_kill_and_confirm(struct percpu_ref *ref, percpu_ref_func_t *confirm_kill) { WARN_ON_ONCE(ref->dead); ref->dead = true; + if (confirm_kill) + confirm_kill(ref); percpu_ref_put(ref); } +static inline void percpu_ref_kill(struct percpu_ref *ref) +{ + percpu_ref_kill_and_confirm(ref, NULL); +} + static inline void percpu_ref_resurrect(struct percpu_ref *ref) { WARN_ON_ONCE(!ref->dead); diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 11d26d336..3462a3780 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -129,7 +129,8 @@ spinlock_t scst_mgmt_lock; struct list_head scst_sess_init_list; struct list_head scst_sess_shut_list; -wait_queue_head_t scst_dev_cmd_waitQ; +static wait_queue_head_t scst_dev_cmd_waitQ; +static struct completion scst_confirm_done; static struct mutex scst_cmd_threads_mutex; /* protected by scst_cmd_threads_mutex */ @@ -792,7 +793,7 @@ static int scst_susp_wait(unsigned long timeout) t = min(timeout, SCST_SUSP_WAIT_REPORT_TIMEOUT); res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ, - percpu_ref_killed, t); + percpu_ref_killed, t); if (res > 0) { res = 0; goto out; @@ -800,15 +801,16 @@ static int scst_susp_wait(unsigned long timeout) goto out; if (res == 0) { - PRINT_INFO("%d active commands to still not completed. See " - "README for possible reasons.", scst_get_cmd_counter()); + PRINT_INFO( + "%d active commands to still not completed. See README for possible reasons.", + scst_get_cmd_counter()); scst_trace_cmds(scst_to_syslog, &hp); scst_trace_mcmds(scst_to_syslog, &hp); } if (timeout != SCST_SUSPEND_TIMEOUT_UNLIMITED) { res = wait_event_interruptible_timeout(scst_dev_cmd_waitQ, - percpu_ref_killed, timeout - t); + percpu_ref_killed, timeout - t); if (res == 0) res = -EBUSY; else if (res > 0) @@ -826,6 +828,11 @@ static int scst_susp_wait(unsigned long timeout) #undef SCST_SUSP_WAIT_REPORT_TIMEOUT } +static void scst_suspend_counter_confirm(struct percpu_ref *ref) +{ + complete(&scst_confirm_done); +} + /* * scst_suspend_activity() - globally suspend activity * @@ -864,8 +871,12 @@ int scst_suspend_activity(unsigned long timeout) goto out_up; /* Cause scst_get_cmd() to fail. */ + init_completion(&scst_confirm_done); + percpu_ref_killed = false; - percpu_ref_kill(&scst_cmd_count); + percpu_ref_kill_and_confirm(&scst_cmd_count, scst_suspend_counter_confirm); + + wait_for_completion(&scst_confirm_done); /* * See comment in scst_user.c::dev_user_task_mgmt_fn() for more @@ -878,7 +889,7 @@ int scst_suspend_activity(unsigned long timeout) if (scst_get_cmd_counter() != 0) { PRINT_INFO("Waiting for %d active commands to complete...", - scst_get_cmd_counter()); + scst_get_cmd_counter()); rep = true; lock_contended(&scst_suspend_dep_map, _RET_IP_); @@ -887,15 +898,19 @@ int scst_suspend_activity(unsigned long timeout) res = scst_susp_wait(timeout); /* Cause scst_get_mcmd() to fail. */ + init_completion(&scst_confirm_done); + percpu_ref_killed = false; - percpu_ref_kill(&scst_mcmd_count); + percpu_ref_kill_and_confirm(&scst_mcmd_count, scst_suspend_counter_confirm); + + wait_for_completion(&scst_confirm_done); if (res != 0) goto out_resume; if (scst_get_cmd_counter() != 0) - TRACE_MGMT_DBG("Waiting for %d active commands finally to " - "complete", scst_get_cmd_counter()); + TRACE_MGMT_DBG("Waiting for %d active commands finally to complete", + scst_get_cmd_counter()); if (timeout != SCST_SUSPEND_TIMEOUT_UNLIMITED) { wait_time = jiffies - cur_time; @@ -913,7 +928,7 @@ int scst_suspend_activity(unsigned long timeout) goto out_resume; if (rep) - PRINT_INFO("%s", "All active commands completed"); + PRINT_INFO("All active commands completed"); out_up: mutex_unlock(&scst_suspend_mutex); @@ -973,8 +988,9 @@ static void __scst_resume_activity(void) spin_lock_irq(&scst_mcmd_lock); list_for_each_entry(m, &scst_delayed_mgmt_cmd_list, mgmt_cmd_list_entry) { - TRACE_MGMT_DBG("Moving delayed mgmt cmd %p to head of active " - "mgmt cmd list", m); + TRACE_MGMT_DBG( + "Moving delayed mgmt cmd %p to head of active mgmt cmd list", + m); } list_splice_init(&scst_delayed_mgmt_cmd_list, &scst_active_mgmt_cmd_list); diff --git a/scst/src/scst_priv.h b/scst/src/scst_priv.h index c9c0d3fb2..492763029 100644 --- a/scst/src/scst_priv.h +++ b/scst/src/scst_priv.h @@ -172,7 +172,6 @@ extern struct list_head scst_template_list; extern struct list_head scst_dev_list; extern struct list_head scst_dev_type_list; extern struct list_head scst_virtual_dev_type_list; -extern wait_queue_head_t scst_dev_cmd_waitQ; extern const struct scst_cl_ops scst_no_dlm_cl_ops; extern const struct scst_cl_ops scst_dlm_cl_ops; From 057224f6691b8ee7fedb677e1c69844d051423b1 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 29 Jun 2023 12:16:49 +0300 Subject: [PATCH 19/93] scst_user: Simplify signal pending check The scst_wait_event_interruptible_lock_irq() function now implicitly checks for pending signals. Therefore, there is no need to check for these signals explicitly. This patch replaces the explicit check with a simple evaluation of the function's return value. This patch doesn't change any functionality. --- scst/src/dev_handlers/scst_user.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index fcf2d90b8..e66a41069 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -36,10 +36,6 @@ #endif #include "scst_dev_handler.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -#include -#endif - #ifndef INSIDE_KERNEL_TREE #if defined(CONFIG_HIGHMEM4G) || defined(CONFIG_HIGHMEM64G) #warning HIGHMEM kernel configurations are not supported by this module, \ @@ -2219,8 +2215,7 @@ static inline int test_cmd_threads(struct scst_user_dev *dev, bool can_block) { int res = !list_empty(&dev->udev_cmd_threads.active_cmd_list) || !list_empty(&dev->ready_cmd_list) || - !can_block || !dev->blocking || dev->cleanup_done || - signal_pending(current); + !can_block || !dev->blocking || dev->cleanup_done; return res; } @@ -2233,9 +2228,11 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, TRACE_ENTRY(); while (1) { - scst_wait_event_interruptible_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ, - test_cmd_threads(dev, can_block), - dev->udev_cmd_threads.cmd_list_lock); + res = scst_wait_event_interruptible_lock_irq(dev->udev_cmd_threads.cmd_list_waitQ, + test_cmd_threads(dev, can_block), + dev->udev_cmd_threads.cmd_list_lock); + if (res) + break; dev_user_process_scst_commands(dev); @@ -2248,12 +2245,6 @@ static int dev_user_get_next_cmd(struct scst_user_dev *dev, TRACE_DBG("No ready commands, returning %d", res); break; } - - if (signal_pending(current)) { - res = -EINTR; - TRACE_DBG("Signal pending, returning %d", res); - break; - } } TRACE_EXIT_RES(res); From 86d5b218e4cbf98da04db81b8e320e490fbbe472 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 29 Jun 2023 15:21:17 +0300 Subject: [PATCH 20/93] scst_targ: Check prepare_to_wait_exclusive_head() return value The prepare_to_wait_exclusive_head() function was modified in commit d8894cbd1157 ("scst.h: Refactor wait_event_locked() to enhance usability and clarity"). It now returns an error if the current interruptible thread has pending signals. This patch introduces the scst_wait_for_cmd() helper function for the scst_cmd_thread(). This new function handles the return value of the prepare_to_wait_exclusive_head() appropriately. This patch fixes the following Coverity complaint: CID 321410 (#1 of 1): Unchecked return value (CHECKED_RETURN) check_return: Calling prepare_to_wait_exclusive_head without checking return value. --- scst/src/scst_targ.c | 51 +++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 70e212e7e..4b4eac7dd 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -4800,6 +4800,39 @@ static inline int test_cmd_threads(struct scst_cmd_thread_t *thr) return res; } +static inline int +scst_wait_for_cmd(struct scst_cmd_threads *p_cmd_threads, struct scst_cmd_thread_t *thr) +{ + DEFINE_WAIT(wq_entry); + int ret = 0; + + if (test_cmd_threads(thr)) + return 0; + + for (;;) { + long __int = prepare_to_wait_exclusive_head(&p_cmd_threads->cmd_list_waitQ, + &wq_entry, TASK_INTERRUPTIBLE); + + if (test_cmd_threads(thr)) + break; + + if (__int) { + ret = __int; + goto out; + } + + spin_unlock(&thr->thr_cmd_list_lock); + spin_unlock_irq(&p_cmd_threads->cmd_list_lock); + schedule(); + spin_lock_irq(&p_cmd_threads->cmd_list_lock); + spin_lock(&thr->thr_cmd_list_lock); + } + finish_wait(&p_cmd_threads->cmd_list_waitQ, &wq_entry); + +out: + return ret; +} + int scst_cmd_thread(void *arg) { struct scst_cmd_thread_t *thr = arg; @@ -4822,23 +4855,7 @@ int scst_cmd_thread(void *arg) spin_lock_irq(&p_cmd_threads->cmd_list_lock); spin_lock(&thr->thr_cmd_list_lock); while (!kthread_should_stop()) { - if (!test_cmd_threads(thr)) { - DEFINE_WAIT(wait); - - do { - prepare_to_wait_exclusive_head( - &p_cmd_threads->cmd_list_waitQ, - &wait, TASK_INTERRUPTIBLE); - if (test_cmd_threads(thr)) - break; - spin_unlock(&thr->thr_cmd_list_lock); - spin_unlock_irq(&p_cmd_threads->cmd_list_lock); - schedule(); - spin_lock_irq(&p_cmd_threads->cmd_list_lock); - spin_lock(&thr->thr_cmd_list_lock); - } while (!test_cmd_threads(thr)); - finish_wait(&p_cmd_threads->cmd_list_waitQ, &wait); - } + scst_wait_for_cmd(p_cmd_threads, thr); if (tm_dbg_is_release()) { spin_unlock_irq(&p_cmd_threads->cmd_list_lock); From 5c14b16fb773a0ed72c32619179d3ad6a4a22be0 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 4 Jul 2023 15:16:35 +0300 Subject: [PATCH 21/93] scst_vdisk: Open block devices exclusively Enable exclusive opening of block devices to prevent concurrent usage. Additionally, remove the redundant 'holder' argument for 'blkdev_get_by_path()' where exclusive opening isn't utilized. --- scst/src/dev_handlers/scst_vdisk.c | 26 +++++++++++++------------- scst/src/scst_lib.c | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 95a3bf4d1..eaa61c5ba 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -503,12 +503,12 @@ static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev) virt_dev->wt_flag || !virt_dev->dev_active) goto out; - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, - (void *)__func__); + bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); if (IS_ERR(bdev)) { if (PTR_ERR(bdev) == -EMEDIUMTYPE) - TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, " - "DRBD passive?", virt_dev->filename); + TRACE(TRACE_MINOR, + "Unable to open %s with EMEDIUMTYPE, DRBD passive?", + virt_dev->filename); else PRINT_ERROR("blkdev_get_by_path(%s) failed: %ld", virt_dev->filename, PTR_ERR(bdev)); @@ -516,9 +516,9 @@ static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev) } if (vdisk_blockio_flush(bdev, GFP_KERNEL, false, NULL, false) != 0) { - PRINT_WARNING("Device %s doesn't support barriers, switching " - "to NV_CACHE mode. Read README for more details.", - virt_dev->filename); + PRINT_WARNING( +"Device %s doesn't support barriers, switching to NV_CACHE mode. Read README for more details.", + virt_dev->filename); virt_dev->nv_cache = 1; } @@ -544,8 +544,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev) goto check; if (virt_dev->blockio) { - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, - (void *)__func__); + bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); res = PTR_ERR_OR_ZERO(bdev); } else { fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600); @@ -966,8 +965,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev) TRACE_ENTRY(); - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, - (void *)__func__); + bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); if (IS_ERR(bdev)) { res = PTR_ERR(bdev); goto out; @@ -1309,11 +1307,13 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only) virt_dev->dev->virt_name); res = -EMEDIUMTYPE; } else if (virt_dev->blockio) { - virt_dev->bdev_mode = FMODE_READ; + virt_dev->bdev_mode = FMODE_READ | FMODE_EXCL; + if (!read_only) virt_dev->bdev_mode |= FMODE_WRITE; + virt_dev->bdev = blkdev_get_by_path(virt_dev->filename, - virt_dev->bdev_mode, (void *)__func__); + virt_dev->bdev_mode, virt_dev); res = PTR_ERR_OR_ZERO(virt_dev->bdev); } else { virt_dev->fd = vdev_open_fd(virt_dev, virt_dev->filename, diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 23149b624..bdb45c4e7 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5983,7 +5983,7 @@ loff_t scst_bdev_size(const char *path) struct block_device *bdev; loff_t res; - bdev = blkdev_get_by_path(path, FMODE_READ, (void *)__func__); + bdev = blkdev_get_by_path(path, FMODE_READ, NULL); if (IS_ERR(bdev)) return PTR_ERR(bdev); res = i_size_read(bdev->bd_inode); From 76750f3352d095e6a544d02a10d84b15147bcb0a Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 30 Jun 2023 11:57:56 +0300 Subject: [PATCH 22/93] scst: Port to Linux kernel v6.5 Support for the following block layer changes in the Linux kernel v6.5: - 05bdb9965305 ("block: replace fmode_t with a block-specific type for block open flags") - 0718afd47f70 ("block: introduce holder ops") - 2736e8eeb0cc ("block: use the holder as indication for exclusive opens") --- .github/workflows/checkpatch_pull.yml | 1 + .github/workflows/checkpatch_push.yml | 1 + scst/include/backport.h | 53 ++++++++++++++++++++++++++- scst/src/dev_handlers/scst_vdisk.c | 24 ++++++------ scst/src/scst_lib.c | 4 +- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/.github/workflows/checkpatch_pull.yml b/.github/workflows/checkpatch_pull.yml index dfee81f03..a9ced9892 100644 --- a/.github/workflows/checkpatch_pull.yml +++ b/.github/workflows/checkpatch_pull.yml @@ -35,6 +35,7 @@ jobs: SPDX_LICENSE_TAG LINUX_VERSION_CODE CONSTANT_COMPARISON + NEW_TYPEDEFS SPACING ) ignore_str=${ignore[*]} diff --git a/.github/workflows/checkpatch_push.yml b/.github/workflows/checkpatch_push.yml index e517ccc07..28acad5e5 100644 --- a/.github/workflows/checkpatch_push.yml +++ b/.github/workflows/checkpatch_push.yml @@ -40,6 +40,7 @@ jobs: SPDX_LICENSE_TAG LINUX_VERSION_CODE CONSTANT_COMPARISON + NEW_TYPEDEFS SPACING ) ignore_str=${ignore[*]} diff --git a/scst/include/backport.h b/scst/include/backport.h index d8e873afa..dd784cffb 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -228,6 +228,55 @@ void blk_execute_rq_nowait_backport(struct request *rq, bool at_head) /* */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) +/* + * See also commit 05bdb9965305 ("block: replace fmode_t with a block-specific + * type for block open flags") # v6.5. + */ +typedef fmode_t blk_mode_t; + +#define BLK_OPEN_READ ((__force blk_mode_t)FMODE_READ) +#define BLK_OPEN_WRITE ((__force blk_mode_t)FMODE_WRITE) +#define BLK_OPEN_EXCL ((__force blk_mode_t)FMODE_EXCL) + +/* + * See also commit 0718afd47f70 ("block: introduce holder ops") # v6.5. + */ +struct blk_holder_ops { + /* empty dummy */ +}; + +static inline struct block_device * +blkdev_get_by_path_backport(const char *path, blk_mode_t mode, + void *holder, const struct blk_holder_ops *hops) +{ + WARN_ON_ONCE(hops); + + /* + * See also commit 2736e8eeb0cc ("block: use the holder as + * indication for exclusive opens") # v6.5. + */ + if (holder) + mode |= BLK_OPEN_EXCL; + + return blkdev_get_by_path(path, mode, holder); +} + +#define blkdev_get_by_path blkdev_get_by_path_backport + +/* + * See also commit 2736e8eeb0cc ("block: use the holder as indication for + * exclusive opens") # v6.5. + */ +static inline void blkdev_put_backport(struct block_device *bdev, void *holder) +{ + blkdev_put(bdev, holder ? BLK_OPEN_EXCL : 0); +} + +#define blkdev_put blkdev_put_backport + +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0) && \ (!defined(RHEL_RELEASE_CODE) || \ RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 1)) @@ -235,8 +284,8 @@ void blk_execute_rq_nowait_backport(struct request *rq, bool at_head) * See also commit 44abff2c0b97 ("block: decouple REQ_OP_SECURE_ERASE * from REQ_OP_DISCARD") # v5.19. */ -static inline -int blkdev_issue_discard_backport(struct block_device *bdev, sector_t sector, +static inline int +blkdev_issue_discard_backport(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask) { return blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, 0); diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index eaa61c5ba..cf6907cc2 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -191,7 +191,6 @@ struct scst_vdisk_dev { struct file *fd; struct file *dif_fd; struct block_device *bdev; - fmode_t bdev_mode; struct bio_set *vdisk_bioset; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) struct bio_set vdisk_bioset_struct; @@ -503,7 +502,7 @@ static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev) virt_dev->wt_flag || !virt_dev->dev_active) goto out; - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); + bdev = blkdev_get_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL); if (IS_ERR(bdev)) { if (PTR_ERR(bdev) == -EMEDIUMTYPE) TRACE(TRACE_MINOR, @@ -522,7 +521,7 @@ static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev) virt_dev->nv_cache = 1; } - blkdev_put(bdev, FMODE_READ); + blkdev_put(bdev, NULL); out: TRACE_EXIT(); @@ -544,7 +543,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev) goto check; if (virt_dev->blockio) { - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); + bdev = blkdev_get_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL); res = PTR_ERR_OR_ZERO(bdev); } else { fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600); @@ -640,7 +639,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev) if (fd_open) { if (virt_dev->blockio) - blkdev_put(bdev, FMODE_READ); + blkdev_put(bdev, NULL); else filp_close(fd, NULL); } @@ -965,7 +964,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev) TRACE_ENTRY(); - bdev = blkdev_get_by_path(virt_dev->filename, FMODE_READ, NULL); + bdev = blkdev_get_by_path(virt_dev->filename, BLK_OPEN_READ, NULL, NULL); if (IS_ERR(bdev)) { res = PTR_ERR(bdev); goto out; @@ -1043,7 +1042,7 @@ static int vdisk_init_block_integrity(struct scst_vdisk_dev *virt_dev) res = 0; out_close: - blkdev_put(bdev, FMODE_READ); + blkdev_put(bdev, NULL); out: TRACE_EXIT_RES(res); @@ -1307,13 +1306,12 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only) virt_dev->dev->virt_name); res = -EMEDIUMTYPE; } else if (virt_dev->blockio) { - virt_dev->bdev_mode = FMODE_READ | FMODE_EXCL; + blk_mode_t bdev_mode = BLK_OPEN_READ; if (!read_only) - virt_dev->bdev_mode |= FMODE_WRITE; + bdev_mode |= BLK_OPEN_WRITE; - virt_dev->bdev = blkdev_get_by_path(virt_dev->filename, - virt_dev->bdev_mode, virt_dev); + virt_dev->bdev = blkdev_get_by_path(virt_dev->filename, bdev_mode, virt_dev, NULL); res = PTR_ERR_OR_ZERO(virt_dev->bdev); } else { virt_dev->fd = vdev_open_fd(virt_dev, virt_dev->filename, @@ -1352,7 +1350,7 @@ static int vdisk_open_fd(struct scst_vdisk_dev *virt_dev, bool read_only) out_close_fd: if (virt_dev->blockio) { - blkdev_put(virt_dev->bdev, virt_dev->bdev_mode); + blkdev_put(virt_dev->bdev, virt_dev); virt_dev->bdev = NULL; } else { filp_close(virt_dev->fd, NULL); @@ -1367,7 +1365,7 @@ static void vdisk_close_fd(struct scst_vdisk_dev *virt_dev) virt_dev->fd, virt_dev->bdev, virt_dev->dif_fd); if (virt_dev->bdev) { - blkdev_put(virt_dev->bdev, virt_dev->bdev_mode); + blkdev_put(virt_dev->bdev, virt_dev); virt_dev->bdev = NULL; } else if (virt_dev->fd) { filp_close(virt_dev->fd, NULL); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index bdb45c4e7..283a28bbd 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -5983,11 +5983,11 @@ loff_t scst_bdev_size(const char *path) struct block_device *bdev; loff_t res; - bdev = blkdev_get_by_path(path, FMODE_READ, NULL); + bdev = blkdev_get_by_path(path, BLK_OPEN_READ, NULL, NULL); if (IS_ERR(bdev)) return PTR_ERR(bdev); res = i_size_read(bdev->bd_inode); - blkdev_put(bdev, FMODE_READ); + blkdev_put(bdev, NULL); return res; } EXPORT_SYMBOL(scst_bdev_size); From 7a1ea234e7e9428c85e0c8a5d66158e369b8e81a Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 4 Jul 2023 17:35:04 +0300 Subject: [PATCH 23/93] scst_tape: Port to Linux kernel v6.5 Support for the following scsi core changes in the Linux kernel v6.5: - a6cdc35fab0d ("scsi: core: Support retrieving sub-pages of mode pages") --- scst/src/dev_handlers/scst_tape.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scst/src/dev_handlers/scst_tape.c b/scst/src/dev_handlers/scst_tape.c index 1bb030180..845b98e7f 100644 --- a/scst/src/dev_handlers/scst_tape.c +++ b/scst/src/dev_handlers/scst_tape.c @@ -171,12 +171,15 @@ static int tape_attach(struct scst_device *dev) TRACE_DBG("%s", "Doing MODE_SENSE"); rc = scsi_mode_sense(dev->scsi_dev, - ((dev->scsi_dev->scsi_level <= SCSI_2) ? - ((dev->scsi_dev->lun << 5) & 0xe0) : 0), - 0 /* Mode Page 0 */, - buffer, buffer_size, - SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES, - &data, NULL); + ((dev->scsi_dev->scsi_level <= SCSI_2) ? + ((dev->scsi_dev->lun << 5) & 0xe0) : 0), + 0 /* Mode Page 0 */, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0) + 0 /* Sub Page */, +#endif + buffer, buffer_size, + SCST_GENERIC_TAPE_SMALL_TIMEOUT, TAPE_RETRIES, + &data, NULL); TRACE_DBG("MODE_SENSE done: %x", rc); if (rc == 0) { From a62b094f4fea3006497c025927575ed35d1e2829 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Tue, 4 Jul 2023 18:22:56 +0300 Subject: [PATCH 24/93] scst_user: Port to Linux kernel v6.5 Support for the following mm layer changes in the Linux kernel v6.5: - 54d020692b34 ("mm/gup: remove unused vmas parameter from get_user_pages()") --- scst/include/backport.h | 73 +++++++++++++------------------ scst/src/dev_handlers/scst_user.c | 4 +- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index dd784cffb..709a88f1b 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -572,60 +572,49 @@ static inline u32 int_sqrt64(u64 x) } #endif -#if LINUX_VERSION_CODE >> 8 == KERNEL_VERSION(4, 4, 0) >> 8 && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168) -/* - * See also commit 8e50b8b07f46 ("mm: replace get_user_pages() write/force - * parameters with gup_flags") # v4.4.168. - */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) static inline long get_user_pages_backport(unsigned long start, unsigned long nr_pages, unsigned int gup_flags, - struct page **pages, - struct vm_area_struct **vmas) + struct page **pages) { +#if LINUX_VERSION_CODE >> 8 == KERNEL_VERSION(4, 4, 0) >> 8 && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168) + /* + * See also commit 8e50b8b07f46 ("mm: replace get_user_pages() write/force + * parameters with gup_flags") # v4.4.168. + */ return get_user_pages(current, current->mm, start, nr_pages, gup_flags, - pages, vmas); -} -#define get_user_pages get_user_pages_backport -#elif !defined(CONFIG_SUSE_KERNEL) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) -/* - * See also commit cde70140fed8 ("mm/gup: Overload get_user_pages() functions") - * # v4.6. - */ -static inline long get_user_pages_backport(unsigned long start, - unsigned long nr_pages, - unsigned int gup_flags, - struct page **pages, - struct vm_area_struct **vmas) -{ - const bool write = gup_flags & FOLL_WRITE; - const bool force = 0; - - WARN_ON_ONCE(gup_flags & ~FOLL_WRITE); - return get_user_pages(current, current->mm, start, nr_pages, write, - force, pages, vmas); -} -#define get_user_pages get_user_pages_backport + pages, NULL); #elif (!defined(CONFIG_SUSE_KERNEL) && \ LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)) || \ LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) -/* - * See also commit 768ae309a961 ("mm: replace get_user_pages() write/force - * parameters with gup_flags") # v4.9. - */ -static inline long get_user_pages_backport(unsigned long start, - unsigned long nr_pages, - unsigned int gup_flags, - struct page **pages, - struct vm_area_struct **vmas) -{ const bool write = gup_flags & FOLL_WRITE; const bool force = 0; WARN_ON_ONCE(gup_flags & ~FOLL_WRITE); - return get_user_pages(start, nr_pages, write, force, pages, vmas); +#if !defined(CONFIG_SUSE_KERNEL) && \ + LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) + /* + * See also commit cde70140fed8 ("mm/gup: Overload get_user_pages() functions") + * # v4.6. + */ + return get_user_pages(current, current->mm, start, nr_pages, write, + force, pages, NULL); +#else + /* + * See also commit 768ae309a961 ("mm: replace get_user_pages() write/force + * parameters with gup_flags") # v4.9. + */ + return get_user_pages(start, nr_pages, write, force, pages, NULL); +#endif +#else + /* + * See also commit 54d020692b34 ("mm/gup: remove unused vmas parameter from + * get_user_pages()") # v6.5. + */ + return get_user_pages(start, nr_pages, gup_flags, pages, NULL); +#endif } #define get_user_pages get_user_pages_backport #endif diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index e66a41069..10ace4193 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -1261,12 +1261,12 @@ static int dev_user_map_buf(struct scst_user_cmd *ucmd, unsigned long ubuff, #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0) down_read(&tsk->mm->mmap_sem); rc = get_user_pages(ubuff, ucmd->num_data_pages, FOLL_WRITE, - ucmd->data_pages, NULL); + ucmd->data_pages); up_read(&tsk->mm->mmap_sem); #else mmap_read_lock(tsk->mm); rc = get_user_pages(ubuff, ucmd->num_data_pages, FOLL_WRITE, - ucmd->data_pages, NULL); + ucmd->data_pages); mmap_read_unlock(tsk->mm); #endif From b5294cbf38caef207f5646a6c7db93a8a9153d4c Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 7 Jul 2023 10:27:35 +0300 Subject: [PATCH 25/93] iscsi-scst: Improve write_data() This patch introduces several improvements to the write_data() function: 1. Remove the redundant 'sendpage' function pointer variable. 2. Update variables related to size to use the size_t type for better type correctness and safety. 3. Introduce a new variable, 'parent_req', to store the 'write_cmnd->parent_req' pointer and reduce redundant accesses. 4. Fix several checkpatch warnings. This patch doesn't change any functionality. --- iscsi-scst/kernel/nthread.c | 73 +++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 593d7eeec..f0110729e 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1098,31 +1098,33 @@ static int write_data(struct iscsi_conn *conn) struct file *file; struct kvec *iop; struct socket *sock; - ssize_t (*sock_sendpage)(struct socket *, struct page *, int, size_t, - int); - ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); - struct iscsi_cmnd *write_cmnd = conn->write_cmnd; + ssize_t (*sock_sendpage)(struct socket *sock, struct page *page, + int offset, size_t size, int flags); + struct iscsi_cmnd *write_cmnd, *parent_req; struct iscsi_cmnd *ref_cmd; struct page *page; struct scatterlist *sg; - int saved_size, size, sendsize; - int length, offset, idx; - int flags, res, count, sg_size; + size_t saved_size, size, sg_size; + size_t sendsize, length; + int offset, idx, flags, res = 0, count; bool ref_cmd_to_parent; TRACE_ENTRY(); + write_cmnd = conn->write_cmnd; + parent_req = write_cmnd->parent_req; + iscsi_extracheck_is_wr_thread(conn); if (!write_cmnd->own_sg) { - ref_cmd = write_cmnd->parent_req; + ref_cmd = parent_req; ref_cmd_to_parent = true; } else { ref_cmd = write_cmnd; ref_cmd_to_parent = false; } - req_add_to_write_timeout_list(write_cmnd->parent_req); + req_add_to_write_timeout_list(parent_req); file = conn->file; size = conn->write_size; @@ -1131,7 +1133,7 @@ static int write_data(struct iscsi_conn *conn) count = conn->write_iop_used; if (iop) { - while (1) { + while (true) { loff_t off = 0; int rest; @@ -1181,9 +1183,9 @@ static int write_data(struct iscsi_conn *conn) sock = conn->sock; - if (write_cmnd->parent_req->scst_cmd && - write_cmnd->parent_req->scst_state != ISCSI_CMD_STATE_AEN && - scst_cmd_get_dh_data_buff_alloced(write_cmnd->parent_req->scst_cmd)) + if (parent_req->scst_cmd && + parent_req->scst_state != ISCSI_CMD_STATE_AEN && + scst_cmd_get_dh_data_buff_alloced(parent_req->scst_cmd)) sock_sendpage = sock_no_sendpage; else sock_sendpage = sock->ops->sendpage; @@ -1201,8 +1203,8 @@ static int write_data(struct iscsi_conn *conn) offset = conn->write_offset + sg[0].offset; idx = offset >> PAGE_SHIFT; offset &= ~PAGE_MASK; - length = min(size, (int)PAGE_SIZE - offset); - TRACE_WRITE("write_offset %d, sg_size %d, idx %d, offset %d, length %d", + length = min_t(size_t, size, PAGE_SIZE - offset); + TRACE_WRITE("write_offset %d, sg_size %lu, idx %d, offset %d, length %lu", conn->write_offset, sg_size, idx, offset, length); } else { /* @@ -1218,25 +1220,23 @@ static int write_data(struct iscsi_conn *conn) length = sg[idx].length - offset; offset += sg[idx].offset; sock_sendpage = sock_no_sendpage; - TRACE_WRITE("rsp_sg: write_offset %d, sg_size %d, idx %d, " - "offset %d, length %d", conn->write_offset, sg_size, - idx, offset, length); + TRACE_WRITE("rsp_sg: write_offset %d, sg_size %lu, idx %d, offset %d, length %lu", + conn->write_offset, sg_size, idx, offset, length); } page = sg_page(&sg[idx]); - while (1) { - sendpage = sock_sendpage; - - sendsize = min(size, length); + while (true) { + sendsize = min_t(size_t, size, length); if (size <= sendsize) { retry2: - res = sendpage(sock, page, offset, size, flags); - TRACE_WRITE("Final %s sid %#Lx, cid %u, res %d (page index %lu, offset %u, size %u, cmd %p, page %p)", - (sendpage != sock_no_sendpage) ? - "sendpage" : "sock_no_sendpage", - (unsigned long long)conn->session->sid, - conn->cid, res, page->index, - offset, size, write_cmnd, page); + res = sock_sendpage(sock, page, offset, size, flags); + TRACE_WRITE( + "Final %s sid %#Lx, cid %u, res %d (page index %lu, offset %u, size %lu, cmd %p, page %p)", + (sock_sendpage != sock_no_sendpage) ? + "sendpage" : "sock_no_sendpage", + (unsigned long long)conn->session->sid, + conn->cid, res, page->index, + offset, size, write_cmnd, page); if (unlikely(res <= 0)) { if (res == -EINTR) goto retry2; @@ -1256,13 +1256,14 @@ static int write_data(struct iscsi_conn *conn) } retry1: - res = sendpage(sock, page, offset, sendsize, flags | MSG_MORE); - TRACE_WRITE("%s sid %#Lx, cid %u, res %d (page index %lu, offset %u, sendsize %u, size %u, cmd %p, page %p)", - (sendpage != sock_no_sendpage) ? "sendpage" : - "sock_no_sendpage", - (unsigned long long)conn->session->sid, conn->cid, - res, page->index, offset, sendsize, size, - write_cmnd, page); + res = sock_sendpage(sock, page, offset, sendsize, flags | MSG_MORE); + TRACE_WRITE( + "%s sid %#Lx, cid %u, res %d (page index %lu, offset %u, sendsize %lu, size %lu, cmd %p, page %p)", + (sock_sendpage != sock_no_sendpage) ? + "sendpage" : "sock_no_sendpage", + (unsigned long long)conn->session->sid, conn->cid, + res, page->index, offset, sendsize, size, + write_cmnd, page); if (unlikely(res <= 0)) { if (res == -EINTR) goto retry1; From c1f7510d80ae39992510589a31430ddd7b9f83ac Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 7 Jul 2023 10:38:36 +0300 Subject: [PATCH 26/93] iscsi-scst: Improve 'write iop loop' in write_data() This patch introduces several improvements to the 'write iop loop' in the write_data() function: 1. Move iop-related variables under the scope of the 'write iop loop'. 2. Eliminate the 'retry' label, use 'continue' instead for simplicity. 3. Remove the redundant 'rest' variable, use just 'res' instead. This patch doesn't change any functionality. --- iscsi-scst/kernel/nthread.c | 43 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index f0110729e..2806142ec 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1095,8 +1095,6 @@ void req_add_to_write_timeout_list(struct iscsi_cmnd *req) static int write_data(struct iscsi_conn *conn) { - struct file *file; - struct kvec *iop; struct socket *sock; ssize_t (*sock_sendpage)(struct socket *sock, struct page *page, int offset, size_t size, int flags); @@ -1106,7 +1104,7 @@ static int write_data(struct iscsi_conn *conn) struct scatterlist *sg; size_t saved_size, size, sg_size; size_t sendsize, length; - int offset, idx, flags, res = 0, count; + int offset, idx, flags, res = 0; bool ref_cmd_to_parent; TRACE_ENTRY(); @@ -1126,40 +1124,45 @@ static int write_data(struct iscsi_conn *conn) req_add_to_write_timeout_list(parent_req); - file = conn->file; - size = conn->write_size; - saved_size = size; - iop = conn->write_iop; - count = conn->write_iop_used; + saved_size = size = conn->write_size; + + if (conn->write_iop) { + struct file *file = conn->file; + struct kvec *iop = conn->write_iop; + int count = conn->write_iop_used; + loff_t off; + + sBUG_ON(count > ARRAY_SIZE(conn->write_iov)); - if (iop) { while (true) { - loff_t off = 0; - int rest; + off = 0; - sBUG_ON(count > ARRAY_SIZE(conn->write_iov)); -retry: res = scst_writev(file, iop, count, &off); TRACE_WRITE("sid %#Lx, cid %u, res %d, iov_len %zd", (unsigned long long)conn->session->sid, conn->cid, res, iop->iov_len); + if (unlikely(res <= 0)) { + if (res == -EINTR) + continue; + if (res == -EAGAIN) { conn->write_iop = iop; conn->write_iop_used = count; goto out_iov; - } else if (res == -EINTR) - goto retry; + } + goto out_err; } - rest = res; size -= res; - while ((typeof(rest))iop->iov_len <= rest && rest) { - rest -= iop->iov_len; + + while ((typeof(res))iop->iov_len <= res && res) { + res -= iop->iov_len; iop++; count--; } + if (count == 0) { conn->write_iop = NULL; conn->write_iop_used = 0; @@ -1169,8 +1172,8 @@ static int write_data(struct iscsi_conn *conn) } sBUG_ON(iop > conn->write_iov + ARRAY_SIZE(conn->write_iov)); - iop->iov_base += rest; - iop->iov_len -= rest; + iop->iov_base += res; + iop->iov_len -= res; } } From 324bf62e28189cd52abfcd6a05047452d04dd846 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 6 Jul 2023 20:03:56 +0300 Subject: [PATCH 27/93] iscsi-scst: Refactor sendpage functionality in write_data() This patch carries out a refactoring of the sendpage functionality in the write_data() function: 1. Reorganize the logic used to select the sock_sendpage function. 2. Streamline the data sending loop by reducing conditional branches and eliminating labels. 3. Adjust the error handling for -EINTR and -EAGAIN to make the code cleaner and easier to follow. This patch doesn't change any functionality. --- iscsi-scst/kernel/nthread.c | 98 ++++++++++++++----------------------- 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index 2806142ec..d33534031 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1185,15 +1185,15 @@ static int write_data(struct iscsi_conn *conn) } sock = conn->sock; + flags = MSG_DONTWAIT; - if (parent_req->scst_cmd && - parent_req->scst_state != ISCSI_CMD_STATE_AEN && - scst_cmd_get_dh_data_buff_alloced(parent_req->scst_cmd)) - sock_sendpage = sock_no_sendpage; - else + if (sg != write_cmnd->rsp_sg && + (!parent_req->scst_cmd || parent_req->scst_state == ISCSI_CMD_STATE_AEN || + !scst_cmd_get_dh_data_buff_alloced(parent_req->scst_cmd))) sock_sendpage = sock->ops->sendpage; + else + sock_sendpage = sock_no_sendpage; - flags = MSG_DONTWAIT; sg_size = size; if (sg != write_cmnd->rsp_sg) { @@ -1222,7 +1222,6 @@ static int write_data(struct iscsi_conn *conn) } length = sg[idx].length - offset; offset += sg[idx].offset; - sock_sendpage = sock_no_sendpage; TRACE_WRITE("rsp_sg: write_offset %d, sg_size %lu, idx %d, offset %d, length %lu", conn->write_offset, sg_size, idx, offset, length); } @@ -1230,84 +1229,59 @@ static int write_data(struct iscsi_conn *conn) while (true) { sendsize = min_t(size_t, size, length); - if (size <= sendsize) { -retry2: - res = sock_sendpage(sock, page, offset, size, flags); + + if (sendsize == size) + flags &= ~MSG_MORE; + else + flags |= MSG_MORE; + + while (sendsize) { + res = sock_sendpage(sock, page, offset, sendsize, flags); TRACE_WRITE( - "Final %s sid %#Lx, cid %u, res %d (page index %lu, offset %u, size %lu, cmd %p, page %p)", + "%s sid %#Lx, cid %u, res %d (page index %lu, offset %u, sendsize %lu, size %lu, cmd %p, page %p)", (sock_sendpage != sock_no_sendpage) ? "sendpage" : "sock_no_sendpage", - (unsigned long long)conn->session->sid, - conn->cid, res, page->index, - offset, size, write_cmnd, page); + (unsigned long long)conn->session->sid, conn->cid, + res, page->index, offset, sendsize, size, + write_cmnd, page); + if (unlikely(res <= 0)) { if (res == -EINTR) - goto retry2; - else - goto out_res; - } + continue; + + if (res == -EAGAIN) { + conn->write_offset += sg_size - size; + goto out_iov; + } - if (res == size) { - conn->write_size = 0; - res = saved_size; - goto out; + goto out_err; } offset += res; + sendsize -= res; size -= res; - goto retry2; - } - -retry1: - res = sock_sendpage(sock, page, offset, sendsize, flags | MSG_MORE); - TRACE_WRITE( - "%s sid %#Lx, cid %u, res %d (page index %lu, offset %u, sendsize %lu, size %lu, cmd %p, page %p)", - (sock_sendpage != sock_no_sendpage) ? - "sendpage" : "sock_no_sendpage", - (unsigned long long)conn->session->sid, conn->cid, - res, page->index, offset, sendsize, size, - write_cmnd, page); - if (unlikely(res <= 0)) { - if (res == -EINTR) - goto retry1; - else - goto out_res; } - size -= res; + if (size == 0) + goto out_iov; - if (res == sendsize) { - idx++; - EXTRACHECKS_BUG_ON(idx >= ref_cmd->sg_cnt); - page = sg_page(&sg[idx]); - length = sg[idx].length; - offset = sg[idx].offset; - } else { - offset += res; - sendsize -= res; - goto retry1; - } + idx++; + EXTRACHECKS_BUG_ON(idx >= ref_cmd->sg_cnt); + page = sg_page(&sg[idx]); + length = sg[idx].length; + offset = sg[idx].offset; } -out_off: - conn->write_offset += sg_size - size; - out_iov: conn->write_size = size; - if ((saved_size == size) && res == -EAGAIN) - goto out; - res = saved_size - size; + if (res != -EAGAIN || saved_size != size) + res = saved_size - size; out: TRACE_EXIT_RES(res); return res; -out_res: - if (res == -EAGAIN) - goto out_off; - /* else go through */ - out_err: #ifndef CONFIG_SCST_DEBUG if (!conn->closing) { From 16a17c259bc6c349871c6c60fe5e254301efd72e Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Thu, 6 Jul 2023 20:44:09 +0300 Subject: [PATCH 28/93] iscsi-scst: Port to Linux kernel v6.5 Use sendmsg() conditionally with MSG_SPLICE_PAGES in write_data() rather than calling sendpage(). Support for the following net layer changes in the Linux kernel v6.5: - dc97391e6610 ("sock: Remove ->sendpage*() in favour of sendmsg(MSG_SPLICE_PAGES)") --- iscsi-scst/kernel/conn.c | 9 ++++----- iscsi-scst/kernel/nthread.c | 26 +++++++++++++++++++++----- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/iscsi-scst/kernel/conn.c b/iscsi-scst/kernel/conn.c index 031e6c305..487cf655a 100644 --- a/iscsi-scst/kernel/conn.c +++ b/iscsi-scst/kernel/conn.c @@ -741,7 +741,6 @@ int conn_activate(struct iscsi_conn *conn) static int conn_setup_sock(struct iscsi_conn *conn) { - int res = 0; int opt = 1; mm_segment_t oldfs; struct iscsi_session *session = conn->session; @@ -750,12 +749,13 @@ static int conn_setup_sock(struct iscsi_conn *conn) conn->sock = SOCKET_I(file_inode(conn->file)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) if (conn->sock->ops->sendpage == NULL) { PRINT_ERROR("Socket for sid %llx doesn't support sendpage()", (unsigned long long)session->sid); - res = -EINVAL; - goto out; + return -EINVAL; } +#endif #if 0 conn->sock->sk->sk_allocation = GFP_NOIO; @@ -768,8 +768,7 @@ static int conn_setup_sock(struct iscsi_conn *conn) KERNEL_SOCKPTR(&opt), sizeof(opt)); set_fs(oldfs); -out: - return res; + return 0; } void iscsi_tcp_conn_free(struct iscsi_conn *conn) diff --git a/iscsi-scst/kernel/nthread.c b/iscsi-scst/kernel/nthread.c index d33534031..09a233017 100644 --- a/iscsi-scst/kernel/nthread.c +++ b/iscsi-scst/kernel/nthread.c @@ -1096,8 +1096,13 @@ void req_add_to_write_timeout_list(struct iscsi_cmnd *req) static int write_data(struct iscsi_conn *conn) { struct socket *sock; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) ssize_t (*sock_sendpage)(struct socket *sock, struct page *page, int offset, size_t size, int flags); +#else + struct msghdr msg = {}; + struct bio_vec bvec; +#endif struct iscsi_cmnd *write_cmnd, *parent_req; struct iscsi_cmnd *ref_cmd; struct page *page; @@ -1190,9 +1195,13 @@ static int write_data(struct iscsi_conn *conn) if (sg != write_cmnd->rsp_sg && (!parent_req->scst_cmd || parent_req->scst_state == ISCSI_CMD_STATE_AEN || !scst_cmd_get_dh_data_buff_alloced(parent_req->scst_cmd))) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0) + flags |= MSG_SPLICE_PAGES; +#else sock_sendpage = sock->ops->sendpage; else sock_sendpage = sock_no_sendpage; +#endif sg_size = size; @@ -1236,14 +1245,21 @@ static int write_data(struct iscsi_conn *conn) flags |= MSG_MORE; while (sendsize) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0) res = sock_sendpage(sock, page, offset, sendsize, flags); +#else + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_flags = flags; + + bvec_set_page(&bvec, page, sendsize, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, sendsize); + res = sock_sendmsg(sock, &msg); +#endif TRACE_WRITE( - "%s sid %#Lx, cid %u, res %d (page index %lu, offset %u, sendsize %lu, size %lu, cmd %p, page %p)", - (sock_sendpage != sock_no_sendpage) ? - "sendpage" : "sock_no_sendpage", + "sid %#Lx cid %u: res %d (page[%p] index %lu, offset %u, sendsize %lu, size %lu, cmd %p)", (unsigned long long)conn->session->sid, conn->cid, - res, page->index, offset, sendsize, size, - write_cmnd, page); + res, page, page->index, offset, sendsize, size, + write_cmnd); if (unlikely(res <= 0)) { if (res == -EINTR) From bc9ec6f9e7bcb9697cc1ddc1b3cbd92c42d0d645 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 17:32:40 +0300 Subject: [PATCH 29/93] scst: Replace all strlcpy() with strscpy() strlcpy() reads the entire source buffer first. This read may exceed the destination size limit. This is both inefficient and can lead to linear read overflows if a source string is not NULL-terminated [1]. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy --- iscsi-scst/kernel/target.c | 2 +- qla2x00t-32gbit/qla_init.c | 8 ++++---- qla2x00t-32gbit/qla_mr.c | 20 ++++++++++---------- qla2x00t/qla_gs.c | 8 ++++---- qla2x00t/qla_init.c | 10 +++++----- qla2x00t/qla_nx.c | 2 +- qla2x00t/qla_os.c | 2 +- scst/include/backport.h | 23 +++++++++++++++++++++++ scst/src/dev_handlers/scst_user.c | 6 +++--- scst/src/dev_handlers/scst_vdisk.c | 2 +- scst/src/scst_debug.c | 2 +- scst/src/scst_event.c | 22 +++++++++++----------- scst/src/scst_main.c | 6 +++--- scst/src/scst_mem.c | 2 +- scst/src/scst_tg.c | 26 ++++++++++++-------------- srpt/src/ib_srpt.c | 6 +++--- 16 files changed, 84 insertions(+), 63 deletions(-) diff --git a/iscsi-scst/kernel/target.c b/iscsi-scst/kernel/target.c index 8840d349d..a74ef486d 100644 --- a/iscsi-scst/kernel/target.c +++ b/iscsi-scst/kernel/target.c @@ -89,7 +89,7 @@ static int iscsi_target_create(struct iscsi_kern_target_info *info, u32 tid, target->tid = info->tid = tid; - strlcpy(target->name, name, sizeof(target->name)); + strscpy(target->name, name, sizeof(target->name)); mutex_init(&target->target_mutex); INIT_LIST_HEAD(&target->session_list); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index b86f9af22..6e1ea1f11 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4864,7 +4864,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { @@ -4872,14 +4872,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { - strlcpy(ha->model_number, + strscpy(ha->model_number, qla2x00_model_name[index * 2], sizeof(ha->model_number)); - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { - strlcpy(ha->model_number, def, + strscpy(ha->model_number, def, sizeof(ha->model_number)); } } diff --git a/qla2x00t-32gbit/qla_mr.c b/qla2x00t-32gbit/qla_mr.c index 84c129f40..ba12fdc84 100644 --- a/qla2x00t-32gbit/qla_mr.c +++ b/qla2x00t-32gbit/qla_mr.c @@ -691,7 +691,7 @@ qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len) struct qla_hw_data *ha = vha->hw; if (pci_is_pcie(ha->pdev)) - strlcpy(str, "PCIe iSA", str_len); + strscpy(str, "PCIe iSA", str_len); return str; } @@ -1860,21 +1860,21 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) phost_info = &preg_hsi->hsi; memset(preg_hsi, 0, sizeof(struct register_host_info)); phost_info->os_type = OS_TYPE_LINUX; - strlcpy(phost_info->sysname, p_sysid->sysname, + strscpy(phost_info->sysname, p_sysid->sysname, sizeof(phost_info->sysname)); - strlcpy(phost_info->nodename, p_sysid->nodename, + strscpy(phost_info->nodename, p_sysid->nodename, sizeof(phost_info->nodename)); if (!strcmp(phost_info->nodename, "(none)")) ha->mr.host_info_resend = true; - strlcpy(phost_info->release, p_sysid->release, + strscpy(phost_info->release, p_sysid->release, sizeof(phost_info->release)); - strlcpy(phost_info->version, p_sysid->version, + strscpy(phost_info->version, p_sysid->version, sizeof(phost_info->version)); - strlcpy(phost_info->machine, p_sysid->machine, + strscpy(phost_info->machine, p_sysid->machine, sizeof(phost_info->machine)); - strlcpy(phost_info->domainname, p_sysid->domainname, + strscpy(phost_info->domainname, p_sysid->domainname, sizeof(phost_info->domainname)); - strlcpy(phost_info->hostdriver, QLA2XXX_VERSION, + strscpy(phost_info->hostdriver, QLA2XXX_VERSION, sizeof(phost_info->hostdriver)); preg_hsi->utc = (uint64_t)ktime_get_real_seconds(); ql_dbg(ql_dbg_init, vha, 0x0149, @@ -1919,9 +1919,9 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type) if (fx_type == FXDISC_GET_CONFIG_INFO) { struct config_info_data *pinfo = (struct config_info_data *) fdisc->u.fxiocb.rsp_addr; - strlcpy(vha->hw->model_number, pinfo->model_num, + strscpy(vha->hw->model_number, pinfo->model_num, ARRAY_SIZE(vha->hw->model_number)); - strlcpy(vha->hw->model_desc, pinfo->model_description, + strscpy(vha->hw->model_desc, pinfo->model_description, ARRAY_SIZE(vha->hw->model_desc)); memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name, sizeof(vha->hw->mr.symbolic_name)); diff --git a/qla2x00t/qla_gs.c b/qla2x00t/qla_gs.c index ec763533d..119949fc8 100644 --- a/qla2x00t/qla_gs.c +++ b/qla2x00t/qla_gs.c @@ -1353,7 +1353,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Model name. */ eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter->type = cpu_to_be16(FDMI_HBA_MODEL); - strlcpy(eiter->a.model, ha->model_number, sizeof(eiter->a.model)); + strscpy(eiter->a.model, ha->model_number, sizeof(eiter->a.model)); alen = strlen(eiter->a.model); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); @@ -1365,7 +1365,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Model description. */ eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter->type = cpu_to_be16(FDMI_HBA_MODEL_DESCRIPTION); - strlcpy(eiter->a.model_desc, ha->model_desc, + strscpy(eiter->a.model_desc, ha->model_desc, sizeof(eiter->a.model_desc)); alen = strlen(eiter->a.model_desc); alen += (alen & 3) ? (4 - (alen & 3)) : 4; @@ -1378,7 +1378,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha) /* Hardware version. */ eiter = (struct ct_fdmi_hba_attr *) (entries + size); eiter->type = cpu_to_be16(FDMI_HBA_HARDWARE_VERSION); - strlcpy(eiter->a.hw_version, ha->adapter_id, + strscpy(eiter->a.hw_version, ha->adapter_id, sizeof(eiter->a.hw_version)); alen = strlen(eiter->a.hw_version); alen += (alen & 3) ? (4 - (alen & 3)) : 4; @@ -1654,7 +1654,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha) ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT); eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = cpu_to_be16(FDMI_PORT_HOST_NAME); - strlcpy(eiter->a.host_name, fc_host_system_hostname(vha->host), + strscpy(eiter->a.host_name, fc_host_system_hostname(vha->host), sizeof(eiter->a.host_name)); alen = strlen(eiter->a.host_name); alen += (alen & 3) ? (4 - (alen & 3)) : 4; diff --git a/qla2x00t/qla_init.c b/qla2x00t/qla_init.c index 8b50a71fd..bf91a3107 100644 --- a/qla2x00t/qla_init.c +++ b/qla2x00t/qla_init.c @@ -2162,7 +2162,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha); if (memcmp(model, BINZERO, len) != 0) { - strncpy(ha->model_number, model, len); + memcpy(ha->model_number, model, len); st = en = ha->model_number; en += len - 1; while (en > st) { @@ -2175,7 +2175,7 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { @@ -2183,14 +2183,14 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len, if (use_tbl && ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC && index < QLA_MODEL_NAMES) { - strlcpy(ha->model_number, + strscpy(ha->model_number, qla2x00_model_name[index * 2], sizeof(ha->model_number)); - strlcpy(ha->model_desc, + strscpy(ha->model_desc, qla2x00_model_name[index * 2 + 1], sizeof(ha->model_desc)); } else { - strlcpy(ha->model_number, def, + strscpy(ha->model_number, def, sizeof(ha->model_number)); } } diff --git a/qla2x00t/qla_nx.c b/qla2x00t/qla_nx.c index 780377fe6..4c3d90ca7 100644 --- a/qla2x00t/qla_nx.c +++ b/qla2x00t/qla_nx.c @@ -1599,7 +1599,7 @@ qla82xx_pci_info_str(struct scsi_qla_host *vha, char *str, int str_len) pci_read_config_word(ha->pdev, pcie_reg + PCI_EXP_LNKSTA, &lnk); ha->link_width = (lnk >> 4) & 0x3f; - strlcpy(str, "PCIe (", str_len); + strscpy(str, "PCIe (", str_len); strncat(str, "2.5Gb/s ", str_len - (strlen(str)+1)); snprintf(lwstr, sizeof(lwstr), "x%d)", ha->link_width); strncat(str, lwstr, str_len - (strlen(str)+1)); diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index 4ffa2f6cd..0c3c70a0a 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -494,7 +494,7 @@ qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, int str_len) }; uint16_t pci_bus; - strlcpy(str, "PCI", str_len); + strscpy(str, "PCI", str_len); pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9; if (pci_bus) { strncat(str, "-X (", str_len - (strlen(str)+1)); diff --git a/scst/include/backport.h b/scst/include/backport.h index 709a88f1b..619ef7082 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -1322,6 +1322,29 @@ static inline void *memdup_user_nul(const void __user *src, size_t len) } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) && \ + (LINUX_VERSION_CODE >> 8 != KERNEL_VERSION(3, 16, 0) >> 8 || \ + LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 60)) && \ + (LINUX_VERSION_CODE >> 8 != KERNEL_VERSION(3, 18, 0) >> 8 || \ + LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 64)) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(7, 7)) +/* + * See also commit 30035e45753b ("string: provide strscpy()") # v4.3, v3.16.60, v3.18.64. + */ +static inline ssize_t strscpy(char *dest, const char *src, size_t count) +{ + size_t ret; + + if (count == 0) + return -E2BIG; + + ret = strlcpy(dest, src, count); + + return ret >= count ? -E2BIG : ret; +} +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) && \ diff --git a/scst/src/dev_handlers/scst_user.c b/scst/src/dev_handlers/scst_user.c index 10ace4193..6f579b865 100644 --- a/scst/src/dev_handlers/scst_user.c +++ b/scst/src/dev_handlers/scst_user.c @@ -3119,10 +3119,10 @@ static int dev_user_attach_tgt(struct scst_tgt_dev *tgt_dev) if (tgtt->get_scsi_transport_version != NULL) ucmd->user_cmd.sess.scsi_transport_version = tgtt->get_scsi_transport_version(tgt); - strlcpy(ucmd->user_cmd.sess.initiator_name, + strscpy(ucmd->user_cmd.sess.initiator_name, tgt_dev->sess->initiator_name, sizeof(ucmd->user_cmd.sess.initiator_name)-1); - strlcpy(ucmd->user_cmd.sess.target_name, + strscpy(ucmd->user_cmd.sess.target_name, tgt_dev->sess->tgt->tgt_name, sizeof(ucmd->user_cmd.sess.target_name)-1); @@ -3369,7 +3369,7 @@ static int dev_user_register_dev(struct file *file, scst_init_threads(&dev->udev_cmd_threads); - strlcpy(dev->name, dev_desc->name, sizeof(dev->name)-1); + strscpy(dev->name, dev_desc->name, sizeof(dev->name)-1); scst_init_mem_lim(&dev->udev_mem_lim); diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index cf6907cc2..262e9c1eb 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -9366,7 +9366,7 @@ static ssize_t vdev_sysfs_bind_alua_state_store(struct kobject *kobj, dev = container_of(kobj, struct scst_device, dev_kobj); virt_dev = dev->dh_priv; - strlcpy(ch, buf, 16); + strscpy(ch, buf, 16); res = kstrtoul(ch, 0, &bind_alua_state); if (res < 0) goto out; diff --git a/scst/src/scst_debug.c b/scst/src/scst_debug.c index d211eb87e..a76a1bb24 100644 --- a/scst/src/scst_debug.c +++ b/scst/src/scst_debug.c @@ -67,7 +67,7 @@ int debug_print_with_prefix(unsigned long trace_flag, const char *severity, spin_lock_irqsave(&trace_buf_lock, flags); - strlcpy(trace_buf, severity, TRACE_BUF_SIZE); + strscpy(trace_buf, severity, TRACE_BUF_SIZE); i = strlen(trace_buf); if (trace_flag & TRACE_PID) diff --git a/scst/src/scst_event.c b/scst/src/scst_event.c index 593548ec1..7221008b4 100644 --- a/scst/src/scst_event.c +++ b/scst/src/scst_event.c @@ -278,7 +278,7 @@ void scst_event_queue(uint32_t event_code, const char *issuer_name, TRACE_DBG("Scheduling event entry %p", e); e->event.event_code = event_code; - strlcpy(e->event.issuer_name, issuer_name, sizeof(e->event.issuer_name)); + strscpy(e->event.issuer_name, issuer_name, sizeof(e->event.issuer_name)); queue_work(scst_event_wq, &e->scst_event_queue_work); @@ -317,9 +317,9 @@ int scst_event_queue_lun_not_found(const struct scst_cmd *cmd) payload = (struct scst_event_lun_not_found_payload *)event->payload; payload->lun = cmd->lun; - strlcpy(payload->initiator_name, cmd->sess->initiator_name, + strscpy(payload->initiator_name, cmd->sess->initiator_name, sizeof(payload->initiator_name)); - strlcpy(payload->target_name, cmd->tgt->tgt_name, + strscpy(payload->target_name, cmd->tgt->tgt_name, sizeof(payload->target_name)); scst_event_queue(SCST_EVENT_LUN_NOT_FOUND, @@ -358,9 +358,9 @@ int scst_event_queue_negative_luns_inquiry(const struct scst_tgt *tgt, event->payload_len = sizeof(*payload); payload = (struct scst_event_negative_luns_inquiry_payload *)event->payload; - strlcpy(payload->initiator_name, initiator_name, + strscpy(payload->initiator_name, initiator_name, sizeof(payload->initiator_name)); - strlcpy(payload->target_name, tgt->tgt_name, + strscpy(payload->target_name, tgt->tgt_name, sizeof(payload->target_name)); scst_event_queue(SCST_EVENT_NEGATIVE_LUNS_INQUIRY, @@ -399,7 +399,7 @@ int scst_event_queue_ext_blocking_done(struct scst_device *dev, void *data, int event->payload_len = sizeof(*payload) + len; payload = (struct scst_event_ext_blocking_done_payload *)event->payload; - strlcpy(payload->device_name, dev->virt_name, sizeof(payload->device_name)); + strscpy(payload->device_name, dev->virt_name, sizeof(payload->device_name)); if (len > 0) memcpy(payload->data, data, len); @@ -442,13 +442,13 @@ int scst_event_queue_tm_fn_received(struct scst_mgmt_cmd *mcmd) payload->fn = mcmd->fn; payload->lun = mcmd->lun; if (mcmd->mcmd_tgt_dev != NULL) - strlcpy(payload->device_name, mcmd->mcmd_tgt_dev->dev->virt_name, + strscpy(payload->device_name, mcmd->mcmd_tgt_dev->dev->virt_name, sizeof(payload->device_name)); - strlcpy(payload->initiator_name, mcmd->sess->initiator_name, + strscpy(payload->initiator_name, mcmd->sess->initiator_name, sizeof(payload->initiator_name)); - strlcpy(payload->target_name, mcmd->sess->tgt->tgt_name, + strscpy(payload->target_name, mcmd->sess->tgt->tgt_name, sizeof(payload->target_name)); - strlcpy(payload->session_sysfs_name, mcmd->sess->sess_name, + strscpy(payload->session_sysfs_name, mcmd->sess->sess_name, sizeof(payload->session_sysfs_name)); if (mcmd->cmd_to_abort != NULL) { payload->cmd_to_abort_tag = mcmd->cmd_to_abort->tag; @@ -493,7 +493,7 @@ int scst_event_queue_reg_vdev(const char *dev_name) event->payload_len = sizeof(*payload); payload = (struct scst_event_reg_vdev_payload *)event->payload; - strlcpy(payload->device_name, dev_name, + strscpy(payload->device_name, dev_name, sizeof(payload->device_name)); scst_event_queue(SCST_EVENT_REG_VIRT_DEV, diff --git a/scst/src/scst_main.c b/scst/src/scst_main.c index 3462a3780..5ca545f4e 100644 --- a/scst/src/scst_main.c +++ b/scst/src/scst_main.c @@ -625,7 +625,7 @@ char *scst_get_cmd_state_name(char *name, int len, unsigned int state) { if (state < ARRAY_SIZE(scst_cmd_state_name) && scst_cmd_state_name[state]) - strlcpy(name, scst_cmd_state_name[state], len); + strscpy(name, scst_cmd_state_name[state], len); else snprintf(name, len, "%d", state); return name; @@ -703,7 +703,7 @@ static const char *const scst_tm_fn_name[] = { char *scst_get_tm_fn_name(char *name, int len, unsigned int fn) { if (fn < ARRAY_SIZE(scst_tm_fn_name) && scst_tm_fn_name[fn]) - strlcpy(name, scst_tm_fn_name[fn], len); + strscpy(name, scst_tm_fn_name[fn], len); else snprintf(name, len, "%d", fn); return name; @@ -723,7 +723,7 @@ char *scst_get_mcmd_state_name(char *name, int len, unsigned int state) { if (state < ARRAY_SIZE(scst_mcmd_state_name) && scst_mcmd_state_name[state]) - strlcpy(name, scst_mcmd_state_name[state], len); + strscpy(name, scst_mcmd_state_name[state], len); else snprintf(name, len, "%d", state); return name; diff --git a/scst/src/scst_mem.c b/scst/src/scst_mem.c index fb438b505..af5cd48cd 100644 --- a/scst/src/scst_mem.c +++ b/scst/src/scst_mem.c @@ -1412,7 +1412,7 @@ static int sgv_pool_init(struct sgv_pool *pool, const char *name, name, sizeof(struct sgv_pool_obj), clustering_type, single_alloc_pages, pool->max_caches, pool->max_cached_pages); - strlcpy(pool->name, name, sizeof(pool->name)-1); + strscpy(pool->name, name, sizeof(pool->name)-1); pool->owner_mm = current->mm; diff --git a/scst/src/scst_tg.c b/scst/src/scst_tg.c index d03dda1d9..0b8c72b4f 100644 --- a/scst/src/scst_tg.c +++ b/scst/src/scst_tg.c @@ -1739,9 +1739,8 @@ static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg, res = 1; - if (strlcpy(payload->device_name, dev->virt_name, - sizeof(payload->device_name)) >= - sizeof(payload->device_name)) { + if (strscpy(payload->device_name, dev->virt_name, + sizeof(payload->device_name)) < 0) { PRINT_ERROR("Device name %s too long", dev->virt_name); goto out_too_long; } @@ -1752,19 +1751,18 @@ static int scst_emit_stpg_event(struct scst_cmd *cmd, struct scst_dev_group *dg, if (osi[j].prev_state == osi[j].new_state) continue; - if (strlcpy(descr->prev_state, + if (strscpy(descr->prev_state, scst_alua_state_name(osi[j].prev_state), - sizeof(descr->prev_state)) >= - sizeof(descr->prev_state) || - strlcpy(descr->new_state, + sizeof(descr->prev_state)) < 0 || + strscpy(descr->new_state, scst_alua_state_name(osi[j].new_state), - sizeof(descr->new_state)) >= - sizeof(descr->new_state) || - strlcpy(descr->dg_name, dg->name, sizeof(descr->dg_name)) - >= sizeof(descr->dg_name) || - strlcpy(descr->tg_name, osi[j].tg->name, - sizeof(descr->tg_name)) >= - sizeof(descr->tg_name)) + sizeof(descr->new_state)) < 0 || + strscpy(descr->dg_name, + dg->name, + sizeof(descr->dg_name)) < 0 || + strscpy(descr->tg_name, + osi[j].tg->name, + sizeof(descr->tg_name)) < 0) goto out_too_long; descr->group_id = osi[j].group_id; diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 8cfac94f8..751b7f68f 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -451,7 +451,7 @@ static void srpt_get_ioc(struct srpt_port *sport, u32 slot, memset(iocp, 0, sizeof(*iocp)); mutex_lock(&sport->mutex); - strlcpy(iocp->id_string, sport->port_id, sizeof(iocp->id_string)); + strscpy(iocp->id_string, sport->port_id, sizeof(iocp->id_string)); mutex_unlock(&sport->mutex); iocp->guid = cpu_to_be64(srpt_service_guid); iocp->vendor_id = cpu_to_be32(sdev->dev_attr.vendor_id); @@ -2707,7 +2707,7 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev, goto free_recv_ring; } - strlcpy(ch->sess_name, src_addr, sizeof(ch->sess_name)); + strscpy(ch->sess_name, src_addr, sizeof(ch->sess_name)); pr_debug("registering session %s\n", ch->sess_name); BUG_ON(!sport->scst_tgt); @@ -4258,7 +4258,7 @@ static void srpt_init_sport(struct srpt_port *sport, struct ib_device *ib_dev) INIT_LIST_HEAD(&sport->nexus_list); init_waitqueue_head(&sport->ch_releaseQ); mutex_init(&sport->mutex); - strlcpy(sport->port_id, DEFAULT_SRPT_ID_STRING, + strscpy(sport->port_id, DEFAULT_SRPT_ID_STRING, sizeof(sport->port_id)); for (i = 0; i < ib_dev->num_comp_vectors; i++) cpumask_set_cpu(i, &sport->comp_v_mask); From 606430be2967e8b4024d0062a62ce76a898222c5 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 19:48:34 +0300 Subject: [PATCH 30/93] scst/include/backport.h: Improve the RHEL 9.2 backport This was detected by smatch. --- scst/include/backport.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index 619ef7082..80683bc64 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -177,7 +177,9 @@ enum { }; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 2)) /* * See also commit 342a72a33407 ("block: Introduce the type blk_opf_t") # v6.0 */ From 9ff415d4077be8702367441cc634c8977610404b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:26:29 +0300 Subject: [PATCH 31/93] qla2x00t-32gbit: Multi-que support for TMF Add queue flush for task management command, before placing it on the wire. Do IO flush for all Request Q's. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202304271702.GpIL391S-lkp@intel.com/ Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-2-njavali@marvell.com Reviewed-by: Himanshu Madhani > Signed-off-by: Martin K. Petersen [ commit d90171dd0da5 upstream ] --- qla2x00t-32gbit/qla_def.h | 8 +++++ qla2x00t-32gbit/qla_gbl.h | 2 +- qla2x00t-32gbit/qla_init.c | 69 +++++++++++++++++++++++++++++--------- qla2x00t-32gbit/qla_iocb.c | 5 +-- 4 files changed, 66 insertions(+), 18 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index d4f7c4dea..9e21fbe60 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -508,6 +508,14 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) return res; } +struct tmf_arg { + struct qla_qpair *qpair; + struct fc_port *fcport; + struct scsi_qla_host *vha; + u64 lun; + u32 flags; +}; + struct els_logo_payload { uint8_t opcode; uint8_t rsvd[3]; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 82701c436..d397c983e 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_prlo(struct scsi_qla_host *, fc_port_t *); extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *, uint16_t *); -extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t); +extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t); struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *, enum qla_work_type); extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 6e1ea1f11..7b9af553f 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2020,17 +2020,19 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res) complete(&tmf->u.tmf.comp); } -int -qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, - uint32_t tag) +static int +__qla2x00_async_tm_cmd(struct tmf_arg *arg) { - struct scsi_qla_host *vha = fcport->vha; + struct scsi_qla_host *vha = arg->vha; struct srb_iocb *tm_iocb; srb_t *sp; + unsigned long flags; int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + /* ref: INIT */ - sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) goto done; @@ -2043,15 +2045,15 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, tm_iocb = &sp->u.iocb_cmd; init_completion(&tm_iocb->u.tmf.comp); - tm_iocb->u.tmf.flags = flags; - tm_iocb->u.tmf.lun = lun; + tm_iocb->u.tmf.flags = arg->flags; + tm_iocb->u.tmf.lun = arg->lun; + rval = qla2x00_start_sp(sp); ql_dbg(ql_dbg_taskm, vha, 0x802f, - "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x.\n", + "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n", sp->handle, fcport->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa); + fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags); - rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) goto done_free_sp; wait_for_completion(&tm_iocb->u.tmf.comp); @@ -2065,12 +2067,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { flags = tm_iocb->u.tmf.flags; - lun = (uint16_t)tm_iocb->u.tmf.lun; + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET| + TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) + flags = MK_SYNC_ID_LUN; + else + flags = MK_SYNC_ID; - /* Issue Marker IOCB */ - qla2x00_marker(vha, vha->hw->base_qpair, - fcport->loop_id, lun, - flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID); + qla2x00_marker(vha, sp->qpair, + sp->fcport->loop_id, arg->lun, flags); } done_free_sp: @@ -2080,6 +2084,41 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, return rval; } +int +qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, + uint32_t tag) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_qpair *qpair; + struct tmf_arg a; + struct completion comp; + int i, rval; + + init_completion(&comp); + a.vha = fcport->vha; + a.fcport = fcport; + a.lun = lun; + + if (vha->hw->mqenable) { + for (i = 0; i < vha->hw->num_qpairs; i++) { + qpair = vha->hw->queue_pair_map[i]; + if (!qpair) + continue; + a.qpair = qpair; + a.flags = flags|TCF_NOTMCMD_TO_TARGET; + rval = __qla2x00_async_tm_cmd(&a); + if (rval) + break; + } + } + + a.qpair = vha->hw->base_qpair; + a.flags = flags; + rval = __qla2x00_async_tm_cmd(&a); + + return rval; +} + int qla24xx_async_abort_command(srb_t *sp) { diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index b007ba435..68b724dd9 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -2557,7 +2557,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; struct srb_iocb *iocb = &sp->u.iocb_cmd; - struct req_que *req = vha->req; + struct req_que *req = sp->qpair->req; flags = iocb->u.tmf.flags; lun = iocb->u.tmf.lun; @@ -2573,7 +2573,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->port_id[2] = fcport->d_id.b.domain; tsk->vp_index = fcport->vha->vp_idx; - if (flags == TCF_LUN_RESET) { + if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET| + TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { int_to_scsilun(lun, &tsk->lun); host_to_fcp_swap((uint8_t *)&tsk->lun, sizeof(tsk->lun)); From 3f90ea13219c67a75bed48abafa22ddf9d51cf5b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:27:30 +0300 Subject: [PATCH 32/93] qla2x00t-32gbit: Fix task management cmd failure Task management cmd failed with status 30h which means FW is not able to finish processing one task management before another task management for the same lun. Hence add wait for completion of marker to space it out. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202304271802.uCZfwQC1-lkp@intel.com/ Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-3-njavali@marvell.com Reviewed-by: Himanshu Madhani > Signed-off-by: Martin K. Petersen [ commit 9803fb5d2759 upstream ] --- qla2x00t-32gbit/qla_def.h | 6 +++ qla2x00t-32gbit/qla_init.c | 102 +++++++++++++++++++++++++++++++------ qla2x00t-32gbit/qla_iocb.c | 28 ++++++++-- qla2x00t-32gbit/qla_isr.c | 26 ++++++++-- 4 files changed, 139 insertions(+), 23 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 9e21fbe60..2717f6ff6 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -514,6 +514,7 @@ struct tmf_arg { struct scsi_qla_host *vha; u64 lun; u32 flags; + uint8_t modifier; }; struct els_logo_payload { @@ -595,6 +596,10 @@ struct srb_iocb { uint32_t data; struct completion comp; __le16 comp_status; + + uint8_t modifier; + uint8_t vp_index; + uint16_t loop_id; } tmf; struct { #define SRB_FXDISC_REQ_DMA_VALID BIT_0 @@ -698,6 +703,7 @@ struct srb_iocb { #define SRB_SA_UPDATE 25 #define SRB_ELS_CMD_HST_NOLOGIN 26 #define SRB_SA_REPLACE 27 +#define SRB_MARKER 28 struct qla_els_pt_arg { u8 els_opcode; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 7b9af553f..1339077df 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2013,6 +2013,80 @@ qla2x00_tmf_iocb_timeout(void *data) } } +static void qla_marker_sp_done(srb_t *sp, int res) +{ + struct srb_iocb *tmf = &sp->u.iocb_cmd; + + if (res != QLA_SUCCESS) + ql_dbg(ql_dbg_taskm, sp->vha, 0x8004, + "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n", + sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, + sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); + + complete(&tmf->u.tmf.comp); +} + +#define START_SP_W_RETRIES(_sp, _rval) \ +{\ + int cnt = 5; \ + do { \ + _rval = qla2x00_start_sp(_sp); \ + if (_rval == EAGAIN) \ + msleep(1); \ + else \ + break; \ + cnt--; \ + } while (cnt); \ +} + +static int +qla26xx_marker(struct tmf_arg *arg) +{ + struct scsi_qla_host *vha = arg->vha; + struct srb_iocb *tm_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; + fc_port_t *fcport = arg->fcport; + + /* ref: INIT */ + sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); + if (!sp) + goto done; + + sp->type = SRB_MARKER; + sp->name = "marker"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done); + sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout; + + tm_iocb = &sp->u.iocb_cmd; + init_completion(&tm_iocb->u.tmf.comp); + tm_iocb->u.tmf.modifier = arg->modifier; + tm_iocb->u.tmf.lun = arg->lun; + tm_iocb->u.tmf.loop_id = fcport->loop_id; + tm_iocb->u.tmf.vp_index = vha->vp_idx; + + START_SP_W_RETRIES(sp, rval); + + ql_dbg(ql_dbg_taskm, vha, 0x8006, + "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8031, + "Marker IOCB failed (%x).\n", rval); + goto done_free_sp; + } + + wait_for_completion(&tm_iocb->u.tmf.comp); + +done_free_sp: + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); +done: + return rval; +} + static void qla2x00_tmf_sp_done(srb_t *sp, int res) { struct srb_iocb *tmf = &sp->u.iocb_cmd; @@ -2026,7 +2100,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) struct scsi_qla_host *vha = arg->vha; struct srb_iocb *tm_iocb; srb_t *sp; - unsigned long flags; int rval = QLA_FUNCTION_FAILED; fc_port_t *fcport = arg->fcport; @@ -2048,11 +2121,12 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) tm_iocb->u.tmf.flags = arg->flags; tm_iocb->u.tmf.lun = arg->lun; - rval = qla2x00_start_sp(sp); + START_SP_W_RETRIES(sp, rval); + ql_dbg(ql_dbg_taskm, vha, 0x802f, - "Async-tmf hdl=%x loop-id=%x portid=%02x%02x%02x ctrl=%x.\n", - sp->handle, fcport->loop_id, fcport->d_id.b.domain, - fcport->d_id.b.area, fcport->d_id.b.al_pa, arg->flags); + "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->flags, arg->lun, sp->qpair->id, rval); if (rval != QLA_SUCCESS) goto done_free_sp; @@ -2065,17 +2139,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) "TM IOCB failed (%x).\n", rval); } - if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { - flags = tm_iocb->u.tmf.flags; - if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET| - TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) - flags = MK_SYNC_ID_LUN; - else - flags = MK_SYNC_ID; - - qla2x00_marker(vha, sp->qpair, - sp->fcport->loop_id, arg->lun, flags); - } + if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) + rval = qla26xx_marker(arg); done_free_sp: /* ref: INIT */ @@ -2099,6 +2164,11 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, a.fcport = fcport; a.lun = lun; + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) + a.modifier = MK_SYNC_ID_LUN; + else + a.modifier = MK_SYNC_ID; + if (vha->hw->mqenable) { for (i = 0; i < vha->hw->num_qpairs; i++) { qpair = vha->hw->queue_pair_map[i]; diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 68b724dd9..2742d370d 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -528,21 +528,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, return (QLA_FUNCTION_FAILED); } + mrk24 = (struct mrk_entry_24xx *)mrk; + mrk->entry_type = MARKER_TYPE; mrk->modifier = type; if (type != MK_SYNC_ALL) { if (IS_FWI2_CAPABLE(ha)) { - mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); } } + + if (IS_FWI2_CAPABLE(ha)) + mrk24->handle = QLA_SKIP_HANDLE; + wmb(); qla2x00_start_iocbs(vha, req); @@ -3869,9 +3873,9 @@ static int qla_get_iocbs_resource(struct srb *sp) case SRB_NACK_LOGO: case SRB_LOGOUT_CMD: case SRB_CTRL_VP: - push_it_through = true; - fallthrough; + case SRB_MARKER: default: + push_it_through = true; get_exch = false; } @@ -3887,6 +3891,19 @@ static int qla_get_iocbs_resource(struct srb *sp) return qla_get_fw_resources(sp->qpair, &sp->iores); } +static void +qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) +{ + mrk->entry_type = MARKER_TYPE; + mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; + if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) { + mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id); + int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); + host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); + mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index; + } +} + int qla2x00_start_sp(srb_t *sp) { @@ -3990,6 +4007,9 @@ qla2x00_start_sp(srb_t *sp) case SRB_SA_REPLACE: qla24xx_sa_replace_iocb(sp, pkt); break; + case SRB_MARKER: + qla_marker_iocb(sp, pkt); + break; default: break; } diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 646a4ebe8..70a8edd42 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -3773,6 +3773,28 @@ static int qla_chk_cont_iocb_avail(struct scsi_qla_host *vha, return rc; } +static void qla_marker_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, + struct mrk_entry_24xx *pkt) +{ + const char func[] = "MRK-IOCB"; + srb_t *sp; + int res = QLA_SUCCESS; + + if (!IS_FWI2_CAPABLE(vha->hw)) + return; + + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); + if (!sp) + return; + + if (pkt->entry_status) { + ql_dbg(ql_dbg_taskm, vha, 0x8025, "marker failure.\n"); + res = QLA_COMMAND_ERROR; + } + sp->u.iocb_cmd.u.tmf.data = res; + sp->done(sp, res); +} + /** * qla24xx_process_response_queue() - Process response queue entries. * @vha: SCSI driver HA context @@ -3889,9 +3911,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, (struct nack_to_isp *)pkt); break; case MARKER_TYPE: - /* Do nothing in this case, this check is to prevent it - * from falling into default case - */ + qla_marker_iocb_entry(vha, rsp->req, (struct mrk_entry_24xx *)pkt); break; case ABORT_IOCB_TYPE: qla24xx_abort_iocb_entry(vha, rsp->req, From 4b813bf125242b6da4e67620fc871e3a449cd8b2 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:28:55 +0300 Subject: [PATCH 33/93] qla2x00t-32gbit: Fix task management cmd fail due to unavailable resource Task management command failed with status 2Ch which is a result of too many task management commands sent to the same target. Hence limit task management commands to 8 per target. Reported-by: kernel test robot Link: https://lore.kernel.org/oe-kbuild-all/202304271952.NKNmoFzv-lkp@intel.com/ Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 6a87679626b5 upstream ] --- qla2x00t-32gbit/qla_def.h | 3 ++ qla2x00t-32gbit/qla_init.c | 63 +++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 2717f6ff6..01c84e203 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -2593,6 +2593,7 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; + struct list_head tmf_pending; unsigned int conf_compl_supported:1; unsigned int deleted:2; @@ -2613,6 +2614,8 @@ typedef struct fc_port { unsigned int do_prli_nvme:1; uint8_t nvme_flag; + uint8_t active_tmf; +#define MAX_ACTIVE_TMF 8 uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 1339077df..dc17acdd9 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2149,6 +2149,54 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) return rval; } +static void qla_put_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + fcport->active_tmf--; + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); +} + +static +int qla_get_tmf(fc_port_t *fcport) +{ + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + int rc = 0; + LIST_HEAD(tmf_elem); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + list_add_tail(&tmf_elem, &fcport->tmf_pending); + + while (fcport->active_tmf >= MAX_ACTIVE_TMF) { + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + msleep(1); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + if (fcport->deleted) { + rc = EIO; + break; + } + if (fcport->active_tmf < MAX_ACTIVE_TMF && + list_is_first(&tmf_elem, &fcport->tmf_pending)) + break; + } + + list_del(&tmf_elem); + + if (!rc) + fcport->active_tmf++; + + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + return rc; +} + int qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, uint32_t tag) @@ -2156,18 +2204,19 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, struct scsi_qla_host *vha = fcport->vha; struct qla_qpair *qpair; struct tmf_arg a; - struct completion comp; int i, rval; - init_completion(&comp); a.vha = fcport->vha; a.fcport = fcport; a.lun = lun; - - if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { a.modifier = MK_SYNC_ID_LUN; - else + + if (qla_get_tmf(fcport)) + return QLA_FUNCTION_FAILED; + } else { a.modifier = MK_SYNC_ID; + } if (vha->hw->mqenable) { for (i = 0; i < vha->hw->num_qpairs; i++) { @@ -2186,6 +2235,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, a.flags = flags; rval = __qla2x00_async_tm_cmd(&a); + if (a.modifier == MK_SYNC_ID_LUN) + qla_put_tmf(fcport); + return rval; } @@ -5403,6 +5455,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); + INIT_LIST_HEAD(&fcport->tmf_pending); INIT_LIST_HEAD(&fcport->sess_cmd_list); spin_lock_init(&fcport->sess_cmd_lock); From 7a1d0ddaf53e3b7d709c17140302e1e139185f2c Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 13:55:19 +0300 Subject: [PATCH 34/93] qla2x00t-32gbit: Backport to older kernel versions Unbreak the build for the previous commit against kernel versions before v5.1. --- scst/include/backport.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scst/include/backport.h b/scst/include/backport.h index 80683bc64..4e693aeab 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -687,6 +687,19 @@ static inline bool list_entry_in_list(const struct list_head *entry) return !list_empty(entry); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(8, 1)) +/* + * See also commit 70b44595eafe ("mm, compaction: use free lists to quickly + * locate a migration source") # v5.1. + */ +static inline int list_is_first(const struct list_head *list, const struct list_head *head) +{ + return list->prev == head; +} +#endif + /* */ /* From 7db9f41baecd437c169cb0c81b299e1bc23146a7 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:29:23 +0300 Subject: [PATCH 35/93] qla2x00t-32gbit: Fix hang in task management Task management command hangs where a side band chip reset failed to nudge the TMF from it's current send path. Add additional error check to block TMF from entering during chip reset and along the TMF path to cause it to bail out, skip over abort of marker. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-5-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 9ae615c5bfd3 upstream ] --- qla2x00t-32gbit/qla_def.h | 4 +++ qla2x00t-32gbit/qla_init.c | 60 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 01c84e203..433d9a801 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -5568,4 +5568,8 @@ struct ql_vnd_tgt_stats_resp { _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ _fp->flags +#define TMF_NOT_READY(_fcport) \ + (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \ + !_fcport->vha->hw->flags.fw_started) + #endif diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index dc17acdd9..69719b6e8 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data) int rc, h; unsigned long flags; + if (sp->type == SRB_MARKER) { + complete(&tmf->u.tmf.comp); + return; + } + rc = qla24xx_async_abort_cmd(sp, false); if (rc) { spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags); @@ -2023,6 +2028,7 @@ static void qla_marker_sp_done(srb_t *sp, int res) sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags, sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id); + sp->u.iocb_cmd.u.tmf.data = res; complete(&tmf->u.tmf.comp); } @@ -2039,6 +2045,11 @@ static void qla_marker_sp_done(srb_t *sp, int res) } while (cnt); \ } +/** + * qla26xx_marker: send marker IOCB and wait for the completion of it. + * @arg: pointer to argument list. + * It is assume caller will provide an fcport pointer and modifier + */ static int qla26xx_marker(struct tmf_arg *arg) { @@ -2048,6 +2059,14 @@ qla26xx_marker(struct tmf_arg *arg) int rval = QLA_FUNCTION_FAILED; fc_port_t *fcport = arg->fcport; + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8039, + "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + /* ref: INIT */ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) @@ -2074,11 +2093,19 @@ qla26xx_marker(struct tmf_arg *arg) if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x8031, - "Marker IOCB failed (%x).\n", rval); + "Marker IOCB send failure (%x).\n", rval); goto done_free_sp; } wait_for_completion(&tm_iocb->u.tmf.comp); + rval = tm_iocb->u.tmf.data; + + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8019, + "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", + sp->handle, fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, sp->qpair->id, rval); + } done_free_sp: /* ref: INIT */ @@ -2091,6 +2118,8 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res) { struct srb_iocb *tmf = &sp->u.iocb_cmd; + if (res) + tmf->u.tmf.data = res; complete(&tmf->u.tmf.comp); } @@ -2104,6 +2133,14 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) fc_port_t *fcport = arg->fcport; + if (TMF_NOT_READY(arg->fcport)) { + ql_dbg(ql_dbg_taskm, vha, 0x8032, + "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n", + fcport->loop_id, fcport->d_id.b24, + arg->modifier, arg->lun, arg->qpair->id); + return QLA_SUSPENDED; + } + /* ref: INIT */ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) @@ -2178,7 +2215,9 @@ int qla_get_tmf(fc_port_t *fcport) msleep(1); spin_lock_irqsave(&ha->tgt.sess_lock, flags); - if (fcport->deleted) { + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x802c, + "Unable to acquire TM resource due to disruption.\n"); rc = EIO; break; } @@ -2204,7 +2243,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, struct scsi_qla_host *vha = fcport->vha; struct qla_qpair *qpair; struct tmf_arg a; - int i, rval; + int i, rval = QLA_SUCCESS; + + if (TMF_NOT_READY(fcport)) + return QLA_SUSPENDED; a.vha = fcport->vha; a.fcport = fcport; @@ -2223,6 +2265,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, qpair = vha->hw->queue_pair_map[i]; if (!qpair) continue; + + if (TMF_NOT_READY(fcport)) { + ql_log(ql_log_warn, vha, 0x8026, + "Unable to send TM due to disruption.\n"); + rval = QLA_SUSPENDED; + break; + } + a.qpair = qpair; a.flags = flags|TCF_NOTMCMD_TO_TARGET; rval = __qla2x00_async_tm_cmd(&a); @@ -2231,10 +2281,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, } } + if (rval) + goto bailout; + a.qpair = vha->hw->base_qpair; a.flags = flags; rval = __qla2x00_async_tm_cmd(&a); +bailout: if (a.modifier == MK_SYNC_ID_LUN) qla_put_tmf(fcport); From 284f4446e18600e59dc93aefbe948b74dd85eac4 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:29:39 +0300 Subject: [PATCH 36/93] qla2x00t-32gbit: Fix mem access after free System crash, where driver is accessing scsi layer's memory (scsi_cmnd->device->host) to search for a well known internal pointer (vha). The scsi_cmnd was released back to upper layer which could be freed, but the driver is still accessing it. 7 [ffffa8e8d2c3f8d0] page_fault at ffffffff86c010fe [exception RIP: __qla2x00_eh_wait_for_pending_commands+240] RIP: ffffffffc0642350 RSP: ffffa8e8d2c3f988 RFLAGS: 00010286 RAX: 0000000000000165 RBX: 0000000000000002 RCX: 00000000000036d8 RDX: 0000000000000000 RSI: ffff9c5c56535188 RDI: 0000000000000286 RBP: ffff9c5bf7aa4a58 R8: ffff9c589aecdb70 R9: 00000000000003d1 R10: 0000000000000001 R11: 0000000000380000 R12: ffff9c5c5392bc78 R13: ffff9c57044ff5c0 R14: ffff9c56b5a3aa00 R15: 00000000000006db ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 8 [ffffa8e8d2c3f9c8] qla2x00_eh_wait_for_pending_commands at ffffffffc0646dd5 [qla2xxx] 9 [ffffa8e8d2c3fa00] __qla2x00_async_tm_cmd at ffffffffc0658094 [qla2xxx] Remove access of freed memory. Currently the driver was checking to see if scsi_done was called by seeing if the sp->type has changed. Instead, check to see if the command has left the oustanding_cmds[] array as sign of scsi_done was called. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-6-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit b843adde8d49 upstream ] --- qla2x00t-32gbit/qla_isr.c | 38 +++++++++-- qla2x00t-32gbit/qla_os.c | 130 +++++++++++++++++++------------------- 2 files changed, 95 insertions(+), 73 deletions(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 70a8edd42..a238f3fe8 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1874,9 +1874,9 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, } } -srb_t * -qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, - struct req_que *req, void *iocb) +static srb_t * +qla_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb, u16 *ret_index) { struct qla_hw_data *ha = vha->hw; sts_entry_t *pkt = iocb; @@ -1911,12 +1911,25 @@ qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, return NULL; } - req->outstanding_cmds[index] = NULL; - + *ret_index = index; qla_put_fw_resources(sp->qpair, &sp->iores); return sp; } +srb_t * +qla2x00_get_sp_from_handle(scsi_qla_host_t *vha, const char *func, + struct req_que *req, void *iocb) +{ + uint16_t index; + srb_t *sp; + + sp = qla_get_sp_from_handle(vha, func, req, iocb, &index); + if (sp) + req->outstanding_cmds[index] = NULL; + + return sp; +} + static void qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, struct mbx_entry *mbx) @@ -3260,13 +3273,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) return; } - req->outstanding_cmds[handle] = NULL; cp = GET_CMD_SP(sp); if (cp == NULL) { ql_dbg(ql_dbg_io, vha, 0x3018, "Command already returned (0x%x/%p).\n", sts->handle, sp); + req->outstanding_cmds[handle] = NULL; return; } @@ -3537,6 +3550,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) if (rsp->status_srb == NULL) sp->done(sp, res); + + /* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */ + req->outstanding_cmds[handle] = NULL; } /** @@ -3613,6 +3629,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) uint16_t que = MSW(pkt->handle); struct req_que *req = NULL; int res = DID_ERROR << 16; + u16 index; ql_dbg(ql_dbg_async, vha, 0x502a, "iocb type %xh with error status %xh, handle %xh, rspq id %d\n", @@ -3631,7 +3648,6 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) switch (pkt->entry_type) { case NOTIFY_ACK_TYPE: - case STATUS_TYPE: case STATUS_CONT_TYPE: case LOGINOUT_PORT_IOCB_TYPE: case CT_IOCB_TYPE: @@ -3651,6 +3667,14 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) case CTIO_TYPE7: case CTIO_CRC2: return 1; + case STATUS_TYPE: + sp = qla_get_sp_from_handle(vha, func, req, pkt, &index); + if (sp) { + sp->done(sp, res); + req->outstanding_cmds[index] = NULL; + return 0; + } + break; } fatal: ql_log(ql_log_warn, vha, 0x5030, diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 490568ee4..e08ddac80 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1119,43 +1119,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, return 0; } -/* - * qla2x00_eh_wait_on_command - * Waits for the command to be returned by the Firmware for some - * max time. - * - * Input: - * cmd = Scsi Command to wait on. - * - * Return: - * Completed in time : QLA_SUCCESS - * Did not complete in time : QLA_FUNCTION_FAILED - */ -static int -qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) -{ -#define ABORT_POLLING_PERIOD 1000 -#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) - unsigned long wait_iter = ABORT_WAIT_ITER; - scsi_qla_host_t *vha = shost_priv(cmd->device->host); - struct qla_hw_data *ha = vha->hw; - srb_t *sp = scsi_cmd_priv(cmd); - int ret = QLA_SUCCESS; - - if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { - ql_dbg(ql_dbg_taskm, vha, 0x8005, - "Return:eh_wait.\n"); - return ret; - } - - while (sp->type && wait_iter--) - msleep(ABORT_POLLING_PERIOD); - if (sp->type) - ret = QLA_FUNCTION_FAILED; - - return ret; -} - /* * qla2x00_wait_for_hba_online * Wait till the HBA is online after going through @@ -1406,6 +1369,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) return ret; } +#define ABORT_POLLING_PERIOD 1000 +#define ABORT_WAIT_ITER ((2 * 1000) / (ABORT_POLLING_PERIOD)) + /* * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED. */ @@ -1419,41 +1385,73 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t, struct req_que *req = qpair->req; srb_t *sp; struct scsi_cmnd *cmd; + unsigned long wait_iter = ABORT_WAIT_ITER; + bool found; + struct qla_hw_data *ha = vha->hw; status = QLA_SUCCESS; - 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]; - if (!sp) - continue; - if (sp->type != SRB_SCSI_CMD) - continue; - if (vha->vp_idx != sp->vha->vp_idx) - continue; - match = 0; - cmd = GET_CMD_SP(sp); - switch (type) { - case WAIT_HOST: - match = 1; - break; - case WAIT_TARGET: - match = cmd->device->id == t; - break; - case WAIT_LUN: - match = (cmd->device->id == t && - cmd->device->lun == l); - break; - } - if (!match) - continue; + while (wait_iter--) { + found = false; - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - status = qla2x00_eh_wait_on_command(cmd); spin_lock_irqsave(qpair->qp_lock_ptr, flags); + for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) { + sp = req->outstanding_cmds[cnt]; + if (!sp) + continue; + if (sp->type != SRB_SCSI_CMD) + continue; + if (vha->vp_idx != sp->vha->vp_idx) + continue; + match = 0; + cmd = GET_CMD_SP(sp); + switch (type) { + case WAIT_HOST: + match = 1; + break; + case WAIT_TARGET: + if (sp->fcport) + match = sp->fcport->d_id.b24 == t; + else + match = 0; + break; + case WAIT_LUN: + if (sp->fcport) + match = (sp->fcport->d_id.b24 == t && + cmd->device->lun == l); + else + match = 0; + break; + } + if (!match) + continue; + + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (unlikely(pci_channel_offline(ha->pdev)) || + ha->flags.eeh_busy) { + ql_dbg(ql_dbg_taskm, vha, 0x8005, + "Return:eh_wait.\n"); + return status; + } + + /* + * SRB_SCSI_CMD is still in the outstanding_cmds array. + * it means scsi_done has not called. Wait for it to + * clear from outstanding_cmds. + */ + msleep(ABORT_POLLING_PERIOD); + spin_lock_irqsave(qpair->qp_lock_ptr, flags); + found = true; + } + spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (!found) + break; } - spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); + + if (!wait_iter && found) + status = QLA_FUNCTION_FAILED; return status; } From e8a1a2f15ab1f2dce00d35accb3d5cc0b44f8e48 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:30:00 +0300 Subject: [PATCH 37/93] qla2x00t-32gbit: Wait for io return on terminate rport System crash due to use after free. Current code allows terminate_rport_io to exit before making sure all IOs has returned. For FCP-2 device, IO's can hang on in HW because driver has not tear down the session in FW at first sign of cable pull. When dev_loss_tmo timer pops, terminate_rport_io is called and upper layer is about to free various resources. Terminate_rport_io trigger qla to do the final cleanup, but the cleanup might not be fast enough where it leave qla still holding on to the same resource. Wait for IO's to return to upper layer before resources are freed. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-7-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit fc0cba0c7be8 upstream ] --- qla2x00t-32gbit/qla_attr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index 16b6b5cc3..c9fc1d757 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -2821,6 +2821,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + scsi_qla_host_t *vha; if (!fcport) return; @@ -2830,9 +2831,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) return; + vha = fcport->vha; if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); + qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, + 0, WAIT_TARGET); return; } /* @@ -2857,6 +2861,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) qla2x00_port_logout(fcport->vha, fcport); } } + + /* check for any straggling io left behind */ + if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) { + ql_log(ql_log_warn, vha, 0x300b, + "IO not return. Resetting. \n"); + set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); + qla2xxx_wake_dpc(vha); + qla2x00_wait_for_chip_reset(vha); + } } static int From ffd578e720b725d6967d4087c4324a982b4fd7b3 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:30:19 +0300 Subject: [PATCH 38/93] qla2x00t-32gbit: Update version to 10.02.08.300-k Update version to 10.02.08.300-k. Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230428075339.32551-8-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit eb91eb809c8d upstream ] --- qla2x00t-32gbit/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 42d69d898..4d6f06fb1 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.200-k" +#define QLA2XXX_VERSION "10.02.08.300-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 200 +#define QLA_DRIVER_BETA_VER 300 From d26ab07ae97c9a877fefb3badb5a2dba03bb15cd Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:30:33 +0300 Subject: [PATCH 39/93] qla2x00t-32gbit: Fix end of loop test This loop will exit successfully when "found" is false or in the failure case it times out with "wait_iter" set to -1. The test for timeouts is impossible as is. Fixes: b843adde8d49 ("scsi: qla2xxx: Fix mem access after free") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/cea5a62f-b873-4347-8f8e-c67527ced8d2@kili.mountain Signed-off-by: Martin K. Petersen [ commit 339020091e24 upstrema ] --- qla2x00t-32gbit/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index e08ddac80..7bd76e8b7 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1450,7 +1450,7 @@ __qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t, break; } - if (!wait_iter && found) + if (wait_iter == -1) status = QLA_FUNCTION_FAILED; return status; From cba2284cd167a62bb5d57b13af9f26573cf27a8a Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:30:54 +0300 Subject: [PATCH 40/93] qla2x00t-32gbit: Replace one-element array with DECLARE_FLEX_ARRAY() helper One-element arrays as fake flex arrays are deprecated and we are moving towards adopting C99 flexible-array members, instead. So, replace one-element array declaration in struct ct_sns_gpnft_rsp, which is ultimately being used inside a union: drivers/scsi/qla2xxx/qla_def.h: 3240 struct ct_sns_gpnft_pkt { 3241 union { 3242 struct ct_sns_req req; 3243 struct ct_sns_gpnft_rsp rsp; 3244 } p; 3245 }; Refactor the rest of the code, accordingly. This issue was found with the help of Coccinelle. Link: https://github.com/KSPP/linux/issues/245 Link: https://github.com/KSPP/linux/issues/193 Reviewed-by: Kees Cook Signed-off-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/ZH+/rZ1R1cBjIxjS@work Signed-off-by: Martin K. Petersen [ commit 512a365368c7 upstream ] --- qla2x00t-32gbit/qla_def.h | 4 ++-- qla2x00t-32gbit/qla_gs.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 433d9a801..4a496a6cd 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3226,12 +3226,12 @@ struct ct_sns_gpnft_rsp { uint8_t vendor_unique; }; /* Assume the largest number of targets for the union */ - struct ct_sns_gpn_ft_data { + DECLARE_FLEX_ARRAY(struct ct_sns_gpn_ft_data { u8 control_byte; u8 port_id[3]; u32 reserved; u8 port_name[8]; - } entries[1]; + }, entries); }; /* CT command response */ diff --git a/qla2x00t-32gbit/qla_gs.c b/qla2x00t-32gbit/qla_gs.c index 4738f8935..1cf9d200d 100644 --- a/qla2x00t-32gbit/qla_gs.c +++ b/qla2x00t-32gbit/qla_gs.c @@ -3776,8 +3776,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp) sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE; rspsz = sizeof(struct ct_sns_gpnft_rsp) + - ((vha->hw->max_fibre_devices - 1) * - sizeof(struct ct_sns_gpn_ft_data)); + vha->hw->max_fibre_devices * + sizeof(struct ct_sns_gpn_ft_data); sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev, rspsz, From d74330aed223228e2051050ae1875d3c5a78ebeb Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:31:58 +0300 Subject: [PATCH 41/93] qla2x00t-32gbit: Backport to older kernel versions Unbreak the build for the previous commit against kernel versions before v5.16. See also commit 3080ea5553cc ("stddef: Introduce DECLARE_FLEX_ARRAY() helper") # v5.16. --- scst/include/backport.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scst/include/backport.h b/scst/include/backport.h index 4e693aeab..f4fc28164 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -1314,6 +1314,14 @@ static inline void __user *KERNEL_SOCKPTR(void *p) #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) #endif +#ifndef DECLARE_FLEX_ARRAY +#define DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) && \ From 6aff6bfacb0188b6627d79e0d09acab8a5552bdd Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:32:08 +0300 Subject: [PATCH 42/93] qla2x00t-32gbit: Drop useless LIST_HEAD 'new_fcports' is unused, so drop it. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/49bb77624c9edc8d9bf8fe71d0c8a4cd7e582175.1685854354.git.christophe.jaillet@wanadoo.fr Signed-off-by: Martin K. Petersen [ commit 022000d3f586 upstream ] --- qla2x00t-32gbit/qla_init.c | 1 - 1 file changed, 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 69719b6e8..3a5edf390 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -6223,7 +6223,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) fc_port_t *fcport; uint16_t mb[MAILBOX_REGISTER_COUNT]; uint16_t loop_id; - LIST_HEAD(new_fcports); struct qla_hw_data *ha = vha->hw; int discovery_gen; From 0b9f73b1d8dc3739dccd729329232f5ecbf8c201 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:32:32 +0300 Subject: [PATCH 43/93] qla2x00t-32gbit: Array index may go out of bound Klocwork reports array 'vha->host_str' of size 16 may use index value(s) 16..19. Use snprintf() instead of sprintf(). Cc: stable@vger.kernel.org Co-developed-by: Bikash Hazarika Signed-off-by: Bikash Hazarika Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-2-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit d721b591b95c upstream ] --- qla2x00t-32gbit/qla_os.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 7bd76e8b7..d83151df5 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -5151,7 +5151,8 @@ struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *sht, } INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn); - sprintf(vha->host_str, "%s_%lu", QLA2XXX_DRIVER_NAME, vha->host_no); + snprintf(vha->host_str, sizeof(vha->host_str), "%s_%lu", + QLA2XXX_DRIVER_NAME, vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha, From 0367c334c36aec8561218cfbab539160be993c66 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:32:56 +0300 Subject: [PATCH 44/93] qla2x00t-32gbit: Fix potential NULL pointer dereference Klocwork tool reported 'cur_dsd' may be dereferenced. Add fix to validate pointer before dereferencing the pointer. Cc: stable@vger.kernel.org Signed-off-by: Bikash Hazarika Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-3-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 464ea494a40c upstream ] --- qla2x00t-32gbit/qla_iocb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 2742d370d..bdf505aa2 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -613,7 +613,8 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type); /* No data transfer */ - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE || + tot_dsds == 0) { cmd_pkt->byte_count = cpu_to_le32(0); return 0; } From bb18381819785f93e24d7b6f12a727579ef63148 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:33:12 +0300 Subject: [PATCH 45/93] qla2x00t-32gbit: Avoid fcport pointer dereference Klocwork reported warning of NULL pointer may be dereferenced. The routine exits when sa_ctl is NULL and fcport is allocated after the exit call thus causing NULL fcport pointer to dereference at the time of exit. To avoid fcport pointer dereference, exit the routine when sa_ctl is NULL. Cc: stable@vger.kernel.org Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 6b504d06976f upstream ] --- qla2x00t-32gbit/qla_edif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_edif.c b/qla2x00t-32gbit/qla_edif.c index 9e0fd61c0..96b45f630 100644 --- a/qla2x00t-32gbit/qla_edif.c +++ b/qla2x00t-32gbit/qla_edif.c @@ -2362,8 +2362,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_host_t *vha, struct qla_work_evt *e) if (!sa_ctl) { ql_dbg(ql_dbg_edif, vha, 0x70e6, "sa_ctl allocation failed\n"); - rval = -ENOMEM; - goto done; + rval = -ENOMEM; + return rval; } fcport = sa_ctl->fcport; From a1edff66778872c41289926c064566e55310dc61 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:33:28 +0300 Subject: [PATCH 46/93] qla2x00t-32gbit: Check valid rport returned by fc_bsg_to_rport() Klocwork reported warning of rport maybe NULL and will be dereferenced. rport returned by call to fc_bsg_to_rport() could be NULL and dereferenced. Check valid rport returned by fc_bsg_to_rport(). Cc: stable@vger.kernel.org Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-5-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit af73f23a2720 upstream ] --- qla2x00t-32gbit/qla_bsg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 8e0f44caa..25de9fb4d 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -286,6 +286,10 @@ qla2x00_process_els(BSG_JOB_TYPE *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) { + rval = -ENOMEM; + goto done; + } fcport = *(fc_port_t **) rport->dd_data; host = rport_to_shost(rport); vha = shost_priv(host); From beabef8afc73404ec92255e7a955cd1d64ba539e Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:33:48 +0300 Subject: [PATCH 47/93] qla2x00t-32gbit: Fix buffer overrun Klocwork warning: Buffer Overflow - Array Index Out of Bounds Driver uses fc_els_flogi to calculate size of buffer. The actual buffer is nested inside of fc_els_flogi which is smaller. Replace structure name to allow proper size calculation. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-6-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit b68710a8094f upstream ] --- qla2x00t-32gbit/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 3a5edf390..88da7b5ac 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5552,7 +5552,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha) __be32 *q; memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); + sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size); rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ha->init_cb, sz); if (rval != QLA_SUCCESS) { From 1f107c7ee56f9f4792e5ed56e16872282c23199b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:34:03 +0300 Subject: [PATCH 48/93] qla2x00t-32gbit: Pointer may be dereferenced Klocwork tool reported pointer 'rport' returned from call to function fc_bsg_to_rport() may be NULL and will be dereferenced. Add a fix to validate rport before dereferencing. Cc: stable@vger.kernel.org Signed-off-by: Shreyas Deodhar Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-7-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 00eca15319d9 upstream ] --- qla2x00t-32gbit/qla_bsg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qla2x00t-32gbit/qla_bsg.c b/qla2x00t-32gbit/qla_bsg.c index 25de9fb4d..cc8c98d16 100644 --- a/qla2x00t-32gbit/qla_bsg.c +++ b/qla2x00t-32gbit/qla_bsg.c @@ -3000,6 +3000,8 @@ qla24xx_bsg_request(BSG_JOB_TYPE *bsg_job) if (bsg_request->msgcode == FC_BSG_RPT_ELS) { rport = fc_bsg_to_rport(bsg_job); + if (!rport) + return ret; host = rport_to_shost(rport); vha = shost_priv(host); } else { From bb9b171dc414eafa2c2cb34eb30799b7ecdafcc9 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:34:18 +0300 Subject: [PATCH 49/93] qla2x00t-32gbit: Correct the index of array Klocwork reported array 'port_dstate_str' of size 10 may use index value(s) 10..15. Add a fix to correct the index of array. Cc: stable@vger.kernel.org Signed-off-by: Bikash Hazarika Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-8-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit b1b9d3825df4 upstream ] --- qla2x00t-32gbit/qla_inline.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index b1bf22d79..d635b42fe 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -117,11 +117,13 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) { int old_val; uint8_t shiftbits, mask; + uint8_t port_dstate_str_sz; /* This will have to change when the max no. of states > 16 */ shiftbits = 4; mask = (1 << shiftbits) - 1; + port_dstate_str_sz = sizeof(port_dstate_str) / sizeof(char *); fcport->disc_state = state; while (1) { old_val = atomic_read(&fcport->shadow_disc_state); @@ -129,7 +131,8 @@ qla2x00_set_fcport_disc_state(fc_port_t *fcport, int state) old_val, (old_val << shiftbits) | state)) { ql_dbg(ql_dbg_disc, fcport->vha, 0x2134, "FCPort %8phC disc_state transition: %s to %s - portid=%06x.\n", - fcport->port_name, port_dstate_str[old_val & mask], + fcport->port_name, (old_val & mask) < port_dstate_str_sz ? + port_dstate_str[old_val & mask] : "Unknown", port_dstate_str[state], fcport->d_id.b24); return; } From 29d26d69db0de122e0f6d2917cd3acfd14b03f7f Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:34:34 +0300 Subject: [PATCH 50/93] qla2x00t-32gbit: Update version to 10.02.08.400-k Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230607113843.37185-9-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 991e7ac609ee upstream ] --- qla2x00t-32gbit/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 4d6f06fb1..e3771923b 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.300-k" +#define QLA2XXX_VERSION "10.02.08.400-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 300 +#define QLA_DRIVER_BETA_VER 400 From 7076a91a3b658dc849dfcf8e1bd95b5290b723a4 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 10 Jul 2023 12:34:52 +0300 Subject: [PATCH 51/93] qla2x00t-32gbit: Remove unused nvme_ls_waitq wait queue System crash when qla2x00_start_sp(sp) returns error code EGAIN and wake_up gets called for uninitialized wait queue sp->nvme_ls_waitq. qla2xxx [0000:37:00.1]-2121:5: Returning existing qpair of ffff8ae2c0513400 for idx=0 qla2xxx [0000:37:00.1]-700e:5: qla2x00_start_sp failed = 11 BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 PGD 0 P4D 0 Oops: 0000 [#1] SMP NOPTI Hardware name: HPE ProLiant DL360 Gen10/ProLiant DL360 Gen10, BIOS U32 09/03/2021 Workqueue: nvme-wq nvme_fc_connect_ctrl_work [nvme_fc] RIP: 0010:__wake_up_common+0x4c/0x190 RSP: 0018:ffff95f3e0cb7cd0 EFLAGS: 00010086 RAX: 0000000000000000 RBX: ffff8b08d3b26328 RCX: 0000000000000000 RDX: 0000000000000001 RSI: 0000000000000003 RDI: ffff8b08d3b26320 RBP: 0000000000000001 R08: 0000000000000000 R09: ffffffffffffffe8 R10: 0000000000000000 R11: ffff95f3e0cb7a60 R12: ffff95f3e0cb7d20 R13: 0000000000000003 R14: 0000000000000000 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8b2fdf6c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000002f1e410002 CR4: 00000000007706e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: __wake_up_common_lock+0x7c/0xc0 qla_nvme_ls_req+0x355/0x4c0 [qla2xxx] ? __nvme_fc_send_ls_req+0x260/0x380 [nvme_fc] ? nvme_fc_send_ls_req.constprop.42+0x1a/0x45 [nvme_fc] ? nvme_fc_connect_ctrl_work.cold.63+0x1e3/0xa7d [nvme_fc] Remove unused nvme_ls_waitq wait queue. nvme_ls_waitq logic was removed previously in the commits tagged Fixed: below. Fixes: 219d27d7147e ("scsi: qla2xxx: Fix race conditions in the code for aborting SCSI commands") Fixes: 5621b0dd7453 ("scsi: qla2xxx: Simpify unregistration of FC-NVMe local/remote ports") Cc: stable@vger.kernel.org Signed-off-by: Manish Rangankar Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230615074633.12721-1-njavali@marvell.com Signed-off-by: Martin K. Petersen [ commit 20fce500b232 upstream ] --- qla2x00t-32gbit/qla_def.h | 1 - qla2x00t-32gbit/qla_nvme.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 4a496a6cd..674d4bdd5 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -750,7 +750,6 @@ typedef struct srb { struct iocb_resource iores; struct kref cmd_kref; /* need to migrate ref_count over to this */ void *priv; - wait_queue_head_t nvme_ls_waitq; struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index de6948680..c3ae67fc7 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -375,7 +375,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x700e, "qla2x00_start_sp failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2x00_rel_sp(sp); @@ -667,7 +666,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (!sp) return -EBUSY; - init_waitqueue_head(&sp->nvme_ls_waitq); kref_init(&sp->cmd_kref); spin_lock_init(&priv->cmd_lock); sp->priv = priv; @@ -686,7 +684,6 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, if (rval != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x212d, "qla2x00_start_nvme_mq failed = %d\n", rval); - wake_up(&sp->nvme_ls_waitq); sp->priv = NULL; priv->sp = NULL; qla2xxx_rel_qpair_sp(sp->qpair, sp); From 1d37f637e649a465eeaedbda07894b3ee11df364 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 12:02:04 +0300 Subject: [PATCH 52/93] qla2x00t-32gbit: Silence a static checker warning Smatch and Clang both complain that LOGIN_TEMPLATE_SIZE is more than sizeof(ha->plogi_els_payld.fl_csp). Smatch warning: drivers/scsi/qla2xxx/qla_iocb.c:3075 qla24xx_els_dcmd2_iocb() warn: '&ha->plogi_els_payld.fl_csp' sometimes too small '16' size = 112 Clang warning: include/linux/fortify-string.h:592:4: error: call to '__read_overflow2_field' declared with 'warning' attribute: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] __read_overflow2_field(q_size_field, size); When I was reading this code I assumed the "- 4" meant that we were skipping the last 4 bytes but actually it turned out that we are skipping the first four bytes. I have re-written it remove the magic numbers, be more clear and silence the static checker warnings. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/4aa0485e-766f-4b02-8d5d-c6781ea8f511@moroto.mountain Signed-off-by: Martin K. Petersen [ commit 134f66959cd0b upstream ] --- qla2x00t-32gbit/qla_def.h | 1 - qla2x00t-32gbit/qla_iocb.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 674d4bdd5..5a3a51921 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4514,7 +4514,6 @@ struct qla_hw_data { /* n2n */ struct fc_els_flogi plogi_els_payld; -#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4) void *swl; diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index bdf505aa2..7cd7ef239 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -3089,7 +3089,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, memset(ptr, 0, sizeof(struct els_plogi_payload)); memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); memcpy(elsio->u.els_plogi.els_plogi_pyld->data, - &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE); + (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp), + sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp)); elsio->u.els_plogi.els_cmd = els_opcode; elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; From ceff753e131d75c9c7a12eadc625d90807943c89 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 12:00:22 +0300 Subject: [PATCH 53/93] qla2x00t-32gbit: Fix error code in qla2x00_start_sp() This should be negative -EAGAIN instead of positive. The callers treat non-zero error codes the same so it doesn't really impact runtime beyond some trivial differences to debug output. Fixes: 80676d054e5a ("scsi: qla2xxx: Fix session cleanup hang") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/49866d28-4cfe-47b0-842b-78f110e61aab@moroto.mountain Signed-off-by: Martin K. Petersen [ commit e579b007eff3f upstream ] --- qla2x00t-32gbit/qla_iocb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 7cd7ef239..6670b3777 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -3928,7 +3928,7 @@ qla2x00_start_sp(srb_t *sp) pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { - rval = EAGAIN; + rval = -EAGAIN; ql_log(ql_log_warn, vha, 0x700c, "qla2x00_alloc_iocbs failed.\n"); goto done; From 87235dfe3a2093b12ec8239553a80eacd3a59b22 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 12:01:19 +0300 Subject: [PATCH 54/93] scst: Use vmalloc_array() and vcalloc() Use vmalloc_array() and vcalloc() to protect against multiplication overflows. The changes were done using the following Coccinelle semantic patch: // @initialize:ocaml@ @@ let rename alloc = match alloc with "vmalloc" -> "vmalloc_array" | "vzalloc" -> "vcalloc" | _ -> failwith "unknown" @@ size_t e1,e2; constant C1, C2; expression E1, E2, COUNT, x1, x2, x3; typedef u8; typedef __u8; type t = {u8,__u8,char,unsigned char}; identifier alloc = {vmalloc,vzalloc}; fresh identifier realloc = script:ocaml(alloc) { rename alloc }; @@ ( alloc(x1*x2*x3) | alloc(C1 * C2) | alloc((sizeof(t)) * (COUNT), ...) | - alloc((e1) * (e2)) + realloc(e1, e2) | - alloc((e1) * (COUNT)) + realloc(COUNT, e1) | - alloc((E1) * (E2)) + realloc(E1, E2) ) // --- iscsi-scst/kernel/isert-scst/iser_rdma.c | 3 +-- qla2x00t-32gbit/qla_init.c | 4 ++-- scst/include/backport.h | 22 ++++++++++++++++++++++ scst/src/scst_dlm.c | 7 +++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index bad41bfe7..439e36942 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -938,8 +938,7 @@ static struct isert_device *isert_device_create(struct ib_device *ib_dev) goto free_isert_dev; } - isert_dev->cq_desc = vmalloc(sizeof(*isert_dev->cq_desc) * - isert_dev->num_cqs); + isert_dev->cq_desc = vmalloc_array(isert_dev->num_cqs, sizeof(*isert_dev->cq_desc)); if (unlikely(isert_dev->cq_desc == NULL)) { PRINT_ERROR("Failed to allocate %zd bytes for iser cq_desc", sizeof(*isert_dev->cq_desc) * isert_dev->num_cqs); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 88da7b5ac..980c8f7d0 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -8437,7 +8437,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr, ql_dbg(ql_dbg_init, vha, 0x0163, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0164, "-> fwdt%u failed allocate template.\n", j); @@ -8692,7 +8692,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr) ql_dbg(ql_dbg_init, vha, 0x0173, "-> fwdt%u template allocate template %#x words...\n", j, risc_size); - fwdt->template = vmalloc(risc_size * sizeof(*dcode)); + fwdt->template = vmalloc_array(risc_size, sizeof(*dcode)); if (!fwdt->template) { ql_log(ql_log_warn, vha, 0x0174, "-> fwdt%u failed allocate template.\n", j); diff --git a/scst/include/backport.h b/scst/include/backport.h index f4fc28164..a57cf531e 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -849,6 +849,28 @@ static inline void kvfree(void *addr) } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) && \ + (LINUX_VERSION_CODE >> 8 != KERNEL_VERSION(5, 15, 0) >> 8 || \ + LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 54)) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 0)) && \ + (!defined(UEK_KABI_RENAME) || \ + LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) +/* + * See also commit a8749a35c3990 ("mm: vmalloc: introduce array allocation functions") # v5.18, + * v5.15.54. + */ +static inline void *vmalloc_array(size_t n, size_t size) +{ + return vmalloc(n * size); +} + +static inline void *vcalloc(size_t n, size_t size) +{ + return vzalloc(n * size); +} +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) && \ diff --git a/scst/src/scst_dlm.c b/scst/src/scst_dlm.c index 8afedb1f8..7e634afcf 100644 --- a/scst/src/scst_dlm.c +++ b/scst/src/scst_dlm.c @@ -304,11 +304,10 @@ static int scst_copy_from_dlm(struct scst_device *dev, dlm_lockspace_t *ls, nr_registrants = be32_to_cpu(lvb->nr_registrants); if (nr_registrants) { - reg_lksb = vzalloc((sizeof(*reg_lksb) + PR_DLM_LVB_LEN) * - nr_registrants); + reg_lksb = vcalloc(nr_registrants, sizeof(*reg_lksb) + PR_DLM_LVB_LEN); if (!reg_lksb) { - PRINT_ERROR("%s: failed to allocate %d * %zd bytes of" - " memory", __func__, nr_registrants, + PRINT_ERROR("%s: failed to allocate %u * %zu bytes of memory", + __func__, nr_registrants, sizeof(*reg_lksb) + PR_DLM_LVB_LEN); goto out; } From 1f0ce86f3c3f37a6f08f1a0e2a62e589ae5d3e7e Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 18:00:09 +0300 Subject: [PATCH 55/93] scst: Fix removal of deprecated create_workqueue() create_workqueue() was replaced with alloc_workqueue() with max_active set to 0. However, the original create_workqueue() implicitly set max_active to 1. This change has led to unexpected bugs because previously, work items could only be executed one by one. With the change, they can now be executed simultaneously. This patch fixes the issue by restoring max_active to 1. Fixes: f4686e9102c1 ("scst: Remove deprecated create_workqueue()") Fixes: https://github.com/SCST-project/scst/issues/179 --- iscsi-scst/kernel/isert-scst/iser_global.c | 2 +- qla2x00t/qla_os.c | 2 +- scst/src/scst_lib.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/iscsi-scst/kernel/isert-scst/iser_global.c b/iscsi-scst/kernel/isert-scst/iser_global.c index 5b8b92b97..e6e0ec2d4 100644 --- a/iscsi-scst/kernel/isert-scst/iser_global.c +++ b/iscsi-scst/kernel/isert-scst/iser_global.c @@ -138,7 +138,7 @@ int isert_global_init(void) spin_lock_init(&isert_glob.portal_lock); init_waitqueue_head(&isert_glob.portal_wq); - isert_glob.conn_wq = alloc_workqueue("isert_conn_wq", WQ_MEM_RECLAIM, 0); + isert_glob.conn_wq = alloc_workqueue("isert_conn_wq", WQ_MEM_RECLAIM, 1); if (!isert_glob.conn_wq) { PRINT_ERROR("Failed to alloc iser conn work queue"); return -ENOMEM; diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index 0c3c70a0a..5d34b93d0 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -450,7 +450,7 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha) "Failed to create request queue.\n"); goto fail; } - ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0); + ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1); vha->req = ha->req_q_map[req]; options |= BIT_1; for (ques = 1; ques < ha->max_rsp_queues; ques++) { diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 283a28bbd..e12623074 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -15499,7 +15499,7 @@ int __init scst_lib_init(void) scst_scsi_op_list_init(); - scst_release_acg_wq = alloc_workqueue("scst_release_acg", WQ_MEM_RECLAIM, 0); + scst_release_acg_wq = alloc_workqueue("scst_release_acg", WQ_MEM_RECLAIM, 1); if (unlikely(!scst_release_acg_wq)) { PRINT_ERROR("Failed to allocate scst_release_acg_wq"); res = -ENOMEM; From 4b840aeee395d554ac699ad2736553d5181ddda5 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 19:37:34 +0300 Subject: [PATCH 56/93] scst: Do not use WQ_MEM_RECLAIM flag for workqueues According to kernel documentation, this flag should be set if the workqueue will be involved in the kernel's memory reclamation flow. Since it is not, there is no need for the driver's WQ to have this flag set so remove it. --- iscsi-scst/kernel/isert-scst/iser_global.c | 2 +- iscsi-scst/kernel/isert-scst/iser_rdma.c | 2 +- scst/src/scst_event.c | 2 +- scst/src/scst_lib.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iscsi-scst/kernel/isert-scst/iser_global.c b/iscsi-scst/kernel/isert-scst/iser_global.c index e6e0ec2d4..c070a66fa 100644 --- a/iscsi-scst/kernel/isert-scst/iser_global.c +++ b/iscsi-scst/kernel/isert-scst/iser_global.c @@ -138,7 +138,7 @@ int isert_global_init(void) spin_lock_init(&isert_glob.portal_lock); init_waitqueue_head(&isert_glob.portal_wq); - isert_glob.conn_wq = alloc_workqueue("isert_conn_wq", WQ_MEM_RECLAIM, 1); + isert_glob.conn_wq = alloc_workqueue("isert_conn_wq", 0, 1); if (!isert_glob.conn_wq) { PRINT_ERROR("Failed to alloc iser conn work queue"); return -ENOMEM; diff --git a/iscsi-scst/kernel/isert-scst/iser_rdma.c b/iscsi-scst/kernel/isert-scst/iser_rdma.c index 439e36942..c5e30b167 100644 --- a/iscsi-scst/kernel/isert-scst/iser_rdma.c +++ b/iscsi-scst/kernel/isert-scst/iser_rdma.c @@ -1792,7 +1792,7 @@ struct isert_portal *isert_portal_create(struct sockaddr *sa, size_t addr_len) goto err_alloc; } - portal->reinit_id_wq = alloc_ordered_workqueue("isert_reinit_id_wq", WQ_MEM_RECLAIM); + portal->reinit_id_wq = alloc_ordered_workqueue("isert_reinit_id_wq", 0); if (unlikely(!portal->reinit_id_wq)) { PRINT_ERROR("Unable to allocate reinit workqueue"); err = -ENOMEM; diff --git a/scst/src/scst_event.c b/scst/src/scst_event.c index 7221008b4..b744e1766 100644 --- a/scst/src/scst_event.c +++ b/scst/src/scst_event.c @@ -1111,7 +1111,7 @@ int scst_event_init(void) TRACE_ENTRY(); - scst_event_wq = alloc_workqueue("scst_event_wq", WQ_MEM_RECLAIM, 0); + scst_event_wq = alloc_workqueue("scst_event_wq", 0, 0); if (unlikely(!scst_event_wq)) { PRINT_ERROR("Failed to allocate scst_event_wq"); res = -ENOMEM; diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index e12623074..208e58d67 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -15499,7 +15499,7 @@ int __init scst_lib_init(void) scst_scsi_op_list_init(); - scst_release_acg_wq = alloc_workqueue("scst_release_acg", WQ_MEM_RECLAIM, 1); + scst_release_acg_wq = alloc_workqueue("scst_release_acg", 0, 1); if (unlikely(!scst_release_acg_wq)) { PRINT_ERROR("Failed to allocate scst_release_acg_wq"); res = -ENOMEM; From c00af8aab9d82d4b61dc466a38e373dd4132c244 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Wed, 19 Jul 2023 20:48:28 +0300 Subject: [PATCH 57/93] scst_lib: Improve scst_put_acg() This patch refactors scst_put_acg() to directly call kref_put() with a release callback that handles removal of scst_acg from the workqueue. This replaces the previous approach of queuing a work item for each kref_put() call, improving efficiency by reducing the number of queued work items. --- scst/src/scst_lib.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 208e58d67..02d03ba15 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -70,7 +70,6 @@ static DEFINE_SPINLOCK(scst_global_stpg_list_lock); static LIST_HEAD(scst_global_stpg_list); -static void scst_put_acg_work(struct work_struct *work); static void scst_free_acn(struct scst_acn *acn, bool reassign); struct scsi_io_context { @@ -4826,49 +4825,47 @@ static void scst_free_acg(struct scst_acg *acg) kobject_put(&tgt->tgt_kobj); } -static void scst_release_acg(struct kref *kref) -{ - struct scst_acg *acg = container_of(kref, struct scst_acg, acg_kref); - - scst_free_acg(acg); -} - -struct scst_acg_put_work { +struct scst_acg_release_work { struct work_struct work; struct scst_acg *acg; }; -static void scst_put_acg_work(struct work_struct *work) +static void scst_release_acg_work(struct work_struct *work) { - struct scst_acg_put_work *put_work = - container_of(work, typeof(*put_work), work); - struct scst_acg *acg = put_work->acg; + struct scst_acg_release_work *release_work = + container_of(work, typeof(*release_work), work); + struct scst_acg *acg = release_work->acg; - kfree(put_work); - kref_put(&acg->acg_kref, scst_release_acg); + kfree(release_work); + scst_free_acg(acg); } -void scst_put_acg(struct scst_acg *acg) +static void scst_release_acg(struct kref *kref) { - struct scst_acg_put_work *put_work; + struct scst_acg *acg = container_of(kref, struct scst_acg, acg_kref); + struct scst_acg_release_work *release_work; bool rc; - put_work = kmalloc(sizeof(*put_work), GFP_KERNEL | __GFP_NOFAIL); - if (WARN_ON_ONCE(!put_work)) { - kref_put(&acg->acg_kref, scst_release_acg); + release_work = kmalloc(sizeof(*release_work), GFP_KERNEL | __GFP_NOFAIL); + if (WARN_ON_ONCE(!release_work)) { + scst_free_acg(acg); return; } - INIT_WORK(&put_work->work, scst_put_acg_work); - put_work->acg = acg; + INIT_WORK(&release_work->work, scst_release_acg_work); + release_work->acg = acg; /* * Schedule the kref_put() call instead of invoking it directly to * avoid deep recursion and a stack overflow. */ - rc = queue_work(scst_release_acg_wq, &put_work->work); + rc = queue_work(scst_release_acg_wq, &release_work->work); WARN_ON_ONCE(!rc); - return; +} + +void scst_put_acg(struct scst_acg *acg) +{ + kref_put(&acg->acg_kref, scst_release_acg); } void scst_get_acg(struct scst_acg *acg) From 3c8f66e2b8876d4bbd9e14b56f48ab011de8d1bd Mon Sep 17 00:00:00 2001 From: Brian Meagher Date: Thu, 17 Aug 2023 09:40:48 -0700 Subject: [PATCH 58/93] Add support for iSCSI TargetAlias This includes both support during iSCSI LOGIN and iSNS. --- iscsi-scst/README | 5 ++++ iscsi-scst/usr/config.c | 26 ++++++++++++++++++++ iscsi-scst/usr/ctldev.c | 12 +++++++++- iscsi-scst/usr/event.c | 53 +++++++++++++++++++++++++++++++++++++++++ iscsi-scst/usr/iscsid.c | 2 ++ iscsi-scst/usr/iscsid.h | 2 ++ iscsi-scst/usr/isns.c | 16 ++++++++++++- iscsi-scst/usr/param.h | 1 + 8 files changed, 115 insertions(+), 2 deletions(-) diff --git a/iscsi-scst/README b/iscsi-scst/README index 9f67fac38..d086c6ec2 100644 --- a/iscsi-scst/README +++ b/iscsi-scst/README @@ -283,6 +283,10 @@ Each target subdirectory contains the following entries: - tid - TID of this target. + - alias - TargetAlias of this target. If not set, it will default to the + empty string and no TargetAlias will be reported in LOGIN RESPONSE or iSNS + for this target. + The "sessions" subdirectory contains the following attribute: - thread_pid - the process identifiers (PIDs) of the iscsird and iscsiwr @@ -559,6 +563,7 @@ both iSCSI-SCST targets will look like: | | |-- NopInInterval | | |-- QueuedCommands | | |-- RspTimeout +| | |-- alias | | |-- enabled | | |-- ini_groups | | | `-- mgmt diff --git a/iscsi-scst/usr/config.c b/iscsi-scst/usr/config.c index e90a05baa..35fb16b5f 100644 --- a/iscsi-scst/usr/config.c +++ b/iscsi-scst/usr/config.c @@ -265,6 +265,32 @@ char *config_sep_string(char **pp) return p; } +/* + * Strip leading and trailing whitespace. + * + * Modifies the contents of the parameter string. + */ +char *config_strip_string(char *s) +{ + size_t size; + char *end; + + size = strlen(s); + + if (!size) + return s; + + end = s + size - 1; + while (end >= s && isspace(*end)) + end--; + *(end + 1) = '\0'; + + while (*s && isspace(*s)) + s++; + + return s; +} + static char *config_gets(char *buf, int size, const char *data, int *offset) { int offs = *offset, i = 0; diff --git a/iscsi-scst/usr/ctldev.c b/iscsi-scst/usr/ctldev.c index 70258cc46..49efe5677 100644 --- a/iscsi-scst/usr/ctldev.c +++ b/iscsi-scst/usr/ctldev.c @@ -78,7 +78,12 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie) info.tid = (tid != NULL) ? *tid : 0; info.cookie = cookie; - info.attrs_num = 2; + /* + * ISCSI_PER_PORTAL_ACL_ATTR_NAME + * ISCSI_TARGET_REDIRECTION_ATTR_NAME + * ISCSI_TARGET_ALIAS_ATTR_NAME + */ + info.attrs_num = 3; for (j = 0; j < session_key_last; j++) { if (session_keys[j].show_in_sysfs) @@ -117,6 +122,11 @@ int kernel_target_create(struct target *target, u32 *tid, u32 cookie) sizeof(ISCSI_TARGET_REDIRECTION_ATTR_NAME)); i++; + kern_attrs[i].mode = 0644; + strlcpy(kern_attrs[i].name, ISCSI_TARGET_ALIAS_ATTR_NAME, + sizeof(ISCSI_TARGET_ALIAS_ATTR_NAME)); + i++; + for (j = 0; j < session_key_last; j++) { if (!session_keys[j].show_in_sysfs) continue; diff --git a/iscsi-scst/usr/event.c b/iscsi-scst/usr/event.c index 61cb13205..e08cd4b0c 100644 --- a/iscsi-scst/usr/event.c +++ b/iscsi-scst/usr/event.c @@ -611,6 +611,17 @@ static int handle_e_get_attr_value(int fd, const struct iscsi_kern_event *event) add_key_mark(res_str, sizeof(res_str), 0); } else *res_str = '\0'; + } else if (strcasecmp(ISCSI_TARGET_ALIAS_ATTR_NAME, pp) == 0) { + if (target == NULL) { + log_error("Target expected for attr %s", pp); + res = -EINVAL; + goto out_free; + } + if (target->alias) { + snprintf(res_str, sizeof(res_str), "%s\n", target->alias); + add_key_mark(res_str, sizeof(res_str), 0); + } else + *res_str = '\0'; } else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) { if (target != NULL) { log_error("Not NULL target %s for global attribute %s", @@ -955,6 +966,48 @@ static int handle_e_set_attr_value(int fd, const struct iscsi_kern_event *event) res = handle_target_redirect(target, p); if (res != 0) goto out_free; + } else if (strcasecmp(ISCSI_TARGET_ALIAS_ATTR_NAME, pp) == 0) { + bool alias_changed = false; + + if (target == NULL) { + log_error("Target expected for attr %s", pp); + res = -EINVAL; + goto out_free; + } + p = config_strip_string(p); + if (*p == '\0') { + if (target->alias) { + free(target->alias); + target->alias = NULL; + alias_changed = true; + } + } else { + char *newval = strdup(p); + + if (newval == NULL) { + log_error("Unable to duplicate alias name %s", p); + res = -ENOMEM; + goto out_free; + } + if (target->alias) + free(target->alias); + target->alias = newval; + alias_changed = true; + } + /* If we previously registered an alias and we need to update it */ + if (alias_changed && target->isns_registered) { + if (target->alias) { + isns_target_register(target->name); + } else { + /* + * We have cleared a previously set alias. + * Work-around to make change visible in + * open-isns server. + */ + isns_target_deregister(target->name); + isns_target_register(target->name); + } + } } else if (strcasecmp(ISCSI_ISNS_SERVER_ATTR_NAME, pp) == 0) { if (target != NULL) { log_error("Not NULL target %s for global attribute %s", diff --git a/iscsi-scst/usr/iscsid.c b/iscsi-scst/usr/iscsid.c index 773fa5083..1ef94ce3c 100644 --- a/iscsi-scst/usr/iscsid.c +++ b/iscsi-scst/usr/iscsid.c @@ -921,6 +921,8 @@ static void login_start(struct connection *conn) return; } } + if (target->alias) + text_key_add(conn, "TargetAlias", target->alias); log_debug(1, "target %s, sessions_count %d", target_name, target->sessions_count); } diff --git a/iscsi-scst/usr/iscsid.h b/iscsi-scst/usr/iscsid.h index 4155d2ac7..69146bd2b 100644 --- a/iscsi-scst/usr/iscsid.h +++ b/iscsi-scst/usr/iscsid.h @@ -198,6 +198,7 @@ struct target { unsigned int tgt_enabled:1; unsigned int per_portal_acl:1; + unsigned int isns_registered:1; unsigned int target_params[target_key_last]; unsigned int session_params[session_key_last]; @@ -353,6 +354,7 @@ extern int nl_open(void); /* config.c */ extern char *config_sep_string(char **pp); +extern char *config_strip_string(char *s); extern int config_parse_main(const char *data, u32 cookie); extern int config_load(const char *config_name); extern int config_target_create(u32 *tid, char *name); diff --git a/iscsi-scst/usr/isns.c b/iscsi-scst/usr/isns.c index 75ffa8a88..323e00c53 100644 --- a/iscsi-scst/usr/isns.c +++ b/iscsi-scst/usr/isns.c @@ -482,7 +482,7 @@ int isns_target_register(char *name) uint32_t port = htonl(server_port); uint32_t node = htonl(ISNS_NODE_TARGET); uint32_t type = htonl(2); - struct target *target; + struct target *target, *alias_target; int err, initial = list_length_is_one(&targets_list); int max_buf; @@ -499,6 +499,7 @@ int isns_target_register(char *name) tlv = (struct isns_tlv *)hdr->pdu; max_buf = sizeof(buf) - offsetof(struct isns_hdr, pdu); + alias_target = target_find_by_name(name); if (strlen(isns_entity_target_name) < 1) { target = list_entry(targets_list.q_forw, struct target, tlist); err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_NAME, @@ -566,6 +567,14 @@ int isns_target_register(char *name) goto out; length += err; + if (alias_target && alias_target->alias) { + err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_ALIAS, + strlen(alias_target->alias) + 1, alias_target->alias); + if (err < 0) + goto out; + length += err; + } + err = isns_tlv_set(&tlv, max_buf - length, ISNS_ATTR_ISCSI_NODE_TYPE, sizeof(node), &node); if (err < 0) @@ -579,6 +588,8 @@ int isns_target_register(char *name) err = write(isns_fd, buf, length + sizeof(struct isns_hdr)); if (err < 0) log_error("%s %d: %s", __func__, __LINE__, strerror(errno)); + else if (alias_target) + alias_target->isns_registered = 1; if (scn_listen_port) isns_scn_register(); @@ -662,6 +673,9 @@ int isns_target_deregister(char *name) if (err < 0) log_error("%s %d: %s", __func__, __LINE__, strerror(errno)); + if (target) + target->isns_registered = 0; + out: return err; } diff --git a/iscsi-scst/usr/param.h b/iscsi-scst/usr/param.h index 994232c86..6a1d8b751 100644 --- a/iscsi-scst/usr/param.h +++ b/iscsi-scst/usr/param.h @@ -25,6 +25,7 @@ #define ISCSI_TARGET_REDIRECTION_ATTR_NAME "redirect" #define ISCSI_TARGET_REDIRECTION_VALUE_TEMP "temp" #define ISCSI_TARGET_REDIRECTION_VALUE_PERM "perm" +#define ISCSI_TARGET_ALIAS_ATTR_NAME "alias" struct iscsi_key; From c71c284f934766ef5feddfe175bd91fea7c2b11e Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Mon, 18 Sep 2023 14:23:07 +0300 Subject: [PATCH 59/93] nightly build: Update kernel versions Another kernel versions update following the 6.5 release. --- nightly/conf/nightly.conf | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/nightly/conf/nightly.conf b/nightly/conf/nightly.conf index 524607468..1f596da5f 100644 --- a/nightly/conf/nightly.conf +++ b/nightly/conf/nightly.conf @@ -3,38 +3,39 @@ ABT_DETAILS="x86_64" ABT_JOBS=5 ABT_KERNELS=" \ -6.4 \ -6.3.9-nc \ +6.5.4 \ +6.4.16-nc \ +6.3.13-nc \ 6.2.16-nc \ -6.1.35-nc \ +6.1.54-nc \ 6.0.19-nc \ 5.19.17-nc \ 5.18.19-nc \ 5.17.15-nc \ 5.16.20-nc \ -5.15.118-nc \ +5.15.132-nc \ 5.14.21-nc \ 5.13.19-nc \ 5.12.19-nc \ 5.11.22-nc \ -5.10.185-nc \ +5.10.195-nc \ 5.9.16-nc \ 5.8.18-nc \ 5.7.19-nc \ 5.6.19-nc \ 5.5.19-nc \ -5.4.248-nc \ +5.4.256-nc \ 5.3.18-nc \ 5.2.21-nc \ 5.1.21-nc \ 5.0.21-nc \ 4.20.17-nc \ -4.19.287-nc \ +4.19.294-nc \ 4.18.20-nc \ 4.17.19-nc \ 4.16.18-nc \ 4.15.18-nc \ -4.14.319-nc \ +4.14.325-nc \ 4.13.16-nc \ 4.12.14-nc \ 4.11.12-nc \ @@ -59,10 +60,10 @@ ABT_KERNELS=" \ 3.12.74-nc \ 3.11.10-nc \ 3.10.108-nc \ -5.14.0-284.11.1.el9_2^AlmaLinux^9.2-nc \ +5.14.0-284.30.1.el9_2^AlmaLinux^9.2-nc \ 5.14.0-162.23.1.el9_1^AlmaLinux^9.1-nc \ 5.14.0-70.30.1.el9_0^AlmaLinux^9.0-nc \ -4.18.0-477.13.1.el8_8^AlmaLinux^8.8-nc \ +4.18.0-477.21.1.el8_8^AlmaLinux^8.8-nc \ 4.18.0-425.19.2.el8_7^AlmaLinux^8.7-nc \ 4.18.0-372.32.1.el8_6^AlmaLinux^8.6-nc \ 4.18.0-348.2.1.el8_5^CentOS^8.5.2111-nc \ @@ -71,18 +72,18 @@ ABT_KERNELS=" \ 4.18.0-193.28.1.el8_2^CentOS^8.2.2004-nc \ 4.18.0-147.8.1.el8_1^CentOS^8.1.1911-nc \ 4.18.0-80.11.2.el8_0^CentOS^8.0.1905-nc \ -3.10.0-1160.90.1.el7^CentOS^7.9.2009-nc \ +3.10.0-1160.95.1.el7^CentOS^7.9.2009-nc \ 3.10.0-1127.19.1.el7^CentOS^7.8.2003-nc \ 3.10.0-1062.18.1.el7^CentOS^7.7.1908-nc \ 3.10.0-957.27.2.el7^CentOS^7.6.1810-nc \ 3.10.0-862.14.4.el7^CentOS^7.5.1804-nc \ -5.15.0-102.110.5.1.el9uek^UEK^9-nc \ -5.15.0-102.110.5.1.el8uek^UEK^8-nc \ -5.4.17-2136.320.7.1.el8uek^UEK^8-nc \ +5.15.0-105.125.6.2.1.el9uek^UEK^9-nc \ +5.15.0-105.125.6.2.1.el8uek^UEK^8-nc \ +5.4.17-2136.323.8.1.el8uek^UEK^8-nc \ 5.4.17-2102.206.1.el8uek^UEK^8-nc \ 5.4.17-2036.104.5.el8uek^UEK^8-nc \ 5.4.17-2011.7.4.el8uek^UEK^8-nc \ -5.4.17-2136.320.7.1.el7uek^UEK^7-nc \ +5.4.17-2136.323.8.1.el7uek^UEK^7-nc \ 5.4.17-2102.206.1.el7uek^UEK^7-nc \ 5.4.17-2036.104.5.el7uek^UEK^7-nc \ 5.4.17-2011.7.4.el7uek^UEK^7-nc \ From 60c26136bf9331ebd80828fc9f97b2a0b8acbdb2 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Sun, 24 Sep 2023 14:38:54 +0300 Subject: [PATCH 60/93] scst/include/backport.h: Unbreak the RHEL 9.3 build Fixes: https://github.com/SCST-project/scst/issues/167 --- scst/include/backport.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scst/include/backport.h b/scst/include/backport.h index a57cf531e..9691bddfd 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -1760,7 +1760,9 @@ enum { #define wwn_to_u64(wwn) get_unaligned_be64(wwn) #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 3, 0) && \ + (!defined(RHEL_RELEASE_CODE) || \ + RHEL_RELEASE_CODE -0 < RHEL_RELEASE_VERSION(9, 3)) /* * See also commit 64fd2ba977b1 ("scsi: scsi_transport_fc: Add an additional * flag to fc_host_fpin_rcv()") # v6.3 From 48e04668d62e76232645ae93ea02150349a18636 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Sat, 23 Sep 2023 10:51:37 +0300 Subject: [PATCH 61/93] qla2x00t: Drop redundant pci_enable_pcie_error_reporting() See also commits: - 7d1afe8a ("qla2x00t-32gbit: Drop redundant pci_enable_pcie_error_reporting()"). - 596800ce ("qla2x00t-32gbit: Backport to older kernel versions"). --- qla2x00t/qla_def.h | 4 ++++ qla2x00t/qla_os.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/qla2x00t/qla_def.h b/qla2x00t/qla_def.h index 19bdec1be..3e78f978a 100644 --- a/qla2x00t/qla_def.h +++ b/qla2x00t/qla_def.h @@ -7,7 +7,9 @@ #ifndef __QLA_DEF_H #define __QLA_DEF_H +#ifndef INSIDE_KERNEL_TREE #include +#endif #include #include #include @@ -24,7 +26,9 @@ #include #include #include +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) #include +#endif #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) || \ diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index 5d34b93d0..f9c3ea8d7 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -2367,8 +2367,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto probe_out; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) /* This may fail but that's ok */ pci_enable_pcie_error_reporting(pdev); +#endif ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL); if (!ha) { @@ -3020,7 +3022,9 @@ qla2x00_remove_one(struct pci_dev *pdev) kfree(ha); ha = NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0) pci_disable_pcie_error_reporting(pdev); +#endif pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } From 55ef00a79a9e9570b0f99b3ecfc3b35214f56f85 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Sat, 23 Sep 2023 11:01:49 +0300 Subject: [PATCH 62/93] qla2x00t: Avoid flush_scheduled_work() usage See also commit c014d35e7d88 ("qla2x00t-32gbit: Avoid flush_scheduled_work() usage"). --- qla2x00t/qla2x00-target/qla2x00t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t/qla2x00-target/qla2x00t.c b/qla2x00t/qla2x00-target/qla2x00t.c index c6aa31e3b..06ade1a19 100644 --- a/qla2x00t/qla2x00-target/qla2x00t.c +++ b/qla2x00t/qla2x00-target/qla2x00t.c @@ -1680,7 +1680,7 @@ static void q2t_target_stop(struct scst_tgt *scst_tgt) spin_lock_irq(&tgt->sess_work_lock); while (!list_empty(&tgt->sess_works_list)) { spin_unlock_irq(&tgt->sess_work_lock); - flush_scheduled_work(); + flush_work(&tgt->sess_work); spin_lock_irq(&tgt->sess_work_lock); } spin_unlock_irq(&tgt->sess_work_lock); From 4635193aa0f96defc58b8375d01d10c327c97302 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:18:36 +0300 Subject: [PATCH 63/93] qla2x00t-32gbit: Fix deletion race condition System crash when using debug kernel due to link list corruption. The cause of the link list corruption is due to session deletion was allowed to queue up twice. Here's the internal trace that show the same port was allowed to double queue for deletion on different cpu. 20808683956 015 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1 20808683957 027 qla2xxx [0000:13:00.1]-e801:4: Scheduling sess ffff93ebf9306800 for deletion 50:06:0e:80:12:48:ff:50 fc4_type 1 Move the clearing/setting of deleted flag lock. Cc: stable@vger.kernel.org Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-2-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 6dfe4344c168 upstream ] --- qla2x00t-32gbit/qla_init.c | 16 ++++++++++++++-- qla2x00t-32gbit/qla_target.c | 14 +++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 980c8f7d0..79b429f93 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -508,6 +508,7 @@ static void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) { struct fc_port *fcport = ea->fcport; + unsigned long flags; ql_dbg(ql_dbg_disc, vha, 0x20d2, "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n", @@ -522,9 +523,15 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) ql_dbg(ql_dbg_disc, vha, 0x2066, "%s %8phC: adisc fail: post delete\n", __func__, ea->fcport->port_name); + + spin_lock_irqsave(&vha->work_lock, flags); /* deleted = 0 & logout_on_delete = force fw cleanup */ - fcport->deleted = 0; + if (fcport->deleted == QLA_SESS_DELETED) + fcport->deleted = 0; + fcport->logout_on_delete = 1; + spin_unlock_irqrestore(&vha->work_lock, flags); + qlt_schedule_sess_for_deletion(ea->fcport); return; } @@ -1446,7 +1453,6 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); ea->fcport->login_gen++; - ea->fcport->deleted = 0; ea->fcport->logout_on_delete = 1; if (!ea->fcport->login_succ && !IS_SW_RESV_ADDR(ea->fcport->d_id)) { @@ -6093,6 +6099,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) void qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) { + unsigned long flags; + if (IS_SW_RESV_ADDR(fcport->d_id)) return; @@ -6102,7 +6110,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT); fcport->login_retry = vha->hw->login_retry_count; fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); + + spin_lock_irqsave(&vha->work_lock, flags); fcport->deleted = 0; + spin_unlock_irqrestore(&vha->work_lock, flags); + if (vha->hw->current_topology == ISP_CFG_NL) fcport->logout_on_delete = 0; else diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index 9c19ba172..564819a4d 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -1083,10 +1083,6 @@ void qlt_free_session_done(struct work_struct *work) (struct imm_ntfy_from_isp *)sess->iocb, SRB_NACK_LOGO); } - spin_lock_irqsave(&vha->work_lock, flags); - sess->flags &= ~FCF_ASYNC_SENT; - spin_unlock_irqrestore(&vha->work_lock, flags); - spin_lock_irqsave(&ha->tgt.sess_lock, flags); if (sess->se_sess) { sess->se_sess = NULL; @@ -1096,7 +1092,6 @@ void qlt_free_session_done(struct work_struct *work) qla2x00_set_fcport_disc_state(sess, DSC_DELETED); sess->fw_login_state = DSC_LS_PORT_UNAVAIL; - sess->deleted = QLA_SESS_DELETED; if (sess->login_succ && !IS_SW_RESV_ADDR(sess->d_id)) { vha->fcport_count--; @@ -1148,10 +1143,15 @@ void qlt_free_session_done(struct work_struct *work) sess->explicit_logout = 0; spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); - sess->free_pending = 0; qla2x00_dfs_remove_rport(vha, sess); + spin_lock_irqsave(&vha->work_lock, flags); + sess->flags &= ~FCF_ASYNC_SENT; + sess->deleted = QLA_SESS_DELETED; + sess->free_pending = 0; + spin_unlock_irqrestore(&vha->work_lock, flags); + ql_dbg(ql_dbg_disc, vha, 0xf001, "Unregistration of sess %p %8phC finished fcp_cnt %d\n", sess, sess->port_name, vha->fcport_count); @@ -1200,12 +1200,12 @@ void qlt_unreg_sess(struct fc_port *sess) * management from being sent. */ sess->flags |= FCF_ASYNC_SENT; + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; spin_unlock_irqrestore(&sess->vha->work_lock, flags); if (sess->se_sess) vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); - sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; qla2x00_set_fcport_disc_state(sess, DSC_DELETE_PEND); sess->last_rscn_gen = sess->rscn_gen; sess->last_login_gen = sess->login_gen; From a4d55cd6bb0854dbb40ca782007ec2a32018aa54 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:19:49 +0300 Subject: [PATCH 64/93] qla2x00t-32gbit: Adjust IOCB resource on qpair create During NVMe queue creation, a new qpair is created. FW resource limit needs to be re-adjusted to take into account the new qpair. Otherwise, NVMe command can not go through. This issue was discovered while testing/forcing FW execution to fail at load time. Add call to readjust IOCB and exchange limit. In addition, get FW state command and require FW to be running. Otherwise, error is generated. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-3-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit efa74a62aaa2 upstream ] --- qla2x00t-32gbit/qla_gbl.h | 1 + qla2x00t-32gbit/qla_init.c | 52 ++++++++++++++++++++++++-------------- qla2x00t-32gbit/qla_mbx.c | 3 +++ qla2x00t-32gbit/qla_nvme.c | 1 + 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index d397c983e..b70f72a04 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -143,6 +143,7 @@ void qla_edif_sess_down(struct scsi_qla_host *vha, struct fc_port *sess); void qla_edif_clear_appdata(struct scsi_qla_host *vha, struct fc_port *fcport); const char *sc_to_str(uint16_t cmd); +void qla_adjust_iocb_limit(scsi_qla_host_t *vha); /* * Global Data in qla_os.c source file. diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 79b429f93..2cd8f76f7 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4156,41 +4156,55 @@ qla24xx_detect_sfp(scsi_qla_host_t *vha) return ha->flags.lr_detected; } -void qla_init_iocb_limit(scsi_qla_host_t *vha) +static void __qla_adjust_iocb_limit(struct qla_qpair *qpair) { - u16 i, num_qps; - u32 limit; - struct qla_hw_data *ha = vha->hw; + u8 num_qps; + u16 limit; + struct qla_hw_data *ha = qpair->vha->hw; num_qps = ha->num_qpairs + 1; limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100; - ha->base_qpair->fwres.iocbs_total = ha->orig_fw_iocb_count; - ha->base_qpair->fwres.iocbs_limit = limit; - ha->base_qpair->fwres.iocbs_qp_limit = limit / num_qps; - ha->base_qpair->fwres.iocbs_used = 0; + qpair->fwres.iocbs_total = ha->orig_fw_iocb_count; + qpair->fwres.iocbs_limit = limit; + qpair->fwres.iocbs_qp_limit = limit / num_qps; + + qpair->fwres.exch_total = ha->orig_fw_xcb_count; + qpair->fwres.exch_limit = (ha->orig_fw_xcb_count * + QLA_IOCB_PCT_LIMIT) / 100; +} + +void qla_init_iocb_limit(scsi_qla_host_t *vha) +{ + u8 i; + struct qla_hw_data *ha = vha->hw; - ha->base_qpair->fwres.exch_total = ha->orig_fw_xcb_count; - ha->base_qpair->fwres.exch_limit = (ha->orig_fw_xcb_count * - QLA_IOCB_PCT_LIMIT) / 100; + __qla_adjust_iocb_limit(ha->base_qpair); + ha->base_qpair->fwres.iocbs_used = 0; ha->base_qpair->fwres.exch_used = 0; for (i = 0; i < ha->max_qpairs; i++) { if (ha->queue_pair_map[i]) { - ha->queue_pair_map[i]->fwres.iocbs_total = - ha->orig_fw_iocb_count; - ha->queue_pair_map[i]->fwres.iocbs_limit = limit; - ha->queue_pair_map[i]->fwres.iocbs_qp_limit = - limit / num_qps; + __qla_adjust_iocb_limit(ha->queue_pair_map[i]); ha->queue_pair_map[i]->fwres.iocbs_used = 0; - ha->queue_pair_map[i]->fwres.exch_total = ha->orig_fw_xcb_count; - ha->queue_pair_map[i]->fwres.exch_limit = - (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100; ha->queue_pair_map[i]->fwres.exch_used = 0; } } } +void qla_adjust_iocb_limit(scsi_qla_host_t *vha) +{ + u8 i; + struct qla_hw_data *ha = vha->hw; + + __qla_adjust_iocb_limit(ha->base_qpair); + + for (i = 0; i < ha->max_qpairs; i++) { + if (ha->queue_pair_map[i]) + __qla_adjust_iocb_limit(ha->queue_pair_map[i]); + } +} + /** * qla2x00_setup_chip() - Load and start RISC firmware. * @vha: HA context diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index 254fd4c64..b05f93037 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -2213,6 +2213,9 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1054, "Entered %s.\n", __func__); + if (!ha->flags.fw_started) + return QLA_FUNCTION_FAILED; + mcp->mb[0] = MBC_GET_FIRMWARE_STATE; mcp->out_mb = MBX_0; if (IS_FWI2_CAPABLE(vha->hw)) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index c3ae67fc7..da3c47996 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -147,6 +147,7 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport, "Failed to allocate qpair\n"); return -EINVAL; } + qla_adjust_iocb_limit(vha); } *handle = qpair; From 10a4c6ef3e110443e05eec46da400115e10d21ad Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:20:19 +0300 Subject: [PATCH 65/93] qla2x00t-32gbit: Limit TMF to 8 per function Per FW recommendation, 8 TMF's can be outstanding for each function. Previously, it allowed 8 per target. Limit TMF to 8 per function. Cc: stable@vger.kernel.org Fixes: 6a87679626b5 ("scsi: qla2xxx: Fix task management cmd fail due to unavailable resource") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit a8ec192427e0 upstream ] --- qla2x00t-32gbit/qla_def.h | 9 ++++--- qla2x00t-32gbit/qla_init.c | 55 +++++++++++++++++++++++--------------- qla2x00t-32gbit/qla_os.c | 2 ++ 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 5a3a51921..406d74298 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -509,6 +509,7 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id) } struct tmf_arg { + struct list_head tmf_elem; struct qla_qpair *qpair; struct fc_port *fcport; struct scsi_qla_host *vha; @@ -2592,7 +2593,6 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; - struct list_head tmf_pending; unsigned int conf_compl_supported:1; unsigned int deleted:2; @@ -2613,9 +2613,6 @@ typedef struct fc_port { unsigned int do_prli_nvme:1; uint8_t nvme_flag; - uint8_t active_tmf; -#define MAX_ACTIVE_TMF 8 - uint8_t node_name[WWN_SIZE]; uint8_t port_name[WWN_SIZE]; port_id_t d_id; @@ -4708,6 +4705,8 @@ struct qla_hw_data { uint32_t flt_region_aux_img_status_sec; }; uint8_t active_image; + uint8_t active_tmf; +#define MAX_ACTIVE_TMF 8 /* Needed for BEACON */ uint16_t beacon_blink_led; @@ -4722,6 +4721,8 @@ struct qla_hw_data { struct qla_msix_entry *msix_entries; + struct list_head tmf_pending; + struct list_head tmf_active; struct list_head vp_list; /* list of VP */ unsigned long vp_idx_map[(MAX_MULTI_ID_FABRIC / 8) / sizeof(unsigned long)]; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 2cd8f76f7..270ae9f94 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2192,30 +2192,42 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) return rval; } -static void qla_put_tmf(fc_port_t *fcport) +static void qla_put_tmf(struct tmf_arg *arg) { - struct scsi_qla_host *vha = fcport->vha; + struct scsi_qla_host *vha = arg->vha; struct qla_hw_data *ha = vha->hw; unsigned long flags; spin_lock_irqsave(&ha->tgt.sess_lock, flags); - fcport->active_tmf--; + ha->active_tmf--; + list_del(&arg->tmf_elem); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); } static -int qla_get_tmf(fc_port_t *fcport) +int qla_get_tmf(struct tmf_arg *arg) { - struct scsi_qla_host *vha = fcport->vha; + struct scsi_qla_host *vha = arg->vha; struct qla_hw_data *ha = vha->hw; unsigned long flags; + fc_port_t *fcport = arg->fcport; int rc = 0; - LIST_HEAD(tmf_elem); + struct tmf_arg *t; spin_lock_irqsave(&ha->tgt.sess_lock, flags); - list_add_tail(&tmf_elem, &fcport->tmf_pending); + list_for_each_entry(t, &ha->tmf_active, tmf_elem) { + if (t->fcport == arg->fcport && t->lun == arg->lun) { + /* reject duplicate TMF */ + ql_log(ql_log_warn, vha, 0x802c, + "found duplicate TMF. Nexus=%ld:%06x:%llu.\n", + vha->host_no, fcport->d_id.b24, arg->lun); + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + return -EINVAL; + } + } - while (fcport->active_tmf >= MAX_ACTIVE_TMF) { + list_add_tail(&arg->tmf_elem, &ha->tmf_pending); + while (ha->active_tmf >= MAX_ACTIVE_TMF) { spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); msleep(1); @@ -2227,15 +2239,17 @@ int qla_get_tmf(fc_port_t *fcport) rc = EIO; break; } - if (fcport->active_tmf < MAX_ACTIVE_TMF && - list_is_first(&tmf_elem, &fcport->tmf_pending)) + if (ha->active_tmf < MAX_ACTIVE_TMF && + list_is_first(&arg->tmf_elem, &ha->tmf_pending)) break; } - list_del(&tmf_elem); + list_del(&arg->tmf_elem); - if (!rc) - fcport->active_tmf++; + if (!rc) { + ha->active_tmf++; + list_add_tail(&arg->tmf_elem, &ha->tmf_active); + } spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); @@ -2257,15 +2271,18 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, a.vha = fcport->vha; a.fcport = fcport; a.lun = lun; + a.flags = flags; + INIT_LIST_HEAD(&a.tmf_elem); + if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) { a.modifier = MK_SYNC_ID_LUN; - - if (qla_get_tmf(fcport)) - return QLA_FUNCTION_FAILED; } else { a.modifier = MK_SYNC_ID; } + if (qla_get_tmf(&a)) + return QLA_FUNCTION_FAILED; + if (vha->hw->mqenable) { for (i = 0; i < vha->hw->num_qpairs; i++) { qpair = vha->hw->queue_pair_map[i]; @@ -2291,13 +2308,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, goto bailout; a.qpair = vha->hw->base_qpair; - a.flags = flags; rval = __qla2x00_async_tm_cmd(&a); bailout: - if (a.modifier == MK_SYNC_ID_LUN) - qla_put_tmf(fcport); - + qla_put_tmf(&a); return rval; } @@ -5529,7 +5543,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); - INIT_LIST_HEAD(&fcport->tmf_pending); INIT_LIST_HEAD(&fcport->sess_cmd_list); spin_lock_init(&fcport->sess_cmd_lock); diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index d83151df5..732fda143 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3066,6 +3066,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) atomic_set(&ha->num_pend_mbx_stage3, 0); atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD); ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD; + INIT_LIST_HEAD(&ha->tmf_pending); + INIT_LIST_HEAD(&ha->tmf_active); /* Assign ISP specific operations. */ if (IS_QLA2100(ha)) { From 1b69e76c4839aaf905ab5a09037bfcd00c5d8811 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:20:40 +0300 Subject: [PATCH 66/93] qla2x00t-32gbit: Fix command flush during TMF For each TMF request, driver iterates through each qpair and flushes commands associated to the TMF. At the end of the qpair flush, a Marker is used to complete the flush transaction. This process was repeated for each qpair. The multiple flush and marker for this TMF request seems to cause confusion for FW. Instead, 1 flush is sent to FW. Driver would wait for FW to go through all the I/Os on each qpair to be read then return. Driver then closes out the transaction with a Marker. Cc: stable@vger.kernel.org Fixes: d90171dd0da5 ("scsi: qla2xxx: Multi-que support for TMF") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-5-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit da7c21b72aa8 upstream ] --- qla2x00t-32gbit/qla_init.c | 74 ++++++++++++++++++++------------------ qla2x00t-32gbit/qla_iocb.c | 1 + qla2x00t-32gbit/qla_os.c | 9 ++--- 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 270ae9f94..921527850 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2002,12 +2002,11 @@ qla2x00_tmf_iocb_timeout(void *data) int rc, h; unsigned long flags; - if (sp->type == SRB_MARKER) { - complete(&tmf->u.tmf.comp); - return; - } + if (sp->type == SRB_MARKER) + rc = QLA_FUNCTION_FAILED; + else + rc = qla24xx_async_abort_cmd(sp, false); - rc = qla24xx_async_abort_cmd(sp, false); if (rc) { spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags); for (h = 1; h < sp->qpair->req->num_outstanding_cmds; h++) { @@ -2129,6 +2128,17 @@ static void qla2x00_tmf_sp_done(srb_t *sp, int res) complete(&tmf->u.tmf.comp); } +static int qla_tmf_wait(struct tmf_arg *arg) +{ + /* there are only 2 types of error handling that reaches here, lun or target reset */ + if (arg->flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET | TCF_CLEAR_TASK_SET)) + return qla2x00_eh_wait_for_pending_commands(arg->vha, + arg->fcport->d_id.b24, arg->lun, WAIT_LUN); + else + return qla2x00_eh_wait_for_pending_commands(arg->vha, + arg->fcport->d_id.b24, arg->lun, WAIT_TARGET); +} + static int __qla2x00_async_tm_cmd(struct tmf_arg *arg) { @@ -2136,8 +2146,9 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) struct srb_iocb *tm_iocb; srb_t *sp; int rval = QLA_FUNCTION_FAILED; - fc_port_t *fcport = arg->fcport; + u32 chip_gen, login_gen; + u64 jif; if (TMF_NOT_READY(arg->fcport)) { ql_dbg(ql_dbg_taskm, vha, 0x8032, @@ -2182,8 +2193,27 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) "TM IOCB failed (%x).\n", rval); } - if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) - rval = qla26xx_marker(arg); + if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { + chip_gen = vha->hw->chip_reset; + login_gen = fcport->login_gen; + + jif = jiffies; + if (qla_tmf_wait(arg)) { + ql_log(ql_log_info, vha, 0x803e, + "Waited %u ms Nexus=%ld:%06x:%llu.\n", + jiffies_to_msecs(jiffies - jif), vha->host_no, + fcport->d_id.b24, arg->lun); + } + + if (chip_gen == vha->hw->chip_reset && login_gen == fcport->login_gen) { + rval = qla26xx_marker(arg); + } else { + ql_log(ql_log_info, vha, 0x803e, + "Skip Marker due to disruption. Nexus=%ld:%06x:%llu.\n", + vha->host_no, fcport->d_id.b24, arg->lun); + rval = QLA_FUNCTION_FAILED; + } + } done_free_sp: /* ref: INIT */ @@ -2261,9 +2291,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, uint32_t tag) { struct scsi_qla_host *vha = fcport->vha; - struct qla_qpair *qpair; struct tmf_arg a; - int i, rval = QLA_SUCCESS; + int rval = QLA_SUCCESS; if (TMF_NOT_READY(fcport)) return QLA_SUSPENDED; @@ -2283,34 +2312,9 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun, if (qla_get_tmf(&a)) return QLA_FUNCTION_FAILED; - if (vha->hw->mqenable) { - for (i = 0; i < vha->hw->num_qpairs; i++) { - qpair = vha->hw->queue_pair_map[i]; - if (!qpair) - continue; - - if (TMF_NOT_READY(fcport)) { - ql_log(ql_log_warn, vha, 0x8026, - "Unable to send TM due to disruption.\n"); - rval = QLA_SUSPENDED; - break; - } - - a.qpair = qpair; - a.flags = flags|TCF_NOTMCMD_TO_TARGET; - rval = __qla2x00_async_tm_cmd(&a); - if (rval) - break; - } - } - - if (rval) - goto bailout; - a.qpair = vha->hw->base_qpair; rval = __qla2x00_async_tm_cmd(&a); -bailout: qla_put_tmf(&a); return rval; } diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 6670b3777..8134648b7 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -3898,6 +3898,7 @@ qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) { mrk->entry_type = MARKER_TYPE; mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; + mrk->handle = make_handle(sp->qpair->req->id, sp->handle); if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) { mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id); int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 732fda143..9a273c908 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -1529,8 +1529,9 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) goto eh_reset_failed; } err = 3; - if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id, - sdev->lun, WAIT_LUN) != QLA_SUCCESS) { + if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24, + cmd->device->lun, + WAIT_LUN) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x800d, "wait for pending cmds failed for cmd=%p.\n", cmd); goto eh_reset_failed; @@ -1596,8 +1597,8 @@ qla2xxx_eh_target_reset(struct scsi_cmnd *cmd) goto eh_reset_failed; } err = 3; - if (qla2x00_eh_wait_for_pending_commands(vha, sdev->id, - 0, WAIT_TARGET) != QLA_SUCCESS) { + if (qla2x00_eh_wait_for_pending_commands(vha, fcport->d_id.b24, 0, + WAIT_TARGET) != QLA_SUCCESS) { ql_log(ql_log_warn, vha, 0x800d, "wait for pending cmds failed for cmd=%p.\n", cmd); goto eh_reset_failed; From e9ff9ea91c5699c31ec7ee3e90bd059e3997999d Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:21:11 +0300 Subject: [PATCH 67/93] qla2x00t-32gbit: Fix erroneous link up failure Link up failure occurred where driver failed to see certain events from FW indicating link up (AEN 8011) and fabric login completion (AEN 8014). Without these 2 events, driver would not proceed forward to scan the fabric. The cause of this is due to delay in the receive of interrupt for Mailbox 60 that causes qla to set the fw_started flag late. The late setting of this flag causes other interrupts to be dropped. These dropped interrupts happen to be the link up (AEN 8011) and fabric login completion (AEN 8014). Set fw_started flag early to prevent interrupts being dropped. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-6-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 5b51f35d127e upstream ] --- qla2x00t-32gbit/qla_init.c | 3 ++- qla2x00t-32gbit/qla_isr.c | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 921527850..137013852 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4818,15 +4818,16 @@ qla2x00_init_rings(scsi_qla_host_t *vha) if (ha->flags.edif_enabled) mid_init_cb->init_cb.frame_payload_size = cpu_to_le16(ELS_MAX_PAYLOAD); + QLA_FW_STARTED(ha); rval = qla2x00_init_firmware(vha, ha->init_cb_size); next_check: if (rval) { + QLA_FW_STOPPED(ha); ql_log(ql_log_fatal, vha, 0x00d2, "Init Firmware **** FAILED ****.\n"); } else { ql_dbg(ql_dbg_init, vha, 0x00d3, "Init Firmware -- success.\n"); - QLA_FW_STARTED(ha); vha->u_ql2xexchoffld = vha->u_ql2xiniexchg = 0; } diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index a238f3fe8..4f569748a 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -1133,8 +1133,12 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) unsigned long flags; fc_port_t *fcport = NULL; - if (!vha->hw->flags.fw_started) + if (!vha->hw->flags.fw_started) { + ql_log(ql_log_warn, vha, 0x50ff, + "Dropping AEN - %04x %04x %04x %04x.\n", + mb[0], mb[1], mb[2], mb[3]); return; + } /* Setup to process RIO completion. */ handle_cnt = 0; From 4fdb8a5c66eccd79f0f413423c4e64e3a5a07239 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:21:36 +0300 Subject: [PATCH 68/93] qla2x00t-32gbit: Fix session hang in gnl Connection does not resume after a host reset / chip reset. The cause of the blockage is due to the FCF_ASYNC_ACTIVE left on. The gnl command was interrupted by the chip reset. On exiting the command, this flag should be turn off to allow relogin to reoccur. Clear this flag to prevent blockage. Cc: stable@vger.kernel.org Fixes: 17e64648aa47 ("scsi: qla2xxx: Correct fcport flags handling") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-7-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 39d22740712c upstream ] --- qla2x00t-32gbit/qla_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 137013852..5ea1532b5 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -1141,7 +1141,7 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) u16 *mb; if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT)) - return rval; + goto done; ql_dbg(ql_dbg_disc, vha, 0x20d9, "Async-gnlist WWPN %8phC \n", fcport->port_name); @@ -1195,8 +1195,9 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) done_free_sp: /* ref: INIT */ kref_put(&sp->cmd_kref, qla2x00_sp_release); + fcport->flags &= ~(FCF_ASYNC_SENT); done: - fcport->flags &= ~(FCF_ASYNC_ACTIVE | FCF_ASYNC_SENT); + fcport->flags &= ~(FCF_ASYNC_ACTIVE); return rval; } From 0f032534c662532855eef8156ee191e802b5c23d Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:22:02 +0300 Subject: [PATCH 69/93] qla2x00t-32gbit: Turn off noisy message log Some consider noisy log as test failure. Turn off noisy message log. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-8-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 8ebaa45163a3 upstream ] --- qla2x00t-32gbit/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index da3c47996..da2988df8 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -683,7 +683,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, rval = qla2x00_start_nvme_mq(sp); if (rval != QLA_SUCCESS) { - ql_log(ql_log_warn, vha, 0x212d, + ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x212d, "qla2x00_start_nvme_mq failed = %d\n", rval); sp->priv = NULL; priv->sp = NULL; From 014cc2d4f802d9c7f2af9ea9b53fb18a941aac0b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:22:22 +0300 Subject: [PATCH 70/93] qla2x00t-32gbit: Fix TMF leak through Task management can retry up to 5 times when FW resource becomes bottle neck. Between the retries, there is a short sleep. Current code assumes the chip has not reset or session has not changed. Check for chip reset or session change before sending Task management. Cc: stable@vger.kernel.org Fixes: 9803fb5d2759 ("scsi: qla2xxx: Fix task management cmd failure") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-9-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 5d3148d8e8b0 upstream ] --- qla2x00t-32gbit/qla_init.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 5ea1532b5..e7946dec4 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2038,10 +2038,14 @@ static void qla_marker_sp_done(srb_t *sp, int res) complete(&tmf->u.tmf.comp); } -#define START_SP_W_RETRIES(_sp, _rval) \ +#define START_SP_W_RETRIES(_sp, _rval, _chip_gen, _login_gen) \ {\ int cnt = 5; \ do { \ + if (_chip_gen != sp->vha->hw->chip_reset || _login_gen != sp->fcport->login_gen) {\ + _rval = EINVAL; \ + break; \ + } \ _rval = qla2x00_start_sp(_sp); \ if (_rval == EAGAIN) \ msleep(1); \ @@ -2064,6 +2068,7 @@ qla26xx_marker(struct tmf_arg *arg) srb_t *sp; int rval = QLA_FUNCTION_FAILED; fc_port_t *fcport = arg->fcport; + u32 chip_gen, login_gen; if (TMF_NOT_READY(arg->fcport)) { ql_dbg(ql_dbg_taskm, vha, 0x8039, @@ -2073,6 +2078,9 @@ qla26xx_marker(struct tmf_arg *arg) return QLA_SUSPENDED; } + chip_gen = vha->hw->chip_reset; + login_gen = fcport->login_gen; + /* ref: INIT */ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) @@ -2090,7 +2098,7 @@ qla26xx_marker(struct tmf_arg *arg) tm_iocb->u.tmf.loop_id = fcport->loop_id; tm_iocb->u.tmf.vp_index = vha->vp_idx; - START_SP_W_RETRIES(sp, rval); + START_SP_W_RETRIES(sp, rval, chip_gen, login_gen); ql_dbg(ql_dbg_taskm, vha, 0x8006, "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n", @@ -2159,6 +2167,9 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) return QLA_SUSPENDED; } + chip_gen = vha->hw->chip_reset; + login_gen = fcport->login_gen; + /* ref: INIT */ sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL); if (!sp) @@ -2176,7 +2187,7 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) tm_iocb->u.tmf.flags = arg->flags; tm_iocb->u.tmf.lun = arg->lun; - START_SP_W_RETRIES(sp, rval); + START_SP_W_RETRIES(sp, rval, chip_gen, login_gen); ql_dbg(ql_dbg_taskm, vha, 0x802f, "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n", @@ -2195,9 +2206,6 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) } if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw)) { - chip_gen = vha->hw->chip_reset; - login_gen = fcport->login_gen; - jif = jiffies; if (qla_tmf_wait(arg)) { ql_log(ql_log_info, vha, 0x803e, From 5795b2ad9d18dde3d502f3ee70ce5b9e3bc38339 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:22:42 +0300 Subject: [PATCH 71/93] qla2x00t-32gbit: fix inconsistent TMF timeout Different behavior were experienced of session being torn down vs not when TMF is timed out. When FW detects the time out, the session is torn down. When driver detects the time out, the session is not torn down. Allow TMF error to return to upper layer without session tear down. Cc: stable@vger.kernel.org Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-10-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 009e7fe4a1ed upstream ] --- qla2x00t-32gbit/qla_isr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 4f569748a..49bfdc69d 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -2555,7 +2555,6 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) case CS_PORT_BUSY: case CS_INCOMPLETE: case CS_PORT_UNAVAILABLE: - case CS_TIMEOUT: case CS_RESET: if (atomic_read(&fcport->state) == FCS_ONLINE) { ql_dbg(ql_dbg_disc, fcport->vha, 0x3021, From b082deba1275d3a4af9bd77fc01ed26d1d2efb45 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:23:13 +0300 Subject: [PATCH 72/93] qla2x00t-32gbit: Update version to 10.02.08.500-k Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230714070104.40052-11-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit a31a596a4265 upstream ] --- qla2x00t-32gbit/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index e3771923b..81bdf6b03 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.400-k" +#define QLA2XXX_VERSION "10.02.08.500-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 400 +#define QLA_DRIVER_BETA_VER 500 From 83393aa2845799c351c800d813dd180386f2336f Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:23:35 +0300 Subject: [PATCH 73/93] qla2x00t-32gbit: Remove unused declarations These declarations are not used anymore, remove them. Signed-off-by: Yue Haibing Link: https://lore.kernel.org/r/20230816130842.16684-1-yuehaibing@huawei.com Signed-off-by: Martin K. Petersen [ commit 1e4474c84554 upstream ] --- qla2x00t-32gbit/qla_gbl.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index b70f72a04..c7539ea35 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -48,8 +48,6 @@ extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool); extern void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha, struct els_plogi *els_plogi); -extern void qla2x00_update_fcports(scsi_qla_host_t *); - extern int qla2x00_abort_isp(scsi_qla_host_t *); extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *); extern void qla2x00_quiesce_io(scsi_qla_host_t *); @@ -212,8 +210,6 @@ extern int qla2x00_post_async_logout_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); extern int qla2x00_post_async_adisc_work(struct scsi_qla_host *, fc_port_t *, uint16_t *); -extern int qla2x00_post_async_adisc_done_work(struct scsi_qla_host *, - fc_port_t *, uint16_t *); extern int qla2x00_set_exlogins_buffer(struct scsi_qla_host *); extern void qla2x00_free_exlogin_buffer(struct qla_hw_data *); extern int qla2x00_set_exchoffld_buffer(struct scsi_qla_host *); @@ -223,7 +219,6 @@ extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *); extern struct scsi_qla_host *qla2x00_create_host(const struct scsi_host_template *, struct qla_hw_data *); -extern void qla2x00_free_host(struct scsi_qla_host *); extern void qla2x00_relogin(struct scsi_qla_host *); extern void qla2x00_do_work(struct scsi_qla_host *); extern void qla2x00_free_fcports(struct scsi_qla_host *); @@ -245,13 +240,10 @@ extern int __qla83xx_clear_drv_presence(scsi_qla_host_t *vha); extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32); extern void qla2x00_disable_board_on_pci_error(struct work_struct *); -extern void qla_eeh_work(struct work_struct *); extern void qla2x00_sp_compl(srb_t *sp, int); extern void qla2xxx_qpair_sp_free_dma(srb_t *sp); extern void qla2xxx_qpair_sp_compl(srb_t *sp, int); extern void qla24xx_sched_upd_fcport(fc_port_t *); -void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *, - uint16_t *); int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_post_relogin_work(struct scsi_qla_host *vha); void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *); @@ -735,7 +727,6 @@ int qla24xx_post_gpsc_work(struct scsi_qla_host *, fc_port_t *); int qla24xx_async_gpsc(scsi_qla_host_t *, fc_port_t *); void qla24xx_handle_gpsc_event(scsi_qla_host_t *, struct event_arg *); int qla2x00_mgmt_svr_login(scsi_qla_host_t *); -void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea); int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport, bool); int qla24xx_async_gpnft(scsi_qla_host_t *, u8, srb_t *); void qla24xx_async_gpnft_done(scsi_qla_host_t *, srb_t *); @@ -865,7 +856,6 @@ extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *); /* Interrupt related */ extern irqreturn_t qla82xx_intr_handler(int, void *); -extern irqreturn_t qla82xx_msi_handler(int, void *); extern irqreturn_t qla82xx_msix_default(int, void *); extern irqreturn_t qla82xx_msix_rsp_q(int, void *); extern void qla82xx_enable_intrs(struct qla_hw_data *); From a08f4369b3f3b5a81785384953721a0e699d42d8 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:24:08 +0300 Subject: [PATCH 74/93] qla2x00t-32gbit: Move resource to allow code reuse dsd_list contains a list of dsd buffer resources allocated during traffic time. It resides in the qla_hw_data location where some of the code is not reusable. Move this list to qpair to allow reuse by either single queue or multi queue adapter / code. Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230817063132.21900-2-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit efeda3bf912f upstream ] --- qla2x00t-32gbit/qla_def.h | 11 ++++++----- qla2x00t-32gbit/qla_init.c | 14 ++++++++++++++ qla2x00t-32gbit/qla_iocb.c | 20 ++++++++++---------- qla2x00t-32gbit/qla_os.c | 36 +++++++++++++++++------------------- 4 files changed, 47 insertions(+), 34 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 406d74298..138867c66 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3839,6 +3839,12 @@ struct qla_qpair { uint16_t id; /* qp number used with FW */ uint16_t vp_idx; /* vport ID */ + + uint16_t dsd_inuse; + uint16_t dsd_avail; + struct list_head dsd_list; +#define NUM_DSD_CHAIN 4096 + mempool_t *srb_mempool; struct pci_dev *pdev; @@ -4766,11 +4772,6 @@ struct qla_hw_data { struct fw_blob *hablob; struct qla82xx_legacy_intr_set nx_legacy_intr; - uint16_t gbl_dsd_inuse; - uint16_t gbl_dsd_avail; - struct list_head gbl_dsd_list; -#define NUM_DSD_CHAIN 4096 - uint8_t fw_type; uint32_t file_prd_off; /* File firmware product offset */ diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index e7946dec4..3b5e11fe7 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -9646,6 +9646,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->vp_idx = vp_idx; qpair->fw_started = ha->flags.fw_started; INIT_LIST_HEAD(&qpair->hints_list); + INIT_LIST_HEAD(&qpair->dsd_list); qpair->chip_reset = ha->base_qpair->chip_reset; qpair->enable_class_2 = ha->base_qpair->enable_class_2; qpair->enable_explicit_conf = @@ -9774,6 +9775,19 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair) if (ret != QLA_SUCCESS) goto fail; + if (!list_empty(&qpair->dsd_list)) { + struct dsd_dma *dsd_ptr, *tdsd_ptr; + + /* clean up allocated prev pool */ + list_for_each_entry_safe(dsd_ptr, tdsd_ptr, + &qpair->dsd_list, list) { + dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr, + dsd_ptr->dsd_list_dma); + list_del(&dsd_ptr->list); + kfree(dsd_ptr); + } + } + mutex_lock(&ha->mq_lock); ha->queue_pair_map[qpair->id] = NULL; clear_bit(qpair->id, ha->qpair_qid_map); diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 8134648b7..88272d9ab 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -642,14 +642,13 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, tot_dsds -= avail_dsds; dsd_list_len = (avail_dsds + 1) * QLA_DSD_SIZE; - dsd_ptr = list_first_entry(&ha->gbl_dsd_list, - struct dsd_dma, list); + dsd_ptr = list_first_entry(&qpair->dsd_list, struct dsd_dma, list); next_dsd = dsd_ptr->dsd_addr; list_del(&dsd_ptr->list); - ha->gbl_dsd_avail--; + qpair->dsd_avail--; list_add_tail(&dsd_ptr->list, &ctx->dsd_list); ctx->dsd_use_cnt++; - ha->gbl_dsd_inuse++; + qpair->dsd_inuse++; if (first_iocb) { first_iocb = 0; @@ -3384,6 +3383,7 @@ qla82xx_start_scsi(srb_t *sp) struct qla_hw_data *ha = vha->hw; struct req_que *req = NULL; struct rsp_que *rsp = NULL; + struct qla_qpair *qpair = sp->qpair; /* Setup device pointers. */ reg = &ha->iobase->isp82; @@ -3432,18 +3432,18 @@ qla82xx_start_scsi(srb_t *sp) uint16_t i; more_dsd_lists = qla24xx_calc_dsd_lists(tot_dsds); - if ((more_dsd_lists + ha->gbl_dsd_inuse) >= NUM_DSD_CHAIN) { + if ((more_dsd_lists + qpair->dsd_inuse) >= NUM_DSD_CHAIN) { ql_dbg(ql_dbg_io, vha, 0x300d, "Num of DSD list %d is than %d for cmd=%p.\n", - more_dsd_lists + ha->gbl_dsd_inuse, NUM_DSD_CHAIN, + more_dsd_lists + qpair->dsd_inuse, NUM_DSD_CHAIN, cmd); goto queuing_error; } - if (more_dsd_lists <= ha->gbl_dsd_avail) + if (more_dsd_lists <= qpair->dsd_avail) goto sufficient_dsds; else - more_dsd_lists -= ha->gbl_dsd_avail; + more_dsd_lists -= qpair->dsd_avail; for (i = 0; i < more_dsd_lists; i++) { dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); @@ -3463,8 +3463,8 @@ qla82xx_start_scsi(srb_t *sp) "for cmd=%p.\n", cmd); goto queuing_error; } - list_add_tail(&dsd_ptr->list, &ha->gbl_dsd_list); - ha->gbl_dsd_avail++; + list_add_tail(&dsd_ptr->list, &qpair->dsd_list); + qpair->dsd_avail++; } sufficient_dsds: diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 9a273c908..6118312fa 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -471,6 +471,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req, ha->base_qpair->msix = &ha->msix_entries[QLA_MSIX_RSP_Q]; ha->base_qpair->srb_mempool = ha->srb_mempool; INIT_LIST_HEAD(&ha->base_qpair->hints_list); + INIT_LIST_HEAD(&ha->base_qpair->dsd_list); ha->base_qpair->enable_class_2 = ql2xenableclass2; /* init qpair to this cpu. Will adjust at run time. */ qla_cpu_update(rsp->qpair, raw_smp_processor_id()); @@ -789,9 +790,9 @@ void qla2x00_sp_free_dma(srb_t *sp) dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); - list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); - ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; - ha->gbl_dsd_avail += ctx1->dsd_use_cnt; + list_splice(&ctx1->dsd_list, &sp->qpair->dsd_list); + sp->qpair->dsd_inuse -= ctx1->dsd_use_cnt; + sp->qpair->dsd_avail += ctx1->dsd_use_cnt; } if (sp->flags & SRB_GOT_BUF) @@ -875,9 +876,9 @@ void qla2xxx_qpair_sp_free_dma(srb_t *sp) dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd, ctx1->fcp_cmnd_dma); - list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list); - ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt; - ha->gbl_dsd_avail += ctx1->dsd_use_cnt; + list_splice(&ctx1->dsd_list, &sp->qpair->dsd_list); + sp->qpair->dsd_inuse -= ctx1->dsd_use_cnt; + sp->qpair->dsd_avail += ctx1->dsd_use_cnt; sp->flags &= ~SRB_FCP_CMND_DMA_VALID; } @@ -4465,7 +4466,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, "sf_init_cb=%p.\n", ha->sf_init_cb); } - INIT_LIST_HEAD(&ha->gbl_dsd_list); /* Get consistent memory allocated for Async Port-Database. */ if (!IS_FWI2_CAPABLE(ha)) { @@ -4997,18 +4997,16 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->gid_list = NULL; ha->gid_list_dma = 0; - if (IS_QLA82XX(ha)) { - if (!list_empty(&ha->gbl_dsd_list)) { - struct dsd_dma *dsd_ptr, *tdsd_ptr; - - /* clean up allocated prev pool */ - list_for_each_entry_safe(dsd_ptr, - tdsd_ptr, &ha->gbl_dsd_list, list) { - dma_pool_free(ha->dl_dma_pool, - dsd_ptr->dsd_addr, dsd_ptr->dsd_list_dma); - list_del(&dsd_ptr->list); - kfree(dsd_ptr); - } + if (!list_empty(&ha->base_qpair->dsd_list)) { + struct dsd_dma *dsd_ptr, *tdsd_ptr; + + /* clean up allocated prev pool */ + list_for_each_entry_safe(dsd_ptr, tdsd_ptr, + &ha->base_qpair->dsd_list, list) { + dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr, + dsd_ptr->dsd_list_dma); + list_del(&dsd_ptr->list); + kfree(dsd_ptr); } } From 927aa370250178bf1c65fe980b9b09efc4809168 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:24:34 +0300 Subject: [PATCH 75/93] qla2x00t-32gbit: Allow 32-byte CDBs System crashes when a 32-byte CDB was sent to a non T10 PI disk: [ 177.143279] ? qla2xxx_dif_start_scsi_mq+0xcd8/0xce0 [qla2xxx] [ 177.149165] ? internal_add_timer+0x42/0x70 [ 177.153372] qla2xxx_mqueuecommand+0x207/0x2b0 [qla2xxx] [ 177.158730] scsi_queue_rq+0x2b7/0xc00 [ 177.162501] blk_mq_dispatch_rq_list+0x3ea/0x7e0 Current code attempted to use CRC IOCB to send the command but failed. Instead, type 6 IOCB should be used to send the I/O. Clone existing type 6 IOCB code with addition of MQ support to allow 32-byte CDBs to go through. Signed-off-by: Quinn Tran Cc: Laurence Oberman Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230817063132.21900-3-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit ae25f65a351c upstream ] --- qla2x00t-32gbit/qla_iocb.c | 269 +++++++++++++++++++++++++++++++++++++ qla2x00t-32gbit/qla_nx.h | 4 +- 2 files changed, 272 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index 88272d9ab..fdd10abd1 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -11,6 +11,7 @@ #include +static int qla_start_scsi_type6(srb_t *sp); /** * qla2x00_get_cmd_direction() - Determine control_flag data direction. * @sp: SCSI command @@ -1737,6 +1738,8 @@ qla24xx_dif_start_scsi(srb_t *sp) if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) { if (cmd->cmd_len <= 16) return qla24xx_start_scsi(sp); + else + return qla_start_scsi_type6(sp); } /* Setup device pointers. */ @@ -2116,6 +2119,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) { if (cmd->cmd_len <= 16) return qla2xxx_start_scsi_mq(sp); + else + return qla_start_scsi_type6(sp); } spin_lock_irqsave(&qpair->qp_lock, flags); @@ -4214,3 +4219,267 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) return rval; } + +/** + * qla_start_scsi_type6() - Send a SCSI command to the ISP + * @sp: command to send to the ISP + * + * Returns non-zero if a failure occurred, else zero. + */ +static int +qla_start_scsi_type6(srb_t *sp) +{ + int nseg; + unsigned long flags; + uint32_t *clr_ptr; + uint32_t handle; + struct cmd_type_6 *cmd_pkt; + uint16_t cnt; + uint16_t req_cnt; + uint16_t tot_dsds; + struct req_que *req = NULL; + struct rsp_que *rsp; + struct scsi_cmnd *cmd = GET_CMD_SP(sp); + struct scsi_qla_host *vha = sp->fcport->vha; + struct qla_hw_data *ha = vha->hw; + struct qla_qpair *qpair = sp->qpair; + uint16_t more_dsd_lists = 0; + struct dsd_dma *dsd_ptr; + uint16_t i; + __be32 *fcp_dl; + uint8_t additional_cdb_len; + struct ct6_dsd *ctx; + + /* Acquire qpair specific lock */ + spin_lock_irqsave(&qpair->qp_lock, flags); + + /* Setup qpair pointers */ + req = qpair->req; + rsp = qpair->rsp; + + /* So we know we haven't pci_map'ed anything yet */ + tot_dsds = 0; + + /* Send marker if required */ + if (vha->marker_needed != 0) { + if (__qla2x00_marker(vha, qpair, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) { + spin_unlock_irqrestore(&qpair->qp_lock, flags); + return QLA_FUNCTION_FAILED; + } + vha->marker_needed = 0; + } + + handle = qla2xxx_get_next_handle(req); + if (handle == 0) + goto queuing_error; + + /* Map the sg table so we have an accurate count of sg entries needed */ + if (scsi_sg_count(cmd)) { + nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), + scsi_sg_count(cmd), cmd->sc_data_direction); + if (unlikely(!nseg)) + goto queuing_error; + } else { + nseg = 0; + } + + tot_dsds = nseg; + + /* eventhough driver only need 1 T6 IOCB, FW still convert DSD to Continueation IOCB */ + req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + + sp->iores.res_type = RESOURCE_IOCB | RESOURCE_EXCH; + sp->iores.exch_cnt = 1; + sp->iores.iocb_cnt = req_cnt; + + if (qla_get_fw_resources(sp->qpair, &sp->iores)) + goto queuing_error; + + more_dsd_lists = qla24xx_calc_dsd_lists(tot_dsds); + if ((more_dsd_lists + qpair->dsd_inuse) >= NUM_DSD_CHAIN) { + ql_dbg(ql_dbg_io, vha, 0x3028, + "Num of DSD list %d is than %d for cmd=%p.\n", + more_dsd_lists + qpair->dsd_inuse, NUM_DSD_CHAIN, cmd); + goto queuing_error; + } + + if (more_dsd_lists <= qpair->dsd_avail) + goto sufficient_dsds; + else + more_dsd_lists -= qpair->dsd_avail; + + for (i = 0; i < more_dsd_lists; i++) { + dsd_ptr = kzalloc(sizeof(*dsd_ptr), GFP_ATOMIC); + if (!dsd_ptr) { + ql_log(ql_log_fatal, vha, 0x3029, + "Failed to allocate memory for dsd_dma for cmd=%p.\n", cmd); + goto queuing_error; + } + INIT_LIST_HEAD(&dsd_ptr->list); + + dsd_ptr->dsd_addr = dma_pool_alloc(ha->dl_dma_pool, + GFP_ATOMIC, &dsd_ptr->dsd_list_dma); + if (!dsd_ptr->dsd_addr) { + kfree(dsd_ptr); + ql_log(ql_log_fatal, vha, 0x302a, + "Failed to allocate memory for dsd_addr for cmd=%p.\n", cmd); + goto queuing_error; + } + list_add_tail(&dsd_ptr->list, &qpair->dsd_list); + qpair->dsd_avail++; + } + +sufficient_dsds: + req_cnt = 1; + + if (req->cnt < (req_cnt + 2)) { + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = (uint16_t)rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } + + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; + else + req->cnt = req->length - (req->ring_index - cnt); + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + } + + ctx = &sp->u.scmd.ct6_ctx; + + memset(ctx, 0, sizeof(struct ct6_dsd)); + ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool, + GFP_ATOMIC, &ctx->fcp_cmnd_dma); + if (!ctx->fcp_cmnd) { + ql_log(ql_log_fatal, vha, 0x3031, + "Failed to allocate fcp_cmnd for cmd=%p.\n", cmd); + goto queuing_error; + } + + /* Initialize the DSD list and dma handle */ + INIT_LIST_HEAD(&ctx->dsd_list); + ctx->dsd_use_cnt = 0; + + if (cmd->cmd_len > 16) { + additional_cdb_len = cmd->cmd_len - 16; + if (cmd->cmd_len % 4 || + cmd->cmd_len > QLA_CDB_BUF_SIZE) { + /* + * SCSI command bigger than 16 bytes must be + * multiple of 4 or too big. + */ + ql_log(ql_log_warn, vha, 0x3033, + "scsi cmd len %d not multiple of 4 for cmd=%p.\n", + cmd->cmd_len, cmd); + goto queuing_error_fcp_cmnd; + } + ctx->fcp_cmnd_len = 12 + cmd->cmd_len + 4; + } else { + additional_cdb_len = 0; + ctx->fcp_cmnd_len = 12 + 16 + 4; + } + + /* Build command packet. */ + req->current_outstanding_cmd = handle; + req->outstanding_cmds[handle] = sp; + sp->handle = handle; + cmd->host_scribble = (unsigned char *)(unsigned long)handle; + req->cnt -= req_cnt; + + cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; + cmd_pkt->handle = make_handle(req->id, handle); + + /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ + clr_ptr = (uint32_t *)cmd_pkt + 2; + memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); + cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); + + /* Set NPORT-ID and LUN number */ + cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); + cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; + cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; + cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; + cmd_pkt->vp_index = sp->vha->vp_idx; + + /* Build IOCB segments */ + qla24xx_build_scsi_type_6_iocbs(sp, cmd_pkt, tot_dsds); + + int_to_scsilun(cmd->device->lun, &cmd_pkt->lun); + host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); + + /* build FCP_CMND IU */ + int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun); + ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len; + + if (cmd->sc_data_direction == DMA_TO_DEVICE) + ctx->fcp_cmnd->additional_cdb_len |= 1; + else if (cmd->sc_data_direction == DMA_FROM_DEVICE) + ctx->fcp_cmnd->additional_cdb_len |= 2; + + /* Populate the FCP_PRIO. */ + if (ha->flags.fcp_prio_enabled) + ctx->fcp_cmnd->task_attribute |= + sp->fcport->fcp_prio << 3; + + memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); + + fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 + + additional_cdb_len); + *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); + + cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len); + put_unaligned_le64(ctx->fcp_cmnd_dma, + &cmd_pkt->fcp_cmnd_dseg_address); + + sp->flags |= SRB_FCP_CMND_DMA_VALID; + cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd)); + /* Set total data segment count. */ + cmd_pkt->entry_count = (uint8_t)req_cnt; + + wmb(); + /* Adjust ring index. */ + req->ring_index++; + if (req->ring_index == req->length) { + req->ring_index = 0; + req->ring_ptr = req->ring; + } else { + req->ring_ptr++; + } + + sp->qpair->cmd_cnt++; + sp->flags |= SRB_DMA_VALID; + + /* Set chip new ring index. */ + wrt_reg_dword(req->req_q_in, req->ring_index); + + /* Manage unprocessed RIO/ZIO commands in response queue. */ + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); + + spin_unlock_irqrestore(&qpair->qp_lock, flags); + + return QLA_SUCCESS; + +queuing_error_fcp_cmnd: + dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd, ctx->fcp_cmnd_dma); + +queuing_error: + if (tot_dsds) + scsi_dma_unmap(cmd); + + qla_put_fw_resources(sp->qpair, &sp->iores); + + if (sp->u.scmd.crc_ctx) { + mempool_free(sp->u.scmd.crc_ctx, ha->ctx_mempool); + sp->u.scmd.crc_ctx = NULL; + } + + spin_unlock_irqrestore(&qpair->qp_lock, flags); + + return QLA_FUNCTION_FAILED; +} diff --git a/qla2x00t-32gbit/qla_nx.h b/qla2x00t-32gbit/qla_nx.h index 6dc80c8dd..5d1bdc15b 100644 --- a/qla2x00t-32gbit/qla_nx.h +++ b/qla2x00t-32gbit/qla_nx.h @@ -857,7 +857,9 @@ struct fcp_cmnd { uint8_t task_attribute; uint8_t task_management; uint8_t additional_cdb_len; - uint8_t cdb[260]; /* 256 for CDB len and 4 for FCP_DL */ +#define QLA_CDB_BUF_SIZE 256 +#define QLA_FCP_DL_SIZE 4 + uint8_t cdb[QLA_CDB_BUF_SIZE + QLA_FCP_DL_SIZE]; /* 256 for CDB len and 4 for FCP_DL */ }; struct dsd_dma { From d2e9e5032a214f6a7a64a61d856102686f64c542 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:24:57 +0300 Subject: [PATCH 76/93] qla2x00t-32gbit: Flush mailbox commands on chip reset Fix race condition between Interrupt thread and Chip reset thread in trying to flush the same mailbox. With the race condition, the "ha->mbx_intr_comp" will get an extra complete() call. The extra complete call create erroneous mailbox timeout condition when the next mailbox is sent where the mailbox call does not wait for interrupt to arrive. Instead, it advances without waiting. Add lock protection around the check for mailbox completion. Cc: stable@vger.kernel.org Fixes: b2000805a975 ("scsi: qla2xxx: Flush mailbox commands on chip reset") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-3-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 6d0b65569c0a upstream ] --- qla2x00t-32gbit/qla_def.h | 1 - qla2x00t-32gbit/qla_init.c | 7 ++++--- qla2x00t-32gbit/qla_mbx.c | 4 ---- qla2x00t-32gbit/qla_os.c | 1 - 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 138867c66..659ef31a4 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -4442,7 +4442,6 @@ struct qla_hw_data { uint8_t aen_mbx_count; atomic_t num_pend_mbx_stage1; atomic_t num_pend_mbx_stage2; - atomic_t num_pend_mbx_stage3; uint16_t frame_payload_size; uint32_t login_retry_count; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 3b5e11fe7..a5ced61c6 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -7393,14 +7393,15 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) } /* purge MBox commands */ - if (atomic_read(&ha->num_pend_mbx_stage3)) { + spin_lock_irqsave(&ha->hardware_lock, flags); + if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) { clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags); complete(&ha->mbx_intr_comp); } + spin_unlock_irqrestore(&ha->hardware_lock, flags); i = 0; - while (atomic_read(&ha->num_pend_mbx_stage3) || - atomic_read(&ha->num_pend_mbx_stage2) || + while (atomic_read(&ha->num_pend_mbx_stage2) || atomic_read(&ha->num_pend_mbx_stage1)) { msleep(20); i++; diff --git a/qla2x00t-32gbit/qla_mbx.c b/qla2x00t-32gbit/qla_mbx.c index b05f93037..21ec32b4f 100644 --- a/qla2x00t-32gbit/qla_mbx.c +++ b/qla2x00t-32gbit/qla_mbx.c @@ -273,7 +273,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) spin_unlock_irqrestore(&ha->hardware_lock, flags); wait_time = jiffies; - 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, @@ -290,7 +289,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) spin_unlock_irqrestore(&ha->hardware_lock, flags); atomic_dec(&ha->num_pend_mbx_stage2); - atomic_dec(&ha->num_pend_mbx_stage3); rval = QLA_ABORTED; goto premature_exit; } @@ -302,11 +300,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) ha->flags.mbox_busy = 0; spin_unlock_irqrestore(&ha->hardware_lock, flags); atomic_dec(&ha->num_pend_mbx_stage2); - atomic_dec(&ha->num_pend_mbx_stage3); rval = QLA_ABORTED; goto premature_exit; } - atomic_dec(&ha->num_pend_mbx_stage3); if (time_after(jiffies, wait_time + 5 * HZ)) ql_log(ql_log_warn, vha, 0x1015, "cmd=0x%x, waited %d msecs\n", diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 6118312fa..041235829 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3065,7 +3065,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->max_exchg = FW_MAX_EXCHANGES_CNT; atomic_set(&ha->num_pend_mbx_stage1, 0); atomic_set(&ha->num_pend_mbx_stage2, 0); - atomic_set(&ha->num_pend_mbx_stage3, 0); atomic_set(&ha->zio_threshold, DEFAULT_ZIO_THRESHOLD); ha->last_zio_threshold = DEFAULT_ZIO_THRESHOLD; INIT_LIST_HEAD(&ha->tmf_pending); From 059cddcd91b384749cdd630bc810e402d121c002 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:25:22 +0300 Subject: [PATCH 77/93] qla2x00t-32gbit: Fix firmware resource tracking The storage was not draining I/Os and the work load was not spread out across different CPUs evenly. This led to firmware resource counters getting overrun on the busy CPU. This overrun prevented error recovery from happening in a timely manner. By switching the counter to atomic, it allows the count to be little more accurate to prevent the overrun. Cc: stable@vger.kernel.org Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit e370b64c7db9 upstream ] --- qla2x00t-32gbit/qla_def.h | 11 +++++++ qla2x00t-32gbit/qla_dfs.c | 10 +++++++ qla2x00t-32gbit/qla_init.c | 8 +++++ qla2x00t-32gbit/qla_inline.h | 57 +++++++++++++++++++++++++++++++++++- qla2x00t-32gbit/qla_os.c | 5 ++-- 5 files changed, 88 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 659ef31a4..413804827 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -3794,6 +3794,16 @@ struct qla_fw_resources { u16 pad; }; +struct qla_fw_res { + u16 iocb_total; + u16 iocb_limit; + atomic_t iocb_used; + + u16 exch_total; + u16 exch_limit; + atomic_t exch_used; +}; + #define QLA_IOCB_PCT_LIMIT 95 struct qla_buf_pool { @@ -4852,6 +4862,7 @@ struct qla_hw_data { struct els_reject elsrej; u8 edif_post_stop_cnt_down; struct qla_vp_map *vp_map; + struct qla_fw_res fwres ____cacheline_aligned; }; #define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES)) diff --git a/qla2x00t-32gbit/qla_dfs.c b/qla2x00t-32gbit/qla_dfs.c index 6fd6f48a6..807fd7fcf 100644 --- a/qla2x00t-32gbit/qla_dfs.c +++ b/qla2x00t-32gbit/qla_dfs.c @@ -280,6 +280,16 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) seq_printf(s, "estimate exchange used[%d] high water limit [%d] n", exch_used, ha->base_qpair->fwres.exch_limit); + + if (ql2xenforce_iocb_limit == 2) { + iocbs_used = atomic_read(&ha->fwres.iocb_used); + exch_used = atomic_read(&ha->fwres.exch_used); + seq_printf(s, " estimate iocb2 used [%d] high water limit [%d]\n", + iocbs_used, ha->fwres.iocb_limit); + + seq_printf(s, " estimate exchange2 used[%d] high water limit [%d] \n", + exch_used, ha->fwres.exch_limit); + } } return 0; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index a5ced61c6..ded889386 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4217,6 +4217,14 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha) ha->queue_pair_map[i]->fwres.exch_used = 0; } } + + ha->fwres.iocb_total = ha->orig_fw_iocb_count; + ha->fwres.iocb_limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100; + ha->fwres.exch_total = ha->orig_fw_xcb_count; + ha->fwres.exch_limit = (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100; + + atomic_set(&ha->fwres.iocb_used, 0); + atomic_set(&ha->fwres.exch_used, 0); } void qla_adjust_iocb_limit(scsi_qla_host_t *vha) diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index d635b42fe..6ce909415 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -394,6 +394,7 @@ enum { RESOURCE_IOCB = BIT_0, RESOURCE_EXCH = BIT_1, /* exchange */ RESOURCE_FORCE = BIT_2, + RESOURCE_HA = BIT_3, }; static inline int @@ -401,7 +402,7 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) { u16 iocbs_used, i; u16 exch_used; - struct qla_hw_data *ha = qp->vha->hw; + struct qla_hw_data *ha = qp->hw; if (!ql2xenforce_iocb_limit) { iores->res_type = RESOURCE_NONE; @@ -436,15 +437,69 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) return -ENOSPC; } } + + if (ql2xenforce_iocb_limit == 2) { + if ((iores->iocb_cnt + atomic_read(&ha->fwres.iocb_used)) >= + ha->fwres.iocb_limit) { + iores->res_type = RESOURCE_NONE; + return -ENOSPC; + } + + if (iores->res_type & RESOURCE_EXCH) { + if ((iores->exch_cnt + atomic_read(&ha->fwres.exch_used)) >= + ha->fwres.exch_limit) { + iores->res_type = RESOURCE_NONE; + return -ENOSPC; + } + } + } + force: qp->fwres.iocbs_used += iores->iocb_cnt; qp->fwres.exch_used += iores->exch_cnt; + if (ql2xenforce_iocb_limit == 2) { + atomic_add(iores->iocb_cnt, &ha->fwres.iocb_used); + atomic_add(iores->exch_cnt, &ha->fwres.exch_used); + iores->res_type |= RESOURCE_HA; + } return 0; } +/* + * decrement to zero. This routine will not decrement below zero + * @v: pointer of type atomic_t + * @amount: amount to decrement from v + */ +static void qla_atomic_dtz(atomic_t *v, int amount) +{ + int c, old, dec; + + c = atomic_read(v); + for (;;) { + dec = c - amount; + if (unlikely(dec < 0)) + dec = 0; + + old = atomic_cmpxchg((v), c, dec); + if (likely(old == c)) + break; + c = old; + } +} + static inline void qla_put_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) { + struct qla_hw_data *ha = qp->hw; + + if (iores->res_type & RESOURCE_HA) { + if (iores->res_type & RESOURCE_IOCB) + qla_atomic_dtz(&ha->fwres.iocb_used, iores->iocb_cnt); + + if (iores->res_type & RESOURCE_EXCH) + qla_atomic_dtz(&ha->fwres.exch_used, iores->exch_cnt); + } + if (iores->res_type & RESOURCE_IOCB) { if (qp->fwres.iocbs_used >= iores->iocb_cnt) { qp->fwres.iocbs_used -= iores->iocb_cnt; diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 041235829..538de0bd0 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -61,10 +61,11 @@ module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql2xfulldump_on_mpifail, "Set this to take full dump on MPI hang."); -int ql2xenforce_iocb_limit = 1; +int ql2xenforce_iocb_limit = 2; module_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ql2xenforce_iocb_limit, - "Enforce IOCB throttling, to avoid FW congestion. (default: 1)"); + "Enforce IOCB throttling, to avoid FW congestion. (default: 2) " + "1: track usage per queue, 2: track usage per adapter"); /* * CT6 CTX allocation cache From e4ff303fd830846bdebcbb1cd38d8be24d37e860 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:25:46 +0300 Subject: [PATCH 78/93] qla2x00t-32gbit: Add logs for SFP temperature monitoring Add logs for SFP Temperature Alert async event to check if laser is enabled/disabled. Signed-off-by: Bikash Hazarika Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-5-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit cd248a95f86d upstream ] --- qla2x00t-32gbit/qla_isr.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 49bfdc69d..944e8aa5b 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -68,6 +68,22 @@ const char *const port_state_str[] = { [FCS_ONLINE] = "ONLINE" }; +#define SFP_DISABLE_LASER_INITIATED 0x15 /* Sub code of 8070 AEN */ +#define SFP_ENABLE_LASER_INITIATED 0x16 /* Sub code of 8070 AEN */ + +static inline void display_Laser_info(scsi_qla_host_t *vha, + u16 mb1, u16 mb2, u16 mb3) { + + if (mb1 == SFP_DISABLE_LASER_INITIATED) + ql_log(ql_log_warn, vha, 0xf0a2, + "SFP temperature (%d C) reached/exceeded the threshold (%d C). Laser is disabled.\n", + mb3, mb2); + if (mb1 == SFP_ENABLE_LASER_INITIATED) + ql_log(ql_log_warn, vha, 0xf0a3, + "SFP temperature (%d C) reached normal operating level. Laser is enabled.\n", + mb3); +} + static void qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt) { @@ -1810,6 +1826,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) break; case MBA_TEMPERATURE_ALERT: + if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) + display_Laser_info(vha, mb[1], mb[2], mb[3]); ql_dbg(ql_dbg_async, vha, 0x505e, "TEMPERATURE ALERT: %04x %04x %04x\n", mb[1], mb[2], mb[3]); break; From a0e75be0ff8228429f8a00c92f36a75138ef5c1f Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:26:07 +0300 Subject: [PATCH 79/93] qla2x00t-32gbit: Error code did not return to upper layer TMF was returned with an error code. The error code was not preserved to be returned to upper layer. Instead, the error code from the Marker was returned. Preserve error code from TMF and return it to upper layer. Cc: stable@vger.kernel.org Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF") Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-6-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 0ba0b018f945 upstream ] --- qla2x00t-32gbit/qla_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index ded889386..8bdd4e3e8 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -2223,6 +2223,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) rval = QLA_FUNCTION_FAILED; } } + if (tm_iocb->u.tmf.data) + rval = tm_iocb->u.tmf.data; done_free_sp: /* ref: INIT */ From 3e9fa7bf407878ef2d1ce33e67de1511b83aed13 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:26:32 +0300 Subject: [PATCH 80/93] qla2x00t-32gbit: Remove unsupported ql2xenabledif option User accidently passed module parameter ql2xenabledif=1 which is unsupported. However, driver still initialized which lead to guard tag errors during device discovery. Remove unsupported ql2xenabledif=1 option and validate the user input. Cc: stable@vger.kernel.org Signed-off-by: Manish Rangankar Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-7-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit e9105c4b7a92 upstream ] --- qla2x00t-32gbit/qla_attr.c | 2 -- qla2x00t-32gbit/qla_dbg.c | 2 +- qla2x00t-32gbit/qla_os.c | 9 +++++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_attr.c b/qla2x00t-32gbit/qla_attr.c index c9fc1d757..c35bdddfe 100644 --- a/qla2x00t-32gbit/qla_attr.c +++ b/qla2x00t-32gbit/qla_attr.c @@ -3164,8 +3164,6 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_user, vha, 0x7082, "Registered for DIF/DIX type 1 and 3 protection.\n"); - if (ql2xenabledif == 1) - prot = SHOST_DIX_TYPE0_PROTECTION; scsi_host_set_prot(vha->host, prot | SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index d9f9dda15..9fcadf877 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -18,7 +18,7 @@ * | Queue Command and IO tracing | 0x3074 | 0x300b | * | | | 0x3027-0x3028 | * | | | 0x303d-0x3041 | - * | | | 0x302d,0x3033 | + * | | | 0x302e,0x3033 | * | | | 0x3036,0x3038 | * | | | 0x303a | * | DPC Thread | 0x4023 | 0x4002,0x4013 | diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 538de0bd0..a8112be17 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -3346,6 +3346,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_id = ha->max_fibre_devices; host->cmd_per_lun = 3; host->unique_id = host->host_no; + + if (ql2xenabledif && ql2xenabledif != 2) { + ql_log(ql_log_warn, base_vha, 0x302d, + "Invalid value for ql2xenabledif, resetting it to default (2)\n"); + ql2xenabledif = 2; + } + if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) host->max_cmd_len = 32; else @@ -3584,8 +3591,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) base_vha->flags.difdix_supported = 1; ql_dbg(ql_dbg_init, base_vha, 0x00f1, "Registering for DIF/DIX type 1 and 3 protection.\n"); - if (ql2xenabledif == 1) - prot = SHOST_DIX_TYPE0_PROTECTION; if (ql2xprotmask) scsi_host_set_prot(host, ql2xprotmask); else From bd33d66883ac2894a49f851c335420b0a80cd545 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:26:58 +0300 Subject: [PATCH 81/93] qla2x00t-32gbit: Fix smatch warn for qla_init_iocb_limit() Fix indentation for warning reported by smatch: drivers/scsi/qla2xxx/qla_init.c:4199 qla_init_iocb_limit() warn: inconsistent indenting Fixes: efa74a62aaa2 ("scsi: qla2xxx: Adjust IOCB resource on qpair create") Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-8-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit b496953dd044 upstream ] --- qla2x00t-32gbit/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 8bdd4e3e8..c277f54d4 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -4208,7 +4208,7 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha) u8 i; struct qla_hw_data *ha = vha->hw; - __qla_adjust_iocb_limit(ha->base_qpair); + __qla_adjust_iocb_limit(ha->base_qpair); ha->base_qpair->fwres.iocbs_used = 0; ha->base_qpair->fwres.exch_used = 0; From 33597b6bba8ae03c534376938880db5764f0cbbd Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:32:37 +0300 Subject: [PATCH 82/93] qla2x00t-32gbit: Revert "qla2x00t-32gbit: Fix buffer overrun" Revert due to Get PLOGI Template failed. This reverts commit b68710a8094fdffe8dd4f7a82c82649f479bb453. Cc: stable@vger.kernel.org Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-9-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 641671d97b91 upstream ] --- qla2x00t-32gbit/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index c277f54d4..75b9a262c 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5609,7 +5609,7 @@ static void qla_get_login_template(scsi_qla_host_t *vha) __be32 *q; memset(ha->init_cb, 0, ha->init_cb_size); - sz = min_t(int, sizeof(struct fc_els_csp), ha->init_cb_size); + sz = min_t(int, sizeof(struct fc_els_flogi), ha->init_cb_size); rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma, ha->init_cb, sz); if (rval != QLA_SUCCESS) { From 0c729fb3eef12ad91bb8d33c5d6e0ad055f8cec2 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:28:22 +0300 Subject: [PATCH 83/93] qla2x00t-32gbit: Update version to 10.02.09.100-k Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-10-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit cc6e67e60fe7 upstream ] --- qla2x00t-32gbit/qla_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_version.h b/qla2x00t-32gbit/qla_version.h index 81bdf6b03..d903563e9 100644 --- a/qla2x00t-32gbit/qla_version.h +++ b/qla2x00t-32gbit/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.08.500-k" +#define QLA2XXX_VERSION "10.02.09.100-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 -#define QLA_DRIVER_PATCH_VER 8 -#define QLA_DRIVER_BETA_VER 500 +#define QLA_DRIVER_PATCH_VER 9 +#define QLA_DRIVER_BETA_VER 100 From 3cbfc93ac315b8d89f8df4c077bb4dfaf994a8e8 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:28:56 +0300 Subject: [PATCH 84/93] qla2x00t-32gbit: Remove unused variables in qla24xx_build_scsi_type_6_iocbs() Sparse warning reported, drivers/scsi/qla2xxx/qla_iocb.c: In function 'qla24xx_build_scsi_type_6_iocbs': >> drivers/scsi/qla2xxx/qla_iocb.c:594:29: warning: variable 'ha' set but not used [-Wunused-but-set-variable] 594 | struct qla_hw_data *ha; | ^~ Remove unused variables 'vha' and 'ha'. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308230757.VKMIztAB-lkp@intel.com/ Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230825070017.46066-1-njavali@marvell.com Signed-off-by: Martin K. Petersen [ commit d4781807f050 upstream ] --- qla2x00t-32gbit/qla_iocb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index fdd10abd1..b86d0e695 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -597,8 +597,6 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, uint16_t tot_dsds) { struct dsd64 *cur_dsd = NULL, *next_dsd; - scsi_qla_host_t *vha; - struct qla_hw_data *ha; struct scsi_cmnd *cmd; struct scatterlist *cur_seg; uint8_t avail_dsds; @@ -620,9 +618,6 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, return 0; } - vha = sp->vha; - ha = vha->hw; - /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA); From bea458054e05daeabe1b4f6749818191a8055110 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:29:22 +0300 Subject: [PATCH 85/93] qla2x00t-32gbit: Use raw_smp_processor_id() instead of smp_processor_id() The following call trace was observed: localhost kernel: nvme nvme0: NVME-FC{0}: controller connect complete localhost kernel: BUG: using smp_processor_id() in preemptible [00000000] code: kworker/u129:4/75092 localhost kernel: nvme nvme0: NVME-FC{0}: new ctrl: NQN "nqn.1992-08.com.netapp:sn.b42d198afb4d11ecad6d00a098d6abfa:subsystem.PR_Channel2022_RH84_subsystem_291" localhost kernel: caller is qla_nvme_post_cmd+0x216/0x1380 [qla2xxx] localhost kernel: CPU: 6 PID: 75092 Comm: kworker/u129:4 Kdump: loaded Tainted: G B W OE --------- --- 5.14.0-70.22.1.el9_0.x86_64+debug #1 localhost kernel: Hardware name: HPE ProLiant XL420 Gen10/ProLiant XL420 Gen10, BIOS U39 01/13/2022 localhost kernel: Workqueue: nvme-wq nvme_async_event_work [nvme_core] localhost kernel: Call Trace: localhost kernel: dump_stack_lvl+0x57/0x7d localhost kernel: check_preemption_disabled+0xc8/0xd0 localhost kernel: qla_nvme_post_cmd+0x216/0x1380 [qla2xxx] Use raw_smp_processor_id() instead of smp_processor_id(). Also use queue_work() across the driver instead of queue_work_on() thus avoiding usage of smp_processor_id() when CONFIG_DEBUG_PREEMPT is enabled. Cc: stable@vger.kernel.org Suggested-by: John Garry Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230831112146.32595-2-njavali@marvell.com Signed-off-by: Martin K. Petersen [ commit 59f10a05b5c7 upstream ] --- qla2x00t-32gbit/qla_inline.h | 2 +- qla2x00t-32gbit/qla_isr.c | 4 ++-- qla2x00t-32gbit/qla_target.c | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_inline.h b/qla2x00t-32gbit/qla_inline.h index 6ce909415..874618471 100644 --- a/qla2x00t-32gbit/qla_inline.h +++ b/qla2x00t-32gbit/qla_inline.h @@ -585,7 +585,7 @@ fcport_is_bigger(fc_port_t *fcport) static inline struct qla_qpair * qla_mapq_nvme_select_qpair(struct qla_hw_data *ha, struct qla_qpair *qpair) { - int cpuid = smp_processor_id(); + int cpuid = raw_smp_processor_id(); if (qpair->cpuid != cpuid && ha->qp_cpu_map[cpuid]) { diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 944e8aa5b..9b89e7e73 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -4349,7 +4349,7 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) } ha = qpair->hw; - queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); + queue_work(ha->wq, &qpair->q_work); return IRQ_HANDLED; } @@ -4375,7 +4375,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT); spin_unlock_irqrestore(&ha->hardware_lock, flags); - queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); + queue_work(ha->wq, &qpair->q_work); return IRQ_HANDLED; } diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index 564819a4d..6ef76bd52 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -4481,8 +4481,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, #endif } else if (ha->msix_count) { if (cmd->atio.u.isp24.fcp_cmnd.rddata) - queue_work_on(raw_smp_processor_id(), qla_tgt_wq, - &cmd->work); + queue_work(qla_tgt_wq, &cmd->work); else #if HAVE_SE_CMD_CPUID queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, From 6552b55c223d1599d19b2b8600f4823d4d2ad57b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:29:44 +0300 Subject: [PATCH 86/93] qla2x00t-32gbit: Fix NULL vs IS_ERR() bug for debugfs_create_dir() Since both debugfs_create_dir() and debugfs_create_file() return ERR_PTR and never NULL, use IS_ERR() instead of checking for NULL. Fixes: 1e98fb0f9208 ("scsi: qla2xxx: Setup debugfs entries for remote ports") Signed-off-by: Jinjie Ruan Link: https://lore.kernel.org/r/20230831140930.3166359-1-ruanjinjie@huawei.com Signed-off-by: Martin K. Petersen [ commit d0b0822e32db upstream ] --- qla2x00t-32gbit/qla_dfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qla2x00t-32gbit/qla_dfs.c b/qla2x00t-32gbit/qla_dfs.c index 807fd7fcf..e0b55d23c 100644 --- a/qla2x00t-32gbit/qla_dfs.c +++ b/qla2x00t-32gbit/qla_dfs.c @@ -120,7 +120,7 @@ qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp) sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name)); fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root); - if (!fp->dfs_rport_dir) + if (IS_ERR(fp->dfs_rport_dir)) return; if (NVME_TARGET(vha->hw, fp)) debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir, @@ -712,14 +712,14 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha) if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) { ha->tgt.dfs_naqp = debugfs_create_file("naqp", 0400, ha->dfs_dir, vha, &dfs_naqp_ops); - if (!ha->tgt.dfs_naqp) { + if (IS_ERR(ha->tgt.dfs_naqp)) { ql_log(ql_log_warn, vha, 0xd011, "Unable to create debugFS naqp node.\n"); goto out; } } vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir); - if (!vha->dfs_rport_root) { + if (IS_ERR(vha->dfs_rport_root)) { ql_log(ql_log_warn, vha, 0xd012, "Unable to create debugFS rports node.\n"); goto out; From 12fd0ea93e3164d21aba5e5abe1a2596cacbfd0b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Sun, 1 Oct 2023 20:16:17 +0300 Subject: [PATCH 87/93] scst/include/backport.h: Backport some debugfs functions Support the previous commit against kernel versions before v5.0. See also commit ff9fb72bc077 ("debugfs: return error values, not NULL") # v5.0. --- scst/include/backport.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/scst/include/backport.h b/scst/include/backport.h index 9691bddfd..56d25e4ee 100644 --- a/scst/include/backport.h +++ b/scst/include/backport.h @@ -31,6 +31,7 @@ #include #endif #include /* struct bsg_job */ +#include #include #include #include @@ -385,6 +386,39 @@ static inline ssize_t debugfs_attr_write(struct file *file, } #endif +/* + * See also commit ff9fb72bc077 ("debugfs: return error values, + * not NULL") # v5.0. + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0) +static inline struct dentry *debugfs_create_dir_backport(const char *name, struct dentry *parent) +{ + struct dentry *dentry; + + dentry = debugfs_create_dir(name, parent); + if (!dentry) + return ERR_PTR(-ENOMEM); + + return dentry; +} + +static inline struct dentry *debugfs_create_file_backport(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) +{ + struct dentry *dentry; + + dentry = debugfs_create_file(name, mode, parent, data, fops); + if (!dentry) + return ERR_PTR(-ENOMEM); + + return dentry; +} + +#define debugfs_create_dir debugfs_create_dir_backport +#define debugfs_create_file debugfs_create_file_backport +#endif + /* */ #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) From 868eb28e20d85a45ebb9409febbdea913bcff1c6 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:30:03 +0300 Subject: [PATCH 88/93] qla2x00t-32gbit: Add Unsolicited LS Request and Response Support for NVMe Introduce infrastructure in the driver to support the processing of unsolicited LS (Link Service) requests. This will involve the utilization of a new pass-up of unsolicited FC-NVMe request IOCB interface. Unsolicited requests will be submitted to the NVMe transport layer through nvme_fc_rcv_ls_req(). Any received LS responses, which are sent using xmt_ls_rsp(), will be forwarded to the firmware through the existing Pass-Through IOCB interface, responsible for sending FC-NVMe Link Service requests and responses. Signed-off-by: Manish Rangankar Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230821130045.34850-2-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen [ commit 875386b98857 upstream ] --- qla2x00t-32gbit/qla_dbg.c | 5 +- qla2x00t-32gbit/qla_dbg.h | 1 + qla2x00t-32gbit/qla_def.h | 34 +++- qla2x00t-32gbit/qla_gbl.h | 15 +- qla2x00t-32gbit/qla_init.c | 1 + qla2x00t-32gbit/qla_iocb.c | 26 ++- qla2x00t-32gbit/qla_isr.c | 146 +++++++++++++- qla2x00t-32gbit/qla_nvme.c | 401 ++++++++++++++++++++++++++++++++++++- qla2x00t-32gbit/qla_nvme.h | 17 +- qla2x00t-32gbit/qla_os.c | 23 ++- 10 files changed, 641 insertions(+), 28 deletions(-) diff --git a/qla2x00t-32gbit/qla_dbg.c b/qla2x00t-32gbit/qla_dbg.c index 9fcadf877..9de6e3a3b 100644 --- a/qla2x00t-32gbit/qla_dbg.c +++ b/qla2x00t-32gbit/qla_dbg.c @@ -12,9 +12,8 @@ * ---------------------------------------------------------------------- * | Module Init and Probe | 0x0199 | | * | Mailbox commands | 0x1206 | 0x11a5-0x11ff | - * | Device Discovery | 0x2134 | 0x210e-0x2115 | - * | | | 0x211c-0x2128 | - * | | | 0x212c-0x2134 | + * | Device Discovery | 0x2134 | 0x2112-0x2115 | + * | | | 0x2127-0x2128 | * | Queue Command and IO tracing | 0x3074 | 0x300b | * | | | 0x3027-0x3028 | * | | | 0x303d-0x3041 | diff --git a/qla2x00t-32gbit/qla_dbg.h b/qla2x00t-32gbit/qla_dbg.h index 4ea3463a3..ecdc747dd 100644 --- a/qla2x00t-32gbit/qla_dbg.h +++ b/qla2x00t-32gbit/qla_dbg.h @@ -368,6 +368,7 @@ ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...); #define ql_dbg_tgt_tmr 0x00001000 /* Target mode task management */ #define ql_dbg_tgt_dif 0x00000800 /* Target mode dif */ #define ql_dbg_edif 0x00000400 /* edif and purex debug */ +#define ql_dbg_unsol 0x00000100 /* Unsolicited path debug */ extern int qla27xx_dump_mpi_ram(struct qla_hw_data *, uint32_t, uint32_t *, uint32_t, void **); diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 413804827..4c143b347 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -389,6 +389,12 @@ struct name_list_extended { u8 sent; }; +struct qla_nvme_fc_rjt { + struct fcnvme_ls_rjt *c; + dma_addr_t cdma; + u16 size; +}; + struct els_reject { struct fc_els_ls_rjt *c; dma_addr_t cdma; @@ -546,6 +552,20 @@ struct ct_arg { port_id_t id; }; +struct qla_nvme_lsrjt_pt_arg { + struct fc_port *fcport; + u8 opcode; + u8 vp_idx; + u8 reason; + u8 explanation; + __le16 nport_handle; + u16 control_flags; + __le16 ox_id; + __le32 xchg_address; + u32 tx_byte_count, rx_byte_count; + dma_addr_t tx_addr, rx_addr; +}; + /* * SRB extensions. */ @@ -654,13 +674,16 @@ struct srb_iocb { void *desc; /* These are only used with ls4 requests */ - int cmd_len; - int rsp_len; + __le32 cmd_len; + __le32 rsp_len; dma_addr_t cmd_dma; dma_addr_t rsp_dma; enum nvmefc_fcp_datadir dir; uint32_t dl; uint32_t timeout_sec; + __le32 exchange_address; + __le16 nport_handle; + __le16 ox_id; struct list_head entry; } nvme; struct { @@ -754,6 +777,10 @@ typedef struct srb { struct fc_port *fcport; struct scsi_qla_host *vha; unsigned int start_timer:1; + unsigned int abort:1; + unsigned int aborted:1; + unsigned int completed:1; + unsigned int unsol_rsp:1; uint32_t handle; uint16_t flags; @@ -2593,6 +2620,7 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; + struct list_head unsol_ctx_head; unsigned int conf_compl_supported:1; unsigned int deleted:2; @@ -4862,6 +4890,7 @@ struct qla_hw_data { struct els_reject elsrej; u8 edif_post_stop_cnt_down; struct qla_vp_map *vp_map; + struct qla_nvme_fc_rjt lsrjt; struct qla_fw_res fwres ____cacheline_aligned; }; @@ -4895,6 +4924,7 @@ struct active_regions { * is variable) starting at "iocb". */ struct purex_item { + void *purls_context; struct list_head list; struct scsi_qla_host *vha; void (*process_item)(struct scsi_qla_host *vha, diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index c7539ea35..767b3823e 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -609,7 +609,13 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id); fc_port_t *qla2x00_find_fcport_by_loopid(scsi_qla_host_t *, uint16_t); fc_port_t *qla2x00_find_fcport_by_wwpn(scsi_qla_host_t *, u8 *, u8); fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8); -void __qla_consume_iocb(struct scsi_qla_host *vha, void **pkt, struct rsp_que **rsp); +void qla24xx_queue_purex_item(scsi_qla_host_t *, struct purex_item *, + void (*process_item)(struct scsi_qla_host *, + struct purex_item *)); +void __qla_consume_iocb(struct scsi_qla_host *, void **, struct rsp_que **); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) +void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp); +#endif /* * Global Function Prototypes in qla_sup.c source file. @@ -672,8 +678,11 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *); extern int qla2x00_mailbox_passthru(BSG_JOB_TYPE *bsg_job); -int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt, - struct rsp_que **rsp, u8 *buf, u32 buf_len); +int qla2x00_sys_ld_info(struct bsg_job *bsg_job); +int __qla_copy_purex_to_buffer(struct scsi_qla_host *, void **, + struct rsp_que **, u8 *, u32); +struct purex_item *qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, + void **pkt, struct rsp_que **rsp, bool is_purls, bool byte_order); int qla_mailbox_passthru(scsi_qla_host_t *vha, uint16_t *mbx_in, uint16_t *mbx_out); diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index 75b9a262c..68d9d220c 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -5567,6 +5567,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); + INIT_LIST_HEAD(&fcport->unsol_ctx_head); INIT_LIST_HEAD(&fcport->sess_cmd_list); spin_lock_init(&fcport->sess_cmd_lock); diff --git a/qla2x00t-32gbit/qla_iocb.c b/qla2x00t-32gbit/qla_iocb.c index b86d0e695..e045f39cb 100644 --- a/qla2x00t-32gbit/qla_iocb.c +++ b/qla2x00t-32gbit/qla_iocb.c @@ -3783,21 +3783,29 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt) nvme = &sp->u.iocb_cmd; cmd_pkt->entry_type = PT_LS4_REQUEST; cmd_pkt->entry_count = 1; - cmd_pkt->control_flags = cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT); cmd_pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec); - cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); cmd_pkt->vp_index = sp->fcport->vha->vp_idx; + if (sp->unsol_rsp) { + cmd_pkt->control_flags = + cpu_to_le16(CF_LS4_RESPONDER << CF_LS4_SHIFT); + cmd_pkt->nport_handle = nvme->u.nvme.nport_handle; + cmd_pkt->exchange_address = nvme->u.nvme.exchange_address; + } else { + cmd_pkt->control_flags = + cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT); + cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); + cmd_pkt->rx_dseg_count = cpu_to_le16(1); + cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len; + cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len; + put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address); + } + cmd_pkt->tx_dseg_count = cpu_to_le16(1); - cmd_pkt->tx_byte_count = cpu_to_le32(nvme->u.nvme.cmd_len); - cmd_pkt->dsd[0].length = cpu_to_le32(nvme->u.nvme.cmd_len); + cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len; + cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len; put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address); - - cmd_pkt->rx_dseg_count = cpu_to_le16(1); - cmd_pkt->rx_byte_count = cpu_to_le32(nvme->u.nvme.rsp_len); - cmd_pkt->dsd[1].length = cpu_to_le32(nvme->u.nvme.rsp_len); - put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address); } static void diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 9b89e7e73..0a2b6b58b 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -851,6 +851,135 @@ qla83xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb) } } +/** + * qla27xx_copy_multiple_pkt() - Copy over purex/purls packets that can + * span over multiple IOCBs. + * @vha: SCSI driver HA context + * @pkt: ELS packet + * @rsp: Response queue + * @is_purls: True, for Unsolicited Received FC-NVMe LS rsp IOCB + * false, for Unsolicited Received ELS IOCB + * @byte_order: True, to change the byte ordering of iocb payload + */ +struct purex_item * +qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt, + struct rsp_que **rsp, bool is_purls, + bool byte_order) +{ + struct purex_entry_24xx *purex = NULL; + struct pt_ls4_rx_unsol *purls = NULL; + struct rsp_que *rsp_q = *rsp; + sts_cont_entry_t *new_pkt; + uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0; + uint16_t buffer_copy_offset = 0, payload_size = 0; + uint16_t entry_count, entry_count_remaining; + struct purex_item *item; + void *iocb_pkt = NULL; + + if (is_purls) { + purls = *pkt; + total_bytes = (le16_to_cpu(purls->frame_size) & 0x0FFF) - + PURX_ELS_HEADER_SIZE; + entry_count = entry_count_remaining = purls->entry_count; + payload_size = sizeof(purls->payload); + } else { + purex = *pkt; + total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF) - + PURX_ELS_HEADER_SIZE; + entry_count = entry_count_remaining = purex->entry_count; + payload_size = sizeof(purex->els_frame_payload); + } + + pending_bytes = total_bytes; + no_bytes = (pending_bytes > payload_size) ? payload_size : + pending_bytes; + ql_dbg(ql_dbg_async, vha, 0x509a, + "%s LS, frame_size 0x%x, entry count %d\n", + (is_purls ? "PURLS" : "FPIN"), total_bytes, entry_count); + + item = qla24xx_alloc_purex_item(vha, total_bytes); + if (!item) + return item; + + iocb_pkt = &item->iocb; + + if (is_purls) + memcpy(iocb_pkt, &purls->payload[0], no_bytes); + else + memcpy(iocb_pkt, &purex->els_frame_payload[0], no_bytes); + buffer_copy_offset += no_bytes; + pending_bytes -= no_bytes; + --entry_count_remaining; + + if (is_purls) + ((response_t *)purls)->signature = RESPONSE_PROCESSED; + else + ((response_t *)purex)->signature = RESPONSE_PROCESSED; + wmb(); + + do { + while ((total_bytes > 0) && (entry_count_remaining > 0)) { + if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) { + ql_dbg(ql_dbg_async, vha, 0x5084, + "Ran out of IOCBs, partial data 0x%x\n", + buffer_copy_offset); + cpu_relax(); + continue; + } + + new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr; + *pkt = new_pkt; + + if (new_pkt->entry_type != STATUS_CONT_TYPE) { + ql_log(ql_log_warn, vha, 0x507a, + "Unexpected IOCB type, partial data 0x%x\n", + buffer_copy_offset); + break; + } + + rsp_q->ring_index++; + if (rsp_q->ring_index == rsp_q->length) { + rsp_q->ring_index = 0; + rsp_q->ring_ptr = rsp_q->ring; + } else { + rsp_q->ring_ptr++; + } + no_bytes = (pending_bytes > sizeof(new_pkt->data)) ? + sizeof(new_pkt->data) : pending_bytes; + if ((buffer_copy_offset + no_bytes) <= total_bytes) { + memcpy(((uint8_t *)iocb_pkt + buffer_copy_offset), + new_pkt->data, no_bytes); + buffer_copy_offset += no_bytes; + pending_bytes -= no_bytes; + --entry_count_remaining; + } else { + ql_log(ql_log_warn, vha, 0x5044, + "Attempt to copy more that we got, optimizing..%x\n", + buffer_copy_offset); + memcpy(((uint8_t *)iocb_pkt + buffer_copy_offset), + new_pkt->data, + total_bytes - buffer_copy_offset); + } + + ((response_t *)new_pkt)->signature = RESPONSE_PROCESSED; + wmb(); + } + + if (pending_bytes != 0 || entry_count_remaining != 0) { + ql_log(ql_log_fatal, vha, 0x508b, + "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n", + total_bytes, entry_count_remaining); + qla24xx_free_purex_item(item); + return NULL; + } + } while (entry_count_remaining > 0); + + if (byte_order) + host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes); + + return item; +} + int qla2x00_is_a_vp_did(scsi_qla_host_t *vha, uint32_t rscn_entry) { @@ -986,7 +1115,7 @@ qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size) return item; } -static void +void qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt, void (*process_item)(struct scsi_qla_host *vha, struct purex_item *pkt)) @@ -3852,6 +3981,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; + struct pt_ls4_rx_unsol *p; u16 rsp_in = 0, cur_ring_index; int is_shadow_hba; @@ -4024,7 +4154,19 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, qla28xx_sa_update_iocb_entry(vha, rsp->req, (struct sa_update_28xx *)pkt); break; - + case PT_LS4_UNSOL: + p = (void *)pkt; + if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) { + rsp->ring_ptr = (response_t *)pkt; + rsp->ring_index = cur_ring_index; + + ql_dbg(ql_dbg_init, vha, 0x2124, + "Defer processing UNSOL LS req opcode %#x...\n", + p->payload[0]); + return; + } + qla2xxx_process_purls_iocb((void **)&pkt, &rsp); + break; default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index da2988df8..acd9b6bf4 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -17,6 +17,26 @@ #include static struct nvme_fc_port_template qla_nvme_fc_transport; +static int qla_nvme_ls_reject_iocb(struct scsi_qla_host *vha, + struct qla_qpair *qp, + struct qla_nvme_lsrjt_pt_arg *a, + bool is_xchg_terminate); + +struct qla_nvme_unsol_ctx { + struct list_head elem; + struct scsi_qla_host *vha; + struct fc_port *fcport; + struct srb *sp; + struct nvmefc_ls_rsp lsrsp; + struct nvmefc_ls_rsp *fd_rsp; + struct work_struct lsrsp_work; + struct work_struct abort_work; + __le32 exchange_address; + __le16 nport_handle; + __le16 ox_id; + int comp_status; + spinlock_t cmd_lock; +}; int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) { @@ -231,6 +251,55 @@ static void qla_nvme_sp_ls_done(srb_t *sp, int res) schedule_work(&priv->ls_work); } +static void qla_nvme_release_lsrsp_cmd_kref(struct kref *kref) +{ + struct srb *sp = container_of(kref, struct srb, cmd_kref); + struct qla_nvme_unsol_ctx *uctx = sp->priv; + struct nvmefc_ls_rsp *fd_rsp; + unsigned long flags; + + if (!uctx) { + qla2x00_rel_sp(sp); + return; + } + + spin_lock_irqsave(&uctx->cmd_lock, flags); + uctx->sp = NULL; + sp->priv = NULL; + spin_unlock_irqrestore(&uctx->cmd_lock, flags); + + fd_rsp = uctx->fd_rsp; + + list_del(&uctx->elem); + + fd_rsp->done(fd_rsp); + kfree(uctx); + qla2x00_rel_sp(sp); +} + +static void qla_nvme_lsrsp_complete(struct work_struct *work) +{ + struct qla_nvme_unsol_ctx *uctx = + container_of(work, struct qla_nvme_unsol_ctx, lsrsp_work); + + kref_put(&uctx->sp->cmd_kref, qla_nvme_release_lsrsp_cmd_kref); +} + +static void qla_nvme_sp_lsrsp_done(srb_t *sp, int res) +{ + struct qla_nvme_unsol_ctx *uctx = sp->priv; + + if (WARN_ON_ONCE(kref_read(&sp->cmd_kref) == 0)) + return; + + if (res) + res = -EINVAL; + + uctx->comp_status = res; + INIT_WORK(&uctx->lsrsp_work, qla_nvme_lsrsp_complete); + schedule_work(&uctx->lsrsp_work); +} + /* it assumed that QPair lock is held. */ static void qla_nvme_sp_done(srb_t *sp, int res) { @@ -303,6 +372,92 @@ static void qla_nvme_abort_work(struct work_struct *work) kref_put(&sp->cmd_kref, sp->put_fn); } +static int qla_nvme_xmt_ls_rsp(struct nvme_fc_local_port *lport, + struct nvme_fc_remote_port *rport, + struct nvmefc_ls_rsp *fd_resp) +{ + struct qla_nvme_unsol_ctx *uctx = container_of(fd_resp, + struct qla_nvme_unsol_ctx, lsrsp); + struct qla_nvme_rport *qla_rport = rport->private; + fc_port_t *fcport = qla_rport->fcport; + struct scsi_qla_host *vha = uctx->vha; + struct qla_hw_data *ha = vha->hw; + struct qla_nvme_lsrjt_pt_arg a; + struct srb_iocb *nvme; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; + uint8_t cnt = 0; + + if (!fcport || fcport->deleted) + goto out; + + if (!ha->flags.fw_started) + goto out; + + /* Alloc SRB structure */ + sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC); + if (!sp) + goto out; + + sp->type = SRB_NVME_LS; + sp->name = "nvme_ls"; + sp->done = qla_nvme_sp_lsrsp_done; + sp->put_fn = qla_nvme_release_lsrsp_cmd_kref; + sp->priv = (void *)uctx; + sp->unsol_rsp = 1; + uctx->sp = sp; + spin_lock_init(&uctx->cmd_lock); + nvme = &sp->u.iocb_cmd; + uctx->fd_rsp = fd_resp; + nvme->u.nvme.desc = fd_resp; + nvme->u.nvme.dir = 0; + nvme->u.nvme.dl = 0; + nvme->u.nvme.timeout_sec = 0; + nvme->u.nvme.cmd_dma = fd_resp->rspdma; + nvme->u.nvme.cmd_len = fd_resp->rsplen; + nvme->u.nvme.rsp_len = 0; + nvme->u.nvme.rsp_dma = 0; + nvme->u.nvme.exchange_address = uctx->exchange_address; + nvme->u.nvme.nport_handle = uctx->nport_handle; + nvme->u.nvme.ox_id = uctx->ox_id; + dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma, + le32_to_cpu(fd_resp->rsplen), DMA_TO_DEVICE); + + ql_dbg(ql_dbg_unsol, vha, 0x2122, + "Unsol lsreq portid=%06x %8phC exchange_address 0x%x ox_id 0x%x hdl 0x%x\n", + fcport->d_id.b24, fcport->port_name, uctx->exchange_address, + uctx->ox_id, uctx->nport_handle); +retry: + rval = qla2x00_start_sp(sp); + switch (rval) { + case QLA_SUCCESS: + break; + case EAGAIN: + msleep(PURLS_MSLEEP_INTERVAL); + cnt++; + if (cnt < PURLS_RETRY_COUNT) + goto retry; + + fallthrough; + default: + ql_dbg(ql_log_warn, vha, 0x2123, + "Failed to xmit Unsol ls response = %d\n", rval); + rval = -EIO; + qla2x00_rel_sp(sp); + goto out; + } + + return 0; +out: + memset((void *)&a, 0, sizeof(a)); + a.vp_idx = vha->vp_idx; + a.nport_handle = uctx->nport_handle; + a.xchg_address = uctx->exchange_address; + qla_nvme_ls_reject_iocb(vha, ha->base_qpair, &a, true); + kfree(uctx); + return rval; +} + static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) { @@ -370,7 +525,7 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, nvme->u.nvme.timeout_sec = fd->timeout; nvme->u.nvme.cmd_dma = fd->rqstdma; dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma, - fd->rqstlen, DMA_TO_DEVICE); + le32_to_cpu(fd->rqstlen), DMA_TO_DEVICE); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { @@ -741,6 +896,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .ls_abort = qla_nvme_ls_abort, .fcp_io = qla_nvme_post_cmd, .fcp_abort = qla_nvme_fcp_abort, + .xmt_ls_rsp = qla_nvme_xmt_ls_rsp, #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) .map_queues = qla_nvme_map_queues, #endif @@ -868,6 +1024,249 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) return ret; } +static void qla_nvme_fc_format_rjt(void *buf, u8 ls_cmd, u8 reason, + u8 explanation, u8 vendor) +{ + struct fcnvme_ls_rjt *rjt = buf; + + rjt->w0.ls_cmd = FCNVME_LSDESC_RQST; + rjt->desc_list_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)); + rjt->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST); + rjt->rqst.desc_len = + fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst)); + rjt->rqst.w0.ls_cmd = ls_cmd; + rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT); + rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt)); + rjt->rjt.reason_code = reason; + rjt->rjt.reason_explanation = explanation; + rjt->rjt.vendor = vendor; +} + +static void qla_nvme_lsrjt_pt_iocb(struct scsi_qla_host *vha, + struct pt_ls4_request *lsrjt_iocb, + struct qla_nvme_lsrjt_pt_arg *a) +{ + lsrjt_iocb->entry_type = PT_LS4_REQUEST; + lsrjt_iocb->entry_count = 1; + lsrjt_iocb->sys_define = 0; + lsrjt_iocb->entry_status = 0; + lsrjt_iocb->handle = QLA_SKIP_HANDLE; + lsrjt_iocb->nport_handle = a->nport_handle; + lsrjt_iocb->exchange_address = a->xchg_address; + lsrjt_iocb->vp_index = a->vp_idx; + + lsrjt_iocb->control_flags = cpu_to_le16(a->control_flags); + + put_unaligned_le64(a->tx_addr, &lsrjt_iocb->dsd[0].address); + lsrjt_iocb->dsd[0].length = cpu_to_le32(a->tx_byte_count); + lsrjt_iocb->tx_dseg_count = cpu_to_le16(1); + lsrjt_iocb->tx_byte_count = cpu_to_le32(a->tx_byte_count); + + put_unaligned_le64(a->rx_addr, &lsrjt_iocb->dsd[1].address); + lsrjt_iocb->dsd[1].length = 0; + lsrjt_iocb->rx_dseg_count = 0; + lsrjt_iocb->rx_byte_count = 0; +} + +static int +qla_nvme_ls_reject_iocb(struct scsi_qla_host *vha, struct qla_qpair *qp, + struct qla_nvme_lsrjt_pt_arg *a, bool is_xchg_terminate) +{ + struct pt_ls4_request *lsrjt_iocb; + + lsrjt_iocb = __qla2x00_alloc_iocbs(qp, NULL); + if (!lsrjt_iocb) { + ql_log(ql_log_warn, vha, 0x210e, + "qla2x00_alloc_iocbs failed.\n"); + return QLA_FUNCTION_FAILED; + } + + if (!is_xchg_terminate) { + qla_nvme_fc_format_rjt((void *)vha->hw->lsrjt.c, a->opcode, + a->reason, a->explanation, 0); + + a->tx_byte_count = sizeof(struct fcnvme_ls_rjt); + a->tx_addr = vha->hw->lsrjt.cdma; + a->control_flags = CF_LS4_RESPONDER << CF_LS4_SHIFT; + + ql_dbg(ql_dbg_unsol, vha, 0x211f, + "Sending nvme fc ls reject ox_id %04x op %04x\n", + a->ox_id, a->opcode); + ql_dump_buffer(ql_dbg_unsol + ql_dbg_verbose, vha, 0x210f, + vha->hw->lsrjt.c, sizeof(*vha->hw->lsrjt.c)); + } else { + a->tx_byte_count = 0; + a->control_flags = CF_LS4_RESPONDER_TERM << CF_LS4_SHIFT; + ql_dbg(ql_dbg_unsol, vha, 0x2110, + "Terminate nvme ls xchg 0x%x\n", a->xchg_address); + } + + qla_nvme_lsrjt_pt_iocb(vha, lsrjt_iocb, a); + /* flush iocb to mem before notifying hw doorbell */ + wmb(); + qla2x00_start_iocbs(vha, qp->req); + return 0; +} + +/* + * qla2xxx_process_purls_pkt() - Pass-up Unsolicited + * Received FC-NVMe Link Service pkt to nvme_fc_rcv_ls_req(). + * LLDD need to provide memory for response buffer, which + * will be used to reference the exchange corresponding + * to the LS when issuing an ls response. LLDD will have to free + * response buffer in lport->ops->xmt_ls_rsp(). + * + * @vha: SCSI qla host + * @item: ptr to purex_item + */ +static void +qla2xxx_process_purls_pkt(struct scsi_qla_host *vha, struct purex_item *item) +{ + struct qla_nvme_unsol_ctx *uctx = item->purls_context; + fc_port_t *fcport = uctx->fcport; + struct qla_nvme_lsrjt_pt_arg a; + int ret; + + ret = nvme_fc_rcv_ls_req(fcport->nvme_remote_port, &uctx->lsrsp, + &item->iocb, item->size); + if (ret) { + ql_dbg(ql_dbg_unsol, vha, 0x2125, "NVMe tranport ls_req failed\n"); + memset((void *)&a, 0, sizeof(a)); + a.vp_idx = vha->vp_idx; + a.nport_handle = uctx->nport_handle; + a.xchg_address = uctx->exchange_address; + qla_nvme_ls_reject_iocb(vha, vha->hw->base_qpair, &a, true); + list_del(&uctx->elem); + kfree(uctx); + } +} + +static scsi_qla_host_t * +qla2xxx_get_vha_from_vp_idx(struct qla_hw_data *ha, uint16_t vp_index) +{ + scsi_qla_host_t *base_vha, *vha, *tvp; + unsigned long flags; + + base_vha = pci_get_drvdata(ha->pdev); + + if (!vp_index && !ha->num_vhosts) + return base_vha; + + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry_safe(vha, tvp, &ha->vp_list, list) { + if (vha->vp_idx == vp_index) { + spin_unlock_irqrestore(&ha->vport_slock, flags); + return vha; + } + } + spin_unlock_irqrestore(&ha->vport_slock, flags); + + return NULL; +} + +void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp) +{ + struct nvme_fc_remote_port *rport; + struct qla_nvme_rport *qla_rport; + struct qla_nvme_lsrjt_pt_arg a; + struct pt_ls4_rx_unsol *p = *pkt; + struct qla_nvme_unsol_ctx *uctx; + struct rsp_que *rsp_q = *rsp; + struct qla_hw_data *ha; + scsi_qla_host_t *vha; + fc_port_t *fcport = NULL; + struct purex_item *item; + port_id_t d_id = {0}; + port_id_t id = {0}; + u8 *opcode; + bool xmt_reject = false; + + ha = rsp_q->hw; + + vha = qla2xxx_get_vha_from_vp_idx(ha, p->vp_index); + if (!vha) { + ql_log(ql_log_warn, NULL, 0x2110, "Invalid vp index %d\n", p->vp_index); + WARN_ON_ONCE(1); + return; + } + + memset((void *)&a, 0, sizeof(a)); + opcode = (u8 *)&p->payload[0]; + a.opcode = opcode[3]; + a.vp_idx = p->vp_index; + a.nport_handle = p->nport_handle; + a.ox_id = p->ox_id; + a.xchg_address = p->exchange_address; + + id.b.domain = p->s_id.domain; + id.b.area = p->s_id.area; + id.b.al_pa = p->s_id.al_pa; + d_id.b.domain = p->d_id[2]; + d_id.b.area = p->d_id[1]; + d_id.b.al_pa = p->d_id[0]; + + fcport = qla2x00_find_fcport_by_nportid(vha, &id, 0); + if (!fcport) { + ql_dbg(ql_dbg_unsol, vha, 0x211e, + "Failed to find sid=%06x did=%06x\n", + id.b24, d_id.b24); + a.reason = FCNVME_RJT_RC_INV_ASSOC; + a.explanation = FCNVME_RJT_EXP_NONE; + xmt_reject = true; + goto out; + } + rport = fcport->nvme_remote_port; + qla_rport = rport->private; + + item = qla27xx_copy_multiple_pkt(vha, pkt, rsp, true, false); + if (!item) { + a.reason = FCNVME_RJT_RC_LOGIC; + a.explanation = FCNVME_RJT_EXP_NONE; + xmt_reject = true; + goto out; + } + + uctx = kzalloc(sizeof(*uctx), GFP_ATOMIC); + if (!uctx) { + ql_log(ql_log_info, vha, 0x2126, "Failed allocate memory\n"); + a.reason = FCNVME_RJT_RC_LOGIC; + a.explanation = FCNVME_RJT_EXP_NONE; + xmt_reject = true; + kfree(item); + goto out; + } + + uctx->vha = vha; + uctx->fcport = fcport; + uctx->exchange_address = p->exchange_address; + uctx->nport_handle = p->nport_handle; + uctx->ox_id = p->ox_id; + qla_rport->uctx = uctx; + INIT_LIST_HEAD(&uctx->elem); + list_add_tail(&uctx->elem, &fcport->unsol_ctx_head); + item->purls_context = (void *)uctx; + + ql_dbg(ql_dbg_unsol, vha, 0x2121, + "PURLS OP[%01x] size %d xchg addr 0x%x portid %06x\n", + item->iocb.iocb[3], item->size, uctx->exchange_address, + fcport->d_id.b24); + /* +48 0 1 2 3 4 5 6 7 8 9 A B C D E F + * ----- ----------------------------------------------- + * 0000: 00 00 00 05 28 00 00 00 07 00 00 00 08 00 00 00 + * 0010: ab ec 0f cc 00 00 8d 7d 05 00 00 00 10 00 00 00 + * 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + */ + ql_dump_buffer(ql_dbg_unsol + ql_dbg_verbose, vha, 0x2120, + &item->iocb, item->size); + + qla24xx_queue_purex_item(vha, item, qla2xxx_process_purls_pkt); +out: + if (xmt_reject) { + qla_nvme_ls_reject_iocb(vha, (*rsp)->qpair, &a, false); + __qla_consume_iocb(vha, pkt, rsp); + } +} + #else void qla_nvme_unregister_remote_port(struct fc_port *fcport) diff --git a/qla2x00t-32gbit/qla_nvme.h b/qla2x00t-32gbit/qla_nvme.h index 78f9dd120..cd73ce7e8 100644 --- a/qla2x00t-32gbit/qla_nvme.h +++ b/qla2x00t-32gbit/qla_nvme.h @@ -24,6 +24,7 @@ #define Q2T_NVME_NUM_TAGS 2048 #define QLA_MAX_FC_SEGMENTS 64 +struct qla_nvme_unsol_ctx; struct scsi_qla_host; struct qla_hw_data; struct req_que; @@ -40,6 +41,7 @@ struct nvme_private { struct qla_nvme_rport { struct fc_port *fcport; + struct qla_nvme_unsol_ctx *uctx; }; #define COMMAND_NVME 0x88 /* Command Type FC-NVMe IOCB */ @@ -78,6 +80,9 @@ struct cmd_nvme { struct dsd64 nvme_dsd; }; +#define PURLS_MSLEEP_INTERVAL 1 +#define PURLS_RETRY_COUNT 5 + #define PT_LS4_REQUEST 0x89 /* Link Service pass-through IOCB (request) */ struct pt_ls4_request { uint8_t entry_type; @@ -121,21 +126,19 @@ struct pt_ls4_rx_unsol { __le32 exchange_address; uint8_t d_id[3]; uint8_t r_ctl; - be_id_t s_id; + le_id_t s_id; uint8_t cs_ctl; uint8_t f_ctl[3]; uint8_t type; __le16 seq_cnt; uint8_t df_ctl; uint8_t seq_id; - __le16 rx_id; - __le16 ox_id; - __le32 param; - __le32 desc0; + __le16 rx_id; + __le16 ox_id; + __le32 desc0; #define PT_LS4_PAYLOAD_OFFSET 0x2c #define PT_LS4_FIRST_PACKET_LEN 20 - __le32 desc_len; - __le32 payload[3]; + __le32 payload[5]; }; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index a8112be17..1626e8742 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -4525,7 +4525,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->elsrej.size = sizeof(struct fc_els_ls_rjt) + 16; ha->elsrej.c = dma_alloc_coherent(&ha->pdev->dev, - ha->elsrej.size, &ha->elsrej.cdma, GFP_KERNEL); + ha->elsrej.size, + &ha->elsrej.cdma, + GFP_KERNEL); if (!ha->elsrej.c) { ql_dbg_pci(ql_dbg_init, ha->pdev, 0xffff, @@ -4535,8 +4537,21 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->elsrej.c->er_cmd = ELS_LS_RJT; ha->elsrej.c->er_reason = ELS_RJT_LOGIC; ha->elsrej.c->er_explan = ELS_EXPL_UNAB_DATA; + + ha->lsrjt.size = sizeof(struct fcnvme_ls_rjt); + ha->lsrjt.c = dma_alloc_coherent(&ha->pdev->dev, ha->lsrjt.size, + &ha->lsrjt.cdma, GFP_KERNEL); + if (!ha->lsrjt.c) { + ql_dbg_pci(ql_dbg_init, ha->pdev, 0xffff, + "Alloc failed for nvme fc reject cmd.\n"); + goto fail_lsrjt; + } + return 0; +fail_lsrjt: + dma_free_coherent(&ha->pdev->dev, ha->elsrej.size, + ha->elsrej.c, ha->elsrej.cdma); fail_elsrej: dma_pool_destroy(ha->purex_dma_pool); fail_flt: @@ -5066,6 +5081,12 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->elsrej.c = NULL; } + if (ha->lsrjt.c) { + dma_free_coherent(&ha->pdev->dev, ha->lsrjt.size, ha->lsrjt.c, + ha->lsrjt.cdma); + ha->lsrjt.c = NULL; + } + ha->init_cb = NULL; ha->init_cb_dma = 0; From c94fdd810a84885047ee9619064bd7ca540f20b7 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Sun, 24 Sep 2023 13:06:25 +0300 Subject: [PATCH 89/93] qla2x00t-32gbit: Backport to older kernel versions Unbreak the build for the previous commit against kernel versions before v5.8. See also commit 72e6329f86c7 ("nvme-fc and nvmet-fc: revise LLDD api for LS reception and LS request") # v5.8. --- qla2x00t-32gbit/qla_def.h | 6 ++++++ qla2x00t-32gbit/qla_gbl.h | 2 +- qla2x00t-32gbit/qla_isr.c | 4 ++++ qla2x00t-32gbit/qla_nvme.c | 10 ++++++++++ qla2x00t-32gbit/qla_nvme.h | 4 ++++ qla2x00t-32gbit/qla_os.c | 6 ++++++ 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 4c143b347..f009d2cfa 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -389,11 +389,13 @@ struct name_list_extended { u8 sent; }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct qla_nvme_fc_rjt { struct fcnvme_ls_rjt *c; dma_addr_t cdma; u16 size; }; +#endif struct els_reject { struct fc_els_ls_rjt *c; @@ -552,6 +554,7 @@ struct ct_arg { port_id_t id; }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct qla_nvme_lsrjt_pt_arg { struct fc_port *fcport; u8 opcode; @@ -565,6 +568,7 @@ struct qla_nvme_lsrjt_pt_arg { u32 tx_byte_count, rx_byte_count; dma_addr_t tx_addr, rx_addr; }; +#endif /* * SRB extensions. @@ -4890,7 +4894,9 @@ struct qla_hw_data { struct els_reject elsrej; u8 edif_post_stop_cnt_down; struct qla_vp_map *vp_map; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct qla_nvme_fc_rjt lsrjt; +#endif struct qla_fw_res fwres ____cacheline_aligned; }; diff --git a/qla2x00t-32gbit/qla_gbl.h b/qla2x00t-32gbit/qla_gbl.h index 767b3823e..ea684de65 100644 --- a/qla2x00t-32gbit/qla_gbl.h +++ b/qla2x00t-32gbit/qla_gbl.h @@ -613,7 +613,7 @@ void qla24xx_queue_purex_item(scsi_qla_host_t *, struct purex_item *, void (*process_item)(struct scsi_qla_host *, struct purex_item *)); void __qla_consume_iocb(struct scsi_qla_host *, void **, struct rsp_que **); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp); #endif diff --git a/qla2x00t-32gbit/qla_isr.c b/qla2x00t-32gbit/qla_isr.c index 0a2b6b58b..a6209b2f2 100644 --- a/qla2x00t-32gbit/qla_isr.c +++ b/qla2x00t-32gbit/qla_isr.c @@ -3981,7 +3981,9 @@ 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; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct pt_ls4_rx_unsol *p; +#endif u16 rsp_in = 0, cur_ring_index; int is_shadow_hba; @@ -4154,6 +4156,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, qla28xx_sa_update_iocb_entry(vha, rsp->req, (struct sa_update_28xx *)pkt); break; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) case PT_LS4_UNSOL: p = (void *)pkt; if (qla_chk_cont_iocb_avail(vha, rsp, (response_t *)pkt, rsp_in)) { @@ -4167,6 +4170,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, } qla2xxx_process_purls_iocb((void **)&pkt, &rsp); break; +#endif default: /* Type Not Supported. */ ql_dbg(ql_dbg_async, vha, 0x5042, diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index acd9b6bf4..1dcae7a65 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -17,6 +17,7 @@ #include static struct nvme_fc_port_template qla_nvme_fc_transport; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) static int qla_nvme_ls_reject_iocb(struct scsi_qla_host *vha, struct qla_qpair *qp, struct qla_nvme_lsrjt_pt_arg *a, @@ -37,6 +38,7 @@ struct qla_nvme_unsol_ctx { int comp_status; spinlock_t cmd_lock; }; +#endif int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport) { @@ -251,6 +253,7 @@ static void qla_nvme_sp_ls_done(srb_t *sp, int res) schedule_work(&priv->ls_work); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) static void qla_nvme_release_lsrsp_cmd_kref(struct kref *kref) { struct srb *sp = container_of(kref, struct srb, cmd_kref); @@ -299,6 +302,7 @@ static void qla_nvme_sp_lsrsp_done(srb_t *sp, int res) INIT_WORK(&uctx->lsrsp_work, qla_nvme_lsrsp_complete); schedule_work(&uctx->lsrsp_work); } +#endif /* it assumed that QPair lock is held. */ static void qla_nvme_sp_done(srb_t *sp, int res) @@ -372,6 +376,7 @@ static void qla_nvme_abort_work(struct work_struct *work) kref_put(&sp->cmd_kref, sp->put_fn); } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) static int qla_nvme_xmt_ls_rsp(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_rsp *fd_resp) @@ -457,6 +462,7 @@ static int qla_nvme_xmt_ls_rsp(struct nvme_fc_local_port *lport, kfree(uctx); return rval; } +#endif static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport, struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd) @@ -896,7 +902,9 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = { .ls_abort = qla_nvme_ls_abort, .fcp_io = qla_nvme_post_cmd, .fcp_abort = qla_nvme_fcp_abort, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) .xmt_ls_rsp = qla_nvme_xmt_ls_rsp, +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) .map_queues = qla_nvme_map_queues, #endif @@ -1024,6 +1032,7 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha) return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) static void qla_nvme_fc_format_rjt(void *buf, u8 ls_cmd, u8 reason, u8 explanation, u8 vendor) { @@ -1266,6 +1275,7 @@ void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp) __qla_consume_iocb(vha, pkt, rsp); } } +#endif #else diff --git a/qla2x00t-32gbit/qla_nvme.h b/qla2x00t-32gbit/qla_nvme.h index cd73ce7e8..c36b7e808 100644 --- a/qla2x00t-32gbit/qla_nvme.h +++ b/qla2x00t-32gbit/qla_nvme.h @@ -24,7 +24,9 @@ #define Q2T_NVME_NUM_TAGS 2048 #define QLA_MAX_FC_SEGMENTS 64 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct qla_nvme_unsol_ctx; +#endif struct scsi_qla_host; struct qla_hw_data; struct req_que; @@ -41,7 +43,9 @@ struct nvme_private { struct qla_nvme_rport { struct fc_port *fcport; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) struct qla_nvme_unsol_ctx *uctx; +#endif }; #define COMMAND_NVME 0x88 /* Command Type FC-NVMe IOCB */ diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 1626e8742..dbdf67f71 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -4538,6 +4538,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, ha->elsrej.c->er_reason = ELS_RJT_LOGIC; ha->elsrej.c->er_explan = ELS_EXPL_UNAB_DATA; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) ha->lsrjt.size = sizeof(struct fcnvme_ls_rjt); ha->lsrjt.c = dma_alloc_coherent(&ha->pdev->dev, ha->lsrjt.size, &ha->lsrjt.cdma, GFP_KERNEL); @@ -4546,12 +4547,15 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, "Alloc failed for nvme fc reject cmd.\n"); goto fail_lsrjt; } +#endif return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) fail_lsrjt: dma_free_coherent(&ha->pdev->dev, ha->elsrej.size, ha->elsrej.c, ha->elsrej.cdma); +#endif fail_elsrej: dma_pool_destroy(ha->purex_dma_pool); fail_flt: @@ -5081,11 +5085,13 @@ qla2x00_mem_free(struct qla_hw_data *ha) ha->elsrej.c = NULL; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) if (ha->lsrjt.c) { dma_free_coherent(&ha->pdev->dev, ha->lsrjt.size, ha->lsrjt.c, ha->lsrjt.cdma); ha->lsrjt.c = NULL; } +#endif ha->init_cb = NULL; ha->init_cb_dma = 0; From 69a6419bed6b62602589ac614b096b495e377435 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:30:29 +0300 Subject: [PATCH 90/93] qla2x00t-32gbit: Fix nvme_fc_rcv_ls_req() undefined error The kernel robot reported below build error, >> ERROR: modpost: "nvme_fc_rcv_ls_req" [drivers/scsi/qla2xxx/qla2xxx.ko] undefined! Use CONFIG_NVME_FC enabled check to fix the build error. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308021445.txlNq7UC-lkp@intel.com/ Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230824151521.35261-1-njavali@marvell.com Signed-off-by: Martin K. Petersen [ commit 27177862de96 upstream ] --- qla2x00t-32gbit/qla_nvme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 1dcae7a65..d6223f522 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -1134,10 +1134,12 @@ qla2xxx_process_purls_pkt(struct scsi_qla_host *vha, struct purex_item *item) struct qla_nvme_unsol_ctx *uctx = item->purls_context; fc_port_t *fcport = uctx->fcport; struct qla_nvme_lsrjt_pt_arg a; - int ret; + int ret = 1; +#if (IS_ENABLED(CONFIG_NVME_FC)) ret = nvme_fc_rcv_ls_req(fcport->nvme_remote_port, &uctx->lsrsp, &item->iocb, item->size); +#endif if (ret) { ql_dbg(ql_dbg_unsol, vha, 0x2125, "NVMe tranport ls_req failed\n"); memset((void *)&a, 0, sizeof(a)); From 4dd1f3f9841d1f1c88e0bf4a73a5694f3ff3418b Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:31:02 +0300 Subject: [PATCH 91/93] qla2x00t-32gbit: Fix spelling mistake "tranport" -> "transport" There is a spelling mistake in a ql_dbg message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20230828213101.758609-1-colin.i.king@gmail.com Acked-by: Nilesh Javali Signed-off-by: Martin K. Petersen [ commit 7a5dee9b72e9 upstream ] --- qla2x00t-32gbit/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index d6223f522..da703c697 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -1141,7 +1141,7 @@ qla2xxx_process_purls_pkt(struct scsi_qla_host *vha, struct purex_item *item) &item->iocb, item->size); #endif if (ret) { - ql_dbg(ql_dbg_unsol, vha, 0x2125, "NVMe tranport ls_req failed\n"); + ql_dbg(ql_dbg_unsol, vha, 0x2125, "NVMe transport ls_req failed\n"); memset((void *)&a, 0, sizeof(a)); a.vp_idx = vha->vp_idx; a.nport_handle = uctx->nport_handle; From 785ac55de75e9cb3273ef02ba70ee585892234b0 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:31:24 +0300 Subject: [PATCH 92/93] qla2x00t-32gbit: Fix unused variable warning in qla2xxx_process_purls_pkt() When CONFIG_NVME_FC is not set, fcport is unused: drivers/scsi/qla2xxx/qla_nvme.c: In function 'qla2xxx_process_purls_pkt': drivers/scsi/qla2xxx/qla_nvme.c:1183:20: warning: unused variable 'fcport' [-Wunused-variable] 1183 | fc_port_t *fcport = uctx->fcport; | ^~~~~~ While this preprocessor usage could be converted to a normal if statement to allow the compiler to always see fcport as used, it is equally easy to just eliminate the fcport variable and use uctx->fcport directly. Fixes: 27177862de96 ("scsi: qla2xxx: Fix nvme_fc_rcv_ls_req() undefined error") Reported-by: Stephen Rothwell Closes: https://lore.kernel.org/linux-next/20230828131304.269a2a40@canb.auug.org.au/ Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308290833.sKkoSSeO-lkp@intel.com/ Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20230829-qla_nvme-fix-unused-fcport-v1-1-51c7560ecaee@kernel.org Acked-by: Nilesh Javali Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen [ commit d4781807f050 upstream ] --- qla2x00t-32gbit/qla_nvme.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index da703c697..8cb93751a 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -1132,12 +1132,11 @@ static void qla2xxx_process_purls_pkt(struct scsi_qla_host *vha, struct purex_item *item) { struct qla_nvme_unsol_ctx *uctx = item->purls_context; - fc_port_t *fcport = uctx->fcport; struct qla_nvme_lsrjt_pt_arg a; int ret = 1; #if (IS_ENABLED(CONFIG_NVME_FC)) - ret = nvme_fc_rcv_ls_req(fcport->nvme_remote_port, &uctx->lsrsp, + ret = nvme_fc_rcv_ls_req(uctx->fcport->nvme_remote_port, &uctx->lsrsp, &item->iocb, item->size); #endif if (ret) { From 4c0fb04abae9e45e31b8f5d69a8cdea446d7b4b4 Mon Sep 17 00:00:00 2001 From: Gleb Chesnokov Date: Fri, 22 Sep 2023 16:31:45 +0300 Subject: [PATCH 93/93] qla2x00t-32gbit: Correct endianness for rqstlen and rsplen rqstlen and rsplen were changed to __le32 to fix sparse warnings: drivers/scsi/qla2xxx/qla_nvme.c:402:30: warning: incorrect type in assignment (different base types) drivers/scsi/qla2xxx/qla_nvme.c:402:30: expected restricted __le32 [usertype] cmd_len drivers/scsi/qla2xxx/qla_nvme.c:402:30: got unsigned short [usertype] rsplen drivers/scsi/qla2xxx/qla_nvme.c:507:30: warning: incorrect type in assignment (different base types) drivers/scsi/qla2xxx/qla_nvme.c:507:30: expected restricted __le32 [usertype] cmd_len drivers/scsi/qla2xxx/qla_nvme.c:507:30: got unsigned int [usertype] rqstlen drivers/scsi/qla2xxx/qla_nvme.c:508:30: warning: incorrect type in assignment (different base types) drivers/scsi/qla2xxx/qla_nvme.c:508:30: expected restricted __le32 [usertype] rsp_len drivers/scsi/qla2xxx/qla_nvme.c:508:30: got unsigned int [usertype] rsplen Correct the endianness in qla2xxx driver thus avoiding changes in nvme-fc-driver.h. Fixes: 875386b98857 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe") Signed-off-by: Nilesh Javali Link: https://lore.kernel.org/r/20230831112146.32595-1-njavali@marvell.com Signed-off-by: Martin K. Petersen [ commit 0be7592885d7 upstream ] --- qla2x00t-32gbit/qla_nvme.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 8cb93751a..e0a9a4f65 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -419,14 +419,14 @@ static int qla_nvme_xmt_ls_rsp(struct nvme_fc_local_port *lport, nvme->u.nvme.dl = 0; nvme->u.nvme.timeout_sec = 0; nvme->u.nvme.cmd_dma = fd_resp->rspdma; - nvme->u.nvme.cmd_len = fd_resp->rsplen; + nvme->u.nvme.cmd_len = cpu_to_le32(fd_resp->rsplen); nvme->u.nvme.rsp_len = 0; nvme->u.nvme.rsp_dma = 0; nvme->u.nvme.exchange_address = uctx->exchange_address; nvme->u.nvme.nport_handle = uctx->nport_handle; nvme->u.nvme.ox_id = uctx->ox_id; dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma, - le32_to_cpu(fd_resp->rsplen), DMA_TO_DEVICE); + fd_resp->rsplen, DMA_TO_DEVICE); ql_dbg(ql_dbg_unsol, vha, 0x2122, "Unsol lsreq portid=%06x %8phC exchange_address 0x%x ox_id 0x%x hdl 0x%x\n", @@ -525,13 +525,13 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport, nvme->u.nvme.desc = fd; nvme->u.nvme.dir = 0; nvme->u.nvme.dl = 0; - nvme->u.nvme.cmd_len = fd->rqstlen; - nvme->u.nvme.rsp_len = fd->rsplen; + nvme->u.nvme.cmd_len = cpu_to_le32(fd->rqstlen); + nvme->u.nvme.rsp_len = cpu_to_le32(fd->rsplen); nvme->u.nvme.rsp_dma = fd->rspdma; nvme->u.nvme.timeout_sec = fd->timeout; nvme->u.nvme.cmd_dma = fd->rqstdma; dma_sync_single_for_device(&ha->pdev->dev, nvme->u.nvme.cmd_dma, - le32_to_cpu(fd->rqstlen), DMA_TO_DEVICE); + fd->rqstlen, DMA_TO_DEVICE); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) {