Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright (c) 2016, Avago Technologies
0004  */
0005 
0006 #ifndef _NVME_FC_TRANSPORT_H
0007 #define _NVME_FC_TRANSPORT_H 1
0008 
0009 
0010 /*
0011  * Common definitions between the nvme_fc (host) transport and
0012  * nvmet_fc (target) transport implementation.
0013  */
0014 
0015 /*
0016  * ******************  FC-NVME LS HANDLING ******************
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);   /* alignment for other things alloc'd with */
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);   /* alignment for other things alloc'd with */
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 /* Validation Error indexes into the string table below */
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      * As the standard changed on the LS, check if old format and scope
0219      * something other than Association (e.g. 0).
0220      */
0221     else if (rqst->discon_cmd.rsvd8[0])
0222         ret = VERR_DISCONN_SCOPE;
0223 
0224     return ret;
0225 }
0226 
0227 #endif /* _NVME_FC_TRANSPORT_H */