From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC05D3E073E; Fri, 11 Sep 2026 02:19:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093170; cv=none; b=XU1BB48pzlqZF1CJeN53abLmoN+PHlar99SVB2H02VpQtkSl5VgecKU9hEZ8wuf9/JeC8+GB4ReaoxqAoPbkYh082vp52lYcvlkIPbPQCClkl0vMwYEOLiR+YuvLkxf/kIE5WM+wK2isDlD5nXwf3Y3n1/aBvlPq657Ogze6Fg8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093170; c=relaxed/simple; bh=6E/N2wy6Fdmr7y1MXO0Qxcd6tAv4JUVu5jev/FtyGOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IyUqAuG6fhEHKkfYYyNAJ+mAMMirI3kU4hTBpjIRM50Rwl8dGd/gROhXPKyxkNRvaK2rmbrpN+5uUNt6DtEazQdIcP9Jpf7ncbqJPkoLzhGKjeNLWwYBzxupvdAqFTM6LiFtPyLfssvOpp3G0uZ50E/TLsmxrGk1cEpbBBTYrH8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=JPBvz2GJ; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="JPBvz2GJ" Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12QMH332057; Fri, 11 Sep 2026 02:19:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=PNfeoblsafp3SYYxA tlZnHU/V+Q8NsM4TyWowhkjveM=; b=JPBvz2GJWFO3VlIXz7aYb83Ma+mBe8QXj vEEIoMFdbNcfUOcgh3OBVyFeBQ0sclFxstIWuj05fZhOmJXOcH5DeeQu0ZjQff6Z qPZnhZisJABCOE05E986Rlq+qyTI8bZjJIKCu4oJMMsZLnh8gzWmkS3gPywXvZO2 Kl4Zl9GVzc1XQkPSSqymWJmBS5mx/4EsT0S1Ny1l034PIijQfAQ8hCcBfX/wmBn1 Ju9MrjWIeVKerntCsj+b6HOFYDjii8/wemCCCPEwYb03M2RQoketRJY05XtmxZ5N I5eQXcf70GRtoo+TPdnXVAxbCCgjV4b6uqzgM1n8dKr59Pdf+4/6A== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8qrs8b-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:15 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B15CZX872208; Fri, 11 Sep 2026 02:19:15 GMT Received: from smtprelay07.wdc07v.mail.ibm.com ([172.16.1.74]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvwk3u2x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:15 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay07.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JDSj32834126 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:13 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AD0D958055; Fri, 11 Sep 2026 02:19:13 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B27685804B; Fri, 11 Sep 2026 02:19:12 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:12 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 1/9] scsi: ibmvfc: add basic FPIN support Date: Thu, 10 Sep 2026 19:19:01 -0700 Message-ID: <20260911021910.1038128-2-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=SpUFe/O0 c=1 sm=1 tr=0 ts=6aa36524 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VnNF1IyMAAAA:8 a=J0p3lhKYf7zTyTyceaYA:9 X-Proofpoint-ORIG-GUID: sTtBM0Vulpz7jyrN1kcpaucfS7j9dPV3 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX0gSRXD128WbK fYa1h9Ewapx/4k4zxxAVGlMmVHD9ZdfwmpjuJjq2Yyqoni0R3GpOBEez6fRZy9iFvqD8rgWj2Cv ZRm9zv6PI/C8AuKpmyDhaqhVbwn3NjYyuxV2V2jKz/0UbFfZjaxaY/x1Jig3/LzoC+Bngaz1coq wpQ+1ecm/qoc0BDWKQ3V9l7zfm8gitRWyW+ZLv9jatRjjblCpM/Rbu1hmO1fGxEkW17yakLof6l C7/GPyShtQzXErfWUT94SlEx6Z6LgqcZQsB93miqAlLnKaMTehNO9ue4fkFkgx6J5af1fl5ekIX 0xkDL+HMvl2NH6P1W/W7peSkdV/c/tVbrId5M/XNUW0vMPp6I4agVz3E7xiEOQ9EYkcO06nuF8J nYHx2QEVSZRHL6v7dGSHFoou6PhFNrcK00H/EfJOTdNUy0yLKTKAcI+3fhfZuKdJeRndhF1pGzT 2CiYsuFEZP4MHiHJDIg== X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX9aOCt2oGTHwx 1k7SefdS/4Lrgs1ByPHe/NkVPeyNi06KdAjRjSVCxWklLiJlgJmgHXYuAoR+ieKcHeSwmKaWzBF VyYG+3W9WnNPs046EdYDgcEcIdNCw3M= X-Proofpoint-GUID: sTtBM0Vulpz7jyrN1kcpaucfS7j9dPV3 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 adultscore=0 lowpriorityscore=0 suspectscore=0 spamscore=0 clxscore=1015 phishscore=0 malwarescore=0 impostorscore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Implement support for a basic level of Fabric Performance Impact Notifications (FPIN) in the ibmvfc driver to enable monitoring of fabric congestion and link integrity events. Add async event handler for IBMVFC_AE_FPIN events that offloads FPIN processing to a dedicated workqueue. Convert VIOS FPIN messages to standard fc_els_fpin structures and pass them to fc_host_fpin_rcv() for processing by the FC transport layer. Introduce common FPIN conversion routines that will be reused for full and extended FPIN support in subsequent patches. Add KUnit test infrastructure to validate FPIN event handling and statistics updates. Add ibmvfc_handle_async() support for IBMVFC_AE_FPIN events, a dedicated workqueue for FPIN processing, FPIN message conversion to fc_els_fpin format, handling of link congestion, port congestion, port cleared, port degraded, and congestion cleared events, and a KUnit test module for FPIN functionality. Signed-off-by: Dave Marquardt Signed-off-by: Tyrel Datwyler --- drivers/scsi/Kconfig | 10 + drivers/scsi/ibmvscsi/Makefile | 1 + drivers/scsi/ibmvscsi/ibmvfc-core.c | 295 ++++++++++++++++++- drivers/scsi/ibmvscsi/ibmvfc.h | 17 ++ drivers/scsi/ibmvscsi/ibmvfc_kunit.c | 408 +++++++++++++++++++++++++++ 5 files changed, 728 insertions(+), 3 deletions(-) create mode 100644 drivers/scsi/ibmvscsi/ibmvfc_kunit.c diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 1eec66195cf4..320c37c4ab36 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -760,6 +760,16 @@ config SCSI_IBMVFC To compile this driver as a module, choose M here: the module will be called ibmvfc. =20 +config SCSI_IBMVFC_KUNIT_TEST + tristate "KUnit tests for the IBM POWER Virtual FC Client" if !KUNIT_ALL_= TESTS + depends on SCSI_IBMVFC && KUNIT + default KUNIT_ALL_TESTS + help + Compile IBM POWER Virtual FC client KUnit tests. These tests + specifically test FPIN functionality. To compile this driver + as a module, choose M here: the module will be called + ibmvfc_kunit. + config SCSI_IBMVFC_TRACE bool "enable driver internal trace" depends on SCSI_IBMVFC diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile index 9408c7f4cdee..a227bc633f3a 100644 --- a/drivers/scsi/ibmvscsi/Makefile +++ b/drivers/scsi/ibmvscsi/Makefile @@ -3,3 +3,4 @@ ibmvfc-objs :=3D ibmvfc-core.o ibmvfc-nvme.o =20 obj-$(CONFIG_SCSI_IBMVSCSI) +=3D ibmvscsi.o obj-$(CONFIG_SCSI_IBMVFC) +=3D ibmvfc.o +obj-$(CONFIG_SCSI_IBMVFC_KUNIT_TEST) +=3D ibmvfc_kunit.o diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index aa7ae81df41b..5259a80958ce 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include "ibmvfc.h" =20 static unsigned int init_timeout =3D IBMVFC_INIT_TIMEOUT; @@ -1433,6 +1436,7 @@ void ibmvfc_release_tgt(struct kref *kref) struct ibmvfc_target *tgt =3D container_of(kref, struct ibmvfc_target, kr= ef); mempool_free(tgt, tgt->vhost->tgt_pool); } +EXPORT_SYMBOL_IF_KUNIT(ibmvfc_release_tgt); =20 /** * ibmvfc_get_starget_node_name - Get SCSI target's node name @@ -3213,6 +3217,7 @@ static const struct ibmvfc_async_desc ae_desc [] =3D { { "Halt", IBMVFC_AE_HALT, IBMVFC_DEFAULT_LOG_LEVEL }, { "Resume", IBMVFC_AE_RESUME, IBMVFC_DEFAULT_LOG_LEVEL }, { "Adapter Failed", IBMVFC_AE_ADAPTER_FAILED, IBMVFC_DEFAULT_LOG_LEVEL }, + { "FPIN", IBMVFC_AE_FPIN, IBMVFC_DEFAULT_LOG_LEVEL }, }; =20 static const struct ibmvfc_async_desc unknown_ae =3D { @@ -3261,16 +3266,259 @@ static const char *ibmvfc_get_link_state(enum ibmv= fc_ae_link_state state) return ""; } =20 +#define IBMVFC_FPIN_CONGN_DESC_SZ (sizeof(struct fc_els_fpin) + sizeof(str= uct fc_fn_congn_desc)) +#define IBMVFC_FPIN_LI_DESC_SZ (sizeof(struct fc_els_fpin) + \ + struct_size_t(struct fc_fn_li_desc, pname_list, 1)) +#define IBMVFC_FPIN_PEER_CONGN_DESC_SZ (sizeof(struct fc_els_fpin) + \ + struct_size_t(struct fc_fn_peer_congn_desc, pname_list, 1)) + +/** + * ibmvfc_fpin_size_helper(): compute fpin structure size based on fpin st= atus + * @fpin_status: status value + * + * Return: + * 0: invalid fpin_status + * other: valid size + */ +static size_t ibmvfc_fpin_size_helper(u8 fpin_status) +{ + size_t size =3D 0; + + switch (fpin_status) { + case IBMVFC_AE_FPIN_LINK_CONGESTED: + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: + size =3D IBMVFC_FPIN_CONGN_DESC_SZ; + break; + case IBMVFC_AE_FPIN_PORT_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CLEARED: + size =3D IBMVFC_FPIN_PEER_CONGN_DESC_SZ; + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + size =3D IBMVFC_FPIN_LI_DESC_SZ; + break; + default: + break; + } + + return size; +} + +/** + * ibmvfc_common_fpin_to_desc(): allocate and populate a struct fc_els_fpi= n struct + * containing a descriptor. + * + * Allocate a struct fc_els_fpin containing a descriptor and populate + * based on data from *ibmvfc_fpin. + * + * Return: + * NULL - unable to allocate structure + * non-NULL - pointer to populated struct fc_els_fpin + */ +static struct fc_els_fpin * +ibmvfc_common_fpin_to_desc(u8 fpin_status, __be64 wwpn, __be16 type, __be1= 6 modifier, + __be32 threshold, __be32 event_count) +{ + struct fc_fn_peer_congn_desc *pdesc; + struct fc_fn_congn_desc *cdesc; + struct fc_fn_li_desc *ldesc; + struct fc_els_fpin *fpin; + size_t size; + + size =3D ibmvfc_fpin_size_helper(fpin_status); + if (!size) + return NULL; + + fpin =3D kzalloc(size, GFP_KERNEL); + if (!fpin) + return NULL; + + fpin->fpin_cmd =3D ELS_FPIN; + + switch (fpin_status) { + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: + case IBMVFC_AE_FPIN_LINK_CONGESTED: + fpin->desc_len =3D cpu_to_be32(sizeof(struct fc_fn_congn_desc)); + cdesc =3D (struct fc_fn_congn_desc *)fpin->fpin_desc; + cdesc->desc_tag =3D cpu_to_be32(ELS_DTAG_CONGESTION); + cdesc->desc_len =3D cpu_to_be32(FC_TLV_DESC_LENGTH_FROM_SZ(*cdesc)); + cdesc->event_type =3D type; + cdesc->event_modifier =3D modifier; + cdesc->event_period =3D cpu_to_be32(IBMVFC_FPIN_DEFAULT_EVENT_PERIOD); + cdesc->severity =3D FPIN_CONGN_SEVERITY_WARNING; + break; + case IBMVFC_AE_FPIN_PORT_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CLEARED: + fpin->desc_len =3D + cpu_to_be32(struct_size_t(struct fc_fn_peer_congn_desc, pname_list, 1)); + pdesc =3D (struct fc_fn_peer_congn_desc *)fpin->fpin_desc; + pdesc->desc_tag =3D cpu_to_be32(ELS_DTAG_PEER_CONGEST); + pdesc->desc_len =3D cpu_to_be32(struct_size_t(struct fc_fn_peer_congn_de= sc, + pname_list, 1) - FC_TLV_DESC_HDR_SZ); + pdesc->event_type =3D type; + pdesc->event_modifier =3D modifier; + pdesc->event_period =3D cpu_to_be32(IBMVFC_FPIN_DEFAULT_EVENT_PERIOD); + pdesc->attached_wwpn =3D wwpn; + pdesc->pname_count =3D cpu_to_be32(1); + pdesc->pname_list[0] =3D wwpn; + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + fpin->desc_len =3D cpu_to_be32(struct_size_t(struct fc_fn_li_desc, pname= _list, 1)); + ldesc =3D (struct fc_fn_li_desc *)fpin->fpin_desc; + ldesc->desc_tag =3D cpu_to_be32(ELS_DTAG_LNK_INTEGRITY); + ldesc->desc_len =3D cpu_to_be32(struct_size_t(struct fc_fn_li_desc, + pname_list, 1) - FC_TLV_DESC_HDR_SZ); + ldesc->event_type =3D type; + ldesc->event_modifier =3D modifier; + ldesc->event_threshold =3D threshold; + ldesc->event_count =3D event_count; + ldesc->attached_wwpn =3D wwpn; + ldesc->pname_count =3D cpu_to_be32(1); + ldesc->pname_list[0] =3D wwpn; + break; + default: + /* This should be caught above. */ + kfree(fpin); + fpin =3D NULL; + break; + } + + return fpin; +} + +/** + * ibmvfc_basic_fpin_to_desc(): allocate and populate a struct fc_els_fpin= struct + * containing a descriptor. + * @ibmvfc_fpin: Pointer to async crq + * + * Allocate a struct fc_els_fpin containing a descriptor and populate + * based on data from *ibmvfc_fpin. + * + * Return: + * NULL - unable to allocate structure + * non-NULL - pointer to populated struct fc_els_fpin + */ +static struct fc_els_fpin * +ibmvfc_basic_fpin_to_desc(struct ibmvfc_async_crq *crq, u64 wwpn) +{ + __be16 type; + + switch (crq->fpin_status) { + case IBMVFC_AE_FPIN_LINK_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CONGESTED: + type =3D cpu_to_be16(FPIN_CONGN_DEVICE_SPEC); + break; + case IBMVFC_AE_FPIN_PORT_CLEARED: + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: + type =3D cpu_to_be16(FPIN_CONGN_CLEAR); + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + type =3D cpu_to_be16(FPIN_LI_UNKNOWN); + break; + default: + return NULL; + } + + return ibmvfc_common_fpin_to_desc(crq->fpin_status, cpu_to_be64(wwpn), + type, cpu_to_be16(0), + cpu_to_be32(IBMVFC_FPIN_DEFAULT_EVENT_THRESHOLD), + cpu_to_be32(1)); +} + +/** + * ibmvfc_find_target - Search for a target in a target list + * @target_list: list head of targets to search + * @scsi_id: SCSI ID to match (0 to skip this check) + * @wwpn: WWPN to match (0 to skip this check) + * @node_name: Node name to match (0 to skip this check) + * + * Returns: + * Pointer to matching target, or NULL if not found + **/ +static struct ibmvfc_target *ibmvfc_find_target(struct list_head *target_l= ist, + __be64 scsi_id, __be64 wwpn, + __be64 node_name) +{ + struct ibmvfc_target *tgt; + + list_for_each_entry(tgt, target_list, queue) { + if (scsi_id && cpu_to_be64(tgt->scsi_id) !=3D scsi_id) + continue; + if (wwpn && cpu_to_be64(tgt->ids.port_name) !=3D wwpn) + continue; + if (node_name && cpu_to_be64(tgt->ids.node_name) !=3D node_name) + continue; + if (!tgt->rport || !tgt->nvme_remote_port) + continue; + return tgt; + } + + return NULL; +} + +/** + * ibmvfc_process_async_work - Process IBMVFC_AE_FPIN async CRQ from work = queue + * @work: pointer to work_struct + */ +static void ibmvfc_process_async_work(struct work_struct *work) +{ + struct ibmvfc_async_work *aw; + struct ibmvfc_async_crq *crq; + struct ibmvfc_target *tgt; + struct ibmvfc_host *vhost; + struct fc_els_fpin *fpin; + unsigned long flags; + + aw =3D container_of_const(work, struct ibmvfc_async_work, async_work_s); + vhost =3D aw->vhost; + crq =3D &aw->crq; + + if (!crq->scsi_id && !crq->wwpn && !crq->node_name) + goto free; + + spin_lock_irqsave(vhost->host->host_lock, flags); + tgt =3D ibmvfc_find_target(&vhost->scsi_scrqs.targets, crq->scsi_id, + crq->wwpn, crq->node_name); + if (!tgt) { + /* Target not found in scsi_scrqs, search nvme_scrqs */ + tgt =3D ibmvfc_find_target(&vhost->nvme_scrqs.targets, + crq->scsi_id, crq->wwpn, + crq->node_name); + } + + if (tgt) { + kref_get(&tgt->kref); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + } else { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + dev_err_ratelimited(vhost->dev, "Invalid target for FPIN\n"); + goto free; + } + + fpin =3D ibmvfc_basic_fpin_to_desc(crq, tgt->wwpn); + if (fpin) { + fc_host_fpin_rcv(tgt->vhost->host, + sizeof(*fpin) + be32_to_cpu(fpin->desc_len), + (char *)fpin, 0); + kfree(fpin); + } else + dev_err_ratelimited(vhost->dev, "FPIN event received, unable to process\= n"); + + kref_put(&tgt->kref, ibmvfc_release_tgt); + free: + kfree(aw); +} + /** * ibmvfc_handle_async - Handle an async event from the adapter * @crq: crq to process * @vhost: ibmvfc host struct * **/ -static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, - struct ibmvfc_host *vhost) +VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, + struct ibmvfc_host *vhost) { const struct ibmvfc_async_desc *desc =3D ibmvfc_get_ae_desc(be64_to_cpu(c= rq->event)); + struct ibmvfc_async_work *aw; struct ibmvfc_target *tgt; =20 ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwp= n: %llx," @@ -3361,11 +3609,25 @@ static void ibmvfc_handle_async(struct ibmvfc_async= _crq *crq, case IBMVFC_AE_HALT: ibmvfc_link_down(vhost, IBMVFC_HALTED); break; + case IBMVFC_AE_FPIN: + if (vhost->state =3D=3D IBMVFC_HOST_OFFLINE) + break; + aw =3D kzalloc(sizeof(struct ibmvfc_async_work), GFP_ATOMIC); + if (aw) { + INIT_WORK(&aw->async_work_s, ibmvfc_process_async_work); + aw->vhost =3D vhost; + aw->crq =3D *crq; + queue_work(vhost->fpin_workq, &aw->async_work_s); + } else + dev_err_ratelimited(vhost->dev, + "can't offload async CRQ to work queue\n"); + break; default: dev_err(vhost->dev, "Unknown async event received: %lld\n", crq->event); break; } } +EXPORT_SYMBOL_IF_KUNIT(ibmvfc_handle_async); =20 /** * ibmvfc_handle_crq - Handles and frees received events in the CRQ @@ -6875,9 +7137,15 @@ static int ibmvfc_probe(struct vio_dev *vdev, const = struct vio_device_id *id) INIT_WORK(&vhost->rport_add_work_q, ibmvfc_rport_add_thread); mutex_init(&vhost->passthru_mutex); =20 - if ((rc =3D ibmvfc_alloc_mem(vhost))) + vhost->fpin_workq =3D alloc_workqueue("%s-fpin-workq-%u", WQ_UNBOUND, 0, + IBMVFC_NAME, shost->host_no); + if (vhost->fpin_workq =3D=3D NULL) goto free_scsi_host; =20 + rc =3D ibmvfc_alloc_mem(vhost); + if (rc) + goto free_workq; + vhost->work_thread =3D kthread_run(ibmvfc_work, vhost, "%s_%d", IBMVFC_NA= ME, shost->host_no); =20 @@ -6923,6 +7191,9 @@ static int ibmvfc_probe(struct vio_dev *vdev, const s= truct vio_device_id *id) kthread_stop(vhost->work_thread); free_host_mem: ibmvfc_free_mem(vhost); +free_workq: + destroy_workqueue(vhost->fpin_workq); + vhost->fpin_workq =3D NULL; free_scsi_host: scsi_host_put(shost); out: @@ -6953,6 +7224,8 @@ static void ibmvfc_remove(struct vio_dev *vdev) ibmvfc_wait_while_resetting(vhost); kthread_stop(vhost->work_thread); flush_work(&vhost->rport_add_work_q); + destroy_workqueue(vhost->fpin_workq); + vhost->fpin_workq =3D NULL; fc_remove_host(vhost->host); scsi_remove_host(vhost->host); =20 @@ -7115,5 +7388,21 @@ static void __exit ibmvfc_module_exit(void) fc_release_transport(ibmvfc_transport_template); } =20 +#if IS_ENABLED(CONFIG_KUNIT) +VISIBLE_IF_KUNIT struct ibmvfc_host *ibmvfc_get_first_vhost(void) +{ + struct ibmvfc_host *vhost =3D NULL; + + spin_lock(&ibmvfc_driver_lock); + if (!list_empty(&ibmvfc_head)) + vhost =3D list_first_entry(&ibmvfc_head, struct ibmvfc_host, queue); + if (vhost) + scsi_host_get(vhost->host); + spin_unlock(&ibmvfc_driver_lock); + return vhost; +} +EXPORT_SYMBOL_IF_KUNIT(ibmvfc_get_first_vhost); +#endif + module_init(ibmvfc_module_init); module_exit(ibmvfc_module_exit); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index ca80ceffe53a..d7a30e7a4a28 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -750,8 +750,12 @@ enum ibmvfc_ae_fpin_status { IBMVFC_AE_FPIN_PORT_CONGESTED =3D 0x2, IBMVFC_AE_FPIN_PORT_CLEARED =3D 0x3, IBMVFC_AE_FPIN_PORT_DEGRADED =3D 0x4, + IBMVFC_AE_FPIN_CONGESTION_CLEARED =3D 0x5, }; =20 +#define IBMVFC_FPIN_DEFAULT_EVENT_PERIOD (5*60*MSEC_PER_SEC) /* 5 minutes = */ +#define IBMVFC_FPIN_DEFAULT_EVENT_THRESHOLD (5*60*MSEC_PER_SEC/2) /* 2.5 m= inutes */ + struct ibmvfc_async_crq { volatile u8 valid; u8 link_state; @@ -781,6 +785,12 @@ struct ibmvfc_async_sub_crq { } id; } __packed __aligned(8); =20 +struct ibmvfc_async_work { + struct ibmvfc_host *vhost; + struct ibmvfc_async_crq crq; + struct work_struct async_work_s; +}; + union ibmvfc_iu { struct ibmvfc_mad_common mad_common; struct ibmvfc_npiv_login_mad npiv_login; @@ -1022,6 +1032,7 @@ struct ibmvfc_host { wait_queue_head_t work_wait_q; struct nvme_fc_local_port *nvme_local_port; struct completion nvme_delete_done; + struct workqueue_struct *fpin_workq; }; =20 struct ibmvfc_event *__ibmvfc_get_event(struct ibmvfc_queue *queue, int re= served); @@ -1088,4 +1099,10 @@ static inline struct ibmvfc_host *ibmvfc_channels_to= _vhost(struct ibmvfc_channel #define ibmvfc_remove_trace_file(kobj, attr) do { } while (0) #endif =20 +#if IS_ENABLED(CONFIG_KUNIT) +#include +VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, st= ruct ibmvfc_host *vhost); +VISIBLE_IF_KUNIT struct ibmvfc_host *ibmvfc_get_first_vhost(void); +#endif + #endif diff --git a/drivers/scsi/ibmvscsi/ibmvfc_kunit.c b/drivers/scsi/ibmvscsi/i= bmvfc_kunit.c new file mode 100644 index 000000000000..80e7f8e0fd70 --- /dev/null +++ b/drivers/scsi/ibmvscsi/ibmvfc_kunit.c @@ -0,0 +1,408 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include "ibmvfc.h" + +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); + +/** + * ibmvfc_async_fpin_event_test - unit test for IBMVFC_AE_FPIN parts of + * ibmvfc_handle_async + * @test: pointer to kunit structure + * + * Tests + * - error returns from ibmvfc_handle_async + * - statistics updates + * + * Return: void + */ +static void ibmvfc_async_fpin_test(struct kunit *test) +{ + u64 post[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1]; + u64 pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1]; + struct ibmvfc_async_crq_event ae[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1] = =3D { + [0 ... IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D { .type =3D IBMVFC_ASYNC_C= RQ_MAIN }, + }; + enum ibmvfc_ae_fpin_status fs; + struct fc_host_attrs *fc_host; + struct ibmvfc_target *tgt; + struct ibmvfc_host *vhost; + struct fc_rport *rport; + unsigned long flags; + + vhost =3D ibmvfc_get_first_vhost(); + if (!vhost) + kunit_skip(test, "No ibmvfc devices available"); + + spin_lock_irqsave(vhost->host->host_lock, flags); + if (vhost->scsi_scrqs.num_targets < 1) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No targets"); + } + tgt =3D list_first_entry(&vhost->scsi_scrqs.targets, struct ibmvfc_target= , queue); + if (!tgt->rport) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No rport"); + } + rport =3D tgt->rport; + get_device(&rport->dev); + kref_get(&tgt->kref); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + fc_host =3D shost_to_fc_host(vhost->host); + + pre[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_d= evice_specific); + pre[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_dev= ice_specific); + pre[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clear= ); + pre[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fail= ure_unknown); + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats.= cn_clear); + + for (fs =3D IBMVFC_AE_FPIN_LINK_CONGESTED; fs <=3D IBMVFC_AE_FPIN_CONGEST= ION_CLEARED; fs++) { + ae[fs].async_crq.valid =3D 0x80; + ae[fs].async_crq.link_state =3D IBMVFC_AE_LS_LINK_UP; + ae[fs].async_crq.fpin_status =3D fs; + ae[fs].async_crq.event =3D cpu_to_be64(IBMVFC_AE_FPIN); + ae[fs].async_crq.scsi_id =3D cpu_to_be64(tgt->scsi_id); + ae[fs].async_crq.wwpn =3D cpu_to_be64(tgt->wwpn); + ae[fs].async_crq.node_name =3D cpu_to_be64(tgt->ids.node_name); + ibmvfc_handle_async(&ae[fs], vhost); + ae[fs].async_crq.valid =3D 0; + wmb(); /* ensure valid bit clear is visible before checking stats */ + } + flush_workqueue(vhost->fpin_workq); + + post[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_= device_specific); + post[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_de= vice_specific); + post[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clea= r); + post[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fai= lure_unknown); + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats= .cn_clear); + + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_LINK_CONGESTED], + pre[IBMVFC_AE_FPIN_LINK_CONGESTED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_CONGESTED], + pre[IBMVFC_AE_FPIN_PORT_CONGESTED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_CLEARED], + pre[IBMVFC_AE_FPIN_PORT_CLEARED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_DEGRADED], + pre[IBMVFC_AE_FPIN_PORT_DEGRADED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_CONGESTION_CLEARED], + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED]+1); + + /* bad path */ + pre[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_d= evice_specific); + pre[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_dev= ice_specific); + pre[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clear= ); + pre[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fail= ure_unknown); + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats.= cn_clear); + + ae[0].async_crq.valid =3D 0x80; + ae[0].async_crq.link_state =3D IBMVFC_AE_LS_LINK_UP; + ae[0].async_crq.fpin_status =3D 0; /* bad value */ + ae[0].async_crq.event =3D cpu_to_be64(IBMVFC_AE_FPIN); + ae[0].async_crq.scsi_id =3D cpu_to_be64(tgt->scsi_id); + ae[0].async_crq.wwpn =3D cpu_to_be64(tgt->wwpn); + ae[0].async_crq.node_name =3D cpu_to_be64(tgt->ids.node_name); + ibmvfc_handle_async(&ae[0], vhost); + ae[0].async_crq.valid =3D 0; + wmb(); /* ensure valid bit clear is visible before checking stats */ + flush_workqueue(vhost->fpin_workq); + + post[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_= device_specific); + post[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_de= vice_specific); + post[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clea= r); + post[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fai= lure_unknown); + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats= .cn_clear); + + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_LINK_CONGESTED], + post[IBMVFC_AE_FPIN_LINK_CONGESTED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_CONGESTED], + post[IBMVFC_AE_FPIN_PORT_CONGESTED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_CLEARED], + post[IBMVFC_AE_FPIN_PORT_CLEARED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_DEGRADED], + post[IBMVFC_AE_FPIN_PORT_DEGRADED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED], + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED]); + + kref_put(&tgt->kref, ibmvfc_release_tgt); +} + +/** + * ibmvfc_full_fpin_test - unit test for IBMVFC_AE_FPIN parts of ibmvfc_ha= ndle_async + * @test: pointer to kunit structure + * + * Tests + * - error returns from ibmvfc_handle_async + * - statistics updates + * + * Return: void + */ +static void ibmvfc_full_fpin_test(struct kunit *test) +{ + u64 post[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1]; + u64 pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1]; + struct ibmvfc_async_crq_event ae[IBMVFC_AE_FPIN_CONGESTION_CLEARED + 1] = =3D { + [0 ... IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D { .type =3D IBMVFC_ASYNC_C= RQ_SUB }, + }; + enum ibmvfc_ae_fpin_status fs; + struct fc_host_attrs *fc_host; + struct ibmvfc_target *tgt; + struct ibmvfc_host *vhost; + struct fc_rport *rport; + unsigned long flags; + + vhost =3D ibmvfc_get_first_vhost(); + if (!vhost) + kunit_skip(test, "No ibmvfc devices available"); + + spin_lock_irqsave(vhost->host->host_lock, flags); + if (vhost->scsi_scrqs.num_targets < 1) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No targets"); + } + tgt =3D list_first_entry(&vhost->scsi_scrqs.targets, struct ibmvfc_target= , queue); + if (!tgt->rport) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No rport"); + } + rport =3D tgt->rport; + get_device(&rport->dev); + kref_get(&tgt->kref); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + fc_host =3D shost_to_fc_host(vhost->host); + + pre[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_d= evice_specific); + pre[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_dev= ice_specific); + pre[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clear= ); + pre[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fail= ure_unknown); + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats.= cn_clear); + + for (fs =3D IBMVFC_AE_FPIN_LINK_CONGESTED; fs <=3D IBMVFC_AE_FPIN_CONGEST= ION_CLEARED; fs++) { + ae[fs].subq.valid =3D 0x80; + ae[fs].subq.link_state =3D IBMVFC_AE_LS_LINK_UP; + ae[fs].subq.fpin_status =3D fs; + ae[fs].subq.event =3D cpu_to_be16(IBMVFC_AE_FPIN); + ae[fs].subq.wwpn =3D cpu_to_be64(tgt->wwpn); + ae[fs].subq.id.node_name =3D cpu_to_be64(tgt->ids.node_name); + ibmvfc_handle_async(&ae[fs], vhost); + ae[fs].subq.valid =3D 0; + wmb(); /* ensure valid bit clear is visible before checking stats */ + } + flush_workqueue(vhost->fpin_workq); + + post[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_= device_specific); + post[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_de= vice_specific); + post[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clea= r); + post[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fai= lure_unknown); + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats= .cn_clear); + + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_LINK_CONGESTED], + pre[IBMVFC_AE_FPIN_LINK_CONGESTED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_CONGESTED], + pre[IBMVFC_AE_FPIN_PORT_CONGESTED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_CLEARED], + pre[IBMVFC_AE_FPIN_PORT_CLEARED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_PORT_DEGRADED], + pre[IBMVFC_AE_FPIN_PORT_DEGRADED]+1); + KUNIT_EXPECT_GE(test, post[IBMVFC_AE_FPIN_CONGESTION_CLEARED], + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED]+1); + + /* bad path */ + pre[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_d= evice_specific); + pre[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_dev= ice_specific); + pre[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clear= ); + pre[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fail= ure_unknown); + pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats.= cn_clear); + + ae[0].subq.valid =3D 0x80; + ae[0].subq.link_state =3D IBMVFC_AE_LS_LINK_UP; + ae[0].subq.fpin_status =3D 0; /* bad value */ + ae[0].subq.event =3D cpu_to_be16(IBMVFC_AE_FPIN); + ae[0].subq.wwpn =3D cpu_to_be64(tgt->wwpn); + ae[0].subq.id.node_name =3D cpu_to_be64(tgt->ids.node_name); + ibmvfc_handle_async(&ae[0], vhost); + ae[0].subq.valid =3D 0; + wmb(); /* ensure valid bit clear is visible before checking stats */ + flush_workqueue(vhost->fpin_workq); + + post[IBMVFC_AE_FPIN_LINK_CONGESTED] =3D READ_ONCE(fc_host->fpin_stats.cn_= device_specific); + post[IBMVFC_AE_FPIN_PORT_CONGESTED] =3D READ_ONCE(rport->fpin_stats.cn_de= vice_specific); + post[IBMVFC_AE_FPIN_PORT_CLEARED] =3D READ_ONCE(rport->fpin_stats.cn_clea= r); + post[IBMVFC_AE_FPIN_PORT_DEGRADED] =3D READ_ONCE(rport->fpin_stats.li_fai= lure_unknown); + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED] =3D READ_ONCE(fc_host->fpin_stats= .cn_clear); + + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_LINK_CONGESTED], + post[IBMVFC_AE_FPIN_LINK_CONGESTED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_CONGESTED], + post[IBMVFC_AE_FPIN_PORT_CONGESTED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_CLEARED], + post[IBMVFC_AE_FPIN_PORT_CLEARED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_PORT_DEGRADED], + post[IBMVFC_AE_FPIN_PORT_DEGRADED]); + KUNIT_EXPECT_EQ(test, pre[IBMVFC_AE_FPIN_CONGESTION_CLEARED], + post[IBMVFC_AE_FPIN_CONGESTION_CLEARED]); + + put_device(&rport->dev); + kref_put(&tgt->kref, ibmvfc_release_tgt); + scsi_host_put(vhost->host); +} + +#define IBMVFC_TEST_FPIN_EXT(fs, ev, stat, crq) { \ + struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; \ + (crq).valid =3D 0x80; \ + (crq).flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; \ + (crq).link_state =3D IBMVFC_AE_LS_LINK_UP; \ + (crq).fpin_status =3D (fs); \ + (crq).event =3D cpu_to_be16(IBMVFC_AE_FPIN); \ + (crq).wwpn =3D cpu_to_be64(tgt->wwpn); \ + (crq).fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; \ + (crq).fpin_data.event_type =3D cpu_to_be16((ev)); \ + ae.subq =3D *(struct ibmvfc_async_sub_crq *)&(crq); \ + pre =3D READ_ONCE(rport->fpin_stats.stat); \ + ibmvfc_handle_async(&ae, vhost); \ + flush_workqueue(vhost->fpin_workq); \ + post =3D READ_ONCE(rport->fpin_stats.stat); \ +} + +/** + * ibmvfc_extended_fpin_test - unit test for extended FPIN events + * @test: pointer to kunit structure + * + * Note: This test exercises extended FPIN code paths but does not check + * that statistics are correctly updated. + * + * Return: void + */ +static void ibmvfc_extended_fpin_test(struct kunit *test) +{ + enum ibmvfc_ae_fpin_status fs; + struct ibmvfc_async_subq_fpin crq[IBMVFC_AE_FPIN_CONGESTION_CLEARED+1] = =3D {}; + struct ibmvfc_async_subq_fpin + crqcn[IBMVFC_AE_FPIN_PORT_CONGESTED][FPIN_CONGN_DEVICE_SPEC+1] =3D {}; + struct ibmvfc_async_subq_fpin crqportdg[FPIN_LI_DEVICE_SPEC+1] =3D {}; + struct ibmvfc_target *tgt; + struct ibmvfc_host *vhost; + struct fc_rport *rport; + LIST_HEAD(evt_doneq); + unsigned long flags; + u64 pre, post; + + vhost =3D ibmvfc_get_first_vhost(); + if (!vhost) + kunit_skip(test, "No ibmvfc devices available"); + + spin_lock_irqsave(vhost->host->host_lock, flags); + if (vhost->scsi_scrqs.num_targets < 1) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No targets"); + } + tgt =3D list_first_entry(&vhost->scsi_scrqs.targets, struct ibmvfc_target= , queue); + if (!tgt->rport) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No rport"); + } + rport =3D tgt->rport; + get_device(&rport->dev); + kref_get(&tgt->kref); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + for (fs =3D IBMVFC_AE_FPIN_LINK_CONGESTED; fs <=3D IBMVFC_AE_FPIN_CONGEST= ION_CLEARED; fs++) { + switch (fs) { + case IBMVFC_AE_FPIN_PORT_CLEARED: + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: { + struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; + + crq[fs].valid =3D 0x80; + crq[fs].flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; + crq[fs].link_state =3D IBMVFC_AE_LS_LINK_UP; + crq[fs].fpin_status =3D fs; + crq[fs].event =3D cpu_to_be16(IBMVFC_AE_FPIN); + crq[fs].wwpn =3D cpu_to_be64(tgt->wwpn); + crq[fs].fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; + crq[fs].fpin_data.event_type =3D cpu_to_be16(FPIN_CONGN_CLEAR); + ae.subq =3D *(struct ibmvfc_async_sub_crq *)&crq[fs]; + pre =3D READ_ONCE(rport->fpin_stats.cn_clear); + ibmvfc_handle_async(&ae, vhost); + flush_workqueue(vhost->fpin_workq); + post =3D READ_ONCE(rport->fpin_stats.cn_clear); + break; + } + case IBMVFC_AE_FPIN_LINK_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CONGESTED: + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CLEAR, cn_clear, + crqcn[fs-1][FPIN_CONGN_CLEAR]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_LOST_CREDIT, + cn_lost_credit, + crqcn[fs-1][FPIN_CONGN_LOST_CREDIT]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CREDIT_STALL, + cn_credit_stall, + crqcn[fs-1][FPIN_CONGN_CREDIT_STALL]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_OVERSUBSCRIPTION, + cn_oversubscription, + crqcn[fs-1][FPIN_CONGN_OVERSUBSCRIPTION]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_DEVICE_SPEC, + cn_device_specific, + crqcn[fs-1][FPIN_CONGN_DEVICE_SPEC]); + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_UNKNOWN, + li_failure_unknown, + crqportdg[FPIN_LI_UNKNOWN]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LINK_FAILURE, + li_link_failure_count, + crqportdg[FPIN_LI_LINK_FAILURE]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SYNC, + li_loss_of_sync_count, + crqportdg[FPIN_LI_LOSS_OF_SYNC]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SIG, + li_loss_of_signals_count, + crqportdg[FPIN_LI_LOSS_OF_SIG]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_PRIM_SEQ_ERR, + li_prim_seq_err_count, + crqportdg[FPIN_LI_PRIM_SEQ_ERR]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_TX_WD, + li_invalid_tx_word_count, + crqportdg[FPIN_LI_INVALID_TX_WD]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_CRC, + li_invalid_crc_count, + crqportdg[FPIN_LI_INVALID_CRC]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_DEVICE_SPEC, + li_device_specific, + crqportdg[FPIN_LI_DEVICE_SPEC]); + break; + } + } + + put_device(&rport->dev); + kref_put(&tgt->kref, ibmvfc_release_tgt); + scsi_host_put(vhost->host); +} + +static struct kunit_case ibmvfc_fpin_test_cases[] =3D { + KUNIT_CASE(ibmvfc_async_fpin_test), + KUNIT_CASE(ibmvfc_full_fpin_test), + KUNIT_CASE(ibmvfc_extended_fpin_test), + {}, +}; + +static struct kunit_suite ibmvfc_fpin_test_suite =3D { + .name =3D "ibmvfc-fpin-test", + .test_cases =3D ibmvfc_fpin_test_cases, +}; +kunit_test_init_section_suite(ibmvfc_fpin_test_suite); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dave Marquardt "); +MODULE_DESCRIPTION("Test module for IBM Virtual Fibre Channel Driver"); --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CC9F35BDDB; Fri, 11 Sep 2026 02:19:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093164; cv=none; b=D+CmAJrtv9AwYyNO/zkjiIKblfDQzOtgGoa1vTMVxZDdfcPNN3CTVZGtEICEzS+j6kMbhKWSzUR1BfWdHBfcdrafY1zupo64MnMFPxR2LgGS1IvehkHd/RGqrXqpZ2dVN0Bj+A5WVeNlmnhucvN9CmgpTlpN1Rk8LsLo8DnFtRI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093164; c=relaxed/simple; bh=9qD3huhzPJ6kQpb04F2WEeP5N1J95nYBIWAjm6IYUGE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MwXSE7aQXAc0Nr+LEeSXxirI0XeXjiZUIltxLJuO0xZ8Ofl/0Vumzx3wVhTyXnYtOmWxMBj23/Xc6ifPU8jPH4Ej8+aeoCH72jZOt6QEY433EXvZGrEADjLMwGp1cVhTPELivHYA/HT//J27hpdWwr9Lm/EH1CkARRCJFEy5Pvk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=GSGtcD0Y; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="GSGtcD0Y" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12L2w311176; Fri, 11 Sep 2026 02:19:17 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=hB/jsEmW11ikjkO8k 0FYDltf+WJSh6vxZDEuJtTTnCI=; b=GSGtcD0YVJdN8RQ90hvl7v8U1IGyjbSHs wJ/EhXY+mI12/8uR/IEyiLZomdE11rxsJ8Iw3aIa8i4Wl0q9g7+53art+Ga6bWTC mkvvsn3dEay6e+zC8vX2DRl97bKvJeDXWzvVsAFZqreZ44C5aFYolcnCfH0hXOi0 1Sof3tjzaI/olHDkd008PZMHYBla04xMbYfZjZqFSfgDwrd6Wa1xlFhb+fAsf/Bs 9Vt1nR37Uj3l63GyJsVgcFIuu+chNPR6SstLU5C9q8L0ErJY1X08W/wBYFnAfaKo HBRbUrbAuU+2TED3EGIMqHvS3X+Wc0Ca37F8nGstTMca+sQ/L02Lw== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8prtbh-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:16 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B153wG891408; Fri, 11 Sep 2026 02:19:16 GMT Received: from smtprelay02.dal12v.mail.ibm.com ([172.16.1.4]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvq2uvpf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:15 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay02.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JEJ628770886 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:15 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BFE3658055; Fri, 11 Sep 2026 02:19:14 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D8C9B5804B; Fri, 11 Sep 2026 02:19:13 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:13 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 2/9] scsi: ibmvfc: add NOOP command support Date: Thu, 10 Sep 2026 19:19:02 -0700 Message-ID: <20260911021910.1038128-3-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=eM2GH3p1 c=1 sm=1 tr=0 ts=6aa36524 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=dMUBAgKGejxRm0SXrm0A:9 X-Proofpoint-ORIG-GUID: 3NAjdYXEQdkQfmtwK0mzu7B04w_fbXuw X-Proofpoint-GUID: 3NAjdYXEQdkQfmtwK0mzu7B04w_fbXuw X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXzkIMJsRpqqwM gSd1F825EW+vrV2mwPZAF9MmrFT26NUhjrtKWokamqh0//Kv1eQsoErO3HVybnY7LzFtTuj1rJx QHIHU7zGmVmiQIfqbPfG2RUbR7KiTv8= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX/zJwLSnVVqN7 NAyLox3Vky5ZQgOgMXevPAG4kU7yPZ2inrvPNKQhZk92+cym7vwsNrMmZVw9Oyn3frPlJqlxllg Fu1gUA2V6U2xQmQwPkJ0dbeSTQuCCuo6my/33Qc5v8UFQBEkx7eBgmzuSXtbwKE9rDgmdHB5/Zl 2M6MVP5YAcn4KI6wyEy5XCddWAjwBggGQPY6lyH6StFfKvPEJwYJUXFbD89T6r8DhYTSrmYi3QZ TcjUPWqXYjs0eU+fYHwZpm6W2R4INEik0gQ13O2bpxkBTSIdNXvU42fwVYgPbV7+XdowjYC7KdE Kg9rUXPZDI1UTq0+gWj60z0Gew0xUU0QvoH8cnhb0hlfBd+aZklQAXZ2nCpLF4c1vENLV8X9xaI J3KQDs3/gdeG3alb32JwMo+Q5KQGKcsuFzMqrTKtLlMuGC0x0EzTK4gxZfKuYSeK4ROAga0ofvc 9nmkLlJZFn6/MNZa28Q== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 malwarescore=0 adultscore=0 phishscore=0 lowpriorityscore=0 suspectscore=0 spamscore=0 priorityscore=1501 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Add support for handling IBMVFC_NOOP format CRQ messages from the VIOS partner. Advertise the client's ability to handle NOOP commands by setting the IBMVFC_CAN_USE_NOOP_CMD capability in ibmvfc_set_login_info(). Handle and ignore IBMVFC_NOOP format messages in both ibmvfc_handle_crq() and ibmvfc_handle_scrq(). In both handlers, log a rate-limited error if a NOOP is received while in the IBMVFC_ACTIVE state without the partner having advertised IBMVFC_SUPPORT_NOOP_CMD. In ibmvfc_handle_scrq(), also fix a typo ("Got and invalid" -> "Got an invalid"), add a missing return on invalid message types, and guard against null event pointers before processing CRQ responses. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index 5259a80958ce..6b2eb82ceb98 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -1578,7 +1578,9 @@ static void ibmvfc_set_login_info(struct ibmvfc_host = *vhost) login_info->flags |=3D cpu_to_be16(IBMVFC_CLIENT_MIGRATED); =20 login_info->max_cmds =3D cpu_to_be32(max_cmds); - login_info->capabilities =3D cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_= SEND_VF_WWPN); + login_info->capabilities =3D + cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN | + IBMVFC_CAN_USE_NOOP_CMD); =20 if (vhost->mq_enabled || vhost->using_channels) { login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_USE_CHANNELS); @@ -3695,6 +3697,14 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq= , struct ibmvfc_host *vhost, if (crq->format =3D=3D IBMVFC_ASYNC_EVENT) return; =20 + if (crq->format =3D=3D IBMVFC_NOOP) { + if (vhost->state =3D=3D IBMVFC_ACTIVE && + !ibmvfc_check_caps(vhost, IBMVFC_SUPPORT_NOOP_CMD)) + dev_err_ratelimited(vhost->dev, + "Received unexpected NOOP command from partner\n"); + return; + } + /* The only kind of payload CRQs we should get are responses to * things we send. Make sure this response is to something we * actually sent @@ -4225,7 +4235,20 @@ static void ibmvfc_handle_scrq(struct ibmvfc_crq *cr= q, struct ibmvfc_host *vhost case IBMVFC_CRQ_XPORT_EVENT: return; default: - dev_err(vhost->dev, "Got and invalid message type 0x%02x\n", crq->valid); + dev_err(vhost->dev, "Got an invalid message type 0x%02x\n", crq->valid); + return; + } + + if (crq->format =3D=3D IBMVFC_NOOP) { + if (vhost->state =3D=3D IBMVFC_ACTIVE && + !ibmvfc_check_caps(vhost, IBMVFC_SUPPORT_NOOP_CMD)) + dev_err_ratelimited(vhost->dev, + "Received unexpected NOOP command from partner\n"); + return; + } + + if (unlikely(!evt)) { + dev_err(vhost->dev, "Received null event\n"); return; } =20 --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F4373DB651; Fri, 11 Sep 2026 02:19:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093165; cv=none; b=SOhMH1Afi6uLEAIxze8HzYBHfcWyw0Z9Q0P5S0GtWecRS6UumLF9rO9deIqOX2nfhI+2p5XQFhM0wN6pox6rhKG1mbYsMhNkOSx9nT6xfsG9+3XbI5br7rcCo/JDSKPxqkmEDPnxj1AMrVlojOqQD+VCo53nXV505V1WFykrsQQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093165; c=relaxed/simple; bh=Yy0OU3dKq8cR/JdYCoiXYE3T/GnzwysU3idedb1DPV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YRdRcC0hTmkocuqicsVnHuRJMIcSC3Wgw6dZTbR38pMMnC76fYWMNsLDajJwHUor1BJkG0knXvaQ6is6vddO5H5W6Hj1mww9PL4TvdQrgwSVwEGfVyzFQ2YStoqJW/Wwyq2LJLHv8cQz7f34IwW24EbZ9qKGigANP2eEzonVSww= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=T4zsGC7B; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="T4zsGC7B" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12J2r311149; Fri, 11 Sep 2026 02:19:18 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=bVsy6e7RIWsa4inSY VWZiBsIlesxYTQaoaS4XZ8tKXk=; b=T4zsGC7BM8fBhzVfvenCKJQ3lKExHkc/m tFhy2b8kJlQHOg26yotKL2KgGQa2ZAyjj9m6RFgIMs2BGbq88Chsa7goH5TNTiLu UX7zUw1XRalHeJN0pDnhdsxPBd5xWgHBfeHSZPWJzMwenM5+Kw9io1jDQjtNbfdo pWNEpUH3aNx/Mdw9Vl5SaQPj0vnHJviKfNsCT25qPe4f9GqC9aTWjw4WUHJGGuEs BMKTjKcZEYnygMzomgB7onFUDKYhoY7cWi4K6AORQCHAualBAxcGGAN+rzkcHoxN ewhMfzDCceQLzocJLd1oxsbcGKJdmdPhU9ThC+GTQURwAQTEUor6Q== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8prtbm-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:18 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B15AC7872168; Fri, 11 Sep 2026 02:19:17 GMT Received: from smtprelay03.dal12v.mail.ibm.com ([172.16.1.5]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvwk3u32-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:17 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay03.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JGVC26411620 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:16 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DDFBA58063; Fri, 11 Sep 2026 02:19:15 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EA86458059; Fri, 11 Sep 2026 02:19:14 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:14 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 3/9] scsi: ibmvfc: add FPIN extended flag and async sub-CRQ queue handle Date: Thu, 10 Sep 2026 19:19:03 -0700 Message-ID: <20260911021910.1038128-4-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=eM2GH3p1 c=1 sm=1 tr=0 ts=6aa36526 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=dC3NDtCKD2fC6gceAXcA:9 X-Proofpoint-ORIG-GUID: CdLyKflFMqogQUlNhQxfQfVAn0POrVpC X-Proofpoint-GUID: CdLyKflFMqogQUlNhQxfQfVAn0POrVpC X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX1Pgz1/tfv3Zo jwD+JQwyJyR1A+NFWn+LDRQfk0Co2ozeeg0cIecIVCCXeWrzvZFlHfhIuAqmsWWupgpjRtLDb2e YYgQf2SuiMBgA/akMwro4Nmv1aGLfgs= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX+bHwBgJqnsd+ UWycja9q87HJSiXt4uY0p6oT3fsjqW2SmSuXh1nwx4AY8hbPzy1VI6YSad2raWF/De+qgElVNag M34FOIuXA2O0FoC+YURpLC7+XAqQwqQEB1+vj5UHnIpnt18+ZN15jdgJDKNsLNmT/6qAL9OWyuM bhOIyV8CVkfjqLdq193jTE32b0JigYVWZT9NRVW8ETu0QOP4PSvYQhFlkQrSYLJJqSvTL9F1MTZ sXhFAmw3mRdZDRZjPA875jedB73nlvV1fosOH101WlhbEb19hVXOCimSsMp20HkXULxJDwJeBHV AmW+GQjEXo11Nsf92/b/AQyfxFNx+JZf3bCHaSwU+qtUw//TSmymiK2+Jim0DiAUtdjNBGsGAUg CYf42Xx95M2JwW9IIIqnY3MbYtusqtKi/aW8VJLGfNZx7EgSfEEx5iBeMdnCCtwZBKNZEI9KxzP SyDWucQ5IYjJmeIqJPQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 malwarescore=0 adultscore=0 phishscore=0 lowpriorityscore=0 suspectscore=0 spamscore=0 priorityscore=1501 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Add IBMVFC_ASYNC_IS_FPIN_EXT flag bit (0x02) to ibmvfc_async_sub_crq.flags to distinguish extended FPIN events from standard ones. Add async_sub_crq field of type ibmvfc_queue to ibmvfc_host to hold the queue handle for the asynchronous sub-CRQ, alongside the existing crq and async_crq queues. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d7a30e7a4a28..a8a063d99564 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -773,6 +773,7 @@ struct ibmvfc_async_sub_crq { volatile u8 valid; u8 flags; #define IBMVFC_ASYNC_ID_IS_ASSOC_ID 0x01 +#define IBMVFC_ASYNC_IS_FPIN_EXT 0x02 u8 link_state; u8 fpin_status; __be16 event; @@ -990,6 +991,7 @@ struct ibmvfc_host { mempool_t *tgt_pool; struct ibmvfc_queue crq; struct ibmvfc_queue async_crq; + struct ibmvfc_queue async_sub_crq; struct ibmvfc_channels scsi_scrqs; struct ibmvfc_channels nvme_scrqs; struct ibmvfc_npiv_login login_info; --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C23353DC4C9; Fri, 11 Sep 2026 02:19:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093172; cv=none; b=c6AOj1ikIhsq6G0OMWdXbP3V4YIP1/13qdqBjgnvcxjIV+2IJg1zuzkT0m8V5n8gdDFwV3p8hGncp2wW1cSCQzwcDc+IP/NCf0I5aG1ZXWUr25Kbc5QxmKBWLFyUjOsl3OeJuYxUcROmsdy4FplyByvdSoMpu+bJza00dAbdvEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093172; c=relaxed/simple; bh=ahRHlM3DTKx8h4H/ECpW9lKJd2sr/sQxGlo1M8lVhvk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XbxNSU8Epn92iTr4GkJHGGPWujKMashES6z3OlAcAX5sWA5HhVZXXgy5ZaLt4OcmPgPNBPVLeIEzN/S3zoAaeu30yFEyPyd0fjGqit+VZuw1KPy/FBk7aXSnF5rimkYJfH+EOny9Ykye/foRROqNwIXWc0c+/M2EpZdwxXaHeco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=GJ+Isc0z; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="GJ+Isc0z" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12I1g2632214; Fri, 11 Sep 2026 02:19:19 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=QgVNL82TfKgV9OoNi ZgUlYNgTH8HJrVrAm0w/XuFu38=; b=GJ+Isc0ziXtEo3N00JI/4qv+wSkvSIrvb yDGoY0OdyDFecARkHujxU5D65guMY2jos9xzHPvFrKZ1lCBO53RNnif5P7lZ8+Gf /RDeumov5bIcJYl12ZKkp07ukDHXVIr5Z/gZd5aWuIFdjpz08Ywj3oeOJzzwGlUE iJAXPEBujDahgw+9z8yO9UmrXXi0pEJuZYO7jilseesm5nGkPX8+DZomfTKbZ0Ww 4/3y5x0NbmAQT8OdivqTfDXsBt6BmVgNHxH3vMSL3HypsDv+qIV8gyzBNbUZe/2j hQL4i/dhBtJzEfYzT4PYZ3v1LhHQcbbwKxMf0MWZ3jSywMw/Yulqw== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8n8sbx-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:18 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B154xM919376; Fri, 11 Sep 2026 02:19:18 GMT Received: from smtprelay05.dal12v.mail.ibm.com ([172.16.1.7]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvmhkwf4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:18 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay05.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JHDV31523330 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:17 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0A3575804B; Fri, 11 Sep 2026 02:19:17 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 14E4258065; Fri, 11 Sep 2026 02:19:16 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:15 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 4/9] scsi: ibmvfc: extend async event handlers for async sub-CRQ events Date: Thu, 10 Sep 2026 19:19:04 -0700 Message-ID: <20260911021910.1038128-5-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=NMVAaE6g c=1 sm=1 tr=0 ts=6aa36527 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=ATO0ceFIgLGo4LxwFAgA:9 X-Proofpoint-GUID: B6wpwu1WZAO48hmyWSzcmsl_a9TvUEqj X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX2W1tlposqB6H IO703gMPkbO27+ZKgidgw8NMOwlyZg8XOBxNBjkYmqZW1jn/aWtLItDtmWTFH3vI0EJnvNvwoD7 AORYkbL6MeBZ/1kUjHHSd+bKS+yawzW8OZdvu0U6QtG08zw6fFRyEAlZDwykTuOb7TRfmRvuVnF ZfGjIWOl6uLl9USBD+MSwp3fffIjgyo/af51K24+QFSXPoWrADnFayia5/7R6MThdL4pIc1JKqw F4W+Ux2wVQ9vtkuw9joa2dfi3CEAxz2a5jn/wP0P4FqCSuORb9OABIBlxvtO960RfoSFz+IRiP+ Ex15ptb7EVJQSvTtsbVEsh+0JOyHIFC6VjZLHnfvGTn/IA9IvnfItVz8rw9/ReUHJ9AOzjBb8ES qRHgLJPSVspogDdxwjXxAXxCPw4JAwaODJRIwk1Ivkh1pjdJ/27LW0zHsqWLyUyPS1RZzapnFio koiof6vQzS61QN+Eftw== X-Proofpoint-ORIG-GUID: B6wpwu1WZAO48hmyWSzcmsl_a9TvUEqj X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX33U7mWuR9Yft wUBjQ4rv2rFKd/LcpC3q0iBasdBt2RwqaWOfiyrJufzkhnu/oI52er3T2qzcXmiGKt1aXij3Kde fplQYI3f+K5DBT8q0Fu06vSVbplw8eg= X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 bulkscore=0 clxscore=1015 malwarescore=0 lowpriorityscore=0 priorityscore=1501 adultscore=0 suspectscore=0 impostorscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Refactor async event handling to support both traditional async CRQs and new asynchronous sub-queue CRQs. Introduce struct ibmvfc_async_crq_event, a tagged union that wraps either an ibmvfc_async_crq (main CRQ) or an ibmvfc_async_sub_crq (async sub-CRQ), with an enum ibmvfc_async_crq_type discriminator. Replace the ibmvfc_async_work bare union and is_subq bool with a single event field of this type. Modify ibmvfc_handle_async() to accept a struct ibmvfc_async_crq_event * instead of a void * plus a bool flag. Update ibmvfc_process_async_work() to dispatch based on event.type. Add ibmvfc_full_fpin_to_desc() to convert full FPIN messages from async sub-queue format to fc_els_fpin structures. Update FPIN processing logic to extract WWPN, node_name, and scsi_id from the appropriate union member based on event type. Update KUnit tests to use struct ibmvfc_async_crq_event arrays at call sites. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 162 +++++++++++++++++++++------ drivers/scsi/ibmvscsi/ibmvfc.h | 18 ++- drivers/scsi/ibmvscsi/ibmvfc_kunit.c | 135 ---------------------- 3 files changed, 141 insertions(+), 174 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index 6b2eb82ceb98..daec81f48857 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -3426,6 +3426,45 @@ ibmvfc_basic_fpin_to_desc(struct ibmvfc_async_crq *c= rq, u64 wwpn) cpu_to_be32(1)); } =20 +/** + * ibmvfc_full_fpin_to_desc(): allocate and populate a struct fc_els_fpin = struct + * containing a descriptor. + * @ibmvfc_fpin: Pointer to async subq FPIN data + * + * Allocate a struct fc_els_fpin containing a descriptor and populate + * based on data from *ibmvfc_fpin. + * + * Return: + * NULL - unable to allocate structure + * non-NULL - pointer to populated struct fc_els_fpin + */ +static struct fc_els_fpin * +ibmvfc_full_fpin_to_desc(struct ibmvfc_async_sub_crq *ibmvfc_fpin) +{ + __be16 type; + + switch (ibmvfc_fpin->fpin_status) { + case IBMVFC_AE_FPIN_LINK_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CONGESTED: + type =3D cpu_to_be16(FPIN_CONGN_DEVICE_SPEC); + break; + case IBMVFC_AE_FPIN_PORT_CLEARED: + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: + type =3D cpu_to_be16(FPIN_CONGN_CLEAR); + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + type =3D cpu_to_be16(FPIN_LI_UNKNOWN); + break; + default: + return NULL; + } + + return ibmvfc_common_fpin_to_desc(ibmvfc_fpin->fpin_status, ibmvfc_fpin->= wwpn, + type, cpu_to_be16(0), + cpu_to_be32(IBMVFC_FPIN_DEFAULT_EVENT_THRESHOLD), + cpu_to_be32(1)); +} + /** * ibmvfc_find_target - Search for a target in a target list * @target_list: list head of targets to search @@ -3463,28 +3502,39 @@ static struct ibmvfc_target *ibmvfc_find_target(str= uct list_head *target_list, */ static void ibmvfc_process_async_work(struct work_struct *work) { + struct ibmvfc_async_sub_crq *subq =3D NULL; struct ibmvfc_async_work *aw; - struct ibmvfc_async_crq *crq; + struct ibmvfc_async_crq *crq =3D NULL; struct ibmvfc_target *tgt; struct ibmvfc_host *vhost; - struct fc_els_fpin *fpin; + struct fc_els_fpin *fpin =3D NULL; unsigned long flags; + __be64 node_name; + __be64 scsi_id; + __be64 wwpn; =20 aw =3D container_of_const(work, struct ibmvfc_async_work, async_work_s); vhost =3D aw->vhost; - crq =3D &aw->crq; + if (aw->event.type =3D=3D IBMVFC_ASYNC_CRQ_SUB) { + subq =3D &aw->event.subq; + scsi_id =3D 0; + wwpn =3D subq->wwpn; + node_name =3D (subq->flags & IBMVFC_ASYNC_ID_IS_ASSOC_ID) ? 0 : subq->id= .node_name; + } else { + crq =3D &aw->event.async_crq; + scsi_id =3D crq->scsi_id; + wwpn =3D crq->wwpn; + node_name =3D crq->node_name; + } =20 - if (!crq->scsi_id && !crq->wwpn && !crq->node_name) + if (!scsi_id && !wwpn && !node_name) goto free; =20 spin_lock_irqsave(vhost->host->host_lock, flags); - tgt =3D ibmvfc_find_target(&vhost->scsi_scrqs.targets, crq->scsi_id, - crq->wwpn, crq->node_name); + tgt =3D ibmvfc_find_target(&vhost->scsi_scrqs.targets, scsi_id, wwpn, nod= e_name); if (!tgt) { /* Target not found in scsi_scrqs, search nvme_scrqs */ - tgt =3D ibmvfc_find_target(&vhost->nvme_scrqs.targets, - crq->scsi_id, crq->wwpn, - crq->node_name); + tgt =3D ibmvfc_find_target(&vhost->nvme_scrqs.targets, scsi_id, wwpn, no= de_name); } =20 if (tgt) { @@ -3496,7 +3546,11 @@ static void ibmvfc_process_async_work(struct work_st= ruct *work) goto free; } =20 - fpin =3D ibmvfc_basic_fpin_to_desc(crq, tgt->wwpn); + if (crq) + fpin =3D ibmvfc_basic_fpin_to_desc(crq, tgt->wwpn); + else + fpin =3D ibmvfc_full_fpin_to_desc(subq); + if (fpin) { fc_host_fpin_rcv(tgt->vhost->host, sizeof(*fpin) + be32_to_cpu(fpin->desc_len), @@ -3512,25 +3566,51 @@ static void ibmvfc_process_async_work(struct work_s= truct *work) =20 /** * ibmvfc_handle_async - Handle an async event from the adapter - * @crq: crq to process + * @ae: tagged union wrapping either an ibmvfc_async_crq (main CRQ) or an + * ibmvfc_async_sub_crq (async sub-CRQ); the type field identifies which * @vhost: ibmvfc host struct * **/ -VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, +VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq_event *a= e, struct ibmvfc_host *vhost) { - const struct ibmvfc_async_desc *desc =3D ibmvfc_get_ae_desc(be64_to_cpu(c= rq->event)); + struct ibmvfc_async_crq *async_crq =3D NULL; + struct ibmvfc_async_sub_crq *subq =3D NULL; + const struct ibmvfc_async_desc *desc; struct ibmvfc_async_work *aw; struct ibmvfc_target *tgt; - - ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwp= n: %llx," - " node_name: %llx%s\n", desc->desc, be64_to_cpu(crq->scsi_id), - be64_to_cpu(crq->wwpn), be64_to_cpu(crq->node_name), - ibmvfc_get_link_state(crq->link_state)); - - switch (be64_to_cpu(crq->event)) { + __be64 node_name; + __be64 scsi_id; + u8 link_state; + __be64 wwpn; + u64 event; + + if (ae->type =3D=3D IBMVFC_ASYNC_CRQ_SUB) { + subq =3D &ae->subq; + event =3D be16_to_cpu(subq->event); + link_state =3D subq->link_state; + scsi_id =3D 0; + wwpn =3D subq->wwpn; + node_name =3D subq->flags & IBMVFC_ASYNC_ID_IS_ASSOC_ID ? 0 : subq->id.n= ode_name; + } else { + async_crq =3D &ae->async_crq; + event =3D be64_to_cpu(async_crq->event); + link_state =3D async_crq->link_state; + scsi_id =3D async_crq->scsi_id; + wwpn =3D async_crq->wwpn; + node_name =3D async_crq->node_name; + } + + desc =3D ibmvfc_get_ae_desc(event); + ibmvfc_log(vhost, desc->log_level, + "%s event received. scsi_id: %llx, wwpn: %llx, node_name: %llx, event= %llx%s\n", + desc->desc, be64_to_cpu(scsi_id), + be64_to_cpu(wwpn), be64_to_cpu(node_name), event, + ibmvfc_get_link_state(link_state)); + + switch (event) { case IBMVFC_AE_RESUME: - switch (crq->link_state) { + switch (link_state) { case IBMVFC_AE_LS_LINK_DOWN: ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); break; @@ -3569,33 +3649,33 @@ VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ib= mvfc_async_crq *crq, case IBMVFC_AE_ELS_PRLO: case IBMVFC_AE_ELS_PLOGI: list_for_each_entry(tgt, &vhost->scsi_scrqs.targets, queue) { - if (!crq->scsi_id && !crq->wwpn && !crq->node_name) + if (!scsi_id && !wwpn && !node_name) break; - if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) !=3D crq->scsi_id) + if (scsi_id && cpu_to_be64(tgt->scsi_id) !=3D scsi_id) continue; - if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) !=3D crq->wwpn) + if (wwpn && cpu_to_be64(tgt->ids.port_name) !=3D wwpn) continue; - if (crq->node_name && cpu_to_be64(tgt->ids.node_name) !=3D crq->node_na= me) + if (node_name && cpu_to_be64(tgt->ids.node_name) !=3D node_name) continue; - if (tgt->need_login && be64_to_cpu(crq->event) =3D=3D IBMVFC_AE_ELS_LOG= O) + if (tgt->need_login && event =3D=3D IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd =3D 1; - if (!tgt->need_login || be64_to_cpu(crq->event) =3D=3D IBMVFC_AE_ELS_PL= OGI) { + if (!tgt->need_login || event =3D=3D IBMVFC_AE_ELS_PLOGI) { ibmvfc_del_tgt(tgt); ibmvfc_reinit_host(vhost); } } list_for_each_entry(tgt, &vhost->nvme_scrqs.targets, queue) { - if (!crq->scsi_id && !crq->wwpn && !crq->node_name) + if (!scsi_id && !wwpn && !node_name) break; - if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) !=3D crq->scsi_id) + if (scsi_id && cpu_to_be64(tgt->scsi_id) !=3D scsi_id) continue; - if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) !=3D crq->wwpn) + if (wwpn && cpu_to_be64(tgt->ids.port_name) !=3D wwpn) continue; - if (crq->node_name && cpu_to_be64(tgt->ids.node_name) !=3D crq->node_na= me) + if (node_name && cpu_to_be64(tgt->ids.node_name) !=3D node_name) continue; - if (tgt->need_login && be64_to_cpu(crq->event) =3D=3D IBMVFC_AE_ELS_LOG= O) + if (tgt->need_login && event =3D=3D IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd =3D 1; - if (!tgt->need_login || be64_to_cpu(crq->event) =3D=3D IBMVFC_AE_ELS_PL= OGI) { + if (!tgt->need_login || event =3D=3D IBMVFC_AE_ELS_PLOGI) { ibmvfc_del_tgt(tgt); ibmvfc_reinit_host(vhost); } @@ -3618,14 +3698,14 @@ VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ib= mvfc_async_crq *crq, if (aw) { INIT_WORK(&aw->async_work_s, ibmvfc_process_async_work); aw->vhost =3D vhost; - aw->crq =3D *crq; + aw->event =3D *ae; queue_work(vhost->fpin_workq, &aw->async_work_s); } else dev_err_ratelimited(vhost->dev, "can't offload async CRQ to work queue\n"); break; default: - dev_err(vhost->dev, "Unknown async event received: %lld\n", crq->event); + dev_err(vhost->dev, "Unknown async event received: %llu\n", event); break; } } @@ -4166,7 +4246,11 @@ static void ibmvfc_tasklet(void *data) while (!done) { /* Pull all the valid messages off the async CRQ */ while ((async =3D ibmvfc_next_async_crq(vhost)) !=3D NULL) { - ibmvfc_handle_async(async, vhost); + struct ibmvfc_async_crq_event ae =3D { + .type =3D IBMVFC_ASYNC_CRQ_MAIN, + .async_crq =3D *async, + }; + ibmvfc_handle_async(&ae, vhost); async->valid =3D 0; wmb(); } @@ -4180,8 +4264,12 @@ static void ibmvfc_tasklet(void *data) =20 vio_enable_interrupts(vdev); if ((async =3D ibmvfc_next_async_crq(vhost)) !=3D NULL) { + struct ibmvfc_async_crq_event ae =3D { + .type =3D IBMVFC_ASYNC_CRQ_MAIN, + .async_crq =3D *async, + }; vio_disable_interrupts(vdev); - ibmvfc_handle_async(async, vhost); + ibmvfc_handle_async(&ae, vhost); async->valid =3D 0; wmb(); } else if ((crq =3D ibmvfc_next_crq(vhost)) !=3D NULL) { diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index a8a063d99564..6fce7a4922bb 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -786,9 +786,22 @@ struct ibmvfc_async_sub_crq { } id; } __packed __aligned(8); =20 +enum ibmvfc_async_crq_type { + IBMVFC_ASYNC_CRQ_MAIN =3D 0, + IBMVFC_ASYNC_CRQ_SUB, +}; + +struct ibmvfc_async_crq_event { + enum ibmvfc_async_crq_type type; + union { + struct ibmvfc_async_crq async_crq; + struct ibmvfc_async_sub_crq subq; + }; +}; + struct ibmvfc_async_work { struct ibmvfc_host *vhost; - struct ibmvfc_async_crq crq; + struct ibmvfc_async_crq_event event; struct work_struct async_work_s; }; =20 @@ -1103,7 +1116,8 @@ static inline struct ibmvfc_host *ibmvfc_channels_to_= vhost(struct ibmvfc_channel =20 #if IS_ENABLED(CONFIG_KUNIT) #include -VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, st= ruct ibmvfc_host *vhost); +VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibmvfc_async_crq_event *e= vent, + struct ibmvfc_host *vhost); VISIBLE_IF_KUNIT struct ibmvfc_host *ibmvfc_get_first_vhost(void); #endif =20 diff --git a/drivers/scsi/ibmvscsi/ibmvfc_kunit.c b/drivers/scsi/ibmvscsi/i= bmvfc_kunit.c index 80e7f8e0fd70..7aaed4f64f26 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc_kunit.c +++ b/drivers/scsi/ibmvscsi/ibmvfc_kunit.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include "ibmvfc.h" @@ -257,143 +256,9 @@ static void ibmvfc_full_fpin_test(struct kunit *test) scsi_host_put(vhost->host); } =20 -#define IBMVFC_TEST_FPIN_EXT(fs, ev, stat, crq) { \ - struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; \ - (crq).valid =3D 0x80; \ - (crq).flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; \ - (crq).link_state =3D IBMVFC_AE_LS_LINK_UP; \ - (crq).fpin_status =3D (fs); \ - (crq).event =3D cpu_to_be16(IBMVFC_AE_FPIN); \ - (crq).wwpn =3D cpu_to_be64(tgt->wwpn); \ - (crq).fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; \ - (crq).fpin_data.event_type =3D cpu_to_be16((ev)); \ - ae.subq =3D *(struct ibmvfc_async_sub_crq *)&(crq); \ - pre =3D READ_ONCE(rport->fpin_stats.stat); \ - ibmvfc_handle_async(&ae, vhost); \ - flush_workqueue(vhost->fpin_workq); \ - post =3D READ_ONCE(rport->fpin_stats.stat); \ -} - -/** - * ibmvfc_extended_fpin_test - unit test for extended FPIN events - * @test: pointer to kunit structure - * - * Note: This test exercises extended FPIN code paths but does not check - * that statistics are correctly updated. - * - * Return: void - */ -static void ibmvfc_extended_fpin_test(struct kunit *test) -{ - enum ibmvfc_ae_fpin_status fs; - struct ibmvfc_async_subq_fpin crq[IBMVFC_AE_FPIN_CONGESTION_CLEARED+1] = =3D {}; - struct ibmvfc_async_subq_fpin - crqcn[IBMVFC_AE_FPIN_PORT_CONGESTED][FPIN_CONGN_DEVICE_SPEC+1] =3D {}; - struct ibmvfc_async_subq_fpin crqportdg[FPIN_LI_DEVICE_SPEC+1] =3D {}; - struct ibmvfc_target *tgt; - struct ibmvfc_host *vhost; - struct fc_rport *rport; - LIST_HEAD(evt_doneq); - unsigned long flags; - u64 pre, post; - - vhost =3D ibmvfc_get_first_vhost(); - if (!vhost) - kunit_skip(test, "No ibmvfc devices available"); - - spin_lock_irqsave(vhost->host->host_lock, flags); - if (vhost->scsi_scrqs.num_targets < 1) { - spin_unlock_irqrestore(vhost->host->host_lock, flags); - scsi_host_put(vhost->host); - kunit_skip(test, "No targets"); - } - tgt =3D list_first_entry(&vhost->scsi_scrqs.targets, struct ibmvfc_target= , queue); - if (!tgt->rport) { - spin_unlock_irqrestore(vhost->host->host_lock, flags); - scsi_host_put(vhost->host); - kunit_skip(test, "No rport"); - } - rport =3D tgt->rport; - get_device(&rport->dev); - kref_get(&tgt->kref); - spin_unlock_irqrestore(vhost->host->host_lock, flags); - - for (fs =3D IBMVFC_AE_FPIN_LINK_CONGESTED; fs <=3D IBMVFC_AE_FPIN_CONGEST= ION_CLEARED; fs++) { - switch (fs) { - case IBMVFC_AE_FPIN_PORT_CLEARED: - case IBMVFC_AE_FPIN_CONGESTION_CLEARED: { - struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; - - crq[fs].valid =3D 0x80; - crq[fs].flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; - crq[fs].link_state =3D IBMVFC_AE_LS_LINK_UP; - crq[fs].fpin_status =3D fs; - crq[fs].event =3D cpu_to_be16(IBMVFC_AE_FPIN); - crq[fs].wwpn =3D cpu_to_be64(tgt->wwpn); - crq[fs].fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; - crq[fs].fpin_data.event_type =3D cpu_to_be16(FPIN_CONGN_CLEAR); - ae.subq =3D *(struct ibmvfc_async_sub_crq *)&crq[fs]; - pre =3D READ_ONCE(rport->fpin_stats.cn_clear); - ibmvfc_handle_async(&ae, vhost); - flush_workqueue(vhost->fpin_workq); - post =3D READ_ONCE(rport->fpin_stats.cn_clear); - break; - } - case IBMVFC_AE_FPIN_LINK_CONGESTED: - case IBMVFC_AE_FPIN_PORT_CONGESTED: - IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CLEAR, cn_clear, - crqcn[fs-1][FPIN_CONGN_CLEAR]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_LOST_CREDIT, - cn_lost_credit, - crqcn[fs-1][FPIN_CONGN_LOST_CREDIT]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CREDIT_STALL, - cn_credit_stall, - crqcn[fs-1][FPIN_CONGN_CREDIT_STALL]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_OVERSUBSCRIPTION, - cn_oversubscription, - crqcn[fs-1][FPIN_CONGN_OVERSUBSCRIPTION]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_DEVICE_SPEC, - cn_device_specific, - crqcn[fs-1][FPIN_CONGN_DEVICE_SPEC]); - break; - case IBMVFC_AE_FPIN_PORT_DEGRADED: - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_UNKNOWN, - li_failure_unknown, - crqportdg[FPIN_LI_UNKNOWN]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LINK_FAILURE, - li_link_failure_count, - crqportdg[FPIN_LI_LINK_FAILURE]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SYNC, - li_loss_of_sync_count, - crqportdg[FPIN_LI_LOSS_OF_SYNC]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SIG, - li_loss_of_signals_count, - crqportdg[FPIN_LI_LOSS_OF_SIG]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_PRIM_SEQ_ERR, - li_prim_seq_err_count, - crqportdg[FPIN_LI_PRIM_SEQ_ERR]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_TX_WD, - li_invalid_tx_word_count, - crqportdg[FPIN_LI_INVALID_TX_WD]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_CRC, - li_invalid_crc_count, - crqportdg[FPIN_LI_INVALID_CRC]); - IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_DEVICE_SPEC, - li_device_specific, - crqportdg[FPIN_LI_DEVICE_SPEC]); - break; - } - } - - put_device(&rport->dev); - kref_put(&tgt->kref, ibmvfc_release_tgt); - scsi_host_put(vhost->host); -} - static struct kunit_case ibmvfc_fpin_test_cases[] =3D { KUNIT_CASE(ibmvfc_async_fpin_test), KUNIT_CASE(ibmvfc_full_fpin_test), - KUNIT_CASE(ibmvfc_extended_fpin_test), {}, }; =20 --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E57D3E0220; Fri, 11 Sep 2026 02:19:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093168; cv=none; b=s2t4VkJfqhARdY6e9XoEcVPp7cVHNOJl/Oo286AhvNae3j6kUi9HKqRtYcHXcTIn9Kj1gI3Xt90Yop6HlH9AgS4eVRgWyuDfJyNXdsi/EKyI9jgZKfnU6RoPfmenXeshiyjU3XP9uSDdLlUIwuSEQlmLK01mO12bStj0OlehvsI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093168; c=relaxed/simple; bh=hSyVSW0UdAzjZ8y21iz9muNELtSLn6sQ5L6QbUFHhBs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=TjjvOZHY0uCWI42tf/M0MfKj7KczhFFyGBs+x6hT+BlbWmY270mDHe1k90FHDoWnH+SbrlzACsbImNts3UajW5A1UO7QNMP6hY9zUeDAktd5XL1WBWszLvoF7fLviFF2hPk3gj8iknrc2t8RELMZWARQ44KbrPm9hFk4H6rntcw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=X6MCXkHv; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="X6MCXkHv" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12miQ3367405; Fri, 11 Sep 2026 02:19:20 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=xRkX0vdTetUU0VI+3 Ap8L3XsiP6kBCiw73CgJoFuutw=; b=X6MCXkHv5Lx4F1x0LtMWeRbp5ElfvG+Il v/nVNaMYaeAZHXojCNcFOApFXaqhDTIW7kD7qX3aexWec171xfzjo9kIjtqrEbF0 Vtx1bmqczmrYUotJ2Vw73XcaV50mWBqsd0YmBkKtVUQwS6Ldyt9JuyVRtSFSPBug tsSry6MaJbAEy2NZPRU+f83eJRHR8u0AJe5mo+PhmjrIzBJ8ApUpCXKUnKBZam00 VEgj8DKqihnL9gQ9UYPT+D8c2h3jb5b2fsqDGffhxU+N/zDzyAcYdB02VeEGzTik gQy7uq2s94uEg6lHTcz0SRCz72zhYM9UtHOQbyk9jbaaInGf1OV6g== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8q8qv6-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:19 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B151IW891383; Fri, 11 Sep 2026 02:19:19 GMT Received: from smtprelay06.dal12v.mail.ibm.com ([172.16.1.8]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvq2uvpk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:19 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay06.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JIGn13107934 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:18 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 13C6E58055; Fri, 11 Sep 2026 02:19:18 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2B7BB58059; Fri, 11 Sep 2026 02:19:17 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:17 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 5/9] scsi: ibmvfc: add interrupt routine for asynchronous sub CRQ Date: Thu, 10 Sep 2026 19:19:05 -0700 Message-ID: <20260911021910.1038128-6-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: BwRh0cR1evkluw0KBcNzPAaHzQTj1GMY X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXxbQthTiMhi52 YlAm6HpnhUEuKjesxF6lI6e4noOrZfpQF1P8l4tEZySTiL9Pui27iAS3+k9qtSJHeinuAmcc5gt DGjLv9Bu0sDZxAtz1zELLsfWawVrL1o= X-Authority-Analysis: v=2.4 cv=E/dYNqdl c=1 sm=1 tr=0 ts=6aa36527 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=w-kvVH-zZ2E7PihfXZYA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX0afsxfLOxAQC MOKjZU4LQKdR1E9klTFWttSxah36iwF5IDMNT2cSVKlaR1shw69/fagwtmpTVKdvu+xQguWC9nz +sCtxbHYG1I6xX5S7JNUlu+dF2I3zC/+vxNXfEl9LdjD6WqVNdmOkvcn0hvFlpXz0WEFTn2Dw9e 3hYnxh+9yiFVtcwmaL/QTnP/KeYXmYePxWw6JqSNVz9SlJCnM/ebG+J7qnP5EWLmGbjD/+auIu2 mB6cspZ64zBZNDPxX/9Cr8YPcU4sN9IfsIywROtB6rCnfMPZhAy1gpg20rXP56VSJ4WY1IJNBLG 9HOvLd85KQgTQ2mkh2kmKiKC4Nkk0dqjAkiQ5rkNpfZfz7BSCOAaWyE+U46jSjb6jTp2oBFx1An CFvcTf3SRxSar1CcisAa8yX07/mwAdpS96i1icJm7sYXi8/KTv3yzfvG56VtC6zpCzLbSWnxLlJ dGeCUwF5FPjmUPc7bWw== X-Proofpoint-GUID: BwRh0cR1evkluw0KBcNzPAaHzQTj1GMY X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 spamscore=0 bulkscore=0 clxscore=1015 impostorscore=0 phishscore=0 adultscore=0 lowpriorityscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Add ibmvfc_interrupt_async_subq(), an IRQ handler dedicated to asynchronous sub-CRQ events from the adapter. The handler disables the sub-CRQ IRQ and then calls ibmvfc_drain_async_subq() to consume all pending entries before re-enabling interrupts. The handler is marked as __maybe_unused until a later patch when it is used. ibmvfc_drain_async_subq() holds the per-queue q_lock while processing. It loops over available CRQ entries via ibmvfc_next_scrq(), wrapping each in a typed struct ibmvfc_async_crq_event and dispatching it to ibmvfc_handle_async(), then clears the valid bit and issues a write barrier. After draining, it re-enables the sub-CRQ IRQ and performs one final check for a newly arrived entry to close the IRQ-enable race; if one is found it is processed before exiting the loop. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index daec81f48857..553fca31cb3a 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -4376,6 +4376,60 @@ static struct ibmvfc_crq *ibmvfc_next_scrq(struct ib= mvfc_queue *scrq) return crq; } =20 +static void ibmvfc_drain_async_subq(struct ibmvfc_queue *scrq) +{ + struct ibmvfc_host *vhost =3D scrq->vhost; + unsigned long flags; + struct ibmvfc_crq *crq; + int done =3D 0; + + spin_lock_irqsave(vhost->host->host_lock, flags); + spin_lock(scrq->q_lock); + while (!done) { + while ((crq =3D ibmvfc_next_scrq(scrq)) !=3D NULL) { + struct ibmvfc_async_crq_event ae =3D { + .type =3D IBMVFC_ASYNC_CRQ_SUB, + .subq =3D *(struct ibmvfc_async_sub_crq *)crq, + }; + ibmvfc_handle_async(&ae, scrq->vhost); + crq->valid =3D 0; + wmb(); /* complete write */ + } + + ibmvfc_toggle_scrq_irq(scrq, 1); + crq =3D ibmvfc_next_scrq(scrq); + if (crq !=3D NULL) { + struct ibmvfc_async_crq_event ae =3D { + .type =3D IBMVFC_ASYNC_CRQ_SUB, + .subq =3D *(struct ibmvfc_async_sub_crq *)crq, + }; + ibmvfc_toggle_scrq_irq(scrq, 0); + ibmvfc_handle_async(&ae, scrq->vhost); + crq->valid =3D 0; + wmb(); /* complete write */ + } else + done =3D 1; + } + spin_unlock(scrq->q_lock); + spin_unlock_irqrestore(vhost->host->host_lock, flags); +} + +/** + * ibmvfc_interrupt_async_subq - Handle an async event from the adapter + * @irq: interrupt request + * @scrq_instance: async subq + * + **/ +static irqreturn_t __maybe_unused ibmvfc_interrupt_async_subq(int irq, voi= d *scrq_instance) +{ + struct ibmvfc_queue *scrq =3D (struct ibmvfc_queue *)scrq_instance; + + ibmvfc_toggle_scrq_irq(scrq, 0); + ibmvfc_drain_async_subq(scrq); + + return IRQ_HANDLED; +} + static void ibmvfc_drain_sub_crq(struct ibmvfc_queue *scrq) { struct ibmvfc_crq *crq; --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E85773DCD90; Fri, 11 Sep 2026 02:19:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093172; cv=none; b=KNm42h4XPga/trm+zBdkxW2phhAJfDD2EhaSItcO46oQfEEEUL2zmiRf3N1qS8RQux7+/hFlpNDV8zH3OnKlgoqRY4ZABy5bkgh1sCK/D3WSZNXpyqiQCNBBMwaw3eBUPLIm/aY01AItUeP8lxS6fGFvDNTWW0U6irPFCr+WXyM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093172; c=relaxed/simple; bh=HYr54WWTa4EgA2aWe0yvMVMVVWLs+RV3f4cEEiT3ZEg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s/y1hAlNZJkSRGlm0qKxHVpV9yelHkXrlc8susEAllA+S8nPNGlfYaGo6BEvrdWCNqTAihaaC3pB293IzxrHTeNa25pnKe4WqEbRM1nGnHm2CUT1ARc1MlAvk5vVOu0+QhooJxWoDH/cVtSbg2vJWq3jsKIRs+1oanyGKBf8xCI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=HGRw3eMC; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="HGRw3eMC" Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12gQd348570; Fri, 11 Sep 2026 02:19:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=ksJLDki+gOxvjijRL ZXeku5IUdICIJyG577Sdp4IWAU=; b=HGRw3eMC46TM1Ohs3FJpN9EeYVQKrNby6 kcBSzI099JgWoP17W06kitPN5SH1WxxJ94nUuGHAQzUZQeMi871mq5Ik+9NAoSCf BRBlT1hwj2C3nrCdDqWuguQ+8YIrXjTmj2xZw8oTUJ4R9rGnZynJbVFi/2NwTixG u/FSLgMhFAsTQ6+oCjs/fsbTNxBY7s2K5EhtP2Rkl4/EIb7/Qq3o5OO8Tjz5uUJZ yViU0CrrIICTQ6lYUuGUOvHO9WHIyc6Ky5s2+Sb+vfbSKio0IcH+fdi+8NaEudRI pCF4PdEdaHeK4dCmUY6C0mdMthrM2JOAIogkG7YpugBrzJyIic7vw== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8t0q5q-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:21 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B159eL872154; Fri, 11 Sep 2026 02:19:20 GMT Received: from smtprelay07.dal12v.mail.ibm.com ([172.16.1.9]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvwk3u38-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:20 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay07.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JJJv6423192 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:19 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2648F58055; Fri, 11 Sep 2026 02:19:19 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3EDFF58059; Fri, 11 Sep 2026 02:19:18 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:18 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 6/9] scsi: ibmvfc: extend channel reg/dereg helpers for async sub-CRQ Date: Thu, 10 Sep 2026 19:19:06 -0700 Message-ID: <20260911021910.1038128-7-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXyQixNceANK4Z j0wmaLh7tzI/eQHNLd7BYXfjmjO0b6KnA86ICXBos16DLDNoYOPqQ+1HYyyx5fwyPxkFFKiBPhS BbjUoKOpKdazFVzpCsKHvBSE7p/WlOA= X-Proofpoint-ORIG-GUID: u5W2iSfyIuAOGOldxr47R09gbE3Nekqe X-Proofpoint-GUID: u5W2iSfyIuAOGOldxr47R09gbE3Nekqe X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX0W4P6pYvXX+l HRCB8p4d6EsF0SJJ0hDHMq5x8lw0kwshFXyuCojnJQDdyAaHncG4nKbYRAo+/N7mUAt9MNuc7Uk Y41ANI3fb6LVOJytqTrGvX+7omDhz9lp91O/QyMd6acW+rp/A+20hvz6UfoKtIrlwzz2QCzfYoj GyAMu5CHXkN5RjymM9e8alIc8DQeQcAdHjwQKJIHOs0+TJA6acDL9LRmy0MLOet7idiIWvEnQEJ wQogYDdIcm/uli3AcMLNLiQGfs8zrH0SeKeYkPmQSJOC1OR3BxhTn6gjJs6NooTTYu5rga/9s+y 5zlc4K9hfbl24avDB06sja6Dyl9gNT+/YBtmqD2OxORCJnGZGRg48Pnu8ECvFzyYtPAwEBobMMP 17NXin+IOb9ygAwen+yJLfgexrHI9qK+tzvmLVT3sOinEll5/AhQdyxlXTAbe0pf6S1juOcJ1jL VZQJSrQrFYSz/JFZ8iA== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa36529 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=tu7rfeQ3xgwDIMifKtoA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 priorityscore=1501 bulkscore=0 adultscore=0 suspectscore=0 lowpriorityscore=0 impostorscore=0 clxscore=1015 spamscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt ibmvfc_register_channel() and ibmvfc_deregister_channel() previously only handled indexed sub-CRQ channels drawn from the channels->scrqs[] array. The async sub-CRQ (vhost->async_sub_crq) had no registration path through these helpers, requiring separate handling. Extend both functions to accept a negative index as a sentinel value signalling that the async sub-CRQ should be operated on instead of an indexed scrq entry. When index < 0, the queue pointer is set to &vhost->async_sub_crq, the IRQ is named "ibmvfc--async", and the handler is set to ibmvfc_interrupt_async_subq rather than the per-protocol ibmvfc_interrupt_mq handler. hwq_id assignment is skipped for the async queue since it has no meaningful hardware queue index. Stopped marking ibmvfc_interrupt_async_subq as __maybe_unused. Error messages in both paths are updated to distinguish async sub-CRQ failures from indexed sub-CRQ failures. Kernel-doc headers are added to both functions documenting the negative-index convention. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 93 ++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index 553fca31cb3a..fa312a58471f 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -4420,7 +4420,7 @@ static void ibmvfc_drain_async_subq(struct ibmvfc_que= ue *scrq) * @scrq_instance: async subq * **/ -static irqreturn_t __maybe_unused ibmvfc_interrupt_async_subq(int irq, voi= d *scrq_instance) +static irqreturn_t ibmvfc_interrupt_async_subq(int irq, void *scrq_instanc= e) { struct ibmvfc_queue *scrq =3D (struct ibmvfc_queue *)scrq_instance; =20 @@ -6811,13 +6811,29 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhos= t) return retrc; } =20 +/** + * ibmvfc_register_channel - Register a sub-CRQ channel with the hypervisor + * @vhost: ibmvfc host struct + * @channels: ibmvfc channels struct containing the channel array and prot= ocol + * @index: index into the channels array for the queue to register, or + * a negative value to register the async sub-CRQ + * + * Register a sub-CRQ with the hypervisor via h_reg_sub_crq, map its hardw= are + * IRQ to a Linux IRQ, and bind an interrupt handler to it. The handler is + * selected based on the channel protocol (SCSI or NVMe) for normal queues= , or + * set to the async sub-CRQ handler when @index is negative. + * + * Return value: + * 0 on success / non-zero on failure + **/ static int ibmvfc_register_channel(struct ibmvfc_host *vhost, struct ibmvfc_channels *channels, int index) { struct device *dev =3D vhost->dev; struct vio_dev *vdev =3D to_vio_dev(dev); - struct ibmvfc_queue *scrq =3D &channels->scrqs[index]; + bool is_async =3D index < 0; + struct ibmvfc_queue *scrq =3D !is_async ? &channels->scrqs[index] : &vhos= t->async_sub_crq; int rc =3D -ENOMEM; =20 ENTER; @@ -6837,36 +6853,49 @@ static int ibmvfc_register_channel(struct ibmvfc_ho= st *vhost, =20 if (!scrq->irq) { rc =3D -EINVAL; - dev_err(dev, "Error mapping sub-crq[%d] irq\n", index); + if (!is_async) + dev_err(dev, "Error mapping sub-crq[%d] irq\n", index); + else + dev_err(dev, "Error mapping async sub-crq irq\n"); goto irq_failed; } =20 - switch (channels->protocol) { - case IBMVFC_PROTO_SCSI: - snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-scsi%d", - vdev->unit_address, index); - scrq->handler =3D ibmvfc_interrupt_mq; - break; - case IBMVFC_PROTO_NVME: - snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-nvmf%d", - vdev->unit_address, index); - scrq->handler =3D ibmvfc_interrupt_mq; - break; - default: - dev_err(dev, "Unknown channel protocol (%d)\n", - channels->protocol); - goto irq_failed; + if (!is_async) { + switch (channels->protocol) { + case IBMVFC_PROTO_SCSI: + snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-scsi%d", + vdev->unit_address, index); + scrq->handler =3D ibmvfc_interrupt_mq; + break; + case IBMVFC_PROTO_NVME: + snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-nvmf%d", + vdev->unit_address, index); + scrq->handler =3D ibmvfc_interrupt_mq; + break; + default: + dev_err(dev, "Unknown channel protocol (%d)\n", + channels->protocol); + goto irq_failed; + } + } else { + snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-async", + vdev->unit_address); + scrq->handler =3D ibmvfc_interrupt_async_subq; } =20 rc =3D request_irq(scrq->irq, scrq->handler, 0, scrq->name, scrq); =20 if (rc) { - dev_err(dev, "Couldn't register sub-crq[%d] irq\n", index); + if (!is_async) + dev_err(dev, "Couldn't register sub-crq[%d] irq\n", index); + else + dev_err(dev, "Couldn't register async sub-crq irq\n"); irq_dispose_mapping(scrq->irq); goto irq_failed; } =20 - scrq->hwq_id =3D index; + if (!is_async) + scrq->hwq_id =3D index; =20 LEAVE; return 0; @@ -6880,13 +6909,26 @@ static int ibmvfc_register_channel(struct ibmvfc_ho= st *vhost, return rc; } =20 +/** + * ibmvfc_deregister_channel - Deregister a sub-CRQ channel with the hyper= visor + * @vhost: ibmvfc host struct + * @channels: ibmvfc channels struct containing the sub-CRQ array + * @index: index into the sub-CRQ array, or -1 to deregister the + * asynchronous sub-CRQ + * + * Frees the IRQ, disposes of the IRQ mapping, and calls H_FREE_SUB_CRQ to + * release the sub-CRQ with the hypervisor. On success the queue message + * buffer is zeroed and the current index is reset. If H_FREE_SUB_CRQ fail= s, + * an error is logged but the channel resources are cleaned up regardless. + */ static void ibmvfc_deregister_channel(struct ibmvfc_host *vhost, struct ibmvfc_channels *channels, int index) { struct device *dev =3D vhost->dev; struct vio_dev *vdev =3D to_vio_dev(dev); - struct ibmvfc_queue *scrq =3D &channels->scrqs[index]; + bool is_async =3D index < 0; + struct ibmvfc_queue *scrq =3D !is_async ? &channels->scrqs[index] : &vhos= t->async_sub_crq; long rc; =20 ENTER; @@ -6900,8 +6942,13 @@ static void ibmvfc_deregister_channel(struct ibmvfc_= host *vhost, scrq->cookie); } while (rc =3D=3D H_BUSY || H_IS_LONG_BUSY(rc)); =20 - if (rc) - dev_err(dev, "Failed to free sub-crq[%d]: rc=3D%ld\n", index, rc); + if (rc) { + if (!is_async) + dev_err(dev, "Failed to free sub-crq[%d]: rc=3D%ld\n", + index, rc); + else + dev_err(dev, "Failed to free async sub-crq: rc=3D%ld\n", rc); + } =20 /* Clean out the queue */ memset(scrq->msgs.crq, 0, PAGE_SIZE); --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 501093E171E; Fri, 11 Sep 2026 02:19:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093171; cv=none; b=qHCUNvYhXMkGr6VW/xdsM/qw5nS0oeOWeLRk33lAsspTp+8dJM51orZMTR38/vjTuRMx528nQyYGs8Zf6QaYRBMkh6QQyE5/uC2lNKGC4E+10AD31UgTWm1sBMVvgfXCCdZ3jnrts3qn69rWZAi4FA74QgSnc8BzX/gCpYgy6Ss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093171; c=relaxed/simple; bh=AYtr4P1+OoFMuKpi0e4Fpa//4fIG28Wi9w5zooY5Kqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t/nW5OTRRjvJa9ghl5xcNtanvQx31kVEqFm5s77+obls/P6wFGFdW+4rbaKqVs86A3i1A7+B4g87h0iKoxlb69WH9zkueJ/bTd4Pd0etfoBS/JWzQQxUSiFqg1xfyAuuwWJnpf4zlProPmOJE397VfYONzycTkb086voAoSgc5k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=W829eATP; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="W829eATP" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12JKi311148; Fri, 11 Sep 2026 02:19:22 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=S0CHDiBfIIn8Lz/9u l9S7S1oBS76OTnFD8iyF+QdJDU=; b=W829eATP3xR4KffzF+ZuvgaPnPBZc9Qrz R0bJDCA9hKdJWkf5o7GTIA/UFUcUcEFheToXp3C8mwxb6jhsudLo16VNJuDE0SKN /doLOk4P+bL96P/Ocmnb/lP3ARu0HlwcqBQUs5JSi6+/FZE9l/HiZKx/rme4i4Ot 8nxxAinERyZ4qOAOsoWeZNnuN0EX8vtUPqaAX7869DnBulQ+cntWNe7bCsh8ip+Z LKtl1CMhT1mXvp0X/aegdANQTKVn07tQex3uQ3GAzuXM4O0kSZtJRPk91fMpgEO5 oQoTTJMXivWZ0zYCOp1X9JbRtTuEwE9MHIpMy75r/vGXokOW7buMA== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8prtbt-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:22 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B15LLD872408; Fri, 11 Sep 2026 02:19:21 GMT Received: from smtprelay01.wdc07v.mail.ibm.com ([172.16.1.68]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvwk3u3b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:21 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay01.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JK9c60948922 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:20 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5523858065; Fri, 11 Sep 2026 02:19:20 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 51A7158059; Fri, 11 Sep 2026 02:19:19 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:19 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 7/9] scsi: ibmvfc: fix IRQ leak and guard deregister on channel reg failure Date: Thu, 10 Sep 2026 19:19:07 -0700 Message-ID: <20260911021910.1038128-8-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=eM2GH3p1 c=1 sm=1 tr=0 ts=6aa3652a cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=acainBHvso6FeXtkDgYA:9 X-Proofpoint-ORIG-GUID: EbBCu-IQjTh674Hirg-pcEkU3xbQTUOa X-Proofpoint-GUID: EbBCu-IQjTh674Hirg-pcEkU3xbQTUOa X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX3KIkdqhrwPMF ONptEwc0zWFvVUK3Sjc2Ib4UOESSQAxS0ktuTPPJYk8kyRdqwVc1XOrEN9xPzkzucsMts6vUYU1 fCzWRR6Hi6SALhYQsXBpef+vNG8oru4= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX1NnCzC8uH1fs RegbpEVXKEy3x1opRJrFT45T2xukgTVtGbLn99Q5AlkyuhL7vUKvIoQtBeWHydoGtmA6euV7oI3 W0mgjurc2Iohtz+/ih915jbG8dtBGQ0HgIkYP2QdCGq1T7PYWjY7+7oLQaV8SyRuT2+y52kjyaQ 88r9tQ19hN7NqLaEbcmmDQ+nRpP9q9MRmx/iUxVoJwCSh2kSBg2/A4XBpgZciZh9z7gjopu3Bnx tTjL2oBXm+6B6snUunyqkjBuKE5NWa5dBFs4sjlN/V60Q9IKLZDbaQM3nPN85D92GXyAkEelnoZ wnkLmqdi8aYS1RoHpDnNHWARe9RRY3DAdCUgUtXh1DgUxb7kdYNM9M9Vw1TNzDXYJi640wxwC9u q18lQ1HCxL1kbui1rKM+C2B5dWLRdBPfjDYdSRoHQKtsvgU5r2VHSdvTYaGmhuHcF/OOGrS2Wo3 7TmeoR3bS7W2CDdb6WQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 impostorscore=0 malwarescore=0 adultscore=0 phishscore=0 lowpriorityscore=0 suspectscore=0 spamscore=0 priorityscore=1501 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt If request_irq() fails during ibmvfc_register_channel(), the error path disposes of the IRQ mapping via irq_dispose_mapping() but leaves scrq->irq populated with the stale virq number. A subsequent call to ibmvfc_deregister_channel() during teardown or reset cleanup then unconditionally invokes free_irq() and irq_dispose_mapping() on the stale IRQ descriptor, triggering kernel warnings. Fix this by: 1. Explicitly setting scrq->irq to 0 after irq_dispose_mapping() in the ibmvfc_register_channel() error path. 2. Guarding free_irq() and irq_dispose_mapping() with a check for scrq->irq in ibmvfc_deregister_channel() so unmapped or unregistered queues are safely skipped. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index fa312a58471f..8eeb125ee13b 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -6891,6 +6891,7 @@ static int ibmvfc_register_channel(struct ibmvfc_host= *vhost, else dev_err(dev, "Couldn't register async sub-crq irq\n"); irq_dispose_mapping(scrq->irq); + scrq->irq =3D 0; goto irq_failed; } =20 @@ -6933,9 +6934,11 @@ static void ibmvfc_deregister_channel(struct ibmvfc_= host *vhost, =20 ENTER; =20 - free_irq(scrq->irq, scrq); - irq_dispose_mapping(scrq->irq); - scrq->irq =3D 0; + if (scrq->irq) { + free_irq(scrq->irq, scrq); + irq_dispose_mapping(scrq->irq); + scrq->irq =3D 0; + } =20 do { rc =3D plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07D2B3E3DB4; Fri, 11 Sep 2026 02:19:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093173; cv=none; b=umAIQcefsbc4tvGXp2GpcSjmDY+qIPVOHGEel7m951C6ka1tuV34e7FyvFMlMh5DZr2PpzUFrQUgxvg5B471cU81wKMKaxJWrM35r+aZvsFH9mzCYiat8cCbdCzZsYOOXPD2LIbb3Y+OH+798rR7RcNsOz/DXOfbfb1rwd+Qjmo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093173; c=relaxed/simple; bh=cFDOesyRchtjzbqWb+xagE27fGimkXLcpYe25pfgCRc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mCA65QmOsg3cp6y2pYHfhvnYOhEgDxA1ujC9DRAlsRCsN4/xk1UrJKjczj1qTKfksderyP4SN67JsqZotCR111DJo61tIA2EgXCpwdJxvRFOoadF4sASq6C/iGKzzseFImAj+zl/VS8YEfu/Eps6EYcJmInrRUz8gY+NzjTV9O0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=SaaRTXK7; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="SaaRTXK7" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12I1h2632214; Fri, 11 Sep 2026 02:19:23 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=+RjGiJXMaV03MYIAU TMYzocFImR+wbC3aWqVmlWRwo4=; b=SaaRTXK7KXw/LrouTUZuiRFNGDC02G5Sg pJfnTUuho1rj0gCu7KOpc1+de6RLMV4NSZ8Im2X7Xv27iAWfePAMQX4LuWG8Ag6N DzLY1knEtR+ZtQBsSF0VXaUIAmNih4btxxeIzV6zWQGtxc75WesQX9xO7BlxlgFe XOjUY87hv0GWzx9gTXfma3SPjdNWoD7Dgj0a2tnUjXqvnCCDEchMidGwwP8SG60Q XyZWO64svT6bjhFVhzB7ckSi74lIEzgxYWvPWFVFsZoHxDbkyN8Ic8nV91ygqN7R pEQ0Lg0iMJyEiue5OBS/T3oYNWU2qj/3kDe14qWnapaPAn2ySI55g== Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8n8sc8-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:23 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B1512Z855011; Fri, 11 Sep 2026 02:19:22 GMT Received: from smtprelay02.wdc07v.mail.ibm.com ([172.16.1.69]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvvrbtj8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:22 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay02.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2JLOW28967548 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:19:21 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 71A4D58055; Fri, 11 Sep 2026 02:19:21 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 81EFC5804B; Fri, 11 Sep 2026 02:19:20 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:20 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 8/9] scsi: ibmvfc: register and use asynchronous sub CRQ for events Date: Thu, 10 Sep 2026 19:19:08 -0700 Message-ID: <20260911021910.1038128-9-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=NMVAaE6g c=1 sm=1 tr=0 ts=6aa3652b cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=EqnsHTcO9pxfbuvt6BcA:9 X-Proofpoint-GUID: B8wKQxkiHQBRQ3YX-BV4mYCDaeQiG9xr X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXwlJFsLZwHYtB VOzo7wohIaRGq2ZA7PEQMKtEVH4fGyw9SHPDsOZoL2OqUagcxNdvX5jJ17wmyU6qQKUdikYcugV 5XuNWiiNQGbq3bIOr4J3IhIC92yOvvYeRn7ZTRl3ZrpLni/E9GMhOS7n0M6P3bVWEb4dgZpHpM5 SMEkfsdncbR5/rAVfFBLiJcPgFDzAweQyy2lPjQspgLIhAxqHm7RzxTLOCVaXgcTa7xLJPRnRW1 sF5qTIU/GWBjhzE9aV3wyR/+ibwT1D1o4BJuflshO1xAUvhJPd1lwdYjhChvySALu6V4LkRp48i gxCX9KCLr0yF1fwgNwZUV/8NlpBbWLafStI/ryumh5opOe4AKCD9PT37DJjYgyLsREysxGyV4Z2 zQ+nrCO689HBGR9Af27hbqlFd9Z4mAV4HAitADWzbAsCd/2LkzpnlWp6lOCV9vE1W/w8m1MHa8I 66WHSGXsdOcptnbHPLg== X-Proofpoint-ORIG-GUID: B8wKQxkiHQBRQ3YX-BV4mYCDaeQiG9xr X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXxTdgaZrwtUEY /+1gJZ46RS0D1ARteJ/5gELS+f7WCralw9WQWJEwMS35xthsXOvYGVzkjBjEKqXuB9G3H0n5aUv gmUpsNh/ZCr/ZNUkfWznLPSS3OKw13Q= X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 bulkscore=0 clxscore=1015 malwarescore=0 lowpriorityscore=0 priorityscore=1501 adultscore=0 suspectscore=0 impostorscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Wire the async sub-CRQ into the sub-CRQ lifecycle so it is allocated, registered, and freed alongside the SCSI channel queues. In ibmvfc_init_sub_crqs(), allocate the async sub-CRQ queue buffer via ibmvfc_alloc_queue() before allocating the SCSI channels. Register it with the VIOS by calling ibmvfc_register_channel() with index -1 (the negative-index sentinel introduced in the previous commit). Either failure disables multi-queue and aborts init. In ibmvfc_release_sub_crqs(), ibmvfc_reenable_crq_queue(), and ibmvfc_reset_crq(), deregister and re-register the async sub-CRQ alongside the SCSI channel queues. In ibmvfc_channel_setup_done(), capture the async sub-CRQ handle returned by the VIOS in the channel setup response and store it in vhost->async_sub_crq.vios_cookie. In ibmvfc_set_login_info(), advertise IBMVFC_USE_ASYNC_SUBQ, IBMVFC_CAN_HANDLE_FPIN, and IBMVFC_YES_SCSI capabilities whenever multi-queue channels are enabled. IBMVFC_YES_SCSI was previously only set for NVMe-enabled configurations; move it to the common multi-queue path so it is always advertised when channels are in use. Fix a variable-shadowing bug in ibmvfc_register_channel() where the irq_failed cleanup loop reused rc for the H_FREE_SUB_CRQ hcall result, clobbering the error code returned to the caller. Introduce hcall_rc for the cleanup loop instead. Guard the memset() in ibmvfc_deregister_channel() behind a check of scrq->msgs.handle to prevent a NULL dereference when the function is called on a queue that was never allocated, such as async_sub_crq when multi-queue is disabled or initialization failed before ibmvfc_alloc_queue() was reached. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 51 +++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index 8eeb125ee13b..6eb299989724 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -192,6 +192,8 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target = *); =20 static void ibmvfc_dereg_sub_crqs(struct ibmvfc_host *, struct ibmvfc_chan= nels *); static void ibmvfc_reg_sub_crqs(struct ibmvfc_host *, struct ibmvfc_channe= ls *); +static void ibmvfc_deregister_channel(struct ibmvfc_host *, struct ibmvfc_= channels *, int); +static int ibmvfc_register_channel(struct ibmvfc_host *, struct ibmvfc_cha= nnels *, int); =20 static const char *unknown_error =3D "unknown error"; =20 @@ -964,6 +966,7 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host= *vhost) struct vio_dev *vdev =3D to_vio_dev(vhost->dev); unsigned long flags; =20 + ibmvfc_deregister_channel(vhost, &vhost->scsi_scrqs, -1); ibmvfc_dereg_sub_crqs(vhost, &vhost->scsi_scrqs); ibmvfc_dereg_sub_crqs(vhost, &vhost->nvme_scrqs); =20 @@ -986,6 +989,7 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host= *vhost) spin_unlock(vhost->crq.q_lock); spin_unlock_irqrestore(&vhost->host->host_lock, flags); =20 + ibmvfc_register_channel(vhost, &vhost->scsi_scrqs, -1); ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs); ibmvfc_reg_sub_crqs(vhost, &vhost->nvme_scrqs); =20 @@ -1006,6 +1010,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) struct vio_dev *vdev =3D to_vio_dev(vhost->dev); struct ibmvfc_queue *crq =3D &vhost->crq; =20 + ibmvfc_deregister_channel(vhost, &vhost->scsi_scrqs, -1); ibmvfc_dereg_sub_crqs(vhost, &vhost->scsi_scrqs); ibmvfc_dereg_sub_crqs(vhost, &vhost->nvme_scrqs); =20 @@ -1042,6 +1047,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) spin_unlock(vhost->crq.q_lock); spin_unlock_irqrestore(&vhost->host->host_lock, flags); =20 + ibmvfc_register_channel(vhost, &vhost->scsi_scrqs, -1); ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs); ibmvfc_reg_sub_crqs(vhost, &vhost->nvme_scrqs); =20 @@ -1584,9 +1590,11 @@ static void ibmvfc_set_login_info(struct ibmvfc_host= *vhost) =20 if (vhost->mq_enabled || vhost->using_channels) { login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_USE_CHANNELS); + login_info->capabilities |=3D cpu_to_be64(IBMVFC_USE_ASYNC_SUBQ); + login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_HANDLE_FPIN); + login_info->capabilities |=3D cpu_to_be64(IBMVFC_YES_SCSI); if (vhost->nvme_enabled) { login_info->capabilities |=3D cpu_to_be64(IBMVFC_YES_NVMEOF); - login_info->capabilities |=3D cpu_to_be64(IBMVFC_YES_SCSI); login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_USE_WWPN_ALL); } } @@ -5812,6 +5820,7 @@ static void ibmvfc_channel_setup_done(struct ibmvfc_e= vent *evt) for (i =3D 0; i < nvme->active_queues; i++) nvme->scrqs[i].vios_cookie =3D be64_to_cpu(setup->channel_handles[scsi->active_queues + i]); + vhost->async_sub_crq.vios_cookie =3D be64_to_cpu(setup->async_sub_crq_ha= ndle); =20 ibmvfc_dbg(vhost, "Using %u SCSI channels\n", scsi->active_queues); @@ -5871,6 +5880,7 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *= vhost) for (i =3D 0; i < nvme_channels; i++) setup_buf->channel_handles[scsi_channels + i] =3D cpu_to_be64(nvme->scrqs[i].cookie); + setup_buf->async_sub_crq_handle =3D cpu_to_be64(vhost->async_sub_crq.coo= kie); } =20 ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT); @@ -6835,6 +6845,7 @@ static int ibmvfc_register_channel(struct ibmvfc_host= *vhost, bool is_async =3D index < 0; struct ibmvfc_queue *scrq =3D !is_async ? &channels->scrqs[index] : &vhos= t->async_sub_crq; int rc =3D -ENOMEM; + int hcall_rc; =20 ENTER; =20 @@ -6903,8 +6914,8 @@ static int ibmvfc_register_channel(struct ibmvfc_host= *vhost, =20 irq_failed: do { - rc =3D plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq->cook= ie); - } while (rc =3D=3D H_BUSY || H_IS_LONG_BUSY(rc)); + hcall_rc =3D plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, scrq= ->cookie); + } while (hcall_rc =3D=3D H_BUSY || H_IS_LONG_BUSY(hcall_rc)); reg_failed: LEAVE; return rc; @@ -6954,8 +6965,10 @@ static void ibmvfc_deregister_channel(struct ibmvfc_= host *vhost, } =20 /* Clean out the queue */ - memset(scrq->msgs.crq, 0, PAGE_SIZE); - scrq->cur =3D 0; + if (scrq->msgs.handle) { + memset(scrq->msgs.crq, 0, PAGE_SIZE); + scrq->cur =3D 0; + } =20 LEAVE; } @@ -6972,7 +6985,9 @@ static void ibmvfc_reg_sub_crqs(struct ibmvfc_host *v= host, for (i =3D 0; i < channels->max_queues; i++) { if (ibmvfc_register_channel(vhost, channels, i)) { for (j =3D i; j > 0; j--) - ibmvfc_deregister_channel(vhost, channels, j - 1); + ibmvfc_deregister_channel( + vhost, channels, j - 1); + vhost->do_enquiry =3D 0; return; } @@ -7027,16 +7042,26 @@ static int ibmvfc_alloc_channels(struct ibmvfc_host= *vhost, =20 static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost) { + int rc =3D 0; + ENTER; if (!vhost->mq_enabled) return; =20 - if (ibmvfc_alloc_channels(vhost, &vhost->scsi_scrqs)) { + rc =3D ibmvfc_alloc_queue(vhost, &vhost->async_sub_crq, IBMVFC_SUB_CRQ_FM= T); + if (rc) { vhost->do_enquiry =3D 0; vhost->mq_enabled =3D 0; return; } =20 + /* register async_sub_crq channel */ + if (ibmvfc_register_channel(vhost, &vhost->scsi_scrqs, -1)) + goto free_async_sub_crq; + + if (ibmvfc_alloc_channels(vhost, &vhost->scsi_scrqs)) + goto deregister_async_sub_crq; + ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs); =20 if (vhost->nvme_enabled) { @@ -7047,6 +7072,15 @@ static void ibmvfc_init_sub_crqs(struct ibmvfc_host = *vhost) } =20 LEAVE; + return; + + deregister_async_sub_crq: + ibmvfc_deregister_channel(vhost, &vhost->scsi_scrqs, -1); +free_async_sub_crq: + ibmvfc_free_queue(vhost, &vhost->async_sub_crq); + vhost->do_enquiry =3D 0; + vhost->mq_enabled =3D 0; + return; } =20 static void ibmvfc_release_channels(struct ibmvfc_host *vhost, @@ -7070,6 +7104,9 @@ static void ibmvfc_release_channels(struct ibmvfc_hos= t *vhost, static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost) { ENTER; + ibmvfc_deregister_channel(vhost, &vhost->scsi_scrqs, -1); + ibmvfc_free_queue(vhost, &vhost->async_sub_crq); + if (!vhost->scsi_scrqs.scrqs) return; =20 --=20 2.55.0 From nobody Fri Sep 25 15:13:49 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B199C3DDAE6; Fri, 11 Sep 2026 02:19:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093174; cv=none; b=NzlJUyIcYE3bLdxOtjWnbPIw7jPQspzkkepvtcf7KY58Yv2CgcX/wrhKELCuCFfZFr6y7FW9jJlYRXiuPoBfSE5xVmH3c5TN4mu3sl3ct3B/XcZ9ej59MfjXEqqlqWHkJQHtUw4A2eYuyQLO1J/sfhlf7CzJXZAogtrKAbbA8MQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789093174; c=relaxed/simple; bh=5LOu4/B2zSincTRkEZB40hJcCZVDzmy98SLnQHrDSek=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mdHbjdMTApG4Gy4zrIQO+y+AUSu1/b/A0cTTvA3EG52Fb9XIH1KPiqqoqNuSY3HhWp0TLbQPW7NWrHb7OogLvHug3CNFbCX2ypgMpgrlQ4gRj/b2EUq33YPU+ZYrXr5TX1OytRVd6i2u6jCtFYdO6NzLXNs/IeJW+A11QrqirNM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=hoAnxcfL; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="hoAnxcfL" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B12SkC3367002; Fri, 11 Sep 2026 02:19:25 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=0eZmCs6e8jccDUIO0 UDJby2+Kk0tdSJFcMWqsUD0w+I=; b=hoAnxcfLsjGA6AmU+Wh9ZXUdW6fHwtdg0 dNEejqSaXrMpxcGw0bUwTjo5TORfi9MnCll+Gvu84PSGbOW6gnXA6NAvX4d8LfZ7 adQAotI6r0KCCQDoSEU8xsRPDHvqs2CF3uko29w8T2QgFlKDw69cLmDebsOME5Vw enNC5T+qEThfufVvo9Xni3qEL6xFJ/+EQwAJrtaV5j6JCucYBBuTVkdIEXsrS8Jh hvWgHiOd7SQQShg4dB29y+M1ZDuJ2B74Z1gRKh96p1Bq3WiHZQM4qAsrHgbkgiwd iPuLP4TnjRFhoq4qZKLIB484aD+laEVNOBnzLyuIijLqYYAU6/5Gw== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8q8qvg-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:24 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B150E1900639; Fri, 11 Sep 2026 02:19:24 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvnrkvkg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:19:24 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (smtpav01.wdc07v.mail.ibm.com [10.39.53.228]) by smtprelay03.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B2IeBQ15467018 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:18:40 GMT Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 86E3F5804B; Fri, 11 Sep 2026 02:19:22 +0000 (GMT) Received: from smtpav01.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9BB0758055; Fri, 11 Sep 2026 02:19:21 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav01.wdc07v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:19:21 +0000 (GMT) From: Tyrel Datwyler To: james.bottomley@hansenpartnership.com, martin.petersen@oracle.com Cc: linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, brking@linux.ibm.com, davemarq@linux.ibm.com, Tyrel Datwyler Subject: [PATCH v9 9/9] scsi: ibmvfc: handle extended FPIN events Date: Thu, 10 Sep 2026 19:19:09 -0700 Message-ID: <20260911021910.1038128-10-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260911021910.1038128-1-tyreld@linux.ibm.com> References: <20260911021910.1038128-1-tyreld@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: co6k16AC7aVEu9mgc8aoL5ZkekeiA38- X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX186l46rjT881 zEqK8FgsfTUJrs2v3N0bP4tcZLTn4mJYVsFmKutqUjy7VXlVFqyb2ULGVvI7r2ZCiHK4N4bJG6Q OFBO/vE4EYPIm3POGzMd9wXebbDohXI= X-Authority-Analysis: v=2.4 cv=E/dYNqdl c=1 sm=1 tr=0 ts=6aa3652c cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=YunXX2DFvQEblV2KXBkA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXxJkCHkjyndP4 owowi0YDkmIcOIL4m8tDg32G+dJOESvCoWNkKPorPx365mtd58a8srnhev9At1jfp8OqCwth58W eoP0dhBlrdRqdzYTUSCbuNxFX1uUh2AanzMmTbDwLump1Ci3LBS7u5rdB7nPa8LtbIOV4bdLN3y OnsN+Qmp9jRAF2Oh3OsKv4qaAZUHf1jN+Y5HBS69De5+X/xVpVNBYuCj2ehG3FMtTzxJzrKhpHw 3RRP6ZsNDipY49CpCnbjFYTQ0Nt9vx8sRgSc3pgRsJQB2rGK8vl5r668CDoDQYqSy0rTgomRS/T QadkAO3nOSSRNtZQNuDnfmutV4zA/HcioLids2CtvYf+EjwmzbOIVfuSdbv9DGlTQOmQmEmy+xm Gw5XNfQRGbGrduEBAsFWlmAEwhcA4cZ52SCxOOYSN9DaDw0FmHZgfxyR3o1Hgajcg5kWbtxoUGG vYj9LqnzK7hlUW4lESg== X-Proofpoint-GUID: co6k16AC7aVEu9mgc8aoL5ZkekeiA38- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-11_01,2026-09-09_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 suspectscore=0 spamscore=0 bulkscore=0 clxscore=1015 impostorscore=0 phishscore=0 adultscore=0 lowpriorityscore=0 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2609040000 definitions=main-2609110024 Content-Type: text/plain; charset="utf-8" From: Dave Marquardt Implement support for extended FPIN messages received via the asynchronous sub-queue, completing full FPIN functionality. Extended FPIN messages provide more detailed information about fabric events compared to basic FPIN messages, including specific event types, modifiers, thresholds, and event counts. Add ibmvfc_ext_fpin_to_desc() to convert extended FPIN messages from async sub-queue format to fc_els_fpin structures with complete descriptor information. Update ibmvfc_process_async_work() and ibmvfc_handle_async() to zero node_name and dispatch to ibmvfc_ext_fpin_to_desc() when the IBMVFC_ASYNC_IS_FPIN_EXT flag is set. Set the IBMVFC_CAN_HANDLE_FPIN_EXT capability bit during login to inform VIOS that the client can process extended FPIN messages. Also add the IBMVFC_SUPPORT_FPIN_EXT response capability bit definition used to gate extended FPIN processing. Add KUnit tests to exercise extended FPIN event handling across all FPIN status and event type combinations. struct ibmvfc_async_subq_fpin uses volatile on its valid and wwpn fields, consistent with the existing ibmvfc_crq, ibmvfc_async_crq, and ibmvfc_async_sub_crq structs in ibmvfc.h, all of which mark their hardware-owned ring-buffer fields volatile to prevent the compiler from caching or eliminating reads of memory written directly by the VIOS. Signed-off-by: Dave Marquardt Acked-by: Tyrel Datwyler --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 67 ++++++++++++- drivers/scsi/ibmvscsi/ibmvfc.h | 30 ++++++ drivers/scsi/ibmvscsi/ibmvfc_kunit.c | 135 +++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ib= mvfc-core.c index 6eb299989724..bd10c3fd5ccf 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -1593,6 +1593,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host = *vhost) login_info->capabilities |=3D cpu_to_be64(IBMVFC_USE_ASYNC_SUBQ); login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_HANDLE_FPIN); login_info->capabilities |=3D cpu_to_be64(IBMVFC_YES_SCSI); + login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_HANDLE_FPIN_EXT); if (vhost->nvme_enabled) { login_info->capabilities |=3D cpu_to_be64(IBMVFC_YES_NVMEOF); login_info->capabilities |=3D cpu_to_be64(IBMVFC_CAN_USE_WWPN_ALL); @@ -3473,6 +3474,41 @@ ibmvfc_full_fpin_to_desc(struct ibmvfc_async_sub_crq= *ibmvfc_fpin) cpu_to_be32(1)); } =20 +/** + * ibmvfc_ext_fpin_to_desc(): allocate and populate a struct fc_els_fpin s= truct + * containing a descriptor. + * @ibmvfc_fpin: Pointer to async subq FPIN data + * + * Allocate a struct fc_els_fpin containing a descriptor and populate + * based on data from *ibmvfc_fpin. + * + * Return: + * NULL - unable to allocate structure + * non-NULL - pointer to populated struct fc_els_fpin + */ +static struct fc_els_fpin * +ibmvfc_ext_fpin_to_desc(struct ibmvfc_async_subq_fpin *ibmvfc_fpin) +{ + u8 flags =3D ibmvfc_fpin->fpin_data.flags; + __be32 threshold =3D cpu_to_be32(IBMVFC_FPIN_DEFAULT_EVENT_THRESHOLD); + __be16 modifier =3D 0; + __be32 count =3D cpu_to_be32(1); + __be16 type =3D 0; + + if (flags & IBMVFC_FPIN_EVENT_TYPE_VALID) + type =3D ibmvfc_fpin->fpin_data.event_type; + if (flags & IBMVFC_FPIN_MODIFIER_VALID) + modifier =3D ibmvfc_fpin->fpin_data.event_type_modifier; + if (flags & IBMVFC_FPIN_THRESHOLD_VALID) + threshold =3D ibmvfc_fpin->fpin_data.event_threshold; + if (flags & IBMVFC_FPIN_EVENT_COUNT_VALID) + count =3D ibmvfc_fpin->fpin_data.event_data.event_count; + + return ibmvfc_common_fpin_to_desc(ibmvfc_fpin->fpin_status, + ibmvfc_fpin->wwpn, type, + modifier, threshold, count); +} + /** * ibmvfc_find_target - Search for a target in a target list * @target_list: list head of targets to search @@ -3511,6 +3547,7 @@ static struct ibmvfc_target *ibmvfc_find_target(struc= t list_head *target_list, static void ibmvfc_process_async_work(struct work_struct *work) { struct ibmvfc_async_sub_crq *subq =3D NULL; + struct ibmvfc_async_subq_fpin *sqfpin; struct ibmvfc_async_work *aw; struct ibmvfc_async_crq *crq =3D NULL; struct ibmvfc_target *tgt; @@ -3527,7 +3564,10 @@ static void ibmvfc_process_async_work(struct work_st= ruct *work) subq =3D &aw->event.subq; scsi_id =3D 0; wwpn =3D subq->wwpn; - node_name =3D (subq->flags & IBMVFC_ASYNC_ID_IS_ASSOC_ID) ? 0 : subq->id= .node_name; + if (subq->flags & (IBMVFC_ASYNC_IS_FPIN_EXT | IBMVFC_ASYNC_ID_IS_ASSOC_I= D)) + node_name =3D 0; + else + node_name =3D subq->id.node_name; } else { crq =3D &aw->event.async_crq; scsi_id =3D crq->scsi_id; @@ -3556,8 +3596,24 @@ static void ibmvfc_process_async_work(struct work_st= ruct *work) =20 if (crq) fpin =3D ibmvfc_basic_fpin_to_desc(crq, tgt->wwpn); - else - fpin =3D ibmvfc_full_fpin_to_desc(subq); + else { + static_assert(sizeof(struct ibmvfc_async_subq_fpin) =3D=3D + sizeof(struct ibmvfc_async_sub_crq)); + static_assert(offsetof(struct ibmvfc_async_subq_fpin, fpin_data) =3D=3D + offsetof(struct ibmvfc_async_sub_crq, nport_id)); + sqfpin =3D (struct ibmvfc_async_subq_fpin *)subq; + if ((subq->flags & IBMVFC_ASYNC_IS_FPIN_EXT) =3D=3D 0) { + fpin =3D ibmvfc_full_fpin_to_desc(subq); + } else if (!(sqfpin->fpin_data.flags & IBMVFC_FPIN_EVENT_TYPE_VALID)) { + dev_err_ratelimited(vhost->dev, + "Invalid extended FPIN event received\n"); + } else if (!ibmvfc_check_caps(vhost, IBMVFC_SUPPORT_FPIN_EXT)) { + dev_err_ratelimited(vhost->dev, + "Unexpected extended FPIN event received\n"); + } else { + fpin =3D ibmvfc_ext_fpin_to_desc(sqfpin); + } + } =20 if (fpin) { fc_host_fpin_rcv(tgt->vhost->host, @@ -3599,7 +3655,10 @@ VISIBLE_IF_KUNIT void ibmvfc_handle_async(struct ibm= vfc_async_crq_event *ae, link_state =3D subq->link_state; scsi_id =3D 0; wwpn =3D subq->wwpn; - node_name =3D subq->flags & IBMVFC_ASYNC_ID_IS_ASSOC_ID ? 0 : subq->id.n= ode_name; + if (subq->flags & (IBMVFC_ASYNC_IS_FPIN_EXT | IBMVFC_ASYNC_ID_IS_ASSOC_I= D)) + node_name =3D 0; + else + node_name =3D subq->id.node_name; } else { async_crq =3D &ae->async_crq; event =3D be64_to_cpu(async_crq->event); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 6fce7a4922bb..20933af59d48 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -210,6 +210,7 @@ struct ibmvfc_npiv_login { #define IBMVFC_CAN_USE_WWPN_ALL 0x080 #define IBMVFC_USE_ASYNC_SUBQ 0x100 #define IBMVFC_CAN_USE_NOOP_CMD 0x200 +#define IBMVFC_CAN_HANDLE_FPIN_EXT 0x800 __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; @@ -261,6 +262,7 @@ struct ibmvfc_npiv_login_resp { #define IBMVFC_SUPPORT_WWPN_ALL 0x0400 #define IBMVFC_ASYNC_SUBQ 0x0800 #define IBMVFC_SUPPORT_NOOP_CMD 0x1000 +#define IBMVFC_SUPPORT_FPIN_EXT 0x2000 __be32 max_cmds; __be32 scsi_id_sz; __be64 max_dma_len; @@ -786,6 +788,34 @@ struct ibmvfc_async_sub_crq { } id; } __packed __aligned(8); =20 +struct ibmvfc_fpin_data { +#define IBMVFC_FPIN_EVENT_TYPE_VALID 0x01 +#define IBMVFC_FPIN_MODIFIER_VALID 0x02 +#define IBMVFC_FPIN_THRESHOLD_VALID 0x04 +#define IBMVFC_FPIN_SEVERITY_VALID 0x08 +#define IBMVFC_FPIN_EVENT_COUNT_VALID 0x10 + u8 flags; + u8 reserved[3]; + __be16 event_type; + __be16 event_type_modifier; + __be32 event_threshold; + union { + u8 severity; + __be32 event_count; + } event_data; +} __packed __aligned(8); + +struct ibmvfc_async_subq_fpin { + volatile u8 valid; + u8 flags; + u8 link_state; + u8 fpin_status; + __be16 event; + __be16 pad; + volatile __be64 wwpn; + struct ibmvfc_fpin_data fpin_data; +} __packed __aligned(8); + enum ibmvfc_async_crq_type { IBMVFC_ASYNC_CRQ_MAIN =3D 0, IBMVFC_ASYNC_CRQ_SUB, diff --git a/drivers/scsi/ibmvscsi/ibmvfc_kunit.c b/drivers/scsi/ibmvscsi/i= bmvfc_kunit.c index 7aaed4f64f26..80e7f8e0fd70 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc_kunit.c +++ b/drivers/scsi/ibmvscsi/ibmvfc_kunit.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "ibmvfc.h" @@ -256,9 +257,143 @@ static void ibmvfc_full_fpin_test(struct kunit *test) scsi_host_put(vhost->host); } =20 +#define IBMVFC_TEST_FPIN_EXT(fs, ev, stat, crq) { \ + struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; \ + (crq).valid =3D 0x80; \ + (crq).flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; \ + (crq).link_state =3D IBMVFC_AE_LS_LINK_UP; \ + (crq).fpin_status =3D (fs); \ + (crq).event =3D cpu_to_be16(IBMVFC_AE_FPIN); \ + (crq).wwpn =3D cpu_to_be64(tgt->wwpn); \ + (crq).fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; \ + (crq).fpin_data.event_type =3D cpu_to_be16((ev)); \ + ae.subq =3D *(struct ibmvfc_async_sub_crq *)&(crq); \ + pre =3D READ_ONCE(rport->fpin_stats.stat); \ + ibmvfc_handle_async(&ae, vhost); \ + flush_workqueue(vhost->fpin_workq); \ + post =3D READ_ONCE(rport->fpin_stats.stat); \ +} + +/** + * ibmvfc_extended_fpin_test - unit test for extended FPIN events + * @test: pointer to kunit structure + * + * Note: This test exercises extended FPIN code paths but does not check + * that statistics are correctly updated. + * + * Return: void + */ +static void ibmvfc_extended_fpin_test(struct kunit *test) +{ + enum ibmvfc_ae_fpin_status fs; + struct ibmvfc_async_subq_fpin crq[IBMVFC_AE_FPIN_CONGESTION_CLEARED+1] = =3D {}; + struct ibmvfc_async_subq_fpin + crqcn[IBMVFC_AE_FPIN_PORT_CONGESTED][FPIN_CONGN_DEVICE_SPEC+1] =3D {}; + struct ibmvfc_async_subq_fpin crqportdg[FPIN_LI_DEVICE_SPEC+1] =3D {}; + struct ibmvfc_target *tgt; + struct ibmvfc_host *vhost; + struct fc_rport *rport; + LIST_HEAD(evt_doneq); + unsigned long flags; + u64 pre, post; + + vhost =3D ibmvfc_get_first_vhost(); + if (!vhost) + kunit_skip(test, "No ibmvfc devices available"); + + spin_lock_irqsave(vhost->host->host_lock, flags); + if (vhost->scsi_scrqs.num_targets < 1) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No targets"); + } + tgt =3D list_first_entry(&vhost->scsi_scrqs.targets, struct ibmvfc_target= , queue); + if (!tgt->rport) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + scsi_host_put(vhost->host); + kunit_skip(test, "No rport"); + } + rport =3D tgt->rport; + get_device(&rport->dev); + kref_get(&tgt->kref); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + for (fs =3D IBMVFC_AE_FPIN_LINK_CONGESTED; fs <=3D IBMVFC_AE_FPIN_CONGEST= ION_CLEARED; fs++) { + switch (fs) { + case IBMVFC_AE_FPIN_PORT_CLEARED: + case IBMVFC_AE_FPIN_CONGESTION_CLEARED: { + struct ibmvfc_async_crq_event ae =3D { .type =3D IBMVFC_ASYNC_CRQ_SUB }; + + crq[fs].valid =3D 0x80; + crq[fs].flags =3D IBMVFC_ASYNC_IS_FPIN_EXT; + crq[fs].link_state =3D IBMVFC_AE_LS_LINK_UP; + crq[fs].fpin_status =3D fs; + crq[fs].event =3D cpu_to_be16(IBMVFC_AE_FPIN); + crq[fs].wwpn =3D cpu_to_be64(tgt->wwpn); + crq[fs].fpin_data.flags =3D IBMVFC_FPIN_EVENT_TYPE_VALID; + crq[fs].fpin_data.event_type =3D cpu_to_be16(FPIN_CONGN_CLEAR); + ae.subq =3D *(struct ibmvfc_async_sub_crq *)&crq[fs]; + pre =3D READ_ONCE(rport->fpin_stats.cn_clear); + ibmvfc_handle_async(&ae, vhost); + flush_workqueue(vhost->fpin_workq); + post =3D READ_ONCE(rport->fpin_stats.cn_clear); + break; + } + case IBMVFC_AE_FPIN_LINK_CONGESTED: + case IBMVFC_AE_FPIN_PORT_CONGESTED: + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CLEAR, cn_clear, + crqcn[fs-1][FPIN_CONGN_CLEAR]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_LOST_CREDIT, + cn_lost_credit, + crqcn[fs-1][FPIN_CONGN_LOST_CREDIT]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_CREDIT_STALL, + cn_credit_stall, + crqcn[fs-1][FPIN_CONGN_CREDIT_STALL]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_OVERSUBSCRIPTION, + cn_oversubscription, + crqcn[fs-1][FPIN_CONGN_OVERSUBSCRIPTION]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_CONGN_DEVICE_SPEC, + cn_device_specific, + crqcn[fs-1][FPIN_CONGN_DEVICE_SPEC]); + break; + case IBMVFC_AE_FPIN_PORT_DEGRADED: + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_UNKNOWN, + li_failure_unknown, + crqportdg[FPIN_LI_UNKNOWN]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LINK_FAILURE, + li_link_failure_count, + crqportdg[FPIN_LI_LINK_FAILURE]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SYNC, + li_loss_of_sync_count, + crqportdg[FPIN_LI_LOSS_OF_SYNC]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_LOSS_OF_SIG, + li_loss_of_signals_count, + crqportdg[FPIN_LI_LOSS_OF_SIG]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_PRIM_SEQ_ERR, + li_prim_seq_err_count, + crqportdg[FPIN_LI_PRIM_SEQ_ERR]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_TX_WD, + li_invalid_tx_word_count, + crqportdg[FPIN_LI_INVALID_TX_WD]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_INVALID_CRC, + li_invalid_crc_count, + crqportdg[FPIN_LI_INVALID_CRC]); + IBMVFC_TEST_FPIN_EXT(fs, FPIN_LI_DEVICE_SPEC, + li_device_specific, + crqportdg[FPIN_LI_DEVICE_SPEC]); + break; + } + } + + put_device(&rport->dev); + kref_put(&tgt->kref, ibmvfc_release_tgt); + scsi_host_put(vhost->host); +} + static struct kunit_case ibmvfc_fpin_test_cases[] =3D { KUNIT_CASE(ibmvfc_async_fpin_test), KUNIT_CASE(ibmvfc_full_fpin_test), + KUNIT_CASE(ibmvfc_extended_fpin_test), {}, }; =20 --=20 2.55.0