root/drivers/target/tcm_fc/tfc_cmd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _ft_dump_cmd
  2. ft_dump_cmd
  3. ft_free_cmd
  4. ft_release_cmd
  5. ft_check_stop_free
  6. ft_queue_status
  7. ft_write_pending
  8. ft_get_cmd_state
  9. ft_recv_seq
  10. ft_send_resp_status
  11. ft_send_resp_code
  12. ft_send_resp_code_and_free
  13. ft_send_tm
  14. ft_queue_tm_resp
  15. ft_aborted_task
  16. ft_recv_cmd
  17. ft_recv_req
  18. ft_send_work

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2010 Cisco Systems, Inc.
   4  */
   5 
   6 /* XXX TBD some includes may be extraneous */
   7 
   8 #include <linux/module.h>
   9 #include <linux/moduleparam.h>
  10 #include <linux/utsname.h>
  11 #include <linux/init.h>
  12 #include <linux/slab.h>
  13 #include <linux/kthread.h>
  14 #include <linux/types.h>
  15 #include <linux/string.h>
  16 #include <linux/configfs.h>
  17 #include <linux/ctype.h>
  18 #include <linux/hash.h>
  19 #include <asm/unaligned.h>
  20 #include <scsi/scsi_tcq.h>
  21 #include <scsi/libfc.h>
  22 #include <scsi/fc_encode.h>
  23 
  24 #include <target/target_core_base.h>
  25 #include <target/target_core_fabric.h>
  26 
  27 #include "tcm_fc.h"
  28 
  29 /*
  30  * Dump cmd state for debugging.
  31  */
  32 static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
  33 {
  34         struct fc_exch *ep;
  35         struct fc_seq *sp;
  36         struct se_cmd *se_cmd;
  37         struct scatterlist *sg;
  38         int count;
  39 
  40         se_cmd = &cmd->se_cmd;
  41         pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
  42                 caller, cmd, cmd->sess, cmd->seq, se_cmd);
  43 
  44         pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
  45                 caller, cmd, se_cmd->t_data_nents,
  46                se_cmd->data_length, se_cmd->se_cmd_flags);
  47 
  48         for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, count)
  49                 pr_debug("%s: cmd %p sg %p page %p "
  50                         "len 0x%x off 0x%x\n",
  51                         caller, cmd, sg,
  52                         sg_page(sg), sg->length, sg->offset);
  53 
  54         sp = cmd->seq;
  55         if (sp) {
  56                 ep = fc_seq_exch(sp);
  57                 pr_debug("%s: cmd %p sid %x did %x "
  58                         "ox_id %x rx_id %x seq_id %x e_stat %x\n",
  59                         caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
  60                         sp->id, ep->esb_stat);
  61         }
  62 }
  63 
  64 void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
  65 {
  66         if (unlikely(ft_debug_logging))
  67                 _ft_dump_cmd(cmd, caller);
  68 }
  69 
  70 static void ft_free_cmd(struct ft_cmd *cmd)
  71 {
  72         struct fc_frame *fp;
  73         struct ft_sess *sess;
  74 
  75         if (!cmd)
  76                 return;
  77         sess = cmd->sess;
  78         fp = cmd->req_frame;
  79         if (fr_seq(fp))
  80                 fc_seq_release(fr_seq(fp));
  81         fc_frame_free(fp);
  82         target_free_tag(sess->se_sess, &cmd->se_cmd);
  83         ft_sess_put(sess);      /* undo get from lookup at recv */
  84 }
  85 
  86 void ft_release_cmd(struct se_cmd *se_cmd)
  87 {
  88         struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
  89 
  90         ft_free_cmd(cmd);
  91 }
  92 
  93 int ft_check_stop_free(struct se_cmd *se_cmd)
  94 {
  95         return transport_generic_free_cmd(se_cmd, 0);
  96 }
  97 
  98 /*
  99  * Send response.
 100  */
 101 int ft_queue_status(struct se_cmd *se_cmd)
 102 {
 103         struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
 104         struct fc_frame *fp;
 105         struct fcp_resp_with_ext *fcp;
 106         struct fc_lport *lport;
 107         struct fc_exch *ep;
 108         size_t len;
 109         int rc;
 110 
 111         if (cmd->aborted)
 112                 return 0;
 113         ft_dump_cmd(cmd, __func__);
 114         ep = fc_seq_exch(cmd->seq);
 115         lport = ep->lp;
 116         len = sizeof(*fcp) + se_cmd->scsi_sense_length;
 117         fp = fc_frame_alloc(lport, len);
 118         if (!fp) {
 119                 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
 120                 return -ENOMEM;
 121         }
 122 
 123         fcp = fc_frame_payload_get(fp, len);
 124         memset(fcp, 0, len);
 125         fcp->resp.fr_status = se_cmd->scsi_status;
 126 
 127         len = se_cmd->scsi_sense_length;
 128         if (len) {
 129                 fcp->resp.fr_flags |= FCP_SNS_LEN_VAL;
 130                 fcp->ext.fr_sns_len = htonl(len);
 131                 memcpy((fcp + 1), se_cmd->sense_buffer, len);
 132         }
 133 
 134         /*
 135          * Test underflow and overflow with one mask.  Usually both are off.
 136          * Bidirectional commands are not handled yet.
 137          */
 138         if (se_cmd->se_cmd_flags & (SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT)) {
 139                 if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT)
 140                         fcp->resp.fr_flags |= FCP_RESID_OVER;
 141                 else
 142                         fcp->resp.fr_flags |= FCP_RESID_UNDER;
 143                 fcp->ext.fr_resid = cpu_to_be32(se_cmd->residual_count);
 144         }
 145 
 146         /*
 147          * Send response.
 148          */
 149         cmd->seq = fc_seq_start_next(cmd->seq);
 150         fc_fill_fc_hdr(fp, FC_RCTL_DD_CMD_STATUS, ep->did, ep->sid, FC_TYPE_FCP,
 151                        FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ, 0);
 152 
 153         rc = fc_seq_send(lport, cmd->seq, fp);
 154         if (rc) {
 155                 pr_info_ratelimited("%s: Failed to send response frame %p, "
 156                                     "xid <0x%x>\n", __func__, fp, ep->xid);
 157                 /*
 158                  * Generate a TASK_SET_FULL status to notify the initiator
 159                  * to reduce it's queue_depth after the se_cmd response has
 160                  * been re-queued by target-core.
 161                  */
 162                 se_cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
 163                 return -ENOMEM;
 164         }
 165         fc_exch_done(cmd->seq);
 166         /*
 167          * Drop the extra ACK_KREF reference taken by target_submit_cmd()
 168          * ahead of ft_check_stop_free() -> transport_generic_free_cmd()
 169          * final se_cmd->cmd_kref put.
 170          */
 171         target_put_sess_cmd(&cmd->se_cmd);
 172         return 0;
 173 }
 174 
 175 /*
 176  * Send TX_RDY (transfer ready).
 177  */
 178 int ft_write_pending(struct se_cmd *se_cmd)
 179 {
 180         struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
 181         struct fc_frame *fp;
 182         struct fcp_txrdy *txrdy;
 183         struct fc_lport *lport;
 184         struct fc_exch *ep;
 185         struct fc_frame_header *fh;
 186         u32 f_ctl;
 187 
 188         ft_dump_cmd(cmd, __func__);
 189 
 190         if (cmd->aborted)
 191                 return 0;
 192         ep = fc_seq_exch(cmd->seq);
 193         lport = ep->lp;
 194         fp = fc_frame_alloc(lport, sizeof(*txrdy));
 195         if (!fp)
 196                 return -ENOMEM; /* Signal QUEUE_FULL */
 197 
 198         txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
 199         memset(txrdy, 0, sizeof(*txrdy));
 200         txrdy->ft_burst_len = htonl(se_cmd->data_length);
 201 
 202         cmd->seq = fc_seq_start_next(cmd->seq);
 203         fc_fill_fc_hdr(fp, FC_RCTL_DD_DATA_DESC, ep->did, ep->sid, FC_TYPE_FCP,
 204                        FC_FC_EX_CTX | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
 205 
 206         fh = fc_frame_header_get(fp);
 207         f_ctl = ntoh24(fh->fh_f_ctl);
 208 
 209         /* Only if it is 'Exchange Responder' */
 210         if (f_ctl & FC_FC_EX_CTX) {
 211                 /* Target is 'exchange responder' and sending XFER_READY
 212                  * to 'exchange initiator (initiator)'
 213                  */
 214                 if ((ep->xid <= lport->lro_xid) &&
 215                     (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
 216                         if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
 217                             lport->tt.ddp_target(lport, ep->xid,
 218                                                  se_cmd->t_data_sg,
 219                                                  se_cmd->t_data_nents))
 220                                 cmd->was_ddp_setup = 1;
 221                 }
 222         }
 223         fc_seq_send(lport, cmd->seq, fp);
 224         return 0;
 225 }
 226 
 227 int ft_get_cmd_state(struct se_cmd *se_cmd)
 228 {
 229         return 0;
 230 }
 231 
 232 /*
 233  * FC sequence response handler for follow-on sequences (data) and aborts.
 234  */
 235 static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
 236 {
 237         struct ft_cmd *cmd = arg;
 238         struct fc_frame_header *fh;
 239 
 240         if (IS_ERR(fp)) {
 241                 /* XXX need to find cmd if queued */
 242                 cmd->seq = NULL;
 243                 cmd->aborted = true;
 244                 return;
 245         }
 246 
 247         fh = fc_frame_header_get(fp);
 248 
 249         switch (fh->fh_r_ctl) {
 250         case FC_RCTL_DD_SOL_DATA:       /* write data */
 251                 ft_recv_write_data(cmd, fp);
 252                 break;
 253         case FC_RCTL_DD_UNSOL_CTL:      /* command */
 254         case FC_RCTL_DD_SOL_CTL:        /* transfer ready */
 255         case FC_RCTL_DD_DATA_DESC:      /* transfer ready */
 256         default:
 257                 pr_debug("%s: unhandled frame r_ctl %x\n",
 258                        __func__, fh->fh_r_ctl);
 259                 ft_invl_hw_context(cmd);
 260                 fc_frame_free(fp);
 261                 transport_generic_free_cmd(&cmd->se_cmd, 0);
 262                 break;
 263         }
 264 }
 265 
 266 /*
 267  * Send a FCP response including SCSI status and optional FCP rsp_code.
 268  * status is SAM_STAT_GOOD (zero) iff code is valid.
 269  * This is used in error cases, such as allocation failures.
 270  */
 271 static void ft_send_resp_status(struct fc_lport *lport,
 272                                 const struct fc_frame *rx_fp,
 273                                 u32 status, enum fcp_resp_rsp_codes code)
 274 {
 275         struct fc_frame *fp;
 276         struct fc_seq *sp;
 277         const struct fc_frame_header *fh;
 278         size_t len;
 279         struct fcp_resp_with_ext *fcp;
 280         struct fcp_resp_rsp_info *info;
 281 
 282         fh = fc_frame_header_get(rx_fp);
 283         pr_debug("FCP error response: did %x oxid %x status %x code %x\n",
 284                   ntoh24(fh->fh_s_id), ntohs(fh->fh_ox_id), status, code);
 285         len = sizeof(*fcp);
 286         if (status == SAM_STAT_GOOD)
 287                 len += sizeof(*info);
 288         fp = fc_frame_alloc(lport, len);
 289         if (!fp)
 290                 return;
 291         fcp = fc_frame_payload_get(fp, len);
 292         memset(fcp, 0, len);
 293         fcp->resp.fr_status = status;
 294         if (status == SAM_STAT_GOOD) {
 295                 fcp->ext.fr_rsp_len = htonl(sizeof(*info));
 296                 fcp->resp.fr_flags |= FCP_RSP_LEN_VAL;
 297                 info = (struct fcp_resp_rsp_info *)(fcp + 1);
 298                 info->rsp_code = code;
 299         }
 300 
 301         fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
 302         sp = fr_seq(fp);
 303         if (sp) {
 304                 fc_seq_send(lport, sp, fp);
 305                 fc_exch_done(sp);
 306         } else {
 307                 lport->tt.frame_send(lport, fp);
 308         }
 309 }
 310 
 311 /*
 312  * Send error or task management response.
 313  */
 314 static void ft_send_resp_code(struct ft_cmd *cmd,
 315                               enum fcp_resp_rsp_codes code)
 316 {
 317         ft_send_resp_status(cmd->sess->tport->lport,
 318                             cmd->req_frame, SAM_STAT_GOOD, code);
 319 }
 320 
 321 
 322 /*
 323  * Send error or task management response.
 324  * Always frees the cmd and associated state.
 325  */
 326 static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
 327                                       enum fcp_resp_rsp_codes code)
 328 {
 329         ft_send_resp_code(cmd, code);
 330         ft_free_cmd(cmd);
 331 }
 332 
 333 /*
 334  * Handle Task Management Request.
 335  */
 336 static void ft_send_tm(struct ft_cmd *cmd)
 337 {
 338         struct fcp_cmnd *fcp;
 339         int rc;
 340         u8 tm_func;
 341 
 342         fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
 343 
 344         switch (fcp->fc_tm_flags) {
 345         case FCP_TMF_LUN_RESET:
 346                 tm_func = TMR_LUN_RESET;
 347                 break;
 348         case FCP_TMF_TGT_RESET:
 349                 tm_func = TMR_TARGET_WARM_RESET;
 350                 break;
 351         case FCP_TMF_CLR_TASK_SET:
 352                 tm_func = TMR_CLEAR_TASK_SET;
 353                 break;
 354         case FCP_TMF_ABT_TASK_SET:
 355                 tm_func = TMR_ABORT_TASK_SET;
 356                 break;
 357         case FCP_TMF_CLR_ACA:
 358                 tm_func = TMR_CLEAR_ACA;
 359                 break;
 360         default:
 361                 /*
 362                  * FCP4r01 indicates having a combination of
 363                  * tm_flags set is invalid.
 364                  */
 365                 pr_debug("invalid FCP tm_flags %x\n", fcp->fc_tm_flags);
 366                 ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
 367                 return;
 368         }
 369 
 370         /* FIXME: Add referenced task tag for ABORT_TASK */
 371         rc = target_submit_tmr(&cmd->se_cmd, cmd->sess->se_sess,
 372                 &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
 373                 cmd, tm_func, GFP_KERNEL, 0, TARGET_SCF_ACK_KREF);
 374         if (rc < 0)
 375                 ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
 376 }
 377 
 378 /*
 379  * Send status from completed task management request.
 380  */
 381 void ft_queue_tm_resp(struct se_cmd *se_cmd)
 382 {
 383         struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
 384         struct se_tmr_req *tmr = se_cmd->se_tmr_req;
 385         enum fcp_resp_rsp_codes code;
 386 
 387         if (cmd->aborted)
 388                 return;
 389         switch (tmr->response) {
 390         case TMR_FUNCTION_COMPLETE:
 391                 code = FCP_TMF_CMPL;
 392                 break;
 393         case TMR_LUN_DOES_NOT_EXIST:
 394                 code = FCP_TMF_INVALID_LUN;
 395                 break;
 396         case TMR_FUNCTION_REJECTED:
 397                 code = FCP_TMF_REJECTED;
 398                 break;
 399         case TMR_TASK_DOES_NOT_EXIST:
 400         case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
 401         default:
 402                 code = FCP_TMF_FAILED;
 403                 break;
 404         }
 405         pr_debug("tmr fn %d resp %d fcp code %d\n",
 406                   tmr->function, tmr->response, code);
 407         ft_send_resp_code(cmd, code);
 408         /*
 409          * Drop the extra ACK_KREF reference taken by target_submit_tmr()
 410          * ahead of ft_check_stop_free() -> transport_generic_free_cmd()
 411          * final se_cmd->cmd_kref put.
 412          */
 413         target_put_sess_cmd(&cmd->se_cmd);
 414 }
 415 
 416 void ft_aborted_task(struct se_cmd *se_cmd)
 417 {
 418         return;
 419 }
 420 
 421 static void ft_send_work(struct work_struct *work);
 422 
 423 /*
 424  * Handle incoming FCP command.
 425  */
 426 static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp)
 427 {
 428         struct ft_cmd *cmd;
 429         struct fc_lport *lport = sess->tport->lport;
 430         struct se_session *se_sess = sess->se_sess;
 431         int tag, cpu;
 432 
 433         tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
 434         if (tag < 0)
 435                 goto busy;
 436 
 437         cmd = &((struct ft_cmd *)se_sess->sess_cmd_map)[tag];
 438         memset(cmd, 0, sizeof(struct ft_cmd));
 439 
 440         cmd->se_cmd.map_tag = tag;
 441         cmd->se_cmd.map_cpu = cpu;
 442         cmd->sess = sess;
 443         cmd->seq = fc_seq_assign(lport, fp);
 444         if (!cmd->seq) {
 445                 target_free_tag(se_sess, &cmd->se_cmd);
 446                 goto busy;
 447         }
 448         cmd->req_frame = fp;            /* hold frame during cmd */
 449 
 450         INIT_WORK(&cmd->work, ft_send_work);
 451         queue_work(sess->tport->tpg->workqueue, &cmd->work);
 452         return;
 453 
 454 busy:
 455         pr_debug("cmd or seq allocation failure - sending BUSY\n");
 456         ft_send_resp_status(lport, fp, SAM_STAT_BUSY, 0);
 457         fc_frame_free(fp);
 458         ft_sess_put(sess);              /* undo get from lookup */
 459 }
 460 
 461 
 462 /*
 463  * Handle incoming FCP frame.
 464  * Caller has verified that the frame is type FCP.
 465  */
 466 void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp)
 467 {
 468         struct fc_frame_header *fh = fc_frame_header_get(fp);
 469 
 470         switch (fh->fh_r_ctl) {
 471         case FC_RCTL_DD_UNSOL_CMD:      /* command */
 472                 ft_recv_cmd(sess, fp);
 473                 break;
 474         case FC_RCTL_DD_SOL_DATA:       /* write data */
 475         case FC_RCTL_DD_UNSOL_CTL:
 476         case FC_RCTL_DD_SOL_CTL:
 477         case FC_RCTL_DD_DATA_DESC:      /* transfer ready */
 478         case FC_RCTL_ELS4_REQ:          /* SRR, perhaps */
 479         default:
 480                 pr_debug("%s: unhandled frame r_ctl %x\n",
 481                        __func__, fh->fh_r_ctl);
 482                 fc_frame_free(fp);
 483                 ft_sess_put(sess);      /* undo get from lookup */
 484                 break;
 485         }
 486 }
 487 
 488 /*
 489  * Send new command to target.
 490  */
 491 static void ft_send_work(struct work_struct *work)
 492 {
 493         struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
 494         struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
 495         struct fcp_cmnd *fcp;
 496         int data_dir = 0;
 497         int task_attr;
 498 
 499         fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
 500         if (!fcp)
 501                 goto err;
 502 
 503         if (fcp->fc_flags & FCP_CFL_LEN_MASK)
 504                 goto err;               /* not handling longer CDBs yet */
 505 
 506         /*
 507          * Check for FCP task management flags
 508          */
 509         if (fcp->fc_tm_flags) {
 510                 ft_send_tm(cmd);
 511                 return;
 512         }
 513 
 514         switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
 515         case 0:
 516                 data_dir = DMA_NONE;
 517                 break;
 518         case FCP_CFL_RDDATA:
 519                 data_dir = DMA_FROM_DEVICE;
 520                 break;
 521         case FCP_CFL_WRDATA:
 522                 data_dir = DMA_TO_DEVICE;
 523                 break;
 524         case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
 525                 goto err;       /* TBD not supported by tcm_fc yet */
 526         }
 527         /*
 528          * Locate the SAM Task Attr from fc_pri_ta
 529          */
 530         switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
 531         case FCP_PTA_HEADQ:
 532                 task_attr = TCM_HEAD_TAG;
 533                 break;
 534         case FCP_PTA_ORDERED:
 535                 task_attr = TCM_ORDERED_TAG;
 536                 break;
 537         case FCP_PTA_ACA:
 538                 task_attr = TCM_ACA_TAG;
 539                 break;
 540         case FCP_PTA_SIMPLE: /* Fallthrough */
 541         default:
 542                 task_attr = TCM_SIMPLE_TAG;
 543         }
 544 
 545         fc_seq_set_resp(cmd->seq, ft_recv_seq, cmd);
 546         cmd->se_cmd.tag = fc_seq_exch(cmd->seq)->rxid;
 547         /*
 548          * Use a single se_cmd->cmd_kref as we expect to release se_cmd
 549          * directly from ft_check_stop_free callback in response path.
 550          */
 551         if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
 552                               &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
 553                               ntohl(fcp->fc_dl), task_attr, data_dir,
 554                               TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID))
 555                 goto err;
 556 
 557         pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd);
 558         return;
 559 
 560 err:
 561         ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID);
 562 }

/* [<][>][^][v][top][bottom][index][help] */