0001
0002
0003
0004
0005
0006 #ifndef _NVME_FC_TRANSPORT_H
0007 #define _NVME_FC_TRANSPORT_H 1
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 union nvmefc_ls_requests {
0020 struct fcnvme_ls_rqst_w0 w0;
0021 struct fcnvme_ls_cr_assoc_rqst rq_cr_assoc;
0022 struct fcnvme_ls_cr_conn_rqst rq_cr_conn;
0023 struct fcnvme_ls_disconnect_assoc_rqst rq_dis_assoc;
0024 struct fcnvme_ls_disconnect_conn_rqst rq_dis_conn;
0025 } __aligned(128);
0026
0027 union nvmefc_ls_responses {
0028 struct fcnvme_ls_rjt rsp_rjt;
0029 struct fcnvme_ls_cr_assoc_acc rsp_cr_assoc;
0030 struct fcnvme_ls_cr_conn_acc rsp_cr_conn;
0031 struct fcnvme_ls_disconnect_assoc_acc rsp_dis_assoc;
0032 struct fcnvme_ls_disconnect_conn_acc rsp_dis_conn;
0033 } __aligned(128);
0034
0035 static inline void
0036 nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
0037 {
0038 struct fcnvme_ls_acc_hdr *acc = buf;
0039
0040 acc->w0.ls_cmd = ls_cmd;
0041 acc->desc_list_len = desc_len;
0042 acc->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST);
0043 acc->rqst.desc_len =
0044 fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst));
0045 acc->rqst.w0.ls_cmd = rqst_ls_cmd;
0046 }
0047
0048 static inline int
0049 nvme_fc_format_rjt(void *buf, u16 buflen, u8 ls_cmd,
0050 u8 reason, u8 explanation, u8 vendor)
0051 {
0052 struct fcnvme_ls_rjt *rjt = buf;
0053
0054 nvme_fc_format_rsp_hdr(buf, FCNVME_LSDESC_RQST,
0055 fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)),
0056 ls_cmd);
0057 rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT);
0058 rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt));
0059 rjt->rjt.reason_code = reason;
0060 rjt->rjt.reason_explanation = explanation;
0061 rjt->rjt.vendor = vendor;
0062
0063 return sizeof(struct fcnvme_ls_rjt);
0064 }
0065
0066
0067 enum {
0068 VERR_NO_ERROR = 0,
0069 VERR_CR_ASSOC_LEN = 1,
0070 VERR_CR_ASSOC_RQST_LEN = 2,
0071 VERR_CR_ASSOC_CMD = 3,
0072 VERR_CR_ASSOC_CMD_LEN = 4,
0073 VERR_ERSP_RATIO = 5,
0074 VERR_ASSOC_ALLOC_FAIL = 6,
0075 VERR_QUEUE_ALLOC_FAIL = 7,
0076 VERR_CR_CONN_LEN = 8,
0077 VERR_CR_CONN_RQST_LEN = 9,
0078 VERR_ASSOC_ID = 10,
0079 VERR_ASSOC_ID_LEN = 11,
0080 VERR_NO_ASSOC = 12,
0081 VERR_CONN_ID = 13,
0082 VERR_CONN_ID_LEN = 14,
0083 VERR_INVAL_CONN = 15,
0084 VERR_CR_CONN_CMD = 16,
0085 VERR_CR_CONN_CMD_LEN = 17,
0086 VERR_DISCONN_LEN = 18,
0087 VERR_DISCONN_RQST_LEN = 19,
0088 VERR_DISCONN_CMD = 20,
0089 VERR_DISCONN_CMD_LEN = 21,
0090 VERR_DISCONN_SCOPE = 22,
0091 VERR_RS_LEN = 23,
0092 VERR_RS_RQST_LEN = 24,
0093 VERR_RS_CMD = 25,
0094 VERR_RS_CMD_LEN = 26,
0095 VERR_RS_RCTL = 27,
0096 VERR_RS_RO = 28,
0097 VERR_LSACC = 29,
0098 VERR_LSDESC_RQST = 30,
0099 VERR_LSDESC_RQST_LEN = 31,
0100 VERR_CR_ASSOC = 32,
0101 VERR_CR_ASSOC_ACC_LEN = 33,
0102 VERR_CR_CONN = 34,
0103 VERR_CR_CONN_ACC_LEN = 35,
0104 VERR_DISCONN = 36,
0105 VERR_DISCONN_ACC_LEN = 37,
0106 };
0107
0108 static char *validation_errors[] = {
0109 "OK",
0110 "Bad CR_ASSOC Length",
0111 "Bad CR_ASSOC Rqst Length",
0112 "Not CR_ASSOC Cmd",
0113 "Bad CR_ASSOC Cmd Length",
0114 "Bad Ersp Ratio",
0115 "Association Allocation Failed",
0116 "Queue Allocation Failed",
0117 "Bad CR_CONN Length",
0118 "Bad CR_CONN Rqst Length",
0119 "Not Association ID",
0120 "Bad Association ID Length",
0121 "No Association",
0122 "Not Connection ID",
0123 "Bad Connection ID Length",
0124 "Invalid Connection ID",
0125 "Not CR_CONN Cmd",
0126 "Bad CR_CONN Cmd Length",
0127 "Bad DISCONN Length",
0128 "Bad DISCONN Rqst Length",
0129 "Not DISCONN Cmd",
0130 "Bad DISCONN Cmd Length",
0131 "Bad Disconnect Scope",
0132 "Bad RS Length",
0133 "Bad RS Rqst Length",
0134 "Not RS Cmd",
0135 "Bad RS Cmd Length",
0136 "Bad RS R_CTL",
0137 "Bad RS Relative Offset",
0138 "Not LS_ACC",
0139 "Not LSDESC_RQST",
0140 "Bad LSDESC_RQST Length",
0141 "Not CR_ASSOC Rqst",
0142 "Bad CR_ASSOC ACC Length",
0143 "Not CR_CONN Rqst",
0144 "Bad CR_CONN ACC Length",
0145 "Not Disconnect Rqst",
0146 "Bad Disconnect ACC Length",
0147 };
0148
0149 #define NVME_FC_LAST_LS_CMD_VALUE FCNVME_LS_DISCONNECT_CONN
0150
0151 static char *nvmefc_ls_names[] = {
0152 "Reserved (0)",
0153 "RJT (1)",
0154 "ACC (2)",
0155 "Create Association",
0156 "Create Connection",
0157 "Disconnect Association",
0158 "Disconnect Connection",
0159 };
0160
0161 static inline void
0162 nvmefc_fmt_lsreq_discon_assoc(struct nvmefc_ls_req *lsreq,
0163 struct fcnvme_ls_disconnect_assoc_rqst *discon_rqst,
0164 struct fcnvme_ls_disconnect_assoc_acc *discon_acc,
0165 u64 association_id)
0166 {
0167 lsreq->rqstaddr = discon_rqst;
0168 lsreq->rqstlen = sizeof(*discon_rqst);
0169 lsreq->rspaddr = discon_acc;
0170 lsreq->rsplen = sizeof(*discon_acc);
0171 lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
0172
0173 discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT_ASSOC;
0174 discon_rqst->desc_list_len = cpu_to_be32(
0175 sizeof(struct fcnvme_lsdesc_assoc_id) +
0176 sizeof(struct fcnvme_lsdesc_disconn_cmd));
0177
0178 discon_rqst->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
0179 discon_rqst->associd.desc_len =
0180 fcnvme_lsdesc_len(
0181 sizeof(struct fcnvme_lsdesc_assoc_id));
0182
0183 discon_rqst->associd.association_id = cpu_to_be64(association_id);
0184
0185 discon_rqst->discon_cmd.desc_tag = cpu_to_be32(
0186 FCNVME_LSDESC_DISCONN_CMD);
0187 discon_rqst->discon_cmd.desc_len =
0188 fcnvme_lsdesc_len(
0189 sizeof(struct fcnvme_lsdesc_disconn_cmd));
0190 }
0191
0192 static inline int
0193 nvmefc_vldt_lsreq_discon_assoc(u32 rqstlen,
0194 struct fcnvme_ls_disconnect_assoc_rqst *rqst)
0195 {
0196 int ret = 0;
0197
0198 if (rqstlen < sizeof(struct fcnvme_ls_disconnect_assoc_rqst))
0199 ret = VERR_DISCONN_LEN;
0200 else if (rqst->desc_list_len !=
0201 fcnvme_lsdesc_len(
0202 sizeof(struct fcnvme_ls_disconnect_assoc_rqst)))
0203 ret = VERR_DISCONN_RQST_LEN;
0204 else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
0205 ret = VERR_ASSOC_ID;
0206 else if (rqst->associd.desc_len !=
0207 fcnvme_lsdesc_len(
0208 sizeof(struct fcnvme_lsdesc_assoc_id)))
0209 ret = VERR_ASSOC_ID_LEN;
0210 else if (rqst->discon_cmd.desc_tag !=
0211 cpu_to_be32(FCNVME_LSDESC_DISCONN_CMD))
0212 ret = VERR_DISCONN_CMD;
0213 else if (rqst->discon_cmd.desc_len !=
0214 fcnvme_lsdesc_len(
0215 sizeof(struct fcnvme_lsdesc_disconn_cmd)))
0216 ret = VERR_DISCONN_CMD_LEN;
0217
0218
0219
0220
0221 else if (rqst->discon_cmd.rsvd8[0])
0222 ret = VERR_DISCONN_SCOPE;
0223
0224 return ret;
0225 }
0226
0227 #endif