linux/drivers/scsi/elx/efct/efct_unsol.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
   4 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
   5 */
   6
   7#include "efct_driver.h"
   8#include "efct_unsol.h"
   9
  10#define frame_printf(efct, hdr, fmt, ...) \
  11        do { \
  12                char s_id_text[16]; \
  13                efc_node_fcid_display(ntoh24((hdr)->fh_s_id), \
  14                        s_id_text, sizeof(s_id_text)); \
  15                efc_log_debug(efct, "[%06x.%s] %02x/%04x/%04x: " fmt, \
  16                        ntoh24((hdr)->fh_d_id), s_id_text, \
  17                        (hdr)->fh_r_ctl, be16_to_cpu((hdr)->fh_ox_id), \
  18                        be16_to_cpu((hdr)->fh_rx_id), ##__VA_ARGS__); \
  19        } while (0)
  20
  21static struct efct_node *
  22efct_node_find(struct efct *efct, u32 port_id, u32 node_id)
  23{
  24        struct efct_node *node;
  25        u64 id = (u64)port_id << 32 | node_id;
  26
  27        /*
  28         * During node shutdown, Lookup will be removed first,
  29         * before announcing to backend. So, no new IOs will be allowed
  30         */
  31        /* Find a target node, given s_id and d_id */
  32        node = xa_load(&efct->lookup, id);
  33        if (node)
  34                kref_get(&node->ref);
  35
  36        return node;
  37}
  38
  39static int
  40efct_dispatch_frame(struct efct *efct, struct efc_hw_sequence *seq)
  41{
  42        struct efct_node *node;
  43        struct fc_frame_header *hdr;
  44        u32 s_id, d_id;
  45
  46        hdr = seq->header->dma.virt;
  47
  48        /* extract the s_id and d_id */
  49        s_id = ntoh24(hdr->fh_s_id);
  50        d_id = ntoh24(hdr->fh_d_id);
  51
  52        if (!(hdr->fh_type == FC_TYPE_FCP || hdr->fh_type == FC_TYPE_BLS))
  53                return -EIO;
  54
  55        if (hdr->fh_type == FC_TYPE_FCP) {
  56                node = efct_node_find(efct, d_id, s_id);
  57                if (!node) {
  58                        efc_log_err(efct,
  59                                    "Node not found, drop cmd d_id:%x s_id:%x\n",
  60                                    d_id, s_id);
  61                        efct_hw_sequence_free(&efct->hw, seq);
  62                        return 0;
  63                }
  64
  65                efct_dispatch_fcp_cmd(node, seq);
  66        } else {
  67                node = efct_node_find(efct, d_id, s_id);
  68                if (!node) {
  69                        efc_log_err(efct, "ABTS: Node not found, d_id:%x s_id:%x\n",
  70                                    d_id, s_id);
  71                        return -EIO;
  72                }
  73
  74                efc_log_err(efct, "Received ABTS for Node:%p\n", node);
  75                efct_node_recv_abts_frame(node, seq);
  76        }
  77
  78        kref_put(&node->ref, node->release);
  79        efct_hw_sequence_free(&efct->hw, seq);
  80        return 0;
  81}
  82
  83int
  84efct_unsolicited_cb(void *arg, struct efc_hw_sequence *seq)
  85{
  86        struct efct *efct = arg;
  87
  88        /* Process FCP command */
  89        if (!efct_dispatch_frame(efct, seq))
  90                return 0;
  91
  92        /* Forward frame to discovery lib */
  93        efc_dispatch_frame(efct->efcport, seq);
  94        return 0;
  95}
  96
  97static int
  98efct_fc_tmf_rejected_cb(struct efct_io *io,
  99                        enum efct_scsi_io_status scsi_status,
 100                        u32 flags, void *arg)
 101{
 102        efct_scsi_io_free(io);
 103        return 0;
 104}
 105
 106static void
 107efct_dispatch_unsol_tmf(struct efct_io *io, u8 tm_flags, u32 lun)
 108{
 109        u32 i;
 110        struct {
 111                u32 mask;
 112                enum efct_scsi_tmf_cmd cmd;
 113        } tmflist[] = {
 114        {FCP_TMF_ABT_TASK_SET, EFCT_SCSI_TMF_ABORT_TASK_SET},
 115        {FCP_TMF_CLR_TASK_SET, EFCT_SCSI_TMF_CLEAR_TASK_SET},
 116        {FCP_TMF_LUN_RESET, EFCT_SCSI_TMF_LOGICAL_UNIT_RESET},
 117        {FCP_TMF_TGT_RESET, EFCT_SCSI_TMF_TARGET_RESET},
 118        {FCP_TMF_CLR_ACA, EFCT_SCSI_TMF_CLEAR_ACA} };
 119
 120        io->exp_xfer_len = 0;
 121
 122        for (i = 0; i < ARRAY_SIZE(tmflist); i++) {
 123                if (tmflist[i].mask & tm_flags) {
 124                        io->tmf_cmd = tmflist[i].cmd;
 125                        efct_scsi_recv_tmf(io, lun, tmflist[i].cmd, NULL, 0);
 126                        break;
 127                }
 128        }
 129        if (i == ARRAY_SIZE(tmflist)) {
 130                /* Not handled */
 131                efc_log_err(io->node->efct, "TMF x%x rejected\n", tm_flags);
 132                efct_scsi_send_tmf_resp(io, EFCT_SCSI_TMF_FUNCTION_REJECTED,
 133                                        NULL, efct_fc_tmf_rejected_cb, NULL);
 134        }
 135}
 136
 137static int
 138efct_validate_fcp_cmd(struct efct *efct, struct efc_hw_sequence *seq)
 139{
 140        /*
 141         * If we received less than FCP_CMND_IU bytes, assume that the frame is
 142         * corrupted in some way and drop it.
 143         * This was seen when jamming the FCTL
 144         * fill bytes field.
 145         */
 146        if (seq->payload->dma.len < sizeof(struct fcp_cmnd)) {
 147                struct fc_frame_header  *fchdr = seq->header->dma.virt;
 148
 149                efc_log_debug(efct,
 150                              "drop ox_id %04x payload (%zd) less than (%zd)\n",
 151                              be16_to_cpu(fchdr->fh_ox_id),
 152                              seq->payload->dma.len, sizeof(struct fcp_cmnd));
 153                return -EIO;
 154        }
 155        return 0;
 156}
 157
 158static void
 159efct_populate_io_fcp_cmd(struct efct_io *io, struct fcp_cmnd *cmnd,
 160                         struct fc_frame_header *fchdr, bool sit)
 161{
 162        io->init_task_tag = be16_to_cpu(fchdr->fh_ox_id);
 163        /* note, tgt_task_tag, hw_tag  set when HW io is allocated */
 164        io->exp_xfer_len = be32_to_cpu(cmnd->fc_dl);
 165        io->transferred = 0;
 166
 167        /* The upper 7 bits of CS_CTL is the frame priority thru the SAN.
 168         * Our assertion here is, the priority given to a frame containing
 169         * the FCP cmd should be the priority given to ALL frames contained
 170         * in that IO. Thus we need to save the incoming CS_CTL here.
 171         */
 172        if (ntoh24(fchdr->fh_f_ctl) & FC_FC_RES_B17)
 173                io->cs_ctl = fchdr->fh_cs_ctl;
 174        else
 175                io->cs_ctl = 0;
 176
 177        io->seq_init = sit;
 178}
 179
 180static u32
 181efct_get_flags_fcp_cmd(struct fcp_cmnd *cmnd)
 182{
 183        u32 flags = 0;
 184
 185        switch (cmnd->fc_pri_ta & FCP_PTA_MASK) {
 186        case FCP_PTA_SIMPLE:
 187                flags |= EFCT_SCSI_CMD_SIMPLE;
 188                break;
 189        case FCP_PTA_HEADQ:
 190                flags |= EFCT_SCSI_CMD_HEAD_OF_QUEUE;
 191                break;
 192        case FCP_PTA_ORDERED:
 193                flags |= EFCT_SCSI_CMD_ORDERED;
 194                break;
 195        case FCP_PTA_ACA:
 196                flags |= EFCT_SCSI_CMD_ACA;
 197                break;
 198        }
 199        if (cmnd->fc_flags & FCP_CFL_WRDATA)
 200                flags |= EFCT_SCSI_CMD_DIR_IN;
 201        if (cmnd->fc_flags & FCP_CFL_RDDATA)
 202                flags |= EFCT_SCSI_CMD_DIR_OUT;
 203
 204        return flags;
 205}
 206
 207static void
 208efct_sframe_common_send_cb(void *arg, u8 *cqe, int status)
 209{
 210        struct efct_hw_send_frame_context *ctx = arg;
 211        struct efct_hw *hw = ctx->hw;
 212
 213        /* Free WQ completion callback */
 214        efct_hw_reqtag_free(hw, ctx->wqcb);
 215
 216        /* Free sequence */
 217        efct_hw_sequence_free(hw, ctx->seq);
 218}
 219
 220static int
 221efct_sframe_common_send(struct efct_node *node,
 222                        struct efc_hw_sequence *seq,
 223                        enum fc_rctl r_ctl, u32 f_ctl,
 224                        u8 type, void *payload, u32 payload_len)
 225{
 226        struct efct *efct = node->efct;
 227        struct efct_hw *hw = &efct->hw;
 228        int rc = 0;
 229        struct fc_frame_header *req_hdr = seq->header->dma.virt;
 230        struct fc_frame_header hdr;
 231        struct efct_hw_send_frame_context *ctx;
 232
 233        u32 heap_size = seq->payload->dma.size;
 234        uintptr_t heap_phys_base = seq->payload->dma.phys;
 235        u8 *heap_virt_base = seq->payload->dma.virt;
 236        u32 heap_offset = 0;
 237
 238        /* Build the FC header reusing the RQ header DMA buffer */
 239        memset(&hdr, 0, sizeof(hdr));
 240        hdr.fh_r_ctl = r_ctl;
 241        /* send it back to whomever sent it to us */
 242        memcpy(hdr.fh_d_id, req_hdr->fh_s_id, sizeof(hdr.fh_d_id));
 243        memcpy(hdr.fh_s_id, req_hdr->fh_d_id, sizeof(hdr.fh_s_id));
 244        hdr.fh_type = type;
 245        hton24(hdr.fh_f_ctl, f_ctl);
 246        hdr.fh_ox_id = req_hdr->fh_ox_id;
 247        hdr.fh_rx_id = req_hdr->fh_rx_id;
 248        hdr.fh_cs_ctl = 0;
 249        hdr.fh_df_ctl = 0;
 250        hdr.fh_seq_cnt = 0;
 251        hdr.fh_parm_offset = 0;
 252
 253        /*
 254         * send_frame_seq_id is an atomic, we just let it increment,
 255         * while storing only the low 8 bits to hdr->seq_id
 256         */
 257        hdr.fh_seq_id = (u8)atomic_add_return(1, &hw->send_frame_seq_id);
 258        hdr.fh_seq_id--;
 259
 260        /* Allocate and fill in the send frame request context */
 261        ctx = (void *)(heap_virt_base + heap_offset);
 262        heap_offset += sizeof(*ctx);
 263        if (heap_offset > heap_size) {
 264                efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
 265                            heap_offset, heap_size);
 266                return -EIO;
 267        }
 268
 269        memset(ctx, 0, sizeof(*ctx));
 270
 271        /* Save sequence */
 272        ctx->seq = seq;
 273
 274        /* Allocate a response payload DMA buffer from the heap */
 275        ctx->payload.phys = heap_phys_base + heap_offset;
 276        ctx->payload.virt = heap_virt_base + heap_offset;
 277        ctx->payload.size = payload_len;
 278        ctx->payload.len = payload_len;
 279        heap_offset += payload_len;
 280        if (heap_offset > heap_size) {
 281                efc_log_err(efct, "Fill send frame failed offset %d size %d\n",
 282                            heap_offset, heap_size);
 283                return -EIO;
 284        }
 285
 286        /* Copy the payload in */
 287        memcpy(ctx->payload.virt, payload, payload_len);
 288
 289        /* Send */
 290        rc = efct_hw_send_frame(&efct->hw, (void *)&hdr, FC_SOF_N3,
 291                                FC_EOF_T, &ctx->payload, ctx,
 292                                efct_sframe_common_send_cb, ctx);
 293        if (rc)
 294                efc_log_debug(efct, "efct_hw_send_frame failed: %d\n", rc);
 295
 296        return rc;
 297}
 298
 299static int
 300efct_sframe_send_fcp_rsp(struct efct_node *node, struct efc_hw_sequence *seq,
 301                         void *rsp, u32 rsp_len)
 302{
 303        return efct_sframe_common_send(node, seq, FC_RCTL_DD_CMD_STATUS,
 304                                      FC_FC_EX_CTX |
 305                                      FC_FC_LAST_SEQ |
 306                                      FC_FC_END_SEQ |
 307                                      FC_FC_SEQ_INIT,
 308                                      FC_TYPE_FCP,
 309                                      rsp, rsp_len);
 310}
 311
 312static int
 313efct_sframe_send_task_set_full_or_busy(struct efct_node *node,
 314                                       struct efc_hw_sequence *seq)
 315{
 316        struct fcp_resp_with_ext fcprsp;
 317        struct fcp_cmnd *fcpcmd = seq->payload->dma.virt;
 318        int rc = 0;
 319        unsigned long flags = 0;
 320        struct efct *efct = node->efct;
 321
 322        /* construct task set full or busy response */
 323        memset(&fcprsp, 0, sizeof(fcprsp));
 324        spin_lock_irqsave(&node->active_ios_lock, flags);
 325        fcprsp.resp.fr_status = list_empty(&node->active_ios) ?
 326                                SAM_STAT_BUSY : SAM_STAT_TASK_SET_FULL;
 327        spin_unlock_irqrestore(&node->active_ios_lock, flags);
 328        *((u32 *)&fcprsp.ext.fr_resid) = be32_to_cpu(fcpcmd->fc_dl);
 329
 330        /* send it using send_frame */
 331        rc = efct_sframe_send_fcp_rsp(node, seq, &fcprsp, sizeof(fcprsp));
 332        if (rc)
 333                efc_log_debug(efct, "efct_sframe_send_fcp_rsp failed %d\n", rc);
 334
 335        return rc;
 336}
 337
 338int
 339efct_dispatch_fcp_cmd(struct efct_node *node, struct efc_hw_sequence *seq)
 340{
 341        struct efct *efct = node->efct;
 342        struct fc_frame_header *fchdr = seq->header->dma.virt;
 343        struct fcp_cmnd *cmnd = NULL;
 344        struct efct_io *io = NULL;
 345        u32 lun;
 346
 347        if (!seq->payload) {
 348                efc_log_err(efct, "Sequence payload is NULL.\n");
 349                return -EIO;
 350        }
 351
 352        cmnd = seq->payload->dma.virt;
 353
 354        /* perform FCP_CMND validation check(s) */
 355        if (efct_validate_fcp_cmd(efct, seq))
 356                return -EIO;
 357
 358        lun = scsilun_to_int(&cmnd->fc_lun);
 359        if (lun == U32_MAX)
 360                return -EIO;
 361
 362        io = efct_scsi_io_alloc(node);
 363        if (!io) {
 364                int rc;
 365
 366                /* Use SEND_FRAME to send task set full or busy */
 367                rc = efct_sframe_send_task_set_full_or_busy(node, seq);
 368                if (rc)
 369                        efc_log_err(efct, "Failed to send busy task: %d\n", rc);
 370
 371                return rc;
 372        }
 373
 374        io->hw_priv = seq->hw_priv;
 375
 376        io->app_id = 0;
 377
 378        /* RQ pair, if we got here, SIT=1 */
 379        efct_populate_io_fcp_cmd(io, cmnd, fchdr, true);
 380
 381        if (cmnd->fc_tm_flags) {
 382                efct_dispatch_unsol_tmf(io, cmnd->fc_tm_flags, lun);
 383        } else {
 384                u32 flags = efct_get_flags_fcp_cmd(cmnd);
 385
 386                if (cmnd->fc_flags & FCP_CFL_LEN_MASK) {
 387                        efc_log_err(efct, "Additional CDB not supported\n");
 388                        return -EIO;
 389                }
 390                /*
 391                 * Can return failure for things like task set full and UAs,
 392                 * no need to treat as a dropped frame if rc != 0
 393                 */
 394                efct_scsi_recv_cmd(io, lun, cmnd->fc_cdb,
 395                                   sizeof(cmnd->fc_cdb), flags);
 396        }
 397
 398        return 0;
 399}
 400
 401static int
 402efct_process_abts(struct efct_io *io, struct fc_frame_header *hdr)
 403{
 404        struct efct_node *node = io->node;
 405        struct efct *efct = io->efct;
 406        u16 ox_id = be16_to_cpu(hdr->fh_ox_id);
 407        u16 rx_id = be16_to_cpu(hdr->fh_rx_id);
 408        struct efct_io *abortio;
 409
 410        /* Find IO and attempt to take a reference on it */
 411        abortio = efct_io_find_tgt_io(efct, node, ox_id, rx_id);
 412
 413        if (abortio) {
 414                /* Got a reference on the IO. Hold it until backend
 415                 * is notified below
 416                 */
 417                efc_log_info(node->efct, "Abort ox_id [%04x] rx_id [%04x]\n",
 418                             ox_id, rx_id);
 419
 420                /*
 421                 * Save the ox_id for the ABTS as the init_task_tag in our
 422                 * manufactured
 423                 * TMF IO object
 424                 */
 425                io->display_name = "abts";
 426                io->init_task_tag = ox_id;
 427                /* don't set tgt_task_tag, don't want to confuse with XRI */
 428
 429                /*
 430                 * Save the rx_id from the ABTS as it is
 431                 * needed for the BLS response,
 432                 * regardless of the IO context's rx_id
 433                 */
 434                io->abort_rx_id = rx_id;
 435
 436                /* Call target server command abort */
 437                io->tmf_cmd = EFCT_SCSI_TMF_ABORT_TASK;
 438                efct_scsi_recv_tmf(io, abortio->tgt_io.lun,
 439                                   EFCT_SCSI_TMF_ABORT_TASK, abortio, 0);
 440
 441                /*
 442                 * Backend will have taken an additional
 443                 * reference on the IO if needed;
 444                 * done with current reference.
 445                 */
 446                kref_put(&abortio->ref, abortio->release);
 447        } else {
 448                /*
 449                 * Either IO was not found or it has been
 450                 * freed between finding it
 451                 * and attempting to get the reference,
 452                 */
 453                efc_log_info(node->efct, "Abort: ox_id [%04x], IO not found\n",
 454                             ox_id);
 455
 456                /* Send a BA_RJT */
 457                efct_bls_send_rjt(io, hdr);
 458        }
 459        return 0;
 460}
 461
 462int
 463efct_node_recv_abts_frame(struct efct_node *node, struct efc_hw_sequence *seq)
 464{
 465        struct efct *efct = node->efct;
 466        struct fc_frame_header *hdr = seq->header->dma.virt;
 467        struct efct_io *io = NULL;
 468
 469        node->abort_cnt++;
 470        io = efct_scsi_io_alloc(node);
 471        if (io) {
 472                io->hw_priv = seq->hw_priv;
 473                /* If we got this far, SIT=1 */
 474                io->seq_init = 1;
 475
 476                /* fill out generic fields */
 477                io->efct = efct;
 478                io->node = node;
 479                io->cmd_tgt = true;
 480
 481                efct_process_abts(io, seq->header->dma.virt);
 482        } else {
 483                efc_log_err(efct,
 484                            "SCSI IO allocation failed for ABTS received ");
 485                efc_log_err(efct, "s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
 486                            ntoh24(hdr->fh_s_id), ntoh24(hdr->fh_d_id),
 487                            be16_to_cpu(hdr->fh_ox_id),
 488                            be16_to_cpu(hdr->fh_rx_id));
 489        }
 490
 491        return 0;
 492}
 493