From 20ccf47aed9936b3e2db2ed0b053f6693c87ac99 Mon Sep 17 00:00:00 2001 From: Ziye Yang Date: Mon, 3 Dec 2018 10:18:36 +0800 Subject: [PATCH] nvme_tcp: correctly support the incapsule data size. According to the TP 8000 spec, the maximal in capsule data size is defined as follows: 1 For the Fabrics command and admin, it should not exceed 8192 bytes. 2 For I/O command, it shoudld be defined according to ioccsz in the Identify controller data. Change-Id: Ic13eda33e1516858e1e8749ee89459e3148d9e37 Signed-off-by: Ziye Yang Reviewed-on: https://review.gerrithub.io/435826 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Sasha Kotchubievsky Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/nvme/nvme_tcp.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/lib/nvme/nvme_tcp.c b/lib/nvme/nvme_tcp.c index e636c238e..7dc45921c 100644 --- a/lib/nvme/nvme_tcp.c +++ b/lib/nvme/nvme_tcp.c @@ -78,7 +78,6 @@ struct nvme_tcp_qpair { TAILQ_HEAD(, nvme_tcp_req) active_r2t_reqs; TAILQ_HEAD(, nvme_tcp_pdu) send_queue; - uint32_t in_capsule_data_size; struct nvme_tcp_pdu recv_pdu; struct nvme_tcp_pdu send_pdu; /* only for error pdu and init pdu */ enum nvme_tcp_pdu_recv_state recv_state; @@ -555,12 +554,20 @@ nvme_tcp_build_sgl_request(struct nvme_tcp_qpair *tqpair, struct nvme_request *r return 0; } +static inline uint32_t +nvme_tcp_icdsz_bytes(struct spdk_nvme_ctrlr *ctrlr) +{ + return (ctrlr->cdata.nvmf_specific.ioccsz * 16 - sizeof(struct spdk_nvme_cmd)); +} + static int nvme_tcp_req_init(struct nvme_tcp_qpair *tqpair, struct nvme_request *req, struct nvme_tcp_req *tcp_req) { + struct spdk_nvme_ctrlr *ctrlr = tqpair->qpair.ctrlr; int rc = 0; enum spdk_nvme_data_transfer xfer; + uint32_t max_incapsule_data_size; tcp_req->req = req; req->cmd.cid = tcp_req->cid; @@ -588,19 +595,21 @@ nvme_tcp_req_init(struct nvme_tcp_qpair *tqpair, struct nvme_request *req, } else { xfer = spdk_nvme_opc_get_data_transfer(req->cmd.opc); } + if (xfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER) { + max_incapsule_data_size = nvme_tcp_icdsz_bytes(ctrlr); + if ((req->cmd.opc == SPDK_NVME_OPC_FABRIC) || nvme_qpair_is_admin_queue(&tqpair->qpair)) { + max_incapsule_data_size = spdk_min(max_incapsule_data_size, NVME_TCP_IN_CAPSULE_DATA_MAX_SIZE); + } - /* Only for fabrics command */ - if ((req->cmd.opc == SPDK_NVME_OPC_FABRIC) && (tqpair->in_capsule_data_size != 0) && - (xfer == SPDK_NVME_DATA_HOST_TO_CONTROLLER) && - (req->payload_size <= tqpair->in_capsule_data_size)) { - req->cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - req->cmd.dptr.sgl1.unkeyed.subtype = SPDK_NVME_SGL_SUBTYPE_OFFSET; - req->cmd.dptr.sgl1.address = 0; - tcp_req->in_capsule_data = true; + if (req->payload_size <= max_incapsule_data_size) { + req->cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; + req->cmd.dptr.sgl1.unkeyed.subtype = SPDK_NVME_SGL_SUBTYPE_OFFSET; + req->cmd.dptr.sgl1.address = 0; + tcp_req->in_capsule_data = true; + } } return 0; - } static void @@ -1705,7 +1714,6 @@ nvme_tcp_ctrlr_create_qpair(struct spdk_nvme_ctrlr *ctrlr, return NULL; } - tqpair->in_capsule_data_size = NVME_TCP_IN_CAPSULE_DATA_MAX_SIZE; tqpair->num_entries = qsize; qpair = &tqpair->qpair;