From: Tyrel Datwyler <tyreld@linux.ibm.com>
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 <tyreld@linux.ibm.com>
Subject: [PATCH v11 10/11] scsi: ibmvfc: register and use asynchronous sub CRQ for events
Date: Thu, 24 Sep 2026 21:48:59 -0700 [thread overview]
Message-ID: <20260925044900.414340-11-tyreld@linux.ibm.com> (raw)
In-Reply-To: <20260925044900.414340-1-tyreld@linux.ibm.com>
From: Dave Marquardt <davemarq@linux.ibm.com>
Wire the async sub-CRQ into the sub-CRQ lifecycle so it is allocated,
registered, and freed alongside the SCSI channel queues.
In ibmvfc_probe(), initialize vhost->async_scrqs with desired_queues=1,
max_queues=1, and protocol=IBMVFC_PROTO_ASYNC. Add ibmvfc_release_channels()
as a helper to free a channels array and its queue buffers.
In ibmvfc_init_sub_crqs(), allocate the async sub-CRQ via
ibmvfc_alloc_channels() before allocating the SCSI channels. Register it
with the VIOS via ibmvfc_reg_sub_crqs(). Either failure disables
multi-queue and aborts init.
In ibmvfc_alloc_channels(), select IBMVFC_ASYNC_SUB_CRQ_FMT for async
protocol channels instead of IBMVFC_SUB_CRQ_FMT, so the queue is sized
for ibmvfc_async_sub_crq entries.
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_scrqs.scrqs[0].vios_cookie. Pass the async sub-CRQ cookie
to the VIOS in ibmvfc_channel_setup() via async_sub_crq_handle.
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.
Signed-off-by: Dave Marquardt <davemarq@linux.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc-core.c | 82 ++++++++++++++++++++---------
1 file changed, 58 insertions(+), 24 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index b967c82e9943..a7bdae2c8571 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -964,6 +964,7 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost)
struct vio_dev *vdev = to_vio_dev(vhost->dev);
unsigned long flags;
+ ibmvfc_dereg_sub_crqs(vhost, &vhost->async_scrqs);
ibmvfc_dereg_sub_crqs(vhost, &vhost->scsi_scrqs);
ibmvfc_dereg_sub_crqs(vhost, &vhost->nvme_scrqs);
@@ -986,6 +987,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);
+ ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs);
ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs);
ibmvfc_reg_sub_crqs(vhost, &vhost->nvme_scrqs);
@@ -1006,6 +1008,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_queue *crq = &vhost->crq;
+ ibmvfc_dereg_sub_crqs(vhost, &vhost->async_scrqs);
ibmvfc_dereg_sub_crqs(vhost, &vhost->scsi_scrqs);
ibmvfc_dereg_sub_crqs(vhost, &vhost->nvme_scrqs);
@@ -1042,6 +1045,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_reg_sub_crqs(vhost, &vhost->async_scrqs);
ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs);
ibmvfc_reg_sub_crqs(vhost, &vhost->nvme_scrqs);
@@ -1584,9 +1588,11 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
if (vhost->mq_enabled || vhost->using_channels) {
login_info->capabilities |= cpu_to_be64(IBMVFC_CAN_USE_CHANNELS);
+ login_info->capabilities |= cpu_to_be64(IBMVFC_USE_ASYNC_SUBQ);
+ login_info->capabilities |= cpu_to_be64(IBMVFC_CAN_HANDLE_FPIN);
+ login_info->capabilities |= cpu_to_be64(IBMVFC_YES_SCSI);
if (vhost->nvme_enabled) {
login_info->capabilities |= cpu_to_be64(IBMVFC_YES_NVMEOF);
- login_info->capabilities |= cpu_to_be64(IBMVFC_YES_SCSI);
login_info->capabilities |= cpu_to_be64(IBMVFC_CAN_USE_WWPN_ALL);
}
}
@@ -5783,6 +5789,7 @@ static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
{
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_channel_setup *setup = vhost->channel_setup_buf;
+ struct ibmvfc_channels *async = &vhost->async_scrqs;
struct ibmvfc_channels *scsi = &vhost->scsi_scrqs;
struct ibmvfc_channels *nvme = &vhost->nvme_scrqs;
u32 mad_status = be16_to_cpu(evt->xfer_iu->channel_setup.common.status);
@@ -5813,6 +5820,7 @@ static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
for (i = 0; i < nvme->active_queues; i++)
nvme->scrqs[i].vios_cookie =
be64_to_cpu(setup->channel_handles[scsi->active_queues + i]);
+ async->scrqs[0].vios_cookie = be64_to_cpu(setup->async_sub_crq_handle);
ibmvfc_dbg(vhost, "Using %u SCSI channels\n",
scsi->active_queues);
@@ -5847,6 +5855,7 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
struct ibmvfc_event *evt = ibmvfc_get_reserved_event(&vhost->crq);
struct ibmvfc_channels *scsi = &vhost->scsi_scrqs;
struct ibmvfc_channels *nvme = &vhost->nvme_scrqs;
+ struct ibmvfc_channels *async = &vhost->async_scrqs;
unsigned int scsi_channels =
min(scsi->desired_queues, vhost->max_vios_scsi_channels);
unsigned int nvme_channels =
@@ -5872,6 +5881,7 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
for (i = 0; i < nvme_channels; i++)
setup_buf->channel_handles[scsi_channels + i] =
cpu_to_be64(nvme->scrqs[i].cookie);
+ setup_buf->async_sub_crq_handle = cpu_to_be64(async->scrqs[0].cookie);
}
ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT);
@@ -6719,6 +6729,9 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
queue->evt_depth = scsi_qdepth;
queue->reserved_depth = IBMVFC_NUM_INTERNAL_SUBQ_REQ;
break;
+ case IBMVFC_ASYNC_SUB_CRQ_FMT:
+ fmt_size = sizeof(*queue->msgs.async_scrq);
+ break;
default:
dev_warn(dev, "Unknown command/response queue message format: %d\n", fmt);
return -EINVAL;
@@ -6993,6 +7006,7 @@ static int ibmvfc_alloc_channels(struct ibmvfc_host *vhost,
struct ibmvfc_channels *channels)
{
struct ibmvfc_queue *scrq;
+ enum ibmvfc_msg_fmt fmt;
int i, j;
int rc = 0;
@@ -7000,9 +7014,10 @@ static int ibmvfc_alloc_channels(struct ibmvfc_host *vhost,
if (!channels->scrqs)
return -ENOMEM;
+ fmt = (channels->protocol != IBMVFC_PROTO_ASYNC) ? IBMVFC_SUB_CRQ_FMT : IBMVFC_ASYNC_SUB_CRQ_FMT;
for (i = 0; i < channels->max_queues; i++) {
scrq = &channels->scrqs[i];
- rc = ibmvfc_alloc_queue(vhost, scrq, IBMVFC_SUB_CRQ_FMT);
+ rc = ibmvfc_alloc_queue(vhost, scrq, fmt);
if (rc) {
for (j = i; j > 0; j--) {
scrq = &channels->scrqs[j - 1];
@@ -7018,17 +7033,39 @@ static int ibmvfc_alloc_channels(struct ibmvfc_host *vhost,
return rc;
}
+static void ibmvfc_release_channels(struct ibmvfc_host *vhost,
+ struct ibmvfc_channels *channels)
+{
+ struct ibmvfc_queue *scrq;
+ int i;
+
+ if (channels->scrqs) {
+ for (i = 0; i < channels->max_queues; i++) {
+ scrq = &channels->scrqs[i];
+ ibmvfc_free_queue(vhost, scrq);
+ }
+
+ kfree(channels->scrqs);
+ channels->scrqs = NULL;
+ channels->active_queues = 0;
+ }
+}
+
static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
{
+
ENTER;
if (!vhost->mq_enabled)
return;
- if (ibmvfc_alloc_channels(vhost, &vhost->scsi_scrqs)) {
- vhost->do_enquiry = 0;
- vhost->mq_enabled = 0;
- return;
- }
+ /* register async_sub_crq channel */
+ if (ibmvfc_alloc_channels(vhost, &vhost->async_scrqs))
+ goto out;
+
+ ibmvfc_reg_sub_crqs(vhost, &vhost->async_scrqs);
+
+ if (ibmvfc_alloc_channels(vhost, &vhost->scsi_scrqs))
+ goto deregister_async_sub_crq;
ibmvfc_reg_sub_crqs(vhost, &vhost->scsi_scrqs);
@@ -7040,29 +7077,23 @@ static void ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
}
LEAVE;
-}
-
-static void ibmvfc_release_channels(struct ibmvfc_host *vhost,
- struct ibmvfc_channels *channels)
-{
- struct ibmvfc_queue *scrq;
- int i;
-
- if (channels->scrqs) {
- for (i = 0; i < channels->max_queues; i++) {
- scrq = &channels->scrqs[i];
- ibmvfc_free_queue(vhost, scrq);
- }
+ return;
- kfree(channels->scrqs);
- channels->scrqs = NULL;
- channels->active_queues = 0;
- }
+deregister_async_sub_crq:
+ ibmvfc_dereg_sub_crqs(vhost, &vhost->async_scrqs);
+ ibmvfc_release_channels(vhost, &vhost->async_scrqs);
+out:
+ vhost->do_enquiry = 0;
+ vhost->mq_enabled = 0;
+ return;
}
static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost)
{
ENTER;
+ ibmvfc_dereg_sub_crqs(vhost, &vhost->async_scrqs);
+ ibmvfc_release_channels(vhost, &vhost->async_scrqs);
+
if (!vhost->scsi_scrqs.scrqs)
return;
@@ -7328,6 +7359,9 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vhost->task_set = 1;
vhost->mq_enabled = mq_enabled;
+ vhost->async_scrqs.desired_queues = 1;
+ vhost->async_scrqs.max_queues = 1;
+ vhost->async_scrqs.protocol = IBMVFC_PROTO_ASYNC;
vhost->scsi_scrqs.desired_queues = min(shost->nr_hw_queues, nr_scsi_channels);
vhost->scsi_scrqs.max_queues = shost->nr_hw_queues;
vhost->scsi_scrqs.protocol = IBMVFC_PROTO_SCSI;
--
2.55.0
next prev parent reply other threads:[~2026-09-25 4:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 4:48 [PATCH v11 00/11] scsi: ibmvfc: make ibmvfc support FPIN messages Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 01/11] scsi: ibmvfc: fix IRQ leak and guard deregister on channel reg failure Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 02/11] scsi: ibmvfc: fix potential clobbering of rc after failed irq setup Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 03/11] scsi: ibmvfc: fix potential NULL pointer dereference on failed queue allocation Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 04/11] scsi: ibmvfc: add basic FPIN support Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 05/11] scsi: ibmvfc: add NOOP command support Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 06/11] scsi: ibmvfc: add FPIN extended flag and async sub-CRQ queue handle Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 07/11] scsi: ibmvfc: extend async event handlers for async sub-CRQ events Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 08/11] scsi: ibmvfc: add interrupt routine for asynchronous sub CRQ Tyrel Datwyler
2026-09-25 4:48 ` [PATCH v11 09/11] scsi: ibmvfc: extend channel reg/dereg helpers for async sub-CRQ Tyrel Datwyler
2026-09-25 4:48 ` Tyrel Datwyler [this message]
2026-09-25 4:49 ` [PATCH v11 11/11] scsi: ibmvfc: handle extended FPIN events Tyrel Datwyler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925044900.414340-11-tyreld@linux.ibm.com \
--to=tyreld@linux.ibm.com \
--cc=brking@linux.ibm.com \
--cc=davemarq@linux.ibm.com \
--cc=james.bottomley@hansenpartnership.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=martin.petersen@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®