Instead of implementing the functionality to abort a SCSI command in the tcm_fc driver, use the existing functionality in the target core to abort SCSI commands. Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx> Cc: Vasu Dev <vasu.dev@xxxxxxxxx> --- drivers/target/tcm_fc/tcm_fc.h | 1 - drivers/target/tcm_fc/tfc_cmd.c | 80 +++++++++++++++++++++++++++++++++-------- drivers/target/tcm_fc/tfc_io.c | 8 ----- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index b453d23..f0ee231 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -122,7 +122,6 @@ struct ft_cmd { /* Local sense buffer */ unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER]; u32 was_ddp_setup:1; /* Set only if ddp is setup */ - u32 aborted:1; /* Set if aborted by reset or timeout */ struct scatterlist *sg; /* Set only if DDP is setup */ u32 sg_cnt; /* No. of item in scatterlist */ }; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 7add680..42a07eb 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -96,13 +96,15 @@ static void ft_free_cmd(struct ft_cmd *cmd) return; sess = cmd->sess; fp = cmd->req_frame; - lport = fr_dev(fp); - sp = fr_seq(fp); - if (sp) { - lport->tt.seq_set_resp(sp, NULL, NULL); - lport->tt.seq_release(sp); + if (fp) { + lport = fr_dev(fp); + sp = fr_seq(fp); + if (sp) { + lport->tt.seq_set_resp(sp, NULL, NULL); + lport->tt.seq_release(sp); + } + fc_frame_free(fp); } - fc_frame_free(fp); percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); ft_sess_put(sess); /* undo get from lookup at recv */ } @@ -134,8 +136,6 @@ int ft_queue_status(struct se_cmd *se_cmd) size_t len; int rc; - if (cmd->aborted) - return 0; ft_dump_cmd(cmd, __func__); ep = fc_seq_exch(cmd->seq); lport = ep->lp; @@ -215,8 +215,6 @@ int ft_write_pending(struct se_cmd *se_cmd) ft_dump_cmd(cmd, __func__); - if (cmd->aborted) - return 0; ep = fc_seq_exch(cmd->seq); lport = ep->lp; fp = fc_frame_alloc(lport, sizeof(*txrdy)); @@ -257,6 +255,59 @@ int ft_get_cmd_state(struct se_cmd *se_cmd) return 0; } +static void ft_abort_cmd(struct ft_cmd *cmd) +{ + struct ft_sess *ft_sess = cmd->sess; + struct se_cmd *se_cmd = &cmd->se_cmd; + struct se_session *se_sess = se_cmd->se_sess; + struct se_lun *se_lun = se_cmd->se_lun; + int lun = se_lun ? se_lun->unpacked_lun : -1; + u16 rxid = se_cmd->tag; + struct ft_cmd *abort_tmr; + int abort_tmr_tag, rc; + + pr_debug("Processing ABTS for LUN %d / RXID %#x\n", lun, rxid); + + if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) { + pr_debug("Ignored an attempt to abort a TMF\n"); + return; + } + + kref_get(&se_cmd->cmd_kref); + + abort_tmr_tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING); + if (abort_tmr_tag < 0) { + pr_err("Ignored ABTS for RXID %#x because out of tags\n", rxid); + return; + } + + abort_tmr = &((struct ft_cmd *)se_sess->sess_cmd_map)[abort_tmr_tag]; + memset(abort_tmr, 0, sizeof(*abort_tmr)); + abort_tmr->se_cmd.map_tag = abort_tmr_tag; + abort_tmr->sess = ft_sess; + + rc = target_submit_tmr(&abort_tmr->se_cmd, se_sess, NULL, lun, + abort_tmr, TMR_ABORT_TASK, GFP_KERNEL, rxid, 0); + if (rc < 0) { + pr_err("Failed to process ABTS for RXID %#x (%d)\n", rxid, rc); + percpu_ida_free(&se_sess->sess_tag_pool, abort_tmr_tag); + } + + if (cmd->write_data_len < se_cmd->data_length) { + /* + * If the above target_submit_tmr() call will set the + * CMD_T_ABORTED flag, ensure that ft_execute_work() will see + * that flag. + */ + while (!(se_cmd->transport_state & CMD_T_ABORTED) && + se_cmd->t_state != TRANSPORT_COMPLETE) + mdelay(100); + ft_queue_execute_work(cmd); + } + + target_put_sess_cmd(se_cmd); +} + /* * FC sequence response handler for follow-on sequences (data) and aborts. */ @@ -266,9 +317,8 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg) struct fc_frame_header *fh; if (unlikely(IS_ERR(fp))) { - /* XXX need to find cmd if queued */ - cmd->seq = NULL; - cmd->aborted = true; + WARN_ON_ONCE(cmd->se_cmd.tag != fc_seq_exch(sp)->rxid); + ft_abort_cmd(cmd); return; } @@ -411,8 +461,10 @@ void ft_queue_tm_resp(struct se_cmd *se_cmd) struct se_tmr_req *tmr = se_cmd->se_tmr_req; enum fcp_resp_rsp_codes code; - if (cmd->aborted) + /* fc_exch_recv_abts() already sent the ABTS response */ + if (se_cmd->se_tmr_req->function == TMR_ABORT_TASK) return; + switch (tmr->response) { case TMR_FUNCTION_COMPLETE: code = FCP_TMF_CMPL; diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index 7fb9fb3..0ebdea3 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -79,9 +79,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd) void *from; void *to = NULL; - if (cmd->aborted) - return 0; - if (se_cmd->scsi_status == SAM_STAT_TASK_SET_FULL) goto queue_status; @@ -120,11 +117,6 @@ int ft_queue_data_in(struct se_cmd *se_cmd) while (remaining) { struct fc_seq *seq = cmd->seq; - if (!seq) { - pr_debug("%s: Command aborted, xid 0x%x\n", - __func__, ep->xid); - break; - } if (!mem_len) { sg = sg_next(sg); mem_len = min((size_t)sg->length, remaining); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html