linux/drivers/nvme/host/fc.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Copyright (c) 2016, Avago Technologies
   4 */
   5
   6#ifndef _NVME_FC_TRANSPORT_H
   7#define _NVME_FC_TRANSPORT_H 1
   8
   9
  10/*
  11 * Common definitions between the nvme_fc (host) transport and
  12 * nvmet_fc (target) transport implementation.
  13 */
  14
  15/*
  16 * ******************  FC-NVME LS HANDLING ******************
  17 */
  18
  19union nvmefc_ls_requests {
  20        struct fcnvme_ls_rqst_w0                w0;
  21        struct fcnvme_ls_cr_assoc_rqst          rq_cr_assoc;
  22        struct fcnvme_ls_cr_conn_rqst           rq_cr_conn;
  23        struct fcnvme_ls_disconnect_assoc_rqst  rq_dis_assoc;
  24        struct fcnvme_ls_disconnect_conn_rqst   rq_dis_conn;
  25} __aligned(128);       /* alignment for other things alloc'd with */
  26
  27union nvmefc_ls_responses {
  28        struct fcnvme_ls_rjt                    rsp_rjt;
  29        struct fcnvme_ls_cr_assoc_acc           rsp_cr_assoc;
  30        struct fcnvme_ls_cr_conn_acc            rsp_cr_conn;
  31        struct fcnvme_ls_disconnect_assoc_acc   rsp_dis_assoc;
  32        struct fcnvme_ls_disconnect_conn_acc    rsp_dis_conn;
  33} __aligned(128);       /* alignment for other things alloc'd with */
  34
  35static inline void
  36nvme_fc_format_rsp_hdr(void *buf, u8 ls_cmd, __be32 desc_len, u8 rqst_ls_cmd)
  37{
  38        struct fcnvme_ls_acc_hdr *acc = buf;
  39
  40        acc->w0.ls_cmd = ls_cmd;
  41        acc->desc_list_len = desc_len;
  42        acc->rqst.desc_tag = cpu_to_be32(FCNVME_LSDESC_RQST);
  43        acc->rqst.desc_len =
  44                        fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rqst));
  45        acc->rqst.w0.ls_cmd = rqst_ls_cmd;
  46}
  47
  48static inline int
  49nvme_fc_format_rjt(void *buf, u16 buflen, u8 ls_cmd,
  50                        u8 reason, u8 explanation, u8 vendor)
  51{
  52        struct fcnvme_ls_rjt *rjt = buf;
  53
  54        nvme_fc_format_rsp_hdr(buf, FCNVME_LSDESC_RQST,
  55                        fcnvme_lsdesc_len(sizeof(struct fcnvme_ls_rjt)),
  56                        ls_cmd);
  57        rjt->rjt.desc_tag = cpu_to_be32(FCNVME_LSDESC_RJT);
  58        rjt->rjt.desc_len = fcnvme_lsdesc_len(sizeof(struct fcnvme_lsdesc_rjt));
  59        rjt->rjt.reason_code = reason;
  60        rjt->rjt.reason_explanation = explanation;
  61        rjt->rjt.vendor = vendor;
  62
  63        return sizeof(struct fcnvme_ls_rjt);
  64}
  65
  66/* Validation Error indexes into the string table below */
  67enum {
  68        VERR_NO_ERROR           = 0,
  69        VERR_CR_ASSOC_LEN       = 1,
  70        VERR_CR_ASSOC_RQST_LEN  = 2,
  71        VERR_CR_ASSOC_CMD       = 3,
  72        VERR_CR_ASSOC_CMD_LEN   = 4,
  73        VERR_ERSP_RATIO         = 5,
  74        VERR_ASSOC_ALLOC_FAIL   = 6,
  75        VERR_QUEUE_ALLOC_FAIL   = 7,
  76        VERR_CR_CONN_LEN        = 8,
  77        VERR_CR_CONN_RQST_LEN   = 9,
  78        VERR_ASSOC_ID           = 10,
  79        VERR_ASSOC_ID_LEN       = 11,
  80        VERR_NO_ASSOC           = 12,
  81        VERR_CONN_ID            = 13,
  82        VERR_CONN_ID_LEN        = 14,
  83        VERR_INVAL_CONN         = 15,
  84        VERR_CR_CONN_CMD        = 16,
  85        VERR_CR_CONN_CMD_LEN    = 17,
  86        VERR_DISCONN_LEN        = 18,
  87        VERR_DISCONN_RQST_LEN   = 19,
  88        VERR_DISCONN_CMD        = 20,
  89        VERR_DISCONN_CMD_LEN    = 21,
  90        VERR_DISCONN_SCOPE      = 22,
  91        VERR_RS_LEN             = 23,
  92        VERR_RS_RQST_LEN        = 24,
  93        VERR_RS_CMD             = 25,
  94        VERR_RS_CMD_LEN         = 26,
  95        VERR_RS_RCTL            = 27,
  96        VERR_RS_RO              = 28,
  97        VERR_LSACC              = 29,
  98        VERR_LSDESC_RQST        = 30,
  99        VERR_LSDESC_RQST_LEN    = 31,
 100        VERR_CR_ASSOC           = 32,
 101        VERR_CR_ASSOC_ACC_LEN   = 33,
 102        VERR_CR_CONN            = 34,
 103        VERR_CR_CONN_ACC_LEN    = 35,
 104        VERR_DISCONN            = 36,
 105        VERR_DISCONN_ACC_LEN    = 37,
 106};
 107
 108static char *validation_errors[] = {
 109        "OK",
 110        "Bad CR_ASSOC Length",
 111        "Bad CR_ASSOC Rqst Length",
 112        "Not CR_ASSOC Cmd",
 113        "Bad CR_ASSOC Cmd Length",
 114        "Bad Ersp Ratio",
 115        "Association Allocation Failed",
 116        "Queue Allocation Failed",
 117        "Bad CR_CONN Length",
 118        "Bad CR_CONN Rqst Length",
 119        "Not Association ID",
 120        "Bad Association ID Length",
 121        "No Association",
 122        "Not Connection ID",
 123        "Bad Connection ID Length",
 124        "Invalid Connection ID",
 125        "Not CR_CONN Cmd",
 126        "Bad CR_CONN Cmd Length",
 127        "Bad DISCONN Length",
 128        "Bad DISCONN Rqst Length",
 129        "Not DISCONN Cmd",
 130        "Bad DISCONN Cmd Length",
 131        "Bad Disconnect Scope",
 132        "Bad RS Length",
 133        "Bad RS Rqst Length",
 134        "Not RS Cmd",
 135        "Bad RS Cmd Length",
 136        "Bad RS R_CTL",
 137        "Bad RS Relative Offset",
 138        "Not LS_ACC",
 139        "Not LSDESC_RQST",
 140        "Bad LSDESC_RQST Length",
 141        "Not CR_ASSOC Rqst",
 142        "Bad CR_ASSOC ACC Length",
 143        "Not CR_CONN Rqst",
 144        "Bad CR_CONN ACC Length",
 145        "Not Disconnect Rqst",
 146        "Bad Disconnect ACC Length",
 147};
 148
 149#define NVME_FC_LAST_LS_CMD_VALUE       FCNVME_LS_DISCONNECT_CONN
 150
 151static char *nvmefc_ls_names[] = {
 152        "Reserved (0)",
 153        "RJT (1)",
 154        "ACC (2)",
 155        "Create Association",
 156        "Create Connection",
 157        "Disconnect Association",
 158        "Disconnect Connection",
 159};
 160
 161static inline void
 162nvmefc_fmt_lsreq_discon_assoc(struct nvmefc_ls_req *lsreq,
 163        struct fcnvme_ls_disconnect_assoc_rqst *discon_rqst,
 164        struct fcnvme_ls_disconnect_assoc_acc *discon_acc,
 165        u64 association_id)
 166{
 167        lsreq->rqstaddr = discon_rqst;
 168        lsreq->rqstlen = sizeof(*discon_rqst);
 169        lsreq->rspaddr = discon_acc;
 170        lsreq->rsplen = sizeof(*discon_acc);
 171        lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
 172
 173        discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT_ASSOC;
 174        discon_rqst->desc_list_len = cpu_to_be32(
 175                                sizeof(struct fcnvme_lsdesc_assoc_id) +
 176                                sizeof(struct fcnvme_lsdesc_disconn_cmd));
 177
 178        discon_rqst->associd.desc_tag = cpu_to_be32(FCNVME_LSDESC_ASSOC_ID);
 179        discon_rqst->associd.desc_len =
 180                        fcnvme_lsdesc_len(
 181                                sizeof(struct fcnvme_lsdesc_assoc_id));
 182
 183        discon_rqst->associd.association_id = cpu_to_be64(association_id);
 184
 185        discon_rqst->discon_cmd.desc_tag = cpu_to_be32(
 186                                                FCNVME_LSDESC_DISCONN_CMD);
 187        discon_rqst->discon_cmd.desc_len =
 188                        fcnvme_lsdesc_len(
 189                                sizeof(struct fcnvme_lsdesc_disconn_cmd));
 190}
 191
 192static inline int
 193nvmefc_vldt_lsreq_discon_assoc(u32 rqstlen,
 194        struct fcnvme_ls_disconnect_assoc_rqst *rqst)
 195{
 196        int ret = 0;
 197
 198        if (rqstlen < sizeof(struct fcnvme_ls_disconnect_assoc_rqst))
 199                ret = VERR_DISCONN_LEN;
 200        else if (rqst->desc_list_len !=
 201                        fcnvme_lsdesc_len(
 202                                sizeof(struct fcnvme_ls_disconnect_assoc_rqst)))
 203                ret = VERR_DISCONN_RQST_LEN;
 204        else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
 205                ret = VERR_ASSOC_ID;
 206        else if (rqst->associd.desc_len !=
 207                        fcnvme_lsdesc_len(
 208                                sizeof(struct fcnvme_lsdesc_assoc_id)))
 209                ret = VERR_ASSOC_ID_LEN;
 210        else if (rqst->discon_cmd.desc_tag !=
 211                        cpu_to_be32(FCNVME_LSDESC_DISCONN_CMD))
 212                ret = VERR_DISCONN_CMD;
 213        else if (rqst->discon_cmd.desc_len !=
 214                        fcnvme_lsdesc_len(
 215                                sizeof(struct fcnvme_lsdesc_disconn_cmd)))
 216                ret = VERR_DISCONN_CMD_LEN;
 217        /*
 218         * As the standard changed on the LS, check if old format and scope
 219         * something other than Association (e.g. 0).
 220         */
 221        else if (rqst->discon_cmd.rsvd8[0])
 222                ret = VERR_DISCONN_SCOPE;
 223
 224        return ret;
 225}
 226
 227#endif /* _NVME_FC_TRANSPORT_H */
 228