aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/tcm_fc/tfc_cmd.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/target/tcm_fc/tfc_cmd.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/target/tcm_fc/tfc_cmd.c')
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c239
1 files changed, 163 insertions, 76 deletions
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index b406f178ff3..80fbcde00cb 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -19,6 +19,8 @@
19 19
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/moduleparam.h> 21#include <linux/moduleparam.h>
22#include <linux/version.h>
23#include <generated/utsrelease.h>
22#include <linux/utsname.h> 24#include <linux/utsname.h>
23#include <linux/init.h> 25#include <linux/init.h>
24#include <linux/slab.h> 26#include <linux/slab.h>
@@ -38,8 +40,12 @@
38#include <scsi/fc_encode.h> 40#include <scsi/fc_encode.h>
39 41
40#include <target/target_core_base.h> 42#include <target/target_core_base.h>
41#include <target/target_core_fabric.h> 43#include <target/target_core_transport.h>
44#include <target/target_core_fabric_ops.h>
45#include <target/target_core_device.h>
46#include <target/target_core_tpg.h>
42#include <target/target_core_configfs.h> 47#include <target/target_core_configfs.h>
48#include <target/target_core_tmr.h>
43#include <target/configfs_macros.h> 49#include <target/configfs_macros.h>
44 50
45#include "tcm_fc.h" 51#include "tcm_fc.h"
@@ -47,7 +53,7 @@
47/* 53/*
48 * Dump cmd state for debugging. 54 * Dump cmd state for debugging.
49 */ 55 */
50static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller) 56void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
51{ 57{
52 struct fc_exch *ep; 58 struct fc_exch *ep;
53 struct fc_seq *sp; 59 struct fc_seq *sp;
@@ -58,6 +64,9 @@ static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
58 se_cmd = &cmd->se_cmd; 64 se_cmd = &cmd->se_cmd;
59 pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n", 65 pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n",
60 caller, cmd, cmd->sess, cmd->seq, se_cmd); 66 caller, cmd, cmd->sess, cmd->seq, se_cmd);
67 pr_debug("%s: cmd %p cdb %p\n",
68 caller, cmd, cmd->cdb);
69 pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun);
61 70
62 pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n", 71 pr_debug("%s: cmd %p data_nents %u len %u se_cmd_flags <0x%x>\n",
63 caller, cmd, se_cmd->t_data_nents, 72 caller, cmd, se_cmd->t_data_nents,
@@ -77,12 +86,8 @@ static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
77 caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid, 86 caller, cmd, ep->sid, ep->did, ep->oxid, ep->rxid,
78 sp->id, ep->esb_stat); 87 sp->id, ep->esb_stat);
79 } 88 }
80} 89 print_hex_dump(KERN_INFO, "ft_dump_cmd ", DUMP_PREFIX_NONE,
81 90 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
82void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
83{
84 if (unlikely(ft_debug_logging))
85 _ft_dump_cmd(cmd, caller);
86} 91}
87 92
88static void ft_free_cmd(struct ft_cmd *cmd) 93static void ft_free_cmd(struct ft_cmd *cmd)
@@ -108,10 +113,9 @@ void ft_release_cmd(struct se_cmd *se_cmd)
108 ft_free_cmd(cmd); 113 ft_free_cmd(cmd);
109} 114}
110 115
111int ft_check_stop_free(struct se_cmd *se_cmd) 116void ft_check_stop_free(struct se_cmd *se_cmd)
112{ 117{
113 transport_generic_free_cmd(se_cmd, 0); 118 transport_generic_free_cmd(se_cmd, 0, 0);
114 return 1;
115} 119}
116 120
117/* 121/*
@@ -126,8 +130,6 @@ int ft_queue_status(struct se_cmd *se_cmd)
126 struct fc_exch *ep; 130 struct fc_exch *ep;
127 size_t len; 131 size_t len;
128 132
129 if (cmd->aborted)
130 return 0;
131 ft_dump_cmd(cmd, __func__); 133 ft_dump_cmd(cmd, __func__);
132 ep = fc_seq_exch(cmd->seq); 134 ep = fc_seq_exch(cmd->seq);
133 lport = ep->lp; 135 lport = ep->lp;
@@ -194,13 +196,11 @@ int ft_write_pending(struct se_cmd *se_cmd)
194 196
195 ft_dump_cmd(cmd, __func__); 197 ft_dump_cmd(cmd, __func__);
196 198
197 if (cmd->aborted)
198 return 0;
199 ep = fc_seq_exch(cmd->seq); 199 ep = fc_seq_exch(cmd->seq);
200 lport = ep->lp; 200 lport = ep->lp;
201 fp = fc_frame_alloc(lport, sizeof(*txrdy)); 201 fp = fc_frame_alloc(lport, sizeof(*txrdy));
202 if (!fp) 202 if (!fp)
203 return -ENOMEM; /* Signal QUEUE_FULL */ 203 return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
204 204
205 txrdy = fc_frame_payload_get(fp, sizeof(*txrdy)); 205 txrdy = fc_frame_payload_get(fp, sizeof(*txrdy));
206 memset(txrdy, 0, sizeof(*txrdy)); 206 memset(txrdy, 0, sizeof(*txrdy));
@@ -220,10 +220,20 @@ int ft_write_pending(struct se_cmd *se_cmd)
220 */ 220 */
221 if ((ep->xid <= lport->lro_xid) && 221 if ((ep->xid <= lport->lro_xid) &&
222 (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) { 222 (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
223 if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && 223 if (se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
224 lport->tt.ddp_target(lport, ep->xid, 224 /*
225 se_cmd->t_data_sg, 225 * cmd may have been broken up into multiple
226 se_cmd->t_data_nents)) 226 * tasks. Link their sgs together so we can
227 * operate on them all at once.
228 */
229 transport_do_task_sg_chain(se_cmd);
230 cmd->sg = se_cmd->t_tasks_sg_chained;
231 cmd->sg_cnt =
232 se_cmd->t_tasks_sg_chained_no;
233 }
234 if (cmd->sg && lport->tt.ddp_target(lport, ep->xid,
235 cmd->sg,
236 cmd->sg_cnt))
227 cmd->was_ddp_setup = 1; 237 cmd->was_ddp_setup = 1;
228 } 238 }
229 } 239 }
@@ -235,8 +245,6 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd)
235{ 245{
236 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); 246 struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
237 247
238 if (cmd->aborted)
239 return ~0;
240 return fc_seq_exch(cmd->seq)->rxid; 248 return fc_seq_exch(cmd->seq)->rxid;
241} 249}
242 250
@@ -245,6 +253,11 @@ int ft_get_cmd_state(struct se_cmd *se_cmd)
245 return 0; 253 return 0;
246} 254}
247 255
256int ft_is_state_remove(struct se_cmd *se_cmd)
257{
258 return 0; /* XXX TBD */
259}
260
248/* 261/*
249 * FC sequence response handler for follow-on sequences (data) and aborts. 262 * FC sequence response handler for follow-on sequences (data) and aborts.
250 */ 263 */
@@ -253,10 +266,11 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
253 struct ft_cmd *cmd = arg; 266 struct ft_cmd *cmd = arg;
254 struct fc_frame_header *fh; 267 struct fc_frame_header *fh;
255 268
256 if (unlikely(IS_ERR(fp))) { 269 if (IS_ERR(fp)) {
257 /* XXX need to find cmd if queued */ 270 /* XXX need to find cmd if queued */
271 cmd->se_cmd.t_state = TRANSPORT_REMOVE;
258 cmd->seq = NULL; 272 cmd->seq = NULL;
259 cmd->aborted = true; 273 transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
260 return; 274 return;
261 } 275 }
262 276
@@ -274,7 +288,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
274 __func__, fh->fh_r_ctl); 288 __func__, fh->fh_r_ctl);
275 ft_invl_hw_context(cmd); 289 ft_invl_hw_context(cmd);
276 fc_frame_free(fp); 290 fc_frame_free(fp);
277 transport_generic_free_cmd(&cmd->se_cmd, 0); 291 transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
278 break; 292 break;
279 } 293 }
280} 294}
@@ -316,12 +330,10 @@ static void ft_send_resp_status(struct fc_lport *lport,
316 330
317 fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0); 331 fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
318 sp = fr_seq(fp); 332 sp = fr_seq(fp);
319 if (sp) { 333 if (sp)
320 lport->tt.seq_send(lport, sp, fp); 334 lport->tt.seq_send(lport, sp, fp);
321 lport->tt.exch_done(sp); 335 else
322 } else {
323 lport->tt.frame_send(lport, fp); 336 lport->tt.frame_send(lport, fp);
324 }
325} 337}
326 338
327/* 339/*
@@ -351,8 +363,9 @@ static void ft_send_resp_code_and_free(struct ft_cmd *cmd,
351 */ 363 */
352static void ft_send_tm(struct ft_cmd *cmd) 364static void ft_send_tm(struct ft_cmd *cmd)
353{ 365{
366 struct se_tmr_req *tmr;
354 struct fcp_cmnd *fcp; 367 struct fcp_cmnd *fcp;
355 int rc; 368 struct ft_sess *sess;
356 u8 tm_func; 369 u8 tm_func;
357 370
358 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); 371 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
@@ -383,12 +396,45 @@ static void ft_send_tm(struct ft_cmd *cmd)
383 return; 396 return;
384 } 397 }
385 398
386 /* FIXME: Add referenced task tag for ABORT_TASK */ 399 pr_debug("alloc tm cmd fn %d\n", tm_func);
387 rc = target_submit_tmr(&cmd->se_cmd, cmd->sess->se_sess, 400 tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func);
388 &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), 401 if (!tmr) {
389 cmd, tm_func, GFP_KERNEL, 0, 0); 402 pr_debug("alloc failed\n");
390 if (rc < 0)
391 ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED); 403 ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
404 return;
405 }
406 cmd->se_cmd.se_tmr_req = tmr;
407
408 switch (fcp->fc_tm_flags) {
409 case FCP_TMF_LUN_RESET:
410 cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
411 if (transport_lookup_tmr_lun(&cmd->se_cmd, cmd->lun) < 0) {
412 /*
413 * Make sure to clean up newly allocated TMR request
414 * since "unable to handle TMR request because failed
415 * to get to LUN"
416 */
417 pr_debug("Failed to get LUN for TMR func %d, "
418 "se_cmd %p, unpacked_lun %d\n",
419 tm_func, &cmd->se_cmd, cmd->lun);
420 ft_dump_cmd(cmd, __func__);
421 sess = cmd->sess;
422 transport_send_check_condition_and_sense(&cmd->se_cmd,
423 cmd->se_cmd.scsi_sense_reason, 0);
424 transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
425 ft_sess_put(sess);
426 return;
427 }
428 break;
429 case FCP_TMF_TGT_RESET:
430 case FCP_TMF_CLR_TASK_SET:
431 case FCP_TMF_ABT_TASK_SET:
432 case FCP_TMF_CLR_ACA:
433 break;
434 default:
435 return;
436 }
437 transport_generic_handle_tmr(&cmd->se_cmd);
392} 438}
393 439
394/* 440/*
@@ -400,8 +446,6 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd)
400 struct se_tmr_req *tmr = se_cmd->se_tmr_req; 446 struct se_tmr_req *tmr = se_cmd->se_tmr_req;
401 enum fcp_resp_rsp_codes code; 447 enum fcp_resp_rsp_codes code;
402 448
403 if (cmd->aborted)
404 return 0;
405 switch (tmr->response) { 449 switch (tmr->response) {
406 case TMR_FUNCTION_COMPLETE: 450 case TMR_FUNCTION_COMPLETE:
407 code = FCP_TMF_CMPL; 451 code = FCP_TMF_CMPL;
@@ -493,9 +537,12 @@ static void ft_send_work(struct work_struct *work)
493{ 537{
494 struct ft_cmd *cmd = container_of(work, struct ft_cmd, work); 538 struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
495 struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame); 539 struct fc_frame_header *fh = fc_frame_header_get(cmd->req_frame);
540 struct se_cmd *se_cmd;
496 struct fcp_cmnd *fcp; 541 struct fcp_cmnd *fcp;
497 int data_dir = 0; 542 int data_dir = 0;
543 u32 data_len;
498 int task_attr; 544 int task_attr;
545 int ret;
499 546
500 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp)); 547 fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
501 if (!fcp) 548 if (!fcp)
@@ -504,6 +551,56 @@ static void ft_send_work(struct work_struct *work)
504 if (fcp->fc_flags & FCP_CFL_LEN_MASK) 551 if (fcp->fc_flags & FCP_CFL_LEN_MASK)
505 goto err; /* not handling longer CDBs yet */ 552 goto err; /* not handling longer CDBs yet */
506 553
554 if (fcp->fc_tm_flags) {
555 task_attr = FCP_PTA_SIMPLE;
556 data_dir = DMA_NONE;
557 data_len = 0;
558 } else {
559 switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) {
560 case 0:
561 data_dir = DMA_NONE;
562 break;
563 case FCP_CFL_RDDATA:
564 data_dir = DMA_FROM_DEVICE;
565 break;
566 case FCP_CFL_WRDATA:
567 data_dir = DMA_TO_DEVICE;
568 break;
569 case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
570 goto err; /* TBD not supported by tcm_fc yet */
571 }
572 /*
573 * Locate the SAM Task Attr from fc_pri_ta
574 */
575 switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
576 case FCP_PTA_HEADQ:
577 task_attr = MSG_HEAD_TAG;
578 break;
579 case FCP_PTA_ORDERED:
580 task_attr = MSG_ORDERED_TAG;
581 break;
582 case FCP_PTA_ACA:
583 task_attr = MSG_ACA_TAG;
584 break;
585 case FCP_PTA_SIMPLE: /* Fallthrough */
586 default:
587 task_attr = MSG_SIMPLE_TAG;
588 }
589
590
591 task_attr = fcp->fc_pri_ta & FCP_PTA_MASK;
592 data_len = ntohl(fcp->fc_dl);
593 cmd->cdb = fcp->fc_cdb;
594 }
595
596 se_cmd = &cmd->se_cmd;
597 /*
598 * Initialize struct se_cmd descriptor from target_core_mod
599 * infrastructure
600 */
601 transport_init_se_cmd(se_cmd, &ft_configfs->tf_ops, cmd->sess->se_sess,
602 data_len, data_dir, task_attr,
603 &cmd->ft_sense_buffer[0]);
507 /* 604 /*
508 * Check for FCP task management flags 605 * Check for FCP task management flags
509 */ 606 */
@@ -512,48 +609,38 @@ static void ft_send_work(struct work_struct *work)
512 return; 609 return;
513 } 610 }
514 611
515 switch (fcp->fc_flags & (FCP_CFL_RDDATA | FCP_CFL_WRDATA)) { 612 fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
516 case 0: 613
517 data_dir = DMA_NONE; 614 cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
518 break; 615 ret = transport_lookup_cmd_lun(&cmd->se_cmd, cmd->lun);
519 case FCP_CFL_RDDATA: 616 if (ret < 0) {
520 data_dir = DMA_FROM_DEVICE; 617 ft_dump_cmd(cmd, __func__);
521 break; 618 transport_send_check_condition_and_sense(&cmd->se_cmd,
522 case FCP_CFL_WRDATA: 619 cmd->se_cmd.scsi_sense_reason, 0);
523 data_dir = DMA_TO_DEVICE; 620 return;
524 break;
525 case FCP_CFL_WRDATA | FCP_CFL_RDDATA:
526 goto err; /* TBD not supported by tcm_fc yet */
527 }
528 /*
529 * Locate the SAM Task Attr from fc_pri_ta
530 */
531 switch (fcp->fc_pri_ta & FCP_PTA_MASK) {
532 case FCP_PTA_HEADQ:
533 task_attr = MSG_HEAD_TAG;
534 break;
535 case FCP_PTA_ORDERED:
536 task_attr = MSG_ORDERED_TAG;
537 break;
538 case FCP_PTA_ACA:
539 task_attr = MSG_ACA_TAG;
540 break;
541 case FCP_PTA_SIMPLE: /* Fallthrough */
542 default:
543 task_attr = MSG_SIMPLE_TAG;
544 } 621 }
545 622
546 fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd); 623 ret = transport_generic_allocate_tasks(se_cmd, cmd->cdb);
547 /* 624
548 * Use a single se_cmd->cmd_kref as we expect to release se_cmd 625 pr_debug("r_ctl %x alloc task ret %d\n", fh->fh_r_ctl, ret);
549 * directly from ft_check_stop_free callback in response path. 626 ft_dump_cmd(cmd, __func__);
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, 0))
554 goto err;
555 627
556 pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl); 628 if (ret == -ENOMEM) {
629 transport_send_check_condition_and_sense(se_cmd,
630 TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
631 transport_generic_free_cmd(se_cmd, 0, 0);
632 return;
633 }
634 if (ret == -EINVAL) {
635 if (se_cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT)
636 ft_queue_status(se_cmd);
637 else
638 transport_send_check_condition_and_sense(se_cmd,
639 se_cmd->scsi_sense_reason, 0);
640 transport_generic_free_cmd(se_cmd, 0, 0);
641 return;
642 }
643 transport_generic_handle_cdb(se_cmd);
557 return; 644 return;
558 645
559err: 646err: