Hannes Reinecke 1c98d5
From: James Smart <jsmart2021@gmail.com>
Hannes Reinecke 1c98d5
Date: Tue, 31 Mar 2020 09:49:49 -0700
Hannes Reinecke 1c98d5
Subject: [PATCH] nvmet-fc: Better size LS buffers
Hannes Reinecke 1c98d5
Git-commit: 3ac7870a98f1ac063a8474f997e28d9f2aa53798
Hannes Reinecke 1c98d5
Git-repo: git://git.infradead.org/nvme.git
Hannes Reinecke 1c98d5
Patch-mainline: Queued in subsystem maintainer repository
Hannes Reinecke 1c98d5
References: bsc#1169045
Hannes Reinecke 1c98d5
Hannes Reinecke 1c98d5
Current code uses NVME_FC_MAX_LS_BUFFER_SIZE (2KB) when allocating
Hannes Reinecke 1c98d5
buffers for LS requests and responses. This is considerable overkill
Hannes Reinecke 1c98d5
for what is actually defined.
Hannes Reinecke 1c98d5
Hannes Reinecke 1c98d5
Rework code to have unions for all possible requests and responses
Hannes Reinecke 1c98d5
and size based on the unions.  Remove NVME_FC_MAX_LS_BUFFER_SIZE.
Hannes Reinecke 1c98d5
Hannes Reinecke 1c98d5
Signed-off-by: James Smart <jsmart2021@gmail.com>
Hannes Reinecke 1c98d5
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Hannes Reinecke 1c98d5
Reviewed-by: Hannes Reinecke <hare@suse.de>
Hannes Reinecke 1c98d5
Signed-off-by: Christoph Hellwig <hch@lst.de>
Hannes Reinecke 1c98d5
Acked-by: Hannes Reinecke <hare@suse.com>
Hannes Reinecke 1c98d5
---
Hannes Reinecke 1c98d5
 drivers/nvme/host/fc.h   | 15 ++++++++++++++
Hannes Reinecke 1c98d5
 drivers/nvme/target/fc.c | 53 +++++++++++++++++++++---------------------------
Hannes Reinecke 1c98d5
 2 files changed, 38 insertions(+), 30 deletions(-)
Hannes Reinecke 1c98d5
Hannes Reinecke 1c98d5
diff --git a/drivers/nvme/host/fc.h b/drivers/nvme/host/fc.h
Hannes Reinecke 1c98d5
index d2861cdd58ee..08fa88381d45 100644
Hannes Reinecke 1c98d5
--- a/drivers/nvme/host/fc.h
Hannes Reinecke 1c98d5
+++ b/drivers/nvme/host/fc.h
Hannes Reinecke 1c98d5
@@ -16,6 +16,21 @@
Hannes Reinecke 1c98d5
  * ******************  FC-NVME LS HANDLING ******************
Hannes Reinecke 1c98d5
  */
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
+union nvmefc_ls_requests {
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_assoc_rqst		rq_cr_assoc;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_conn_rqst		rq_cr_conn;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_disconnect_assoc_rqst	rq_dis_assoc;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_disconnect_conn_rqst	rq_dis_conn;
Hannes Reinecke 1c98d5
+} __aligned(128);	/* alignment for other things alloc'd with */
Hannes Reinecke 1c98d5
+
Hannes Reinecke 1c98d5
+union nvmefc_ls_responses {
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_rjt			rsp_rjt;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_assoc_acc		rsp_cr_assoc;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_conn_acc		rsp_cr_conn;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_disconnect_assoc_acc	rsp_dis_assoc;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_disconnect_conn_acc	rsp_dis_conn;
Hannes Reinecke 1c98d5
+} __aligned(128);	/* alignment for other things alloc'd with */
Hannes Reinecke 1c98d5
+
Hannes Reinecke 1c98d5
 static inline void
Hannes Reinecke 1c98d5
 nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
Hannes Reinecke 1c98d5
 {
Hannes Reinecke 1c98d5
diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c
Hannes Reinecke 1c98d5
index 1f3118a3b0a3..66de6bd8f4fd 100644
Hannes Reinecke 1c98d5
--- a/drivers/nvme/target/fc.c
Hannes Reinecke 1c98d5
+++ b/drivers/nvme/target/fc.c
Hannes Reinecke 1c98d5
@@ -22,9 +22,6 @@
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 #define NVMET_LS_CTX_COUNT		256
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
-/* for this implementation, assume small single frame rqst/rsp */
Hannes Reinecke 1c98d5
-#define NVME_FC_MAX_LS_BUFFER_SIZE		2048
Hannes Reinecke 1c98d5
-
Hannes Reinecke 1c98d5
 struct nvmet_fc_tgtport;
Hannes Reinecke 1c98d5
 struct nvmet_fc_tgt_assoc;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -37,8 +34,8 @@ struct nvmet_fc_ls_iod {
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgtport		*tgtport;
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgt_assoc	*assoc;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
-	u8				*rqstbuf;
Hannes Reinecke 1c98d5
-	u8				*rspbuf;
Hannes Reinecke 1c98d5
+	union nvmefc_ls_requests	*rqstbuf;
Hannes Reinecke 1c98d5
+	union nvmefc_ls_responses	*rspbuf;
Hannes Reinecke 1c98d5
 	u16				rqstdatalen;
Hannes Reinecke 1c98d5
 	dma_addr_t			rspdma;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -340,15 +337,16 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
Hannes Reinecke 1c98d5
 		iod->tgtport = tgtport;
Hannes Reinecke 1c98d5
 		list_add_tail(&iod->ls_list, &tgtport->ls_list);
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
-		iod->rqstbuf = kcalloc(2, NVME_FC_MAX_LS_BUFFER_SIZE,
Hannes Reinecke 1c98d5
-			GFP_KERNEL);
Hannes Reinecke 1c98d5
+		iod->rqstbuf = kzalloc(sizeof(union nvmefc_ls_requests) +
Hannes Reinecke 1c98d5
+				       sizeof(union nvmefc_ls_responses),
Hannes Reinecke 1c98d5
+				       GFP_KERNEL);
Hannes Reinecke 1c98d5
 		if (!iod->rqstbuf)
Hannes Reinecke 1c98d5
 			goto out_fail;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
-		iod->rspbuf = iod->rqstbuf + NVME_FC_MAX_LS_BUFFER_SIZE;
Hannes Reinecke 1c98d5
+		iod->rspbuf = (union nvmefc_ls_responses *)&iod->rqstbuf[1];
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 		iod->rspdma = fc_dma_map_single(tgtport->dev, iod->rspbuf,
Hannes Reinecke 1c98d5
-						NVME_FC_MAX_LS_BUFFER_SIZE,
Hannes Reinecke 1c98d5
+						sizeof(*iod->rspbuf),
Hannes Reinecke 1c98d5
 						DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
 		if (fc_dma_mapping_error(tgtport->dev, iod->rspdma))
Hannes Reinecke 1c98d5
 			goto out_fail;
Hannes Reinecke 1c98d5
@@ -361,7 +359,7 @@ nvmet_fc_alloc_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
Hannes Reinecke 1c98d5
 	list_del(&iod->ls_list);
Hannes Reinecke 1c98d5
 	for (iod--, i--; i >= 0; iod--, i--) {
Hannes Reinecke 1c98d5
 		fc_dma_unmap_single(tgtport->dev, iod->rspdma,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
+				sizeof(*iod->rspbuf), DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
 		kfree(iod->rqstbuf);
Hannes Reinecke 1c98d5
 		list_del(&iod->ls_list);
Hannes Reinecke 1c98d5
 	}
Hannes Reinecke 1c98d5
@@ -379,7 +377,7 @@ nvmet_fc_free_ls_iodlist(struct nvmet_fc_tgtport *tgtport)
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	for (i = 0; i < NVMET_LS_CTX_COUNT; iod++, i++) {
Hannes Reinecke 1c98d5
 		fc_dma_unmap_single(tgtport->dev,
Hannes Reinecke 1c98d5
-				iod->rspdma, NVME_FC_MAX_LS_BUFFER_SIZE,
Hannes Reinecke 1c98d5
+				iod->rspdma, sizeof(*iod->rspbuf),
Hannes Reinecke 1c98d5
 				DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
 		kfree(iod->rqstbuf);
Hannes Reinecke 1c98d5
 		list_del(&iod->ls_list);
Hannes Reinecke 1c98d5
@@ -1262,10 +1260,8 @@ static void
Hannes Reinecke 1c98d5
 nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			struct nvmet_fc_ls_iod *iod)
Hannes Reinecke 1c98d5
 {
Hannes Reinecke 1c98d5
-	struct fcnvme_ls_cr_assoc_rqst *rqst =
Hannes Reinecke 1c98d5
-				(struct fcnvme_ls_cr_assoc_rqst *)iod->rqstbuf;
Hannes Reinecke 1c98d5
-	struct fcnvme_ls_cr_assoc_acc *acc =
Hannes Reinecke 1c98d5
-				(struct fcnvme_ls_cr_assoc_acc *)iod->rspbuf;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_assoc_rqst *rqst = &iod->rqstbuf->rq_cr_assoc;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_assoc_acc *acc = &iod->rspbuf->rsp_cr_assoc;
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgt_queue *queue;
Hannes Reinecke 1c98d5
 	int ret = 0;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -1313,7 +1309,7 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			"Create Association LS failed: %s\n",
Hannes Reinecke 1c98d5
 			validation_errors[ret]);
Hannes Reinecke 1c98d5
 		iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
+				sizeof(*acc), rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
 				FCNVME_RJT_RC_LOGIC,
Hannes Reinecke 1c98d5
 				FCNVME_RJT_EXP_NONE, 0);
Hannes Reinecke 1c98d5
 		return;
Hannes Reinecke 1c98d5
@@ -1348,10 +1344,8 @@ static void
Hannes Reinecke 1c98d5
 nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			struct nvmet_fc_ls_iod *iod)
Hannes Reinecke 1c98d5
 {
Hannes Reinecke 1c98d5
-	struct fcnvme_ls_cr_conn_rqst *rqst =
Hannes Reinecke 1c98d5
-				(struct fcnvme_ls_cr_conn_rqst *)iod->rqstbuf;
Hannes Reinecke 1c98d5
-	struct fcnvme_ls_cr_conn_acc *acc =
Hannes Reinecke 1c98d5
-				(struct fcnvme_ls_cr_conn_acc *)iod->rspbuf;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_conn_rqst *rqst = &iod->rqstbuf->rq_cr_conn;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_cr_conn_acc *acc = &iod->rspbuf->rsp_cr_conn;
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgt_queue *queue;
Hannes Reinecke 1c98d5
 	int ret = 0;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -1404,7 +1398,7 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			"Create Connection LS failed: %s\n",
Hannes Reinecke 1c98d5
 			validation_errors[ret]);
Hannes Reinecke 1c98d5
 		iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
+				sizeof(*acc), rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
 				(ret == VERR_NO_ASSOC) ?
Hannes Reinecke 1c98d5
 					FCNVME_RJT_RC_INV_ASSOC :
Hannes Reinecke 1c98d5
 					FCNVME_RJT_RC_LOGIC,
Hannes Reinecke 1c98d5
@@ -1437,9 +1431,9 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			struct nvmet_fc_ls_iod *iod)
Hannes Reinecke 1c98d5
 {
Hannes Reinecke 1c98d5
 	struct fcnvme_ls_disconnect_assoc_rqst *rqst =
Hannes Reinecke 1c98d5
-			(struct fcnvme_ls_disconnect_assoc_rqst *)iod->rqstbuf;
Hannes Reinecke 1c98d5
+						&iod->rqstbuf->rq_dis_assoc;
Hannes Reinecke 1c98d5
 	struct fcnvme_ls_disconnect_assoc_acc *acc =
Hannes Reinecke 1c98d5
-			(struct fcnvme_ls_disconnect_assoc_acc *)iod->rspbuf;
Hannes Reinecke 1c98d5
+						&iod->rspbuf->rsp_dis_assoc;
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgt_assoc *assoc;
Hannes Reinecke 1c98d5
 	int ret = 0;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -1484,7 +1478,7 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			"Disconnect LS failed: %s\n",
Hannes Reinecke 1c98d5
 			validation_errors[ret]);
Hannes Reinecke 1c98d5
 		iod->lsrsp->rsplen = nvme_fc_format_rjt(acc,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
+				sizeof(*acc), rqst->w0.ls_cmd,
Hannes Reinecke 1c98d5
 				(ret == VERR_NO_ASSOC) ?
Hannes Reinecke 1c98d5
 					FCNVME_RJT_RC_INV_ASSOC :
Hannes Reinecke 1c98d5
 					FCNVME_RJT_RC_LOGIC,
Hannes Reinecke 1c98d5
@@ -1522,7 +1516,7 @@ nvmet_fc_xmt_ls_rsp_done(struct nvmefc_ls_rsp *lsrsp)
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgtport *tgtport = iod->tgtport;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	fc_dma_sync_single_for_cpu(tgtport->dev, iod->rspdma,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
+				sizeof(*iod->rspbuf), DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
 	nvmet_fc_free_ls_iod(tgtport, iod);
Hannes Reinecke 1c98d5
 	nvmet_fc_tgtport_put(tgtport);
Hannes Reinecke 1c98d5
 }
Hannes Reinecke 1c98d5
@@ -1534,7 +1528,7 @@ nvmet_fc_xmt_ls_rsp(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 	int ret;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	fc_dma_sync_single_for_device(tgtport->dev, iod->rspdma,
Hannes Reinecke 1c98d5
-				  NVME_FC_MAX_LS_BUFFER_SIZE, DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
+				  sizeof(*iod->rspbuf), DMA_TO_DEVICE);
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	ret = tgtport->ops->xmt_ls_rsp(&tgtport->fc_target_port, iod->lsrsp);
Hannes Reinecke 1c98d5
 	if (ret)
Hannes Reinecke 1c98d5
@@ -1548,8 +1542,7 @@ static void
Hannes Reinecke 1c98d5
 nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 			struct nvmet_fc_ls_iod *iod)
Hannes Reinecke 1c98d5
 {
Hannes Reinecke 1c98d5
-	struct fcnvme_ls_rqst_w0 *w0 =
Hannes Reinecke 1c98d5
-			(struct fcnvme_ls_rqst_w0 *)iod->rqstbuf;
Hannes Reinecke 1c98d5
+	struct fcnvme_ls_rqst_w0 *w0 = &iod->rqstbuf->rq_cr_assoc.w0;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	iod->lsrsp->nvme_fc_private = iod;
Hannes Reinecke 1c98d5
 	iod->lsrsp->rspbuf = iod->rspbuf;
Hannes Reinecke 1c98d5
@@ -1580,7 +1573,7 @@ nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
Hannes Reinecke 1c98d5
 		break;
Hannes Reinecke 1c98d5
 	default:
Hannes Reinecke 1c98d5
 		iod->lsrsp->rsplen = nvme_fc_format_rjt(iod->rspbuf,
Hannes Reinecke 1c98d5
-				NVME_FC_MAX_LS_BUFFER_SIZE, w0->ls_cmd,
Hannes Reinecke 1c98d5
+				sizeof(*iod->rspbuf), w0->ls_cmd,
Hannes Reinecke 1c98d5
 				FCNVME_RJT_RC_INVAL, FCNVME_RJT_EXP_NONE, 0);
Hannes Reinecke 1c98d5
 	}
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
@@ -1627,7 +1620,7 @@ nvmet_fc_rcv_ls_req(struct nvmet_fc_target_port *target_port,
Hannes Reinecke 1c98d5
 	struct nvmet_fc_tgtport *tgtport = targetport_to_tgtport(target_port);
Hannes Reinecke 1c98d5
 	struct nvmet_fc_ls_iod *iod;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
-	if (lsreqbuf_len > NVME_FC_MAX_LS_BUFFER_SIZE)
Hannes Reinecke 1c98d5
+	if (lsreqbuf_len > sizeof(union nvmefc_ls_requests))
Hannes Reinecke 1c98d5
 		return -E2BIG;
Hannes Reinecke 1c98d5
 
Hannes Reinecke 1c98d5
 	if (!nvmet_fc_tgtport_get(tgtport))
Hannes Reinecke 1c98d5
-- 
Hannes Reinecke 1c98d5
2.16.4
Hannes Reinecke 1c98d5