From nobody Fri Sep 25 18:24:27 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 749D03CB56A; Fri, 11 Sep 2026 02:08:36 +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=1789092519; cv=none; b=upatun5T/woNAbP62gfn0DSfK2WNLT5t0olu+KpUmZpC5SFrJo2cTcNu/0haoeZBiRCW5qshcDz12kpMtHL5uzPoTLmr717jZ306ymMZiGur+41aNAdGWVR6z+IcAMiZmP3ZTB+o14SmcuGDj88Sujq36h9x/bM0SDHivR4GDKc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092519; c=relaxed/simple; bh=6E/N2wy6Fdmr7y1MXO0Qxcd6tAv4JUVu5jev/FtyGOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l/kTmjSC0Fb+9VN2VWQJJZZh32oXcmnGmEdvZzA3Pw54qfIWBEAeoOdrL98NbbyNM1DT47jrQIsPjsD2kKSCZKwzAoEVNsGj+UbfFkDbH+TL3cuCOThPQUds1oQ0elebUZ072fY9VkRnDpHw+GDf4Ji/S1mDqNbWFwdhY4kb/IY= 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=KaC2e7P5; 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="KaC2e7P5" 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 68B12Nvt2632254; Fri, 11 Sep 2026 02:08: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=PNfeoblsafp3SYYxA tlZnHU/V+Q8NsM4TyWowhkjveM=; b=KaC2e7P5j6IuEwJe0k3vGeEX0IxKk67nk EUuhKtfKRyvb0wDoubuJwxsFXa83C60VXS9D2MawTmb35zzsDKpfW3QcObLZoH6n Aa9osCd8nAh5cuveTvtiuWJ/57q2s88vq/ZIPZs7jH160cRfwjBFKO9x4tDxCo/5 K8hWoHKAl8yNUc+dnXg8uMvG0kJOwk78cl1lg9n+pZbaoa9MrUPafXPNuEkVjaPo 16MYTQ1807AsEqqZtHOYxbd0Jgut080WAJIIIqemFOytUFBL49Xoa3hTy+y+ydr9 uVCtP71+ILE1MKKfCpnj/cujbHKe2+b5pePNW8l/G8JkaUrjBzzgQ== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8n8rc8-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B159KP892255; Fri, 11 Sep 2026 02:08:19 GMT Received: from smtprelay05.dal12v.mail.ibm.com ([172.16.1.7]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvtfbu79-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:19 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay05.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28I647733842 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:18 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7419A58056; Fri, 11 Sep 2026 02:08:18 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BD33D58052; Fri, 11 Sep 2026 02:08:17 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 1/9] scsi: ibmvfc: add basic FPIN support Date: Thu, 10 Sep 2026 19:08:07 -0700 Message-ID: <20260911020817.1033789-1-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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=6aa36294 cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=J0p3lhKYf7zTyTyceaYA:9 X-Proofpoint-GUID: _Uz8ZMfrW39PI8jNDEGqVUoMqC-qduoC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXyYkJefVl/XYH 6QKIKH4OaUx2fwbs0JOvzUY82f0uDtIwwG6dpdpJcGBuSqH02f1fmytxuNoKhsgHQOVoCeMYOf/ HyufinX6+1gnKtBHr7HY6Cgvc8WA+B6r+SRThmFXmidNgKeUaSWYLSCzKnXoBewyT6HWCsTuBSS OxXjbSHdk0ygws9DeGM43FdLD3I1VX/YxWLFJY7cQ0xtotoHj3qLY/nngrbfK3nJvgVdAU+xjmK CrkoqbRxAz3LXWZFEmTfHTrWLu9bL1xS1HavR/nMT7yNf6YIMwujztYOWAOhNDqlPZIb3Qn0+A2 r8BkQPAu/u5YOXsokDJruEtB7lK09LXZEVjHP8V+6DXZ0o4H0Umu5ul2cshXUl5QLZTjEX9ryFR 73GSbIipObzrVCEHtgLIn3yf8SmXoiv5EJ8sVP4HehN45nZigFREYyYdVcAszpqX7D3jzD7rgK0 22TydG2tP9GPfOHfV2g== X-Proofpoint-ORIG-GUID: _Uz8ZMfrW39PI8jNDEGqVUoMqC-qduoC X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX0eANtn5yNWQZ p+evxfADKJ7k8RIS2CkwpTOczrvBD5VDZzVmUnoXAY5mEMd6j9Yh9hMjHwluyXx3copcSEve0wB aQhgiCgYl2xpEExyu60NSHmzI1ON3Ok= 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 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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 5861433B970; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=VdfpaQafbyycDnQvcsFtI54K0fSBYUxPZ1IkSluieoZV4cxygRL+SNxicqqFjRkNTtajBeNrXyPoOB4Cu7M2IGe5O11gB66CE+4W6CcoezH5TuFW19lYw4XmMBfBTNInfI8emfrTirHkigI2mgWokPxfg1CX2kEpOOdCuv+kolo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=0IKwgt1kISyw2ioB/vEVY5A6eKR1dPneSO7lDk/tGYQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=S3QO6LZ4MNHLxDdQD+ADrR2oVGOyoT36ZWTNUhTlk1BtZPCDAwmfuVLCeaSEnlajmmx8EIWEYWXQ3BYzEVuMHoFrpxlWedPpHF6FSZrQgImM00K9qfqcR177TKVbtGUM9461TGHFJQ1XPW8y/4leEJYKZydMqQ0NuK0yNSRLmIQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=m0ZGmRwk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="m0ZGmRwk" Received: by smtp.kernel.org (Postfix) with ESMTPS id DD4CFC2BCB9; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=0IKwgt1kISyw2ioB/vEVY5A6eKR1dPneSO7lDk/tGYQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=m0ZGmRwkDlkPfHoExsJ+sy87HQYou6142mbbIsmg0v8NbApPls2TDVOQ1icNl0GxF DdFa9s6u4At5JWXxH/F/pQE4lA00cu4TBtW1ePZ9tNRyK0+eHlURVD0VZEQ3Z9gVq5 TK7/BukLmhNpfyDjdGpvo9Uzg14XZYbXpClxR9gz5QOPqdhsGZMNU1MVjoFqD1paV5 CjiUQw9m4xzqD4pjXBnmDz0kXrbs/gkh/JmvsQBqigEznQXccauBvEhuSc0g7WYRa/ QPcSLsWkQokPkzZVyU6Tg4HF3WMc14PQ8EwjsZFpiRHqPX5Fn3nK4GuV3g+22QtsiF xIT9GdbIoFMsA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id BB19DC79FB6; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:07:56 -0500 Subject: [PATCH v8 1/9] scsi: ibmvfc: add basic FPIN support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-1-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=34098; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=mG5mGboOx4GaF11aWs5hjjwijmRJDy4cXn09+r6D5dg=; b=WUiy0jxm8lgCcdIQh+smUCfYemkqGZcKvI+foE6wGuI2/06PQnRUxBAVarMx4au5hj7i15LiY xoY9qxVTKijCCPi18k6jXEo91AtRaDlkwuJXMlC1U1iCGgPXDSPnrQg X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 --- drivers/scsi/Kconfig | 10 + drivers/scsi/ibmvscsi/Makefile | 1 + drivers/scsi/ibmvscsi/ibmvfc-core.c | 297 ++++++++++++++++++++++++- drivers/scsi/ibmvscsi/ibmvfc.h | 17 ++ drivers/scsi/ibmvscsi/ibmvfc_kunit.c | 408 +++++++++++++++++++++++++++++++= ++++ 5 files changed, 728 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4a2af0f702e1..352abe10da58 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -759,6 +759,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 b3bc3ce872d6..0dde8dcf43de 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) + 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,23 @@ 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: + 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 @@ -6874,9 +7134,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 @@ -6922,6 +7188,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: @@ -6952,8 +7221,6 @@ 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); - fc_remove_host(vhost->host); - scsi_remove_host(vhost->host); =20 spin_lock_irqsave(vhost->host->host_lock, flags); ibmvfc_purge_requests(vhost, DID_ERROR); @@ -6962,6 +7229,10 @@ static void ibmvfc_remove(struct vio_dev *vdev) ibmvfc_complete_purge(&purge); ibmvfc_release_sub_crqs(vhost); ibmvfc_release_crq_queue(vhost); + destroy_workqueue(vhost->fpin_workq); + vhost->fpin_workq =3D NULL; + fc_remove_host(vhost->host); + scsi_remove_host(vhost->host); =20 ibmvfc_free_mem(vhost); spin_lock(&ibmvfc_driver_lock); @@ -7114,5 +7385,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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 94F013B0587; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=Cew4kawB+TEL6e63zMIG59rI9kNembVUAHJweJReMDnJd3Y9YhrIzBj4HzuT5Zbtw1LhnQxNZq9EmTuiW3GOfyspQYGG53o3gmlCUmssIkthjXJan0ZeT8P0ebKvJFFgC19OhPjJU3YqFrBESoAiqmZWSO7LeizmJCEuN5mRY84= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=zm1X29U/vKcllzl32RPS7yA8qi0SPokOMP9lYNJdA1Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RciZ13xDo+5jZfK4QEsD80ylzMRfUsEQQua9Xzzz6kkiIUrbux9HUwiMbMlK0QiEAP3NKEbhmvZfjFLgHnRdbOPbW2oN3ff6Ir2GTqYutWmX83FHCzXh4eYV7coIeeGYfYJHwmskRDwcMS6gIAeCd5GIguVZy40+gINlIVejT9k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RfjRIknE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RfjRIknE" Received: by smtp.kernel.org (Postfix) with ESMTPS id EE2D8C4AF09; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=zm1X29U/vKcllzl32RPS7yA8qi0SPokOMP9lYNJdA1Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=RfjRIknE78IFiqPyGIxK88t+XCKf3X7KBLODQCk0PEZcClJMwMVDvro74g/BMVxid wYT8RumGVTsuaTPUcsMqZXjc/VdT8Yt9hzY5X/JHMY8dyT+aa8obl3XRrmN70erLaS PYrvRBpQF/BR+aWmqFQfuy90wmV2mffMi5RxaRQkuYTpuxEmXL7Hk0KGei2jcE1JMT 4OZdrG+rNPZjxjLdVD4esDIt704FwN4+8WYpy8fMnqKhEj4eV2qQ+Pk3jdxZpCIYzJ EnskaHyQHJukTwFBt5AsK2DlUh7Ay3aOUBQFQz5rhtDwT5X8af7vXjs550U/3CuU5N mOP86ImXjbUEw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCA47C79FB7; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:07:57 -0500 Subject: [PATCH v8 2/9] scsi: ibmvfc: add NOOP command support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-2-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=2910; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=/6eLsH9Lr0XeUeY8Iw7EQ5VPLah0UpDEqJG+hBif1nY=; b=gmGftYvv+WImx24YrY7QsSxYhaKlXOF6CJcLvxPIGAadLcgumas5X9exJOR73MKco3UPa9l6Q WYQGPck9TdaAH0oIOVm68F8jjwaSB/9drKRwVCveCXAKYc9HRKpfofQ X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 0dde8dcf43de..c985eb3400a7 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); @@ -3693,6 +3695,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 @@ -4223,7 +4233,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 18:24:27 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 5A8323C3C06; Fri, 11 Sep 2026 02:08: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=1789092508; cv=none; b=Ci9BZFHLYO3c0Au0+oK2O2oJUshReWYIAYTzUjI+a40Wa+Ewxoq+yFsLQXRJB7X4dwF6nNMtS8I3+W23aAq2Zzt4o6ZqBG1ssso0BkebP/gnAIjYLnJvNwfYDenh2SdOoxWtEtyO0JM5UG+0cYdGJktc9VSF1/PM/n6G6f7SGOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092508; c=relaxed/simple; bh=9qD3huhzPJ6kQpb04F2WEeP5N1J95nYBIWAjm6IYUGE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eTHk0v68CYe3pBs4PwA9GMVM/zIskYivvwShYGCn0vbPRaVcXccIE78z9oQ5xdyGky3wTGw9a1VmdKAO9I3dLruC2b8S/Ipyqe9gPTnOWbE/ik8Wv/1mVxm9YcBL+Ddi0/vc1T/KaPJuexQr6SjQem7SnEPf9x6LGraBbqxbGdY= 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=jADBRVpW; 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="jADBRVpW" 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 68B12Nwa3366925; Fri, 11 Sep 2026 02:08: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=hB/jsEmW11ikjkO8k 0FYDltf+WJSh6vxZDEuJtTTnCI=; b=jADBRVpWAQAiJC1rTaYxTceFG0MskgC63 U1gEHeYpjWCNatCZHgGxSl97WrosQLPGluLnqx00rhtI80bu4Tc38h5PvWhDjyee Xr+7AwPdKPo9T72DCsOL3cosAKiAn33FVrxaX6vMHNhlAoGYTf+OHCoip6nZoyLf BvCiWSzzMjycBcZIZ0jSPtQyGF8oG7OafLsUFHEecEN1U0EpbNMf8KB4lawoveDF jiRNkvJnxUIx/LSoClmhksLWyoZbr0ujfdkKaU03SMaXtm31nMuFN/lLJv85F4fK 0wOvIjsZC7pNAeMRFd2qiAk0vXukp1AfIlWR6bao23l7RsXAfF5og== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4gkd8q8puu-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.11/8.18.1.11) with ESMTP id 68B152NZ892168; Fri, 11 Sep 2026 02:08:20 GMT Received: from smtprelay03.dal12v.mail.ibm.com ([172.16.1.5]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvtfbu7b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay03.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28JA530999148 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:19 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3A8E75805A; Fri, 11 Sep 2026 02:08:19 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 91FA15805E; Fri, 11 Sep 2026 02:08:18 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 2/9] scsi: ibmvfc: add NOOP command support Date: Thu, 10 Sep 2026 19:08:08 -0700 Message-ID: <20260911020817.1033789-2-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: kWEKGaODSiopfrF8Rnlop1f3FMrec0v6 X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX0WUElv4LdYJk RpUPcJb0xMBZfJwVV8zaJzHCe1Oql+fcXWkbt9p075zQlubn8COHs3De5OjrFuXl8JIFu2eEkQ8 MLkq+qRtEk3bfifzdTJbnwUMGnTJ2ac= X-Authority-Analysis: v=2.4 cv=E/dYNqdl c=1 sm=1 tr=0 ts=6aa36294 cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=dMUBAgKGejxRm0SXrm0A:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXzAA7Bq0EeXuK 2zaI0FLwlDucSZNgXzStI2ApNpq8olEFWnLYMyFABCvDD+hw/NFLoK6IXz+KLr8CLW9rg5HF2LO wLx6pVQX0IZlmSms690PU/OFinwFp5qEoUX5VbwyOBYAPJOnKd88lghtzzA/R+0AUMIn3Ms5Bkd INnBkQs8pCI8RgL9QIURb183kTSCyM97r11dVCNNVb42ekwRZK1kmm0r7DZHJjCf4BvezTGpdxA 9c6d+nw0kFEmT7DhgYiepgIFT///ukgynrZ0tjhjmQro+eWaT3wiKjC6OCs9iq816m1EIpF/DIq Hel8/CBKiK09ZqDtCxAqQVI/YnKnKkZq7rD1SpKrglsEJZLq5VbuQiCokuw1ljH52gMTF7LXIxM 8ME+NJ0sQujrO9TeZVrkByJ6BzkrnegibiZBIY7Lf0p9wHFccMJWFG8wHP0le1r/u636tZJkIps 9nR/kobbmpXG0sCwlUA== X-Proofpoint-GUID: kWEKGaODSiopfrF8Rnlop1f3FMrec0v6 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 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 18:24:27 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 27E4A3CE0A4; Fri, 11 Sep 2026 02:08:28 +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=1789092510; cv=none; b=gJelLMCcR4IPu+f8L7FEq083BO8lU/Sc5FPuD5ipr9aoDTOsgFsZHnNLkMXc6vC8STygSkOexGGF6DT6N77/VYJ3MPxYUaLVYkYsYINpuYEwgfurJAslpXY5GIr2NCC93rxDW+ESl1/C5jJkFebsR9F0f6YVc5NLq2B/upQjGdA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092510; c=relaxed/simple; bh=Yy0OU3dKq8cR/JdYCoiXYE3T/GnzwysU3idedb1DPV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n2vUmVBarOIErH31arz9Az464vz52yVGU3kXPd9BINYioot3C1kHimUAo5PY8REbhk034pvxEP4PlPNlQ46v1GbtAe0512PLgKbN7CU+zwR8LsvN5BWLnQkX6tZujmzZdeY4j8R3SJk/o4+88tyHLBF9y96wx0JGb7orTjnmrGU= 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=fDbosF1t; 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="fDbosF1t" 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 68B12Q3U348209; Fri, 11 Sep 2026 02:08: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=bVsy6e7RIWsa4inSY VWZiBsIlesxYTQaoaS4XZ8tKXk=; b=fDbosF1tPg9d+nBN5tD16l6aFDBGod/iq NmuS1+g1DVQG2RgKk+TlQf7kKQT3XkOURvnEx/U1++DujX3X8U4TKHuwIgBFDLk/ LZkO58mKLUPn+d7PFYj771G97Y1eBY5JndZxGqu0XhHwpdAYcEyZJV/E6DO3ieDM w7/FCl9t3QJgvctDb3S7Ff+puJn0tBqdIonYCpa4EZx9zk3XwQvvoO/lz9gs6NCK fuRfLWwmnf3cUI+ARbLwBcwA9LW33H4IneUCrNTijbBjKwg5qVrd1LWzL89S15yD BiXhtdj00axNeusNj0laGTTTqqqIp0nfgBXXBXRWBfGFuVLxK38iw== 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 4gkd8t0p5k-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:22 +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 68B154OC919386; Fri, 11 Sep 2026 02:08:21 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvmhkvf2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:21 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay03.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B27cxk28050100 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:07:38 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0CDAA58052; Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 58A7958063; Fri, 11 Sep 2026 02:08:19 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 3/9] scsi: ibmvfc: add FPIN extended flag and async sub-CRQ queue handle Date: Thu, 10 Sep 2026 19:08:09 -0700 Message-ID: <20260911020817.1033789-3-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX7M3gp2qud/N+ gx9GaBDIF5ljDTbiEClk90n0k6lCvF5QxtO0YH7CKqCNpRGc0+mYQH8Ehja6AtgcPkfZ8OGYINR /tbzgAizXhoynbIS5gLVAaw/Izoa95M= X-Proofpoint-ORIG-GUID: l6iYNfgYEL254GTn9esFTMyWulottP_W X-Proofpoint-GUID: l6iYNfgYEL254GTn9esFTMyWulottP_W X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXyPmDRXSTjcha uiIh4kVsapqOA5BtuJeWBcd2aH/z1hT9hc8IKDmgt0bKYdAFlt9yNF+MFrxBlsegWqV3DR7uLe9 /JvbQta4yxP/CCZrRxl0B+g/whjiXEyQPcDI86ylh0I6pYA5HNCPX1AtQEnHz0V/m2e4R2BlJcV Cwixszdx0WSWbbrP2z1MlZQyss6vP6BSf4Wyvf/Bq3IXfO7/gvsQqXqJwll+iGIqMJHDLeLPTLm RIlJXju16a6b6lXXIwXRusmUjjoRrBQLDmYF2S6inP/TjEKXY7FPJpNUT4qPAlNot6Yiqam+dZh K7I8YvN5MhjtuLKyizmeyjiyNYPXM1s7Ig4nTv7AdED0/USApXEalKCw/8rpqAVkH+isebYalCq wPxaEjl0aPmKI0EqcRJUEV+gMpezdyflTKZGFiEJ8szda8Kq/RU0FpH6hwnyTbKCtRY7sLn3EKS 9UgZJB9IUnnd0TWbu/Q== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa36296 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=dC3NDtCKD2fC6gceAXcA: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 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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 655E1368263; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=I4Fijrn5UjYy1O21XKdRLAC7dmaJesPGUGnfagOGvEUgSXiUmL8pZfoZ43xSf+A4RaUAwRKyFt6WFvINPkUnr2wgQ7/2pa9T4SgBuMkF68KacmREMxSCv+gu5vpQRw5DttmDWKG/PoCFHEzdigpKpFJoKozhZ5+2eqFdQcIpimE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=mFnlH7/qPv+L0T9B45mohz9x62pSXgPbs74b2lQ0Hdk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LoNaGgpUuTxCwnQ8MIIO+iurHNM/bsA2PGqDZ+rBShlbMFJdTKgbTOk7T3uA4ZiS+o0qEuLer/P79aLj9tL3FXu0d/el9N302yTK0Z4eekErZY+UAtFh6EzbC5C0sUB5LTwZ4k7OP3oFppFyh7iiE5MisvQkjSZumTYh17pvUAc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UpDkrlqa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UpDkrlqa" Received: by smtp.kernel.org (Postfix) with ESMTPS id 102F6C2BCFB; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=mFnlH7/qPv+L0T9B45mohz9x62pSXgPbs74b2lQ0Hdk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=UpDkrlqaOjTxG1bQxA+syvZdV6zcAJP62pfqIqdHcFG+KjNVARy2+Af74NHuUQqgQ tFsi+IhP9jgKUu0bxIXHut983VefNf4UCCCn+8KT34REA5n/ir3PzGIgGjK/AhI9ei g7e4LLn3QlAHcaujhJQdadSQyCRdZ3XG/L0vw4HckDN9PrE7uPud/v3gXjeOVp0z2/ z4F/YSInFX7rQFqAOa1hnyvxi0Y5b+hnfrPsHQDBo0jSQeMcpvm+jd9gI/jp4DHVW9 i1zAnAq/d6+P2anMRyziIjKLMbyDyfH4X5G2DxE8uaw+FuByW0mtvPPouoHtE43KaT xH91iYoNw18ug== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE385C88E40; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:07:58 -0500 Subject: [PATCH v8 3/9] scsi: ibmvfc: add FPIN extended flag and async sub-CRQ queue handle Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-3-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=1156; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=6+Vf0PoqfDYiBtRPDVPvMbpbtiabmKU9+0zi74lACkM=; b=wZL86Y4MW/fnRBDZlJyyY4UdT/X/nD6f0brUZLcFM2YlQr6XJnLQNQVuKYivvf1QE5AebfEUH SKBLxmoBjV3DW7Hp3o3bXIKCGBaLPQGbV/mBveo1wfVKoZtuKgpGJJe X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 18:24:27 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 21B973CB567; Fri, 11 Sep 2026 02:08:31 +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=1789092518; cv=none; b=RxGHnR/1BD0fqDUgXLyopJsk+jhQIpR3v3emh2lIuwQSLSh5nIBBAEgPWeAdRKrciUEwzGDw1Ou59oRQpBJ36SLbbhQnJl+0ozUqtU2iGVVC7OgEpUjHTQao3fjn5s/ZFLquALw6TqqlZNizyMM//b0ZlnlIkvlU4F120hQ+Kow= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092518; c=relaxed/simple; bh=ahRHlM3DTKx8h4H/ECpW9lKJd2sr/sQxGlo1M8lVhvk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uDRadUfAurkqE5Tx0QDajUg01/WU5ZPz7g5vs6ksBe2NhMANcGOhheLpBBi9835pD4gLW8yLvhHwPfuW78ptx8AixPC6KE5EASoCDuiRZFiUOVXcGsTZtx9fzw+DhZ3VLVgxSxYsdhUSKNwcrXOk72Rys2U/781Noknp0kAJCxU= 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=n/NNtnCY; 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="n/NNtnCY" 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 68B12Nge348198; Fri, 11 Sep 2026 02:08: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=QgVNL82TfKgV9OoNi ZgUlYNgTH8HJrVrAm0w/XuFu38=; b=n/NNtnCYekzZ4WRQyyQCljxGaNqxKUa40 BY85ZbjV6RlKP8l991xpw00OoXHUcVHhw9kkyPiO1yU1QbidhiQ8BLPVVgMgh5Ao DK4lfSThAuGDtsNUsAJKTNDTiYhkhimTZUGol1cl+7gzyWCiZg9gtkAO/HDVFk+b upw2IG/fB0+aFy7sZpvARBbv/MhQLopm/l2LUoI+M89cOA4C1y+0GlbxxQP60Pds ljwpdmrEsjN90zLfxcTjdQs6H2vqSF4pQOqAzhgwQvq+5LTR5g+zXaNVHKwze3j5 vA2N0vM/IhLDCojB3pvPJnOU1wI5kav1VXdMtsuNC2LjBGATtQRfA== 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 4gkd8t0p5m-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:22 +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 68B152Bq855014; Fri, 11 Sep 2026 02:08:22 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvvrbsgv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:22 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay03.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B27c6R28050102 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:07:39 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CB0F25805E; Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2CBF658056; Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 4/9] scsi: ibmvfc: extend async event handlers for async sub-CRQ events Date: Thu, 10 Sep 2026 19:08:10 -0700 Message-ID: <20260911020817.1033789-4-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX8GUGeWrGmq0g /yHvv5F1wdF3Spz1HIiTnrNXtJ40NZUQ2DG8gbhPOnjtuMzXcvbrRIrHt50DpDPTUhJ8JKdJLNM ZAwQ9EGio0ucEoeO/bYqg8s4QlmT5jY= X-Proofpoint-ORIG-GUID: 95AGnYDomKrOlBf5lw3q3FlWi2aOEA5q X-Proofpoint-GUID: 95AGnYDomKrOlBf5lw3q3FlWi2aOEA5q X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX8aBQYNoZa9az DJAL61KPG39L3ghuv/xBwmOZeJdFyOtWllUsjHAu4gVpUbYwRBX5gq+HmSlnBqCCy8ZJAmbLv6b W/KeV/XUhZWO6jG5ghvcOvpRfsu/PY8TMZW6IfZG4OaLNCCJb87Y6TYevgv6R7cucFCwj55r8Za NJ+aCWHzCAEkxfrHFP1MgnTDk0GKEApj6gWmbS++S69hYcyjxXRgxuuY6ZXzv5rNOdcB8NIoAIu TPyFHIpZaE1tjLMMPW/sqIBVL6K0eLsGEOplSqZxiaOishRWhFANFP6CgvaU17r+QncFl59j9Ev pxoaZ2WEllHcBhANHsg/fY+amklBN7B8Wg7avbHwrm4/WgBG6+kBHOFT5e0Hf5ZW9gl7GIkPMTO GHv/3HZw2w6cy7EuHl0D0RNpoANJ2mp2fXEPTyEFzo2ly5LMn6TFOfF41DmEOqUDSvpvuhYatel PU7rj6qnWjPe6VejZtQ== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa36296 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=ATO0ceFIgLGo4LxwFAgA: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 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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 7CDD23AE1A3; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=KSB2d4v/SSnKkVRG8dP8zFF96E85bja8J04zSM56c0ecEkAM7MFNqjk77IyafsrfeY3Nm7uMDgQIdQL7uwtN7WZyzoPBlR3SqitjeLCte+rADqGagznQOv43oY5GzKsHYPVfzaolYtV4CPdZZoO33brXMRuBniKav36jLV+KLbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=KYjQcqiQCD+Ck/7QyH49x0/ee2OXN5zZTuQqBPGT21E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KPWQ3bfhrdmQLDnUbFn4T4kYHdVC0kMe/xLf8wzHs4sM7xHQI8UAGvcTW4CgdY/f5KzcA20vTJjGKzz9u3saEExBd5l6JFcK9zLmB+v1DD+eVbi7YbVyYmMClP6CFROheZD7s+0XNrR77oFswXoItzd5lgLVt2CHiaqJFHW3gQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cwLDUTpF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cwLDUTpF" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1B7BEC2BCFF; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=KYjQcqiQCD+Ck/7QyH49x0/ee2OXN5zZTuQqBPGT21E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=cwLDUTpFQcx4kgySEgdOUypyMfT+Zg2p1Hg/3pWIKQo+9FhuxFbzCgtBBZPWpmVbY U4QpYa+iTalwbh9McIiBv4rhvkibO2Qee/8004IivYfDmApKBG8ms+DTCD2pYvwj3s 1vNq6o82avXjQag2tOuvwfH7NjrUNRLWLnLchgEkO9eZ/Yepd6GVJM1T/FaVqLPOMh qT7FdefRI01HqsfrlSvf/uYIpIxDKcYBqGq0FmKsrp7EtvQOlJ/8budpYf5E8ynNnq fiIXjafoaD0vaaVGv7VXWkK+h3lISZey/Diw0xoue557pCEkDivqqZfOKnsb2M2CfB 5OKRgxcUVJqAA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0B19C79FBD; Wed, 9 Sep 2026 19:07:59 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:07:59 -0500 Subject: [PATCH v8 4/9] scsi: ibmvfc: extend async event handlers for async sub-CRQ events Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-4-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=17890; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=7eFJ87zkPibvJhk7qxtmxB11SLEertGMnL5YoeifeQ4=; b=23OHdLTCzLTT2J1VOUDoyF3v3bksk264VEAmjLBXAkqr/wafYUwpOu/GoHmedGB7jhYf7b4yT AZrjR2OjtLcDDO3XeuF4zcfapJUJZNM2rsssLqCo+9byDbBYjPZ+OFb X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 c985eb3400a7..1126c86d08fa 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); } @@ -3616,14 +3696,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; } } @@ -4164,7 +4244,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(); } @@ -4178,8 +4262,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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 656D739B97E; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=KaCs8XTQ4b/MuijdO7xsiDkXwIdw/uVRdVSVzHB8FXDrtwCMwRT78FYbC2m0n89CJQNvmUZKNAXH2vAjdzvN69r6fUx+VNkZQyiTvJmYIy0JW1CHMMxYjAOHUREwe+52rQ0GYPQsiX6dNwj3GzsWERg1I0NI7/nHJucUplfpt6o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=jcozd/dmw2hLGVzJVKwdhFg6OBg9XjpiexgWscaE9Ps=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cDgNdmF14qhUjSOq+0vpNTm8k2XLNHnYSn76Dn/aQyj/BzCyZmvWI3fXqjhXst8cP6WY7Ypi+14dMzKQ5ggL85Xp6i2rrRCB5sirH0c/UTk9XP1fr9KUrZqyb4c3an5fbTPQM/IVNwncvhkuBuJtEJgHPnllvEwIXvcAkddHdVE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I8ClQwt2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I8ClQwt2" Received: by smtp.kernel.org (Postfix) with ESMTPS id 24D63C2BCFD; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=jcozd/dmw2hLGVzJVKwdhFg6OBg9XjpiexgWscaE9Ps=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=I8ClQwt2vM7fHGDE5lC/y3z0aq5qwDJJ8txxK2JzT3O666ihur7LF2l84h6VeveDU DdqpLiddcW8rM9lIo/j9IGelb4Dxy8d0wNppYQteCy2S3KZySvPGv4sRzS5gSTepn2 svRP8XOFrbXgbEG+V5DiGSjELxm4a7EB9mdQesw0dyhbGJ1JAvqcVb0IGkVHfDZSGL Apr21md7iXnoRNljLFZVNxY1LmjVU2IylWsd6BYBXFihS9Nkg+NpT4tCIn5qN0JU9h 0xrDL2nQtFs53YcXZjbEzZHq6Eqn0xUS9N2JMClSQAKCEfjhu6grqmgHCELTyF8N0Q NT8IMa/mImuUQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0FA78C79FB9; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:08:00 -0500 Subject: [PATCH v8 5/9] scsi: ibmvfc: add interrupt routine for asynchronous sub CRQ Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-5-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=2943; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=tSZBA1TX2Ay4N3YekCkCjDMBwV4xcAORZV0DygkdGcI=; b=Eq65XXdRIHq7Hjn65JC4ZKyU50Mw/8wmOh0U044GQ8bqMgcamBbbRGk1lK/89nAMSjZHLefTB uKA35m8tmvqBqmzvSRhqfOK3vkZkElH/Uz6PWANXsIbflcj5dNmvjA/ X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 1126c86d08fa..2e5f4c4c55e2 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -4374,6 +4374,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 18:24:27 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 1CF3F3C2BAF; Fri, 11 Sep 2026 02:08:35 +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=1789092517; cv=none; b=OaYDemY5CR2xID13iguhs48Zjx9/+NK6OrU8+SYZiyO7RQ5P9YtMsb0GdXaoHRX2L/Xu/Ph8VNQt1rOX9UXAArMalf4X6ApWT0o+dxLfVvTiMigLhEcHjJan3PbwkFM71R68gQ9dS1gHA/EsHER/tJre+LoNnUCB+g50Siy7o/Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092517; c=relaxed/simple; bh=hSyVSW0UdAzjZ8y21iz9muNELtSLn6sQ5L6QbUFHhBs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WQOOaKuXn/81r2ZfygI5Wq6vXrBqXCHO1OS+Ka3GhVaQcKAiX6+UG45rSor/CBZgUCViZUUQQcKhov5YepiAMwFgsWAOqk5aVLyPOO7bQxYvQooiHc6d1Mry4a9slpxQyVizQeDR9Jjg05Wtc3Z1fTZxaAmIxaL3tbrMvk7qBvE= 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=h6zP2SjY; 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="h6zP2SjY" 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 68B12N07348191; Fri, 11 Sep 2026 02:08:24 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=h6zP2SjYh6AYZXG8z1aC6fEJSo0PPW7bQ +nwj4iyWvBOR0Uxmj54rdMMk553NyP393iFVT6KWibU62G5prpC4b2wYOmoo5C04 ZV26Hnk0z6eQzUB7e1XG8DyvYsV402NGfJHtWsrNJboN2wmKSS8qGmpm8Nt5oq0G 9EF5YN2aVweYD7TifNFuS+ftFEvs/2GrXD6UMQzjoU1If9U+g7BDoHgOQCAUfCJZ XKN6ZfV8F+rD5BbA33kzojOhrdvvafYc0J6REL6gDf0UpK5OSxzIEDK0LAZxqGiA IWICUlkFbb1NrpX61v5fnoPynwd2Vv76AwqNkptkafzNbnWH6a+QA== 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 4gkd8t0p5n-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:24 +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 68B150Kf891377; Fri, 11 Sep 2026 02:08:23 GMT Received: from smtprelay04.wdc07v.mail.ibm.com ([172.16.1.71]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvq2uukj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay04.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28LoE32309846 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:21 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8AE4B58056; Fri, 11 Sep 2026 02:08:21 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E7DC658052; Fri, 11 Sep 2026 02:08:20 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 5/9] scsi: ibmvfc: add interrupt routine for asynchronous sub CRQ Date: Thu, 10 Sep 2026 19:08:11 -0700 Message-ID: <20260911020817.1033789-5-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX5n85MCS7Tx0W 2ZXbNSlTDKDqqDTTVCZJ+S3q/RNH+dLGz8rE+fl+PD+0jM0zyZfhl5TEIi/jma57tSTurPvcazo A4gO4pMmE77+M+i4q2C+vOr8NkJJlMk= X-Proofpoint-ORIG-GUID: Pqd9w9tTv2mao-F3KHS0wcnOn7hvLEQS X-Proofpoint-GUID: Pqd9w9tTv2mao-F3KHS0wcnOn7hvLEQS X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfXwu6VIYmSj4mr So7ww+Cv4gedkwKxSWqQab0VGYTj20/agKA8NP4nrHYe8Ce282zwEoLOFX88+86lLy6s+zMZ8Gw X6G5PBjlobwZYHJ0NHbFGhpbLmjW7rWnVln7JUnLwdOMqZGBQPQ1xyMlNAcOClAq21K/6zdnSAV 5Xy+p/MefifWbf978Pe5A870aAyLXObkfooOtAbGN6Rb8HKgakJWHODRE2FsBtwSqF3oE3gE0a7 cOboKF6+Y02iZVt84l6r2EIdCEbPfQqY4w7XxqRAJCKfSAn8wPrRHsv+5Y/fiemzpTYv6eTM4ZL QqincR6I0/rR2OCs2W9RgTQxAHglH7KrMLxP8AUzQhENBxU1c3Amt188WzuCpjwGAo52J8m606L N0JsFny0OLHVEGBNW5wrBEgPSFU9L4RSCt4bXlwcCvZK/oTf9NDSQV2Hyf0CohdINmbDP8LI3UP LrJHYp7LLpp4pDZrhHA== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa36298 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=w-kvVH-zZ2E7PihfXZYA: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 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 18:24:27 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 1CFDA3C456F; Fri, 11 Sep 2026 02:08:35 +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=1789092517; cv=none; b=OuyS2rp6LKbkYAuDUHU1Uw3NogZgCaRz4SzDsN97C6pKphNC7eVZCltbcXcmxyxmLua4Ch3125zonXUATC/Rsh5bnl3izpgMZGvCPoF8kWTxbDnKCs1tC9WaOflCzb9IC2O6xbYOcqWOzyZFeqDJ+qH+FfXvWTQYkV+b2mr5ZP8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092517; c=relaxed/simple; bh=HYr54WWTa4EgA2aWe0yvMVMVVWLs+RV3f4cEEiT3ZEg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EDq+3f4ro/0P/+qFplKAB+AcUWLWBDeUWQjMwu3paZ7w7jGDkaa+L7PzPFbYYM3Gbod+npXi9mU92JCHhFzuA7tn1Gef2qmdNJ1V7TifdigOAudQExGWtr91DS4l41zVUxPMTkeKddnp7QfQnWtgOZQGtwmPvMV44R5LR4G89y8= 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=GrvZisDh; 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="GrvZisDh" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 68B13SwI179785; Fri, 11 Sep 2026 02:08:24 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=GrvZisDhr5bVSbd1fSbCJl+Fq6vn/t8AM lH1366k70zpSMCXNmN9RFRn78+gRmlu7L8IIYPRdsHt3MhL6SGr23riIWz43D+nS uTsUDzoUSbRrxp1m49KbkB3s8k6QfhiLe8c4C4kiFQv9hUNFeLjm+tBhBbxamQ0y cWhZ52m1JhjGybLCxGPCCCNN6PhFYZ/0Q7H0A79BvlqEZZ24ZyosDaCi1csyh17x to54FggoKpaHRO87J8b82KvW96/aU2wMPdiJkcGpR9HACwGsUT5BisSFVnHkUF6k BiiMKKV/F3WEuXX6pK66nGxBi464I85nGFW27X49MPiHydG6nFT9Q== 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 4gkd8s8nsu-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:24 +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 68B155KR855203; Fri, 11 Sep 2026 02:08:23 GMT Received: from smtprelay05.wdc07v.mail.ibm.com ([172.16.1.72]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvvrbsgy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay05.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28M5v25231914 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:22 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4E4BC58063; Fri, 11 Sep 2026 02:08:22 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A79FB58052; Fri, 11 Sep 2026 02:08:21 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08: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 6/9] scsi: ibmvfc: extend channel reg/dereg helpers for async sub-CRQ Date: Thu, 10 Sep 2026 19:08:12 -0700 Message-ID: <20260911020817.1033789-6-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: P11WDrrFea3CBXyPM80IUXnn8uVXvuc2 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX7o647i/rNrRG NKJMHRsuCX4EHOxWbmGJTB39qsEOX9QU7Qkt19hmfM4tJRk2XbfOCpMeie8VXPd/84JGSWk25z4 Jmllq/VMUEx9B8G8ro/mblVmkSTF9CEvu+RE+3I05uehUWndP2IKWByjK59KV1TrYxsZbicjeEj gjnAfdDOecaRO/UnPj7OqoL7A9NdJ4flxv3FyPPW1dX7D+BwbfLob4/gj+ZzgRU6T9EsatnlJ8A Gmoz1LTH/nSRFp4fK2/47s6PaTK3rvLg5OcVVqL7qTPGlL6PfDk1qM9TmLaOXKYhmaW9ekAL/Rq zg/LgNk20ti/DBiLy09LL+BLKoqqAwxvjGwur+bg8e1oqR0FQqP0B3imYbZn3+jHpkxtrJ26Qhm dQ0tN4Rpx3z/9YwQAE7cLFCK37fOkla9V+ZOszX9avHbaxMZFJ/p/4/yGoI4Hbo4tZFiv7ZnsGJ oU0Tt0/krp+R+98YaYw== X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX120vfUIEYVJd USPaoHfFU6NbJWtFHeF8wHyq0T/stlsVQfSamTwrlpLQoUdsuXaCpUSG6beUjAnSKTRnIPFbZAi Gf2DHyNkNrR5jGRaP85Pp/+wIDb7NlA= X-Authority-Analysis: v=2.4 cv=MpXHeGae c=1 sm=1 tr=0 ts=6aa36298 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=tu7rfeQ3xgwDIMifKtoA:9 X-Proofpoint-GUID: P11WDrrFea3CBXyPM80IUXnn8uVXvuc2 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 suspectscore=0 priorityscore=1501 clxscore=1015 impostorscore=0 adultscore=0 spamscore=0 lowpriorityscore=0 bulkscore=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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 95ECE3B05BD; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=XoTQQsqUaCOXV4gcAxWOhf3cU20+bYp66YPEZ46leH+UMUcr2WD9LvT9Rcrq44sRPRjvTTYvVI53YBDZ0icoQZSBMvA4tn1MaNdvbz8MgFX6mkQxswjOT4BVrWGv208GKxJOUg4UilfuVdAX6n5c1bucz0GOLLGSrxeARYicrP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=AWw3K6sjRvRkZJbz1oUCRvfpf+qyaEBlIZslgrmfYa4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=olyWIwcxue2cf5+03hsLARRprHFD+4mWPkV0tqGGAyOseHejt+aWAn05/VRk/PAbe3/5TX1Nkt/P1LO/cVqtxzSKzyQUQ5Sf25ZQJnc411ZXfLEH3Md9dAFlNQ9WCqlWPijd8lV7OGyyoV3sSNI5aAwG8WZf9UViZtVkf5IJJhw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=A0w80BKo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="A0w80BKo" Received: by smtp.kernel.org (Postfix) with ESMTPS id 4513CC2BD04; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=AWw3K6sjRvRkZJbz1oUCRvfpf+qyaEBlIZslgrmfYa4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=A0w80BKoEWKBhQ6SYt4zTByPvWAsdxE22LRQ1SrVSzhqsYfRdv0HK40FV3STLIQzP d2FnZRMcVkdOTDKyjJBMCLkw/HT7LPxcSa9pG7Yx3FE5942aHGPdkoYPdRNjQZOpEc eTuWkDbEVegjp6EAgqLzh74AOWJASMeYcKgvdH519uqnGM2qpy7jcNjCD5MiWTPVRD cSLZ0bt0QQbwt23d8eYjweh++DFV8FLPPgOkvyps36D8opWFi45MaZgdVCW/3hHlkk XfaOHDBfv98fbd47r0p6Us2w246gNrdsS7EhOe4bZNDOQ3aV/wDu/xYOassOpkVEYc 4Lww/9BkeQ7uw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 213ABC88E42; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:08:01 -0500 Subject: [PATCH v8 6/9] scsi: ibmvfc: extend channel reg/dereg helpers for async sub-CRQ Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-6-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=6716; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=4EjGhWprczcxjAPV5hsLUCQusZB4eMxBu/fLpWAUd7c=; b=ayTMmNji44X6EgOswxSTxkZjPJfzjRBTPNPr635O+yU29Q1RqK20mTcbdXN5/SKyakdL2eVlr IKWOYuQ3Su2DPwSSclvTtuZjr6LBdICPrDGSY/z/e7I6tLgpYrd7O5A X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 2e5f4c4c55e2..1c660edcf608 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -4418,7 +4418,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 @@ -6808,13 +6808,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; @@ -6834,36 +6850,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; @@ -6877,13 +6906,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; @@ -6897,8 +6939,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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 95E2B3B0599; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=A9L90vIG2cEvDohsdz+29w0CPXQe+5a9v08HTd6aUWbXHDTJjW865lrW9iWGenVNkZyQdDtzFTYOdYiZAHZYyDlF4wWqpe3EN5mH+3JlII1k29kQ2nfYUBlPlqzjh3AFri7j6wloRRaZAgdCVuyqvK+UwvW9ivtpoPR/3d+tjao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=XkBXrQmmKWZ+hf01Y8mXNBZ2JaNJ3dWvop4CqYBj65M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ir5maHxTXADs7xW2PEEfUJSdI8VEF+Gonwk6P1BnBQ9B8AbYiL4G+Hlrk6DUGOIIRBq2KigpaBus31ERseKfTUATyRctomQEDCzoQF7oKCqA/nouP/UQwCb/VFkIuZXGBwrgOWlIxOTfooHaM4Z6X9vL04FxlhOjiQB1MVfmzJo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ooCEZ8Ym; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ooCEZ8Ym" Received: by smtp.kernel.org (Postfix) with ESMTPS id 55131C2BD01; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=XkBXrQmmKWZ+hf01Y8mXNBZ2JaNJ3dWvop4CqYBj65M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=ooCEZ8Ym5Qao96wo4dkQoNKP5xdJZr0iOg5K4mnVOIuKuX/6Tw4LZ7LYHb1eNAZNr 2wBYZSdgUkTxA9v4Ev5JZ2GUj/kddRTnKpbcHonZn5gEW1lPtsimA+z5sqauX36Nw0 EInd/qB0VQH84fAl6oKpa5uLrwMbwYLjf7V4M/Gr7kp8T5q+FdVSUbTLvMkbs2b3hu OBO9ueoZcFDfDy2YBqQdY8T51Mv7hLZuxTMl7DmLKfoUt5Eo4dKxfIxde075XTgjZD oylgNEQoptrouTYadVZtw3oRntP8tYy2CqIz3L6Z9vmfuXrq8W9/O6927Khgb2vYNF 4iT4VQRZgtkcg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 33785C88E41; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:08:02 -0500 Subject: [PATCH v8 7/9] scsi: ibmvfc: fix IRQ leak and guard deregister on channel reg failure Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-7-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=1707; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=S7JoJv6nrDtzuAz4WAYCfne5ZRPe72ADWh4nieJY2a8=; b=9EKpDYXsAWuyIv5VClmdHCHj6iXDLtkM3OFohJa0odSJLkXvi8TC85rn2+NQ4uM+X/Coewesr DFIQNkDhKVyDB7dezOZNN7ASZMQYys04zY0EeMvwzD9v0uoG+Ewmwr8 X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 1c660edcf608..f88262ffad13 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -6888,6 +6888,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 @@ -6930,9 +6931,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 18:24:27 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 C2B8E24DFF9; Fri, 11 Sep 2026 02:08:34 +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=1789092517; cv=none; b=unc36M18EkD9sGKac9/WFJXM+FTfZ/6VCDJ6v9qRr2vzCZuciYjCDRXTikFGH2Of+tb6fMC5oWi+qSl8/k/x4YIKANM9Y7q6kG/xtPsGGbYqnXVPz9cRlN0Sdgs/VnaeZFZGDaulgmqDB4TvwNCl5CbgLWs7sFaeo0lkvDixh4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092517; c=relaxed/simple; bh=AYtr4P1+OoFMuKpi0e4Fpa//4fIG28Wi9w5zooY5Kqs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SED9nSmgzBiLNJW4VlAgaoN+m95gs+fWajGMW222+c3oBvF8tCKFC6aDuMOpiIPK68yuKTeRCUp/bMOZmmMhzggfCbO4zSMG9Aw910iam2zsAWpbL95a7dtWIWoEtSnZ2hFPn1jIoaOjAxx7+MLs8lk01MMIawyw3oF1bFQb/yY= 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=EQLzXjJr; 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="EQLzXjJr" 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 68B12Qik311303; Fri, 11 Sep 2026 02:08: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=S0CHDiBfIIn8Lz/9u l9S7S1oBS76OTnFD8iyF+QdJDU=; b=EQLzXjJraAQeeih3L+xaOoHjlfpKuRsBu XMeyImxEQjvwWSdXhxflG4sz+5jx5sveD2LhL7/VO5iW79LA8hWoOJ/9Pwk0glMy w7dYcQw8s0ZvfU2CVEXkbMUoqZ+SssmTqmQmlSV6dWb/2ooPqAx0YSHX0TsqmHa3 J80Bjek8Dv5PAxCbIJA0z9OIFB6S0Iqayy8BSaLPf5o3BGQXE+I7/qQfMy4HVOZ3 Fp0orLmZmjRITEQj0WcapbLoZmyKiMqlsU3usadVtxuYMt4yvrAxnsOZYwSJnrJR Solqqup19ZlxE48EsEznOuL9MHcP+WpK8spbUCdrLg9RZIF3Me+gg== 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 4gkd8prsbm-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:25 +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 68B152SD855015; Fri, 11 Sep 2026 02:08:24 GMT Received: from smtprelay06.wdc07v.mail.ibm.com ([172.16.1.73]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvvrbsh0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:24 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay06.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28NZl11665994 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:23 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1307E58052; Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6A40958064; Fri, 11 Sep 2026 02:08:22 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08:22 +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:08:13 -0700 Message-ID: <20260911020817.1033789-7-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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=6aa36299 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=acainBHvso6FeXtkDgYA:9 X-Proofpoint-ORIG-GUID: 87nYsn-AaV4speGzRed953VrIEXilVqW X-Proofpoint-GUID: 87nYsn-AaV4speGzRed953VrIEXilVqW X-Proofpoint-Spam-Info: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX22NoQWZGJv/6 EF6OqO4WkGWznpp+uHz5JcWk7q/mSaQHssydw/W54blCT5SiRXLO6fSjTzw+D1WeY430FGW8pOl XnML+t8z0gprhdUWX/z41dIYDZhlje4= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX54tKHZTqp8qC DCcus6HgtKjU432O1wAYoWAdpw2kXyltfuWo2vyBgrkFgtC2NUO1AvD4uVeOpNZPXo5Re02btS0 1+k/EfU5OqUca3s1sskb11gXjjg7u8s0pExYrCorrw/c+VEDFYxEaViw59w9AWP2Y2w146t/6Ga AbSZePn5KLU+8+AwgpWH03wXZ0WzbD3oEHhPT3+4Qym9Jc+Y8Q8Cqk6Yl+NU18XdNay8QE1v6fo n33Z+3UkavMYkDTO1SmWPHwJoAJMMmI47XwtPUoBnWxD/kiIdFAzsM3ordHlzimmubACwQJEmJL 6/pxynzMKreBrJzq36FSuHSEcr06MBp0uDJU4WfunRyuYOQfVroOg5W0QPSLJFEux7hMjd1bUyi vDJvVkYTMdiNsA2TzYiyhOieUiRi9qtfHzfqLsE5tkNi0+zr7Wo/AJvnZwsvGs1ojh+vJckw+6W T8sRejzPIdEbPBRc3Ew== 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 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 907543AFD0F; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=BMbWMoN+18GAAycTTdRVPnybtzLpuTNxqWbg+GnUXmSwNYYxNIEBE744chvLlnAPrM32RICD/IknvdSOR2VM/4nLG5eYgYtZRVPYNZwELhwVfTfZSd2iMOROjits6nU1EnljQ3QqoKaKdrnbzmuoZh6lE4dW65JE+zNliKr7GFg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=T0t/PnFoPgrVtOZm1tM4mB/0habVdlxANIoRfc3Ue6s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=d14OgtpMGc6HYi63OMgfr6FE9xnrUNWjswX9Rxcs41y+BeohDxJaR+A1W/XUeoVsabGrbz/28Ey/ArQyTquTGSOoHGj80g+GttHnAHcNzcxEk2e9ysi2k7ZEtAsmpEaYfXlTIksjZjbqh08O1i7r58dE3zoVgHbRMzgXyIXzyGI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TdUF9+rF; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TdUF9+rF" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5D050C4AF0E; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=T0t/PnFoPgrVtOZm1tM4mB/0habVdlxANIoRfc3Ue6s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=TdUF9+rFp9DfkshqWhrI39LLdqP7zZwndoFsMUf7u5xYa+UVjK5XY1LbgOXgrSFEj MvJBdwpGeSXgBkaVyngXAWHqe4XX1UEqAF48fRaYvYxC9+CEoLADsPOiwtwVb4BtiS z9sXqhF+7CZa8jOkGih0Tmdb4WQBKk8FbuUbd3nkbg/r2hwQM5RL8KFEI/o4gaJyMS aNP8AgO9CCugUftSNSmzGGYM9oDcTZoZUw7jETNVwegs+4J6OFpInIVv6Pmes3arjr /mdQsgeZuZyq5GNp3wdflLjWGObTh4oI2oe5wCU+iAMrc3TiTnQCjrAtlyUQ4Aih9C 5JWZBbzZ06Nsg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46281C79FB6; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:08:03 -0500 Subject: [PATCH v8 8/9] scsi: ibmvfc: register and use asynchronous sub CRQ for events Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-8-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=8263; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=P/y/m4IYJHpKt739kYnzaytO6yfjYsjo3oP1eJ9dUKw=; b=bNcdxz58fPYyX2UvTjsAN2/TXSQRdCgar+ngICgdeW6i8deXeyQ7nxknzYDvTnR4Nr7j6wmRx qvovPgIaT6mB9TuIrZ5+DjeE5AJClW9G17LAmXPWD5g9pDgyTzY5ob1 X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 f88262ffad13..edd1b2e0504c 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); } } @@ -5809,6 +5817,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); @@ -5868,6 +5877,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); @@ -6832,6 +6842,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 @@ -6900,8 +6911,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; @@ -6951,8 +6962,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; } @@ -6969,7 +6982,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; } @@ -7024,16 +7039,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) { @@ -7044,6 +7069,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, @@ -7067,6 +7101,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 18:24:27 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 3091B3CBE69; Fri, 11 Sep 2026 02:08:37 +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=1789092518; cv=none; b=KzCUJN4W2GmxE3b5+AUVZLKhkgSF9EE2U9F/N8SPa00Kj9icVZApY3ujoCNNwZOTh1B8dZjAYt3TuFWjLBUntZlNlj1d2wHeYoOPw8CDSY/TArvHbqFdg3K0a4yxXQ7QiayMYNiSz9HKaQq3fsMa09jweQT5eKm9zZ57gxEHCFE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092518; c=relaxed/simple; bh=cFDOesyRchtjzbqWb+xagE27fGimkXLcpYe25pfgCRc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I9arBjHhNtfM2TKed8MJj7nVw6Guk+322YRla6icHNuuFMM5Q1Lfro33zXid6Wub8JfAfo+wx35TlbokovX11/i6nIYgn96/gYdUStPx43QUddSjvRotFvUAsD2XKC8wc+iDZ1CZAyFFZ0Mc/xuxHr/YFxGTk1KfU7oYZJFU33I= 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=bUzP4jA1; 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="bUzP4jA1" 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 68B12ND1348194; Fri, 11 Sep 2026 02:08:26 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=bUzP4jA1SAa1VnUDm9Mda/UM9KVLRWyUO W3RpTmFTVcRkxv5fRnHRAvTKwOmTPpNVyAmjMszTp9RzaxUKEE6oP3sbT4xs8Ryh tdv9CgN552P/AkpGmCEJGiFp9PAPed9g9VMg5+njRxSzK+dVqEPILq5baXtDMyPy Z8fiXYWHrDwWVl/WJbPQspFEfUSbELb5hzBT6yMunrILJ+WAeEeQajbxAzY90Hxi j3ZPgNVevSbh7WalyGU1pv09uG0lXHmX2J6Ns1ikpk0TwRrJFcOcXgX8F04rnqg6 vaIRXU4AXQ48OxvHw6sdMGKczcGMdbLTUxnVirFprEC/M+4e+XiwA== 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 4gkd8t0p5r-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:25 +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 68B158l0872144; Fri, 11 Sep 2026 02:08:25 GMT Received: from smtprelay06.wdc07v.mail.ibm.com ([172.16.1.73]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4gkvwk3t33-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:25 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay06.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28NIv58720636 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:24 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D2CC758052; Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 313C15805A; Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08:23 +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:08:14 -0700 Message-ID: <20260911020817.1033789-8-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX24xc+XLQ+BjB FOOvCYkIcfAHVVHU08gw8IEkJv8W+NCxATjH3AZq/hWEwOFNjhP8b3Zk9oHZ75QjxyE4TUWHLsM O0hsEp2/h0JZHan9wKHHXfKFgSoEFPA= X-Proofpoint-ORIG-GUID: 0X86DSCnWwNq4WdfXva8XsXMTA8OMIr5 X-Proofpoint-GUID: 0X86DSCnWwNq4WdfXva8XsXMTA8OMIr5 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX6WR0wWTLAEA2 vxu4PwgKLsnNwaEUCheKmVM2gg43vtwkZfgmK2MHZn2GXU1GDlZ9r1k9dLI3ozvthZxM3+eahXG /OypIej2ZJ3AhgK6HfTmUoZB77oae7VE3GS1fvwKoIZ/zw5S/MnvIArAEaYfcx0J6eFUjQOgKHG hxY6MT5lugXNe7LZhy4xFfcKdyd7asYKVmIZxkJ75tO/GL4470EQ64SUiPrOCBLsNJdnyvJl9NB blJ0MCpFSkpjHvBYD4EOD2qyXjR5paCq30HjXQ9u6bBtfTdptL+fLRIR5LAsomZw24/GUOPIlLo GtTWAgwbfrPZtgtOCYOQtUJHTeSSUnNbbfe0hKLvGE7sz6W8xZ5xK6vhU3xqJntVVUpUBAXD9xe tfl7TIzPKRwe0cHw3QfKeSw9ozxACnZyxCYnowq34pbSh7jHGamo9dFZCtV+CQ4tejYz0N74Bot gdQzdqgh6v+Q2L/EsfQ== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa36299 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=EqnsHTcO9pxfbuvt6BcA: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 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 18:24:27 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 42C673D092F; Fri, 11 Sep 2026 02:08:37 +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=1789092520; cv=none; b=puY9THfFZHAOqSy6C3xD2C7u3glTBr6u5qtqiEhDONaa4zvA7LjvRavMmFMBxYWCIYa0baFkc8FN8nh2hIKiDvlw2ZAXs2kb3BlghHKBH4K+ysuGQdQkHxRbEw8VHK0c9ySuAtJOnbs8IXYj5j8TE0OvnteDc909zbK6K+1B9K8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789092520; c=relaxed/simple; bh=5LOu4/B2zSincTRkEZB40hJcCZVDzmy98SLnQHrDSek=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JyyWSCbacAHet6MDUiDrcMjSbi6RhId4OPLglgY+vbz/boC+4vcqRyl6MFKFamxj1jYmVYEDmKIKIg4iFavOdzD0Bdp0B0479W+G8UyQq5ZQaWlASrFAeCR6zRdu7AQWk36AfBWTgeBvv+sNGqVs6eucMyQSCcf1oXsjuok2ZW8= 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=ZDmB9t8G; 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="ZDmB9t8G" 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 68B12ND2348194; Fri, 11 Sep 2026 02:08:27 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=ZDmB9t8GXQbzpMyNi0fdySS4fL15mtNfe rM9MBSMYXui0GqB1TNW5O0jnc6B8Zx74g/fS77VlR/HR/O0VjFMbhWs5Vid5AplA SWo8zeDudgb+qoEjMlM1qJSSbqnYGGjBriZYS+fkPPVxdHzPhU1xAgNrJJnHQetu wQpQg8npyW+3aaGGvXKJsXCmgXesaRoR0UR+S4PmWs5aCpVhBMYTpdnutvq9RkXk 4pfpGXy5N3m7IoKTJ+Ss29HpkpOlBpWChjszuMzXiyW1KMOSmums0KMuOUWbe6R/ 0tz+N3FJvpsORcG24NT3nreEsxAw+djUOpmgY+YbcfxSOAwKvF7fQ== 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 4gkd8t0p5t-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:27 +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 68B154cv919383; Fri, 11 Sep 2026 02:08:26 GMT Received: from smtprelay07.wdc07v.mail.ibm.com ([172.16.1.74]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4gkvmhkvf9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 11 Sep 2026 02:08:26 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com [10.241.53.103]) by smtprelay07.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 68B28OBv14942888 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 11 Sep 2026 02:08:25 GMT Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 992565805A; Fri, 11 Sep 2026 02:08:24 +0000 (GMT) Received: from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F0D8E58056; Fri, 11 Sep 2026 02:08:23 +0000 (GMT) Received: from li-4c4c4544-0054-3910-8039-c3c04f423534.ibm.com.com (unknown [9.61.103.123]) by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 11 Sep 2026 02:08:23 +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:08:15 -0700 Message-ID: <20260911020817.1033789-9-tyreld@linux.ibm.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@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: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX7H/Rq9odZ+uZ uTKuskcCMZsj2XLLfShjicVmUBXzjZU02qMit2w8XzxsRMkXeKRqZqneuloX4Eszi4TOJEeXVZt Zg6oljOvfOiCHPrtA+V6oxDBxInHISo= X-Proofpoint-ORIG-GUID: w4J5e4RjoariHqfcd3CRyHSp3U5nEVvR X-Proofpoint-GUID: w4J5e4RjoariHqfcd3CRyHSp3U5nEVvR X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTExMDAyNCBTYWx0ZWRfX1bkscfGMnEIk VzqM7bKUZzURZB8jjhnMc/nCgmdL2y8b/8yv29imgqCh+c0wtrmx67jZAbmYLnLR9Cq9h0hYy1B DRZ/l1sKOGkM9/r2gyt1IW4D9HZMCWgVNFuPHTJKPjxYD7vsrNfiifFrDxtHqpQIB4rvLGvQOP6 xYdMW4tT9U0xErWQngM3Kiv2TRirrolEhcOvZTVTV5PUz12rMtuA6CljDDSYdQWQAprXCRwv8NP 4vutIE5BJRVzou49C+mzqbSnvI3JylOlY16ZWcw7Vqjm5VS+41H+l5WrMLSGtgZFwHsOWT6EYGB 7oycQ6zyLA6InLDRfQd7CuKJViMXY+miuMq2ET7rpvxpzXghm/6gWDXHsid8tzKVwy4ypMCYB0Y EvBQ/Ew3BkSmxbMq79RKvhMq/bdso5ZeAfd/+XaXRjdP+woCc71YkCEV1SIyJ1+a660FRRMILk+ kF+VVmW8FH10ZP41ylA== X-Authority-Analysis: v=2.4 cv=PIGaavqC c=1 sm=1 tr=0 ts=6aa3629b cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=VdqzKS8jKosA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=YunXX2DFvQEblV2KXBkA: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 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 From nobody Fri Sep 25 18:24:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 981993B1013; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; cv=none; b=hYqZePpyypNA8WMKqA6KIyfAl9Umnq896L5Ll6PpAAjpvtzptFyQL/NxrKqkptIzCaK26lxQLpwCTlkUH1ta6Pv2VRt760C2nx9pN9M83aPAdc9/bd9i6w/yz/Wq0B2a/OpUEUV6v6c+zbqP60hNNcmzROgaqM6tZNmRndQ2/EY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788980880; c=relaxed/simple; bh=Gxkv9u/5QSR6ZxH48W/Cd7x1i3UoZuCI33uRbS4xMJ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dYK6EkideuINvOvfyzkKkeQPLaBY8w78oQWWiXlOeXwBYtj/46d0dcID7epqTMzqIbtQ4JkcKKI/ajtCfKyDc4F17MmWO9TFW3v5Hy84t0yjwnTp+4fSiT6quUcIZHm4LjJzkbWUKueUjU1ktrfbDkEI9kn2Sw/N6QIuq/Qu2Zo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gDIQ7h2J; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gDIQ7h2J" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6A192C32786; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788980880; bh=Gxkv9u/5QSR6ZxH48W/Cd7x1i3UoZuCI33uRbS4xMJ4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=gDIQ7h2Jr7h6sPRcY1uVH4bNVrKocm8lBi7gSCU9oXW+vFLOobNuRCLPkeu6s3Fmt lZWy4slUNPoUBPgFkXcq1ZILMHoCw+dzQCEvdZeenW4hH50qbeyr+YxjXdDFE5lL7e Lzw00TVd9IY5W2oWvxWkVNKX2RunXrLF/r2M6wjHLKiHYKhAU2sOK7R6kuPODTAgWq Y9Qm2WFgsJoa6/7eEOhzMgPBTM7ltmLD8ar5pOGLOpwadzFwbeAiPzazazs0Sje/Lc /xCgsCSQ/Q0wPbIO2k+mYjPU95i9I/h3UWFyoXEXDOpP7SYS4JEmTlCP5B48ozKLTD D27u3PSQEbwhg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58253C79FB9; Wed, 9 Sep 2026 19:08:00 +0000 (UTC) From: Dave Marquardt via B4 Relay Date: Wed, 09 Sep 2026 14:08:04 -0500 Subject: [PATCH v8 9/9] scsi: ibmvfc: handle extended FPIN events Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260909-ibmvfc-fpin-support-v8-9-b27183b055af@linux.ibm.com> References: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> In-Reply-To: <20260909-ibmvfc-fpin-support-v8-0-b27183b055af@linux.ibm.com> To: "James E.J. Bottomley" , "Martin K. Petersen" , Madhavan Srinivasan , Michael Ellerman , Nicholas Piggin , "Christophe Leroy (CS GROUP)" , Tyrel Datwyler Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Brian King , Greg Joyce , Kyle Mahlkuch , Dave Marquardt X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788980878; l=13812; i=davemarq@linux.ibm.com; s=20260216; h=from:subject:message-id; bh=P8SGgzdm157JzMx5N65HRfAFIWCBQdx6nA65w7KkvPs=; b=wCVGuSwGMCr/It3REY7mX4MUK7EafklEW7+MaweimstZZxo43i3vf2MFfkqwsoJp8JR20UbQh Hp7dM9PKhMGB+E6I9Z5cQZ0XAqozSQpzuoe9Ue5ydzdFFxprOPBKzQ2 X-Developer-Key: i=davemarq@linux.ibm.com; a=ed25519; pk=vy0/nfobrje6EqZxuyw6a3ZstytG8WK2vf5Y3xtGrEg= X-Endpoint-Received: by B4 Relay for davemarq@linux.ibm.com/20260216 with auth_id=689 X-Original-From: Dave Marquardt Reply-To: davemarq@linux.ibm.com 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 edd1b2e0504c..589a0d478206 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