git: 8ced50767933 - main - nvmft: Honor any IOCCSZ limit imposed by the transport

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 10 Nov 2025 15:51:24 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=8ced50767933f3e2949456367d4d9a64797daec3

commit 8ced50767933f3e2949456367d4d9a64797daec3
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-11-10 15:50:47 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-11-10 15:50:47 +0000

    nvmft: Honor any IOCCSZ limit imposed by the transport
    
    Sponsored by:   Chelsio Communications
---
 sys/dev/nvmf/controller/nvmft_controller.c | 14 ++++++++++++++
 sys/dev/nvmf/controller/nvmft_qpair.c      |  6 ++++++
 sys/dev/nvmf/controller/nvmft_var.h        |  1 +
 3 files changed, 21 insertions(+)

diff --git a/sys/dev/nvmf/controller/nvmft_controller.c b/sys/dev/nvmf/controller/nvmft_controller.c
index e618972f46cf..1618c1f96dac 100644
--- a/sys/dev/nvmf/controller/nvmft_controller.c
+++ b/sys/dev/nvmf/controller/nvmft_controller.c
@@ -103,6 +103,19 @@ nvmft_keep_alive_timer(void *arg)
 	callout_schedule_sbt(&ctrlr->ka_timer, ctrlr->ka_sbt, 0, C_HARDCLOCK);
 }
 
+static void
+nvmft_update_cdata(struct nvmft_controller *ctrlr)
+{
+	uint32_t ioccsz, val;
+
+	val = nvmft_max_ioccsz(ctrlr->admin);
+	if (val != 0) {
+		ioccsz = le32toh(ctrlr->cdata.ioccsz) * 16;
+		if (val < ioccsz)
+			ctrlr->cdata.ioccsz = htole32(val / 16);
+	}
+}
+
 int
 nvmft_handoff_admin_queue(struct nvmft_port *np, enum nvmf_trtype trtype,
     const nvlist_t *params, const struct nvmf_fabric_connect_cmd *cmd,
@@ -160,6 +173,7 @@ nvmft_handoff_admin_queue(struct nvmft_port *np, enum nvmf_trtype trtype,
 	    (int)sizeof(data->hostnqn), data->hostnqn);
 	ctrlr->admin = qp;
 	ctrlr->trtype = trtype;
+	nvmft_update_cdata(ctrlr);
 
 	/*
 	 * The spec requires a non-zero KeepAlive timer, but allow a
diff --git a/sys/dev/nvmf/controller/nvmft_qpair.c b/sys/dev/nvmf/controller/nvmft_qpair.c
index 73c7bb280780..1300c9ec91fc 100644
--- a/sys/dev/nvmf/controller/nvmft_qpair.c
+++ b/sys/dev/nvmf/controller/nvmft_qpair.c
@@ -182,6 +182,12 @@ nvmft_qpair_name(struct nvmft_qpair *qp)
 	return (qp->name);
 }
 
+uint32_t
+nvmft_max_ioccsz(struct nvmft_qpair *qp)
+{
+	return (nvmf_max_ioccsz(qp->qp));
+}
+
 static int
 _nvmft_send_response(struct nvmft_qpair *qp, const void *cqe)
 {
diff --git a/sys/dev/nvmf/controller/nvmft_var.h b/sys/dev/nvmf/controller/nvmft_var.h
index 85032b2dc55f..b3a5278a639c 100644
--- a/sys/dev/nvmf/controller/nvmft_var.h
+++ b/sys/dev/nvmf/controller/nvmft_var.h
@@ -145,6 +145,7 @@ struct nvmft_controller *nvmft_qpair_ctrlr(struct nvmft_qpair *qp);
 void	nvmft_qpair_datamove(struct nvmft_qpair *qp, union ctl_io *io);
 uint16_t nvmft_qpair_id(struct nvmft_qpair *qp);
 const char *nvmft_qpair_name(struct nvmft_qpair *qp);
+uint32_t nvmft_max_ioccsz(struct nvmft_qpair *qp);
 void	nvmft_command_completed(struct nvmft_qpair *qp,
     struct nvmf_capsule *nc);
 int	nvmft_send_response(struct nvmft_qpair *qp, const void *cqe);