diff options
Diffstat (limited to 'drivers/target/tcm_fc/tfc_cmd.c')
-rw-r--r-- | drivers/target/tcm_fc/tfc_cmd.c | 90 |
1 files changed, 11 insertions, 79 deletions
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 5654dc22f7ae..80fbcde00cb6 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
@@ -62,8 +62,8 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | |||
62 | int count; | 62 | int count; |
63 | 63 | ||
64 | se_cmd = &cmd->se_cmd; | 64 | se_cmd = &cmd->se_cmd; |
65 | pr_debug("%s: cmd %p state %d sess %p seq %p se_cmd %p\n", | 65 | pr_debug("%s: cmd %p sess %p seq %p se_cmd %p\n", |
66 | caller, cmd, cmd->state, cmd->sess, cmd->seq, se_cmd); | 66 | caller, cmd, cmd->sess, cmd->seq, se_cmd); |
67 | pr_debug("%s: cmd %p cdb %p\n", | 67 | pr_debug("%s: cmd %p cdb %p\n", |
68 | caller, cmd, cmd->cdb); | 68 | caller, cmd, cmd->cdb); |
69 | pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun); | 69 | pr_debug("%s: cmd %p lun %d\n", caller, cmd, cmd->lun); |
@@ -90,38 +90,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | |||
90 | 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); | 90 | 16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0); |
91 | } | 91 | } |
92 | 92 | ||
93 | static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd) | ||
94 | { | ||
95 | struct ft_tpg *tpg = sess->tport->tpg; | ||
96 | struct se_queue_obj *qobj = &tpg->qobj; | ||
97 | unsigned long flags; | ||
98 | |||
99 | qobj = &sess->tport->tpg->qobj; | ||
100 | spin_lock_irqsave(&qobj->cmd_queue_lock, flags); | ||
101 | list_add_tail(&cmd->se_req.qr_list, &qobj->qobj_list); | ||
102 | atomic_inc(&qobj->queue_cnt); | ||
103 | spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags); | ||
104 | |||
105 | wake_up_process(tpg->thread); | ||
106 | } | ||
107 | |||
108 | static struct ft_cmd *ft_dequeue_cmd(struct se_queue_obj *qobj) | ||
109 | { | ||
110 | unsigned long flags; | ||
111 | struct se_queue_req *qr; | ||
112 | |||
113 | spin_lock_irqsave(&qobj->cmd_queue_lock, flags); | ||
114 | if (list_empty(&qobj->qobj_list)) { | ||
115 | spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags); | ||
116 | return NULL; | ||
117 | } | ||
118 | qr = list_first_entry(&qobj->qobj_list, struct se_queue_req, qr_list); | ||
119 | list_del(&qr->qr_list); | ||
120 | atomic_dec(&qobj->queue_cnt); | ||
121 | spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags); | ||
122 | return container_of(qr, struct ft_cmd, se_req); | ||
123 | } | ||
124 | |||
125 | static void ft_free_cmd(struct ft_cmd *cmd) | 93 | static void ft_free_cmd(struct ft_cmd *cmd) |
126 | { | 94 | { |
127 | struct fc_frame *fp; | 95 | struct fc_frame *fp; |
@@ -282,9 +250,7 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd) | |||
282 | 250 | ||
283 | int ft_get_cmd_state(struct se_cmd *se_cmd) | 251 | int ft_get_cmd_state(struct se_cmd *se_cmd) |
284 | { | 252 | { |
285 | struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); | 253 | return 0; |
286 | |||
287 | return cmd->state; | ||
288 | } | 254 | } |
289 | 255 | ||
290 | int ft_is_state_remove(struct se_cmd *se_cmd) | 256 | int ft_is_state_remove(struct se_cmd *se_cmd) |
@@ -505,6 +471,8 @@ int ft_queue_tm_resp(struct se_cmd *se_cmd) | |||
505 | return 0; | 471 | return 0; |
506 | } | 472 | } |
507 | 473 | ||
474 | static void ft_send_work(struct work_struct *work); | ||
475 | |||
508 | /* | 476 | /* |
509 | * Handle incoming FCP command. | 477 | * Handle incoming FCP command. |
510 | */ | 478 | */ |
@@ -523,7 +491,9 @@ static void ft_recv_cmd(struct ft_sess *sess, struct fc_frame *fp) | |||
523 | goto busy; | 491 | goto busy; |
524 | } | 492 | } |
525 | cmd->req_frame = fp; /* hold frame during cmd */ | 493 | cmd->req_frame = fp; /* hold frame during cmd */ |
526 | ft_queue_cmd(sess, cmd); | 494 | |
495 | INIT_WORK(&cmd->work, ft_send_work); | ||
496 | queue_work(sess->tport->tpg->workqueue, &cmd->work); | ||
527 | return; | 497 | return; |
528 | 498 | ||
529 | busy: | 499 | busy: |
@@ -563,12 +533,13 @@ void ft_recv_req(struct ft_sess *sess, struct fc_frame *fp) | |||
563 | /* | 533 | /* |
564 | * Send new command to target. | 534 | * Send new command to target. |
565 | */ | 535 | */ |
566 | static void ft_send_cmd(struct ft_cmd *cmd) | 536 | static void ft_send_work(struct work_struct *work) |
567 | { | 537 | { |
538 | struct ft_cmd *cmd = container_of(work, struct ft_cmd, work); | ||
568 | 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); |
569 | struct se_cmd *se_cmd; | 540 | struct se_cmd *se_cmd; |
570 | struct fcp_cmnd *fcp; | 541 | struct fcp_cmnd *fcp; |
571 | int data_dir; | 542 | int data_dir = 0; |
572 | u32 data_len; | 543 | u32 data_len; |
573 | int task_attr; | 544 | int task_attr; |
574 | int ret; | 545 | int ret; |
@@ -675,42 +646,3 @@ static void ft_send_cmd(struct ft_cmd *cmd) | |||
675 | err: | 646 | err: |
676 | ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID); | 647 | ft_send_resp_code_and_free(cmd, FCP_CMND_FIELDS_INVALID); |
677 | } | 648 | } |
678 | |||
679 | /* | ||
680 | * Handle request in the command thread. | ||
681 | */ | ||
682 | static void ft_exec_req(struct ft_cmd *cmd) | ||
683 | { | ||
684 | pr_debug("cmd state %x\n", cmd->state); | ||
685 | switch (cmd->state) { | ||
686 | case FC_CMD_ST_NEW: | ||
687 | ft_send_cmd(cmd); | ||
688 | break; | ||
689 | default: | ||
690 | break; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | /* | ||
695 | * Processing thread. | ||
696 | * Currently one thread per tpg. | ||
697 | */ | ||
698 | int ft_thread(void *arg) | ||
699 | { | ||
700 | struct ft_tpg *tpg = arg; | ||
701 | struct se_queue_obj *qobj = &tpg->qobj; | ||
702 | struct ft_cmd *cmd; | ||
703 | |||
704 | while (!kthread_should_stop()) { | ||
705 | schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); | ||
706 | if (kthread_should_stop()) | ||
707 | goto out; | ||
708 | |||
709 | cmd = ft_dequeue_cmd(qobj); | ||
710 | if (cmd) | ||
711 | ft_exec_req(cmd); | ||
712 | } | ||
713 | |||
714 | out: | ||
715 | return 0; | ||
716 | } | ||