nvme_fc: repost spec updates and fixes
Subsystems (3)
cover nvme_fc: repost spec updates and fixes
From: James Smart <[email protected]>
The following items have been posted prior, but not pulled in. Resubmitting
James Smart (6):
nvme_fc: Sync FC-NVME header with standard
nvme_fc: Add check of status_code in ERSP_IU
nvmet_fc: Sync NVME LS reject reasons with spec
nvme_fc: correct LS validation
nvmet_fc: Clear SG list to avoid double frees
nvme_fc: Clean up host fcpio done status handling
drivers/nvme/host/fc.c | 24 ++++++++------- drivers/nvme/target/fc.c | 21 ++++++++----- include/linux/nvme-fc-driver.h | 6 ++-- include/linux/nvme-fc.h | 68 ++++++++++++++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 30 deletions(-)
Signature · 1 line
2.9.3
PATCH 1/6 nvme_fc: Sync FC-NVME header with standard
From: James Smart <[email protected]>
Update FC-NVME definitions to match FC-NVME r1.14 (16-020vB) plus change voted in by 2/22 FC-NVME Adhoc (see HOSTID below).
Includes the following:
- Addition of "status_code" field to ERSP IU
- Addition of FC-NVME LS RJT reason_codes and reason_explanations
- CreateAssociation payload, HostID field shortened to 16 bytes
--- include/linux/nvme-fc.h | 68 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 9 deletions(-)
include/linux/nvme-fc.h +59 -9
@@ -16,8 +16,7 @@*/ /* -* This file contains definitions relative to FC-NVME r1.11 and a few -* newer items +* This file contains definitions relative to FC-NVME r1.14 (16-020vB). */ #ifndef _NVME_FC_H
@@ -47,8 +46,15 @@ struct nvme_fc_cmd_iu {#define NVME_FC_SIZEOF_ZEROS_RSP 12 +enum { +FCNVME_SC_SUCCESS =0 , +FCNVME_SC_INVALID_FIELD =1 , +FCNVME_SC_INVALID_CONNID =2 , +}; +struct nvme_fc_ersp_iu { -__u8 rsvd0[2 ]; +__u8 status_code; +__u8 rsvd1;__be16 iu_len;__be32 rsn;__be32 xfrd_len;
@@ -58,7 +64,7 @@ struct nvme_fc_ersp_iu { }; -/* FC-NVME r1.03/16-119v0 NVME Link Services */ +/* FC-NVME Link Services */ enum {FCNVME_LS_RSVD =0 ,FCNVME_LS_RJT =1 ,
@@ -68,7 +74,7 @@ enum { FCNVME_LS_DISCONNECT = 5, }; -/* FC-NVME r1.03/16-119v0 NVME Link Service Descriptors */ +/* FC-NVME Link Service Descriptors */ enum {FCNVME_LSDESC_RSVD =0x0 ,FCNVME_LSDESC_RQST =0x1 ,
@@ -92,7 +98,6 @@ static inline __be32 fcnvme_lsdesc_len(size_t sz)return cpu_to_be32 (sz - (2 *sizeof (u32))); } -struct fcnvme_ls_rqst_w0 {u8 ls_cmd;/* FCNVME_LS_xxx */ u8 zeros[3 ];
@@ -106,8 +111,53 @@ struct fcnvme_lsdesc_rqst {__be32 rsvd12; }; +/* FC-NVME LS RJT reason_code values */ +enum fcnvme_ls_rjt_reason { +FCNVME_RJT_RC_NONE =0 , +/* no reason - not to be sent */ + +FCNVME_RJT_RC_INVAL =0x01 , +/* invalid NVMe_LS command code */ + +FCNVME_RJT_RC_LOGIC =0x03 , +/* logical error */ + +FCNVME_RJT_RC_UNAB =0x09 , +/* unable to perform command request */ + +FCNVME_RJT_RC_UNSUP =0x0b , +/* command not supported */ + +FCNVME_RJT_RC_INPROG =0x0e , +/* command already in progress */ +FCNVME_RJT_RC_INV_ASSOC =0x40 , +/* Invalid Association ID*/ +FCNVME_RJT_RC_INV_CONN =0x41 , +/* Invalid Connection ID*/ + +FCNVME_RJT_RC_VENDOR =0xff , +/* vendor specific error */ +}; + +/* FC-NVME LS RJT reason_explanation values */ +enum fcnvme_ls_rjt_explan { +FCNVME_RJT_EXP_NONE =0x00 , +/* No additional explanation */ + +FCNVME_RJT_EXP_OXID_RXID =0x17 , +/* invalid OX_ID-RX_ID combination */ + +FCNVME_RJT_EXP_INSUF_RES =0x29 , +/* insufficient resources */ + +FCNVME_RJT_EXP_UNAB_DATA =0x2a , +/* unable to supply requested data */ + +FCNVME_RJT_EXP_INV_LEN =0x2d , +/* Invalid payload length */ +};/* FCNVME_LSDESC_RJT */ struct fcnvme_lsdesc_rjt {
@@ -119,15 +169,15 @@ struct fcnvme_lsdesc_rjt {* Reject reason and explanaction codes are generic * to ELs's from LS-3. */ -u8 reason_code; -u8 reason_explanation; +u8 reason_code;/* fcnvme_ls_rjt_reason */ +u8 reason_explanation;/* fcnvme_ls_rjt_explan */ u8 vendor;__be32 rsvd12; }; -#define FCNVME_ASSOC_HOSTID_LEN 64 +#define FCNVME_ASSOC_HOSTID_LEN 16#define FCNVME_ASSOC_HOSTNQN_LEN 256#define FCNVME_ASSOC_SUBNQN_LEN 256
Signature · 1 line
2.9.3
PATCH 1/6 nvme_fc: Sync FC-NVME header with standard
Looks fine,
PATCH 2/6 nvme_fc: Add check of status_code in ERSP_IU
In reply to [email protected]From: James Smart <[email protected]>
Add check of status_code in ERSP_IU
--- drivers/nvme/host/fc.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/host/fc.c +1 -0
@@ -1226,6 +1226,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) (freq->rcv_rsplen / 4) || be32_to_cpu(op->rsp_iu.xfrd_len) != freq->transferred_length || + op->rsp_iu.status_code || op->rqno != le16_to_cpu(cqe->command_id))) { status = -EIO ; goto done;
Signature · 1 line
2.9.3
PATCH 2/6 nvme_fc: Add check of status_code in ERSP_IU
Looks fine,
PATCH 3/6 nvmet_fc: Sync NVME LS reject reasons with spec
In reply to [email protected]From: James Smart <[email protected]>
nvmet_fc: Sync NVME LS reject reasons with spec
--- drivers/nvme/target/fc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/nvme/target/fc.c +12 -7
@@ -1189,8 +1189,8 @@ nvmet_fc_ls_create_association(struct nvmet_fc_tgtport *tgtport, validation_errors[ret]); iod->lsreq->rsplen =nvmet_fc_format_rjt (acc,NVME_FC_MAX_LS_BUFFER_SIZE , rqst->w0.ls_cmd, -ELS_RJT_LOGIC , -ELS_EXPL_NONE ,0 ); +FCNVME_RJT_RC_LOGIC , +FCNVME_RJT_EXP_NONE ,0 );return ; }
@@ -1281,8 +1281,9 @@ nvmet_fc_ls_create_connection(struct nvmet_fc_tgtport *tgtport, iod->lsreq->rsplen =nvmet_fc_format_rjt (acc,NVME_FC_MAX_LS_BUFFER_SIZE , rqst->w0.ls_cmd, (ret ==VERR_NO_ASSOC ) ? -ELS_RJT_PROT :ELS_RJT_LOGIC , -ELS_EXPL_NONE ,0 ); +FCNVME_RJT_RC_INV_ASSOC : +FCNVME_RJT_RC_LOGIC , +FCNVME_RJT_EXP_NONE ,0 );return ; }
@@ -1369,8 +1370,12 @@ nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport, validation_errors[ret]); iod->lsreq->rsplen =nvmet_fc_format_rjt (acc,NVME_FC_MAX_LS_BUFFER_SIZE , rqst->w0.ls_cmd, - (ret ==8 ) ?ELS_RJT_PROT :ELS_RJT_LOGIC , -ELS_EXPL_NONE ,0 ); + (ret ==VERR_NO_ASSOC ) ? +FCNVME_RJT_RC_INV_ASSOC : + (ret ==VERR_NO_CONN ) ? +FCNVME_RJT_RC_INV_CONN : +FCNVME_RJT_RC_LOGIC , +FCNVME_RJT_EXP_NONE ,0 );return ; }
@@ -1479,7 +1484,7 @@ nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,default : iod->lsreq->rsplen =nvmet_fc_format_rjt (iod->rspbuf,NVME_FC_MAX_LS_BUFFER_SIZE , w0->ls_cmd, -ELS_RJT_INVAL ,ELS_EXPL_NONE ,0 ); +FCNVME_RJT_RC_INVAL ,FCNVME_RJT_EXP_NONE ,0 ); }nvmet_fc_xmt_ls_rsp (tgtport, iod);
Signature · 1 line
2.9.3
PATCH 3/6 nvmet_fc: Sync NVME LS reject reasons with spec
Looks fine,
PATCH 4/6 nvme_fc: correct LS validation
In reply to [email protected]From: James Smart <[email protected]>
LS validations shouldn't have been independent checks.
--- drivers/nvme/host/fc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/nvme/host/fc.c +5 -4
@@ -848,11 +848,12 @@ nvme_fc_connect_admin_queue(struct nvme_fc_ctrl *ctrl,/* validate the ACC response */ if (assoc_acc->hdr.w0.ls_cmd !=FCNVME_LS_ACC ) fcret =VERR_LSACC ; -if (assoc_acc->hdr.desc_list_len != +else if (assoc_acc->hdr.desc_list_len !=fcnvme_lsdesc_len (sizeof (struct fcnvme_ls_cr_assoc_acc ))) fcret =VERR_CR_ASSOC_ACC_LEN ; -if (assoc_acc->hdr.rqst.desc_tag !=cpu_to_be32 (FCNVME_LSDESC_RQST )) +else if (assoc_acc->hdr.rqst.desc_tag != +cpu_to_be32 (FCNVME_LSDESC_RQST )) fcret =VERR_LSDESC_RQST ;else if (assoc_acc->hdr.rqst.desc_len !=fcnvme_lsdesc_len (sizeof (struct fcnvme_lsdesc_rqst )))
@@ -955,10 +956,10 @@ nvme_fc_connect_queue(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue,/* validate the ACC response */ if (conn_acc->hdr.w0.ls_cmd !=FCNVME_LS_ACC ) fcret =VERR_LSACC ; -if (conn_acc->hdr.desc_list_len != +else if (conn_acc->hdr.desc_list_len !=fcnvme_lsdesc_len (sizeof (struct fcnvme_ls_cr_conn_acc ))) fcret =VERR_CR_CONN_ACC_LEN ; -if (conn_acc->hdr.rqst.desc_tag !=cpu_to_be32 (FCNVME_LSDESC_RQST )) +else if (conn_acc->hdr.rqst.desc_tag !=cpu_to_be32 (FCNVME_LSDESC_RQST )) fcret =VERR_LSDESC_RQST ;else if (conn_acc->hdr.rqst.desc_len !=fcnvme_lsdesc_len (sizeof (struct fcnvme_lsdesc_rqst )))
Signature · 1 line
2.9.3
PATCH 4/6 nvme_fc: correct LS validation
Looks fine,
PATCH 5/6 nvmet_fc: Clear SG list to avoid double frees
In reply to [email protected]From: James Smart <[email protected]>
Clear SG list to avoid double frees of payload page list
--- drivers/nvme/target/fc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/nvme/target/fc.c +2 -0
@@ -1624,6 +1624,8 @@ nvmet_fc_free_tgt_pgs(struct nvmet_fc_fcp_iod *fod)for_each_sg (fod->data_sg, sg, fod->data_sg_cnt, count)__free_page (sg_page (sg));kfree (fod->data_sg); + fod->data_sg =NULL ; + fod->data_sg_cnt =0 ; }
Signature · 1 line
2.9.3
PATCH 5/6 nvmet_fc: Clear SG list to avoid double frees
Looks fine,
PATCH 6/6 nvme_fc: Clean up host fcpio done status handling
In reply to [email protected]From: James Smart <[email protected]>
As Dan Carpenter pointed out: mixing 16-bit nvme status with 32-bit error status from driver. Corrected comment on fcp request struct status field, and converted done routine to explicitly set nvme status codes for nvme status.
--- drivers/nvme/host/fc.c | 14 +++++++------- include/linux/nvme-fc-driver.h | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-)
drivers/nvme/host/fc.c +7 -7
@@ -1147,7 +1147,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)struct nvme_fc_ctrl *ctrl = op->ctrl;struct nvme_fc_queue *queue = op->queue;struct nvme_completion *cqe = &op->rsp_iu.cqe; -u16 status; +u16 status =NVME_SC_SUCCESS ;/* * WARNING:
@@ -1183,8 +1183,8 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)if (atomic_read (&op->state) ==FCPOP_STATE_ABORTED ) status =NVME_SC_ABORT_REQ |NVME_SC_DNR ; -else - status = freq->status; +else if (freq->status) + status =NVME_SC_FC_TRANSPORT_ERROR ;/* * For the linux implementation, if we have an unsuccesful
@@ -1212,7 +1212,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)*/ if (freq->transferred_length !=be32_to_cpu (op->cmd_iu.data_len)) { - status = -EIO ; + status =NVME_SC_FC_TRANSPORT_ERROR ; goto done; } op->nreq.result.u64 =0 ;
@@ -1229,7 +1229,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req) freq->transferred_length || op->rsp_iu.status_code || op->rqno != le16_to_cpu(cqe->command_id))) { - status = -EIO ; + status =NVME_SC_FC_TRANSPORT_ERROR ; goto done; } op->nreq.result = cqe->result;
@@ -1237,7 +1237,7 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)break ;default : - status = -EIO ; + status =NVME_SC_FC_TRANSPORT_ERROR ; goto done; }
@@ -1763,7 +1763,7 @@ nvme_fc_start_fcp_op(struct nvme_fc_ctrl *ctrl, struct nvme_fc_queue *queue, op->fcp_req.io_dir = io_dir; op->fcp_req.transferred_length =0 ; op->fcp_req.rcv_rsplen =0 ; - op->fcp_req.status =0 ; + op->fcp_req.status =NVME_SC_SUCCESS ; op->fcp_req.sqid =cpu_to_le16 (queue->qnum);/*
include/linux/nvme-fc-driver.h +3 -3
@@ -137,9 +137,9 @@ enum nvmefc_fcp_datadir {* transferred. Should equal payload_length on success. * @rcv_rsplen: length, in bytes, of the FCP RSP IU received. * @status: Completion status of the FCP operation. must be 0 upon success, -* NVME_SC_FC_xxx value upon failure. Note: this is NOT a -* reflection of the NVME CQE completion status. Only the status -* of the FCP operation at the NVME-FC level. +* negative errno value upon failure (ex: -EIO). Note: this is +* NOT a reflection of the NVME CQE completion status. Only the +* status of the FCP operation at the NVME-FC level. */ struct nvmefc_fcp_req {void *cmdaddr;
Signature · 1 line
2.9.3
PATCH 6/6 nvme_fc: Clean up host fcpio done status handling
Looks fine,