[PATCH v11 09/11] scsi: ibmvfc: extend channel reg/dereg helpers for async sub-CRQ
From: Tyrel Datwyler
Date: Fri Sep 25 2026 - 00:52:58 EST
From: Dave Marquardt <davemarq@xxxxxxxxxxxxx>
ibmvfc_register_channel() and ibmvfc_deregister_channel() previously only
handled SCSI and NVMe sub-CRQ channels identified by the channel protocol
(IBMVFC_PROTO_SCSI, IBMVFC_PROTO_NVME). The async sub-CRQ had no
registration path through these helpers, requiring separate handling.
Add a new IBMVFC_PROTO_ASYNC protocol value to enum ibmvfc_protocol.
Extend both functions to handle IBMVFC_PROTO_ASYNC channels: the IRQ is
named "ibmvfc-<addr>-async<index>" and the handler is set to
ibmvfc_interrupt_async_subq rather than the per-protocol
ibmvfc_interrupt_mq handler.
Remove the __maybe_unused annotation from ibmvfc_interrupt_async_subq
now that it is referenced in ibmvfc_register_channel().
Error messages in both paths are updated to include the channel protocol
to distinguish async sub-CRQ failures from SCSI/NVMe sub-CRQ failures.
Kernel-doc headers are added to both functions.
Signed-off-by: Dave Marquardt <davemarq@xxxxxxxxxxxxx>
Signed-off-by: Tyrel Datwyler <tyreld@xxxxxxxxxxxxx>
---
drivers/scsi/ibmvscsi/ibmvfc-core.c | 46 +++++++++++++++++++++++++----
drivers/scsi/ibmvscsi/ibmvfc.h | 1 +
2 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index b354bfb1a9b6..b967c82e9943 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -4421,7 +4421,7 @@ static void ibmvfc_drain_async_subq(struct ibmvfc_queue *scrq)
* @scrq_instance: async subq
*
**/
-static irqreturn_t __maybe_unused ibmvfc_interrupt_async_subq(int irq, void *scrq_instance)
+static irqreturn_t ibmvfc_interrupt_async_subq(int irq, void *scrq_instance)
{
struct ibmvfc_queue *scrq = (struct ibmvfc_queue *)scrq_instance;
@@ -6812,6 +6812,21 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
return retrc;
}
+/**
+ * ibmvfc_register_channel - Register a sub-CRQ channel with the hypervisor
+ * @vhost: ibmvfc host struct
+ * @channels: ibmvfc channels struct containing the channel array and protocol
+ * @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 hardware
+ * 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)
@@ -6839,7 +6854,8 @@ static int ibmvfc_register_channel(struct ibmvfc_host *vhost,
if (!scrq->irq) {
rc = -EINVAL;
- dev_err(dev, "Error mapping sub-crq[%d] irq\n", index);
+ dev_err(dev, "Error mapping protocol (%d) sub-crq[%d] irq\n",
+ channels->protocol, index);
goto irq_failed;
}
@@ -6854,6 +6870,11 @@ static int ibmvfc_register_channel(struct ibmvfc_host *vhost,
vdev->unit_address, index);
scrq->handler = ibmvfc_interrupt_mq;
break;
+ case IBMVFC_PROTO_ASYNC:
+ snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-async%d",
+ vdev->unit_address, index);
+ scrq->handler = ibmvfc_interrupt_async_subq;
+ break;
default:
dev_err(dev, "Unknown channel protocol (%d)\n",
channels->protocol);
@@ -6863,7 +6884,8 @@ static int ibmvfc_register_channel(struct ibmvfc_host *vhost,
rc = request_irq(scrq->irq, scrq->handler, 0, scrq->name, scrq);
if (rc) {
- dev_err(dev, "Couldn't register sub-crq[%d] irq\n", index);
+ dev_err(dev, "Couldn't register protocol (%d) sub-crq[%d] irq\n",
+ channels->protocol, index);
irq_dispose_mapping(scrq->irq);
scrq->irq = 0;
goto irq_failed;
@@ -6883,6 +6905,18 @@ static int ibmvfc_register_channel(struct ibmvfc_host *vhost,
return rc;
}
+/**
+ * ibmvfc_deregister_channel - Deregister a sub-CRQ channel with the hypervisor
+ * @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 fails,
+ * 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)
@@ -6905,8 +6939,10 @@ static void ibmvfc_deregister_channel(struct ibmvfc_host *vhost,
scrq->cookie);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
- if (rc)
- dev_err(dev, "Failed to free sub-crq[%d]: rc=%ld\n", index, rc);
+ if (rc) {
+ dev_err(dev, "Failed to free protocol (%d) sub-crq[%d]: rc=%ld\n",
+ channels->protocol, index, rc);
+ }
/* Clean out the queue */
if (scrq->msgs.handle) {
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index ebbcb911f639..1cb6f20b0626 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -839,6 +839,7 @@ enum ibmvfc_target_action {
enum ibmvfc_protocol {
IBMVFC_PROTO_SCSI = 0,
IBMVFC_PROTO_NVME = 1,
+ IBMVFC_PROTO_ASYNC = 2,
};
struct ibmvfc_target {
--
2.55.0