From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch converts qla2xxx/tcm_qla2xxx to use the new generic active I/O shutdown logic. This includes the conversion and removal of existing internal active I/O shutdown code for qla_tgt_sess->sess_cmd_list with the following changes: *) Convert tcm_qla2xxx_handle_cmd() to use target_get_sess_cmd() for incoming I/O processing *) Refactoring of tcm_qla2xxx_release_cmd() into tcm_qla2xxx_check_release_cmd() for TFO->check_release_cmd() *) Make tcm_qla2xxx_check_release_cmd() to use target_put_sess_cmd() to check for active I/O completion. *) Add target_splice_sess_cmd_list() and target_wait_for_sess_cmds() callers into tcm_qla2xxx_free_session() to wait for outstanding I/O to complete during session shutdown. *) Removal of qla_tgt_wait_for_cmds() and associated qla_tgt_cmd and qla_tgt_sess members *) Removal of tcm_qla2xxx_release_shutdown_check() Cc: Christoph Hellwig <hch@xxxxxx> Cc: Roland Dreier <roland@xxxxxxxxxxxxxxx> Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx> --- drivers/scsi/qla2xxx/qla_target.c | 59 ------------------ drivers/scsi/qla2xxx/qla_target.h | 4 - drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c | 10 +++ drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c | 67 +++++++-------------- drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h | 1 + 5 files changed, 34 insertions(+), 107 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0cfd448..121db91 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -369,61 +369,6 @@ void qla_tgt_response_pkt_all_vps(struct scsi_qla_host *vha, response_t *pkt) } -/* - * Called with qla_hw_data->hardware_lock held. - */ -static void qla_tgt_wait_for_cmds(struct qla_tgt_sess *sess, struct qla_hw_data *ha) -{ - LIST_HEAD(tmp_list); - struct qla_tgt_cmd *cmd; - struct se_cmd *se_cmd; - - list_splice_init(&sess->sess_cmd_list, &tmp_list); - - while (!list_empty(&tmp_list)) { - - cmd = list_entry(tmp_list.next, struct qla_tgt_cmd, cmd_list); - ql_dbg(ql_dbg_tgt_mgt, sess->vha, 0xe100, "Waiting for cmd:" - " %p\n", cmd); - /* - * This will signal that completion should be called from - * tcm_qla2xxx_release_cmd() context. - */ - atomic_set(&cmd->cmd_free_comp_set, 1); - spin_unlock_irq(&ha->hardware_lock); - - list_del(&cmd->cmd_list); - - se_cmd = &cmd->se_cmd; - /* - * Wait for completion of the outstanding descriptor in - * tcm_qla2xxx_release_cmd() from transport processing - * context, then a direct call to qla_tgt_free_cmd() below. - */ - ql_dbg(ql_dbg_tgt_mgt, sess->vha, 0xe101, "Before" - " wait_for_completion(&cmd->cmd_free_comp); cmd: %p," - " se_cmd: %p\n", cmd, se_cmd); - - wait_for_completion(&cmd->cmd_free_comp); - - ql_dbg(ql_dbg_tgt_mgt, sess->vha, 0xe102, "After" - " wait_for_completion(&cmd->cmd_free_comp); cmd: %p," - " se_cmd: %p\n", cmd, se_cmd); - - atomic_set(&cmd->cmd_free, 0); - smp_mb__after_atomic_dec(); - - qla_tgt_free_cmd(cmd); - - ql_dbg(ql_dbg_tgt_mgt, sess->vha, 0xe103, "After" - " qla_tgt_free_cmd --------------------->\n"); - - spin_lock_irq(&ha->hardware_lock); - } - -} - - /* ha->hardware_lock supposed to be held on entry */ static void qla_tgt_free_session_done(struct qla_tgt_sess *sess) { @@ -434,7 +379,6 @@ static void qla_tgt_free_session_done(struct qla_tgt_sess *sess) tgt = sess->tgt; sess->tearing_down = 1; - qla_tgt_wait_for_cmds(sess, ha); /* * Release the target session for FC Nexus from fabric module code. @@ -921,8 +865,6 @@ static struct qla_tgt_sess *qla_tgt_create_sess( sess->loop_id = fcport->loop_id; sess->local = local; - INIT_LIST_HEAD(&sess->sess_cmd_list); - ql_dbg(ql_dbg_tgt_mgt, vha, 0xe109, "Adding sess %p to tgt %p via" " ->check_initiator_node_acl()\n", sess, ha->qla_tgt); @@ -3197,7 +3139,6 @@ static int qla_tgt_handle_cmd_for_atio(struct scsi_qla_host *vha, atio_t *atio) } INIT_LIST_HEAD(&cmd->cmd_list); - init_completion(&cmd->cmd_free_comp); init_completion(&cmd->cmd_stop_free_comp); memcpy(&cmd->atio.atio2x, atio, sizeof(*atio)); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 34ffe3c..96aa4e2 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -913,8 +913,6 @@ struct qla_tgt_sess { unsigned long expires; struct list_head del_list_entry; - struct list_head sess_cmd_list; /* Protected by qla_hw_data->hardware_lock */ - uint8_t port_name[WWN_SIZE]; }; @@ -924,8 +922,6 @@ struct qla_tgt_cmd { int locked_rsp; atomic_t cmd_stop_free; atomic_t cmd_free; - atomic_t cmd_free_comp_set; - struct completion cmd_free_comp; struct completion cmd_stop_free_comp; struct se_cmd se_cmd; struct work_struct work_free; diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c index 0a51acc..d907c14 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_configfs.c @@ -733,6 +733,15 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) dump_stack(); return; } + + target_splice_sess_cmd_list(se_sess); + spin_unlock_irq(&ha->hardware_lock); + + target_wait_for_sess_cmds(se_sess, 0); + + spin_lock_irq(&ha->hardware_lock); + + /* * Now clear the struct se_node_acl->nacl_sess pointer */ @@ -1214,6 +1223,7 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = { .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, .new_cmd_map = tcm_qla2xxx_new_cmd_map, .check_stop_free = tcm_qla2xxx_check_stop_free, + .check_release_cmd = tcm_qla2xxx_check_release_cmd, .release_cmd = tcm_qla2xxx_release_cmd, .shutdown_session = tcm_qla2xxx_shutdown_session, .close_session = tcm_qla2xxx_close_session, diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c index 1aa8ee4..cb6d8bd 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c @@ -459,46 +459,16 @@ int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) return 0; } -/* - * Called with qla_hw_data->hardware_lock held.. - */ -static int tcm_qla2xxx_release_shutdown_check( - struct qla_tgt_cmd *cmd, - struct qla_tgt_sess *sess) -{ - /* - * During shutdown, qla_tgt_wait_for_cmds() will be waiting on - * this outstanding qla_tgt_cmd descriptor. For this case, - * perform the completion and return, and qla_tgt_wait_for_cmds() - * will handle the direct call to qla_tgt_free_cmd() - */ - if (cmd->tgt->tgt_stop || sess->tearing_down) { - if (atomic_read(&cmd->cmd_free_comp_set) || - atomic_read(&cmd->cmd_free)) { - pr_warn("Detected shutdown, calling complete(" - "&cmd->cmd_free_comp): cmd: %p\n", cmd); - complete(&cmd->cmd_free_comp); - return 1; - } - } - list_del(&cmd->cmd_list); - - return 0; -} - -/* - * Callback from TCM Core to release underlying fabric descriptor - */ -void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) +int tcm_qla2xxx_check_release_cmd(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd; struct qla_tgt_sess *sess; struct qla_hw_data *ha; unsigned long flags; - int ret; + int ret = 0; if (se_cmd->se_tmr_req != NULL) - return; + return 0; cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); sess = cmd->sess; @@ -512,30 +482,39 @@ void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) * exception path.. This also skips the possible wait for * completion on cmd_stop_free_comp below.. */ - if (!cmd->locked_rsp) { - if (!tcm_qla2xxx_release_shutdown_check(cmd, sess)) - qla_tgt_free_cmd(cmd); - return; - } + if (!cmd->locked_rsp) + return target_put_sess_cmd(sess->se_sess, se_cmd); /* * If the callback to tcm_qla2xxx_check_stop_free() has not finished, * before the release path is invoked, go ahead and wait on * cmd_stop_free_comp until tcm_qla2xxx_check_stop_free completes. */ spin_lock_irqsave(&ha->hardware_lock, flags); - if ((atomic_read(&cmd->cmd_stop_free) != 1) && - (atomic_read(&cmd->cmd_free_comp_set) == 0)) { + if (atomic_read(&cmd->cmd_stop_free) != 1) { pr_warn("Detected cmd->cmd_stop_free != 0, waiting on" " cmd_stop_free_comp for cmd: %p\n", cmd); spin_unlock_irqrestore(&ha->hardware_lock, flags); wait_for_completion(&cmd->cmd_stop_free_comp); spin_lock_irqsave(&ha->hardware_lock, flags); } - ret = tcm_qla2xxx_release_shutdown_check(cmd, sess); + ret = target_put_sess_cmd(sess->se_sess, se_cmd); spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (!ret) - qla_tgt_free_cmd(cmd); + return ret; +} + +/* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying fabric descriptor + * @se_cmd command to release + */ +void tcm_qla2xxx_release_cmd(struct se_cmd *se_cmd) +{ + struct qla_tgt_cmd *cmd; + + if (se_cmd->se_tmr_req != NULL) + return; + + cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + qla_tgt_free_cmd(cmd); } int tcm_qla2xxx_shutdown_session(struct se_session *se_sess) @@ -722,7 +701,7 @@ int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, /* * Protected by qla_hw_data->hardware_lock */ - list_add_tail(&cmd->cmd_list, &sess->sess_cmd_list); + target_get_sess_cmd(se_sess, se_cmd); /* * Signal BIDI usage with T_TASK(cmd)->t_tasks_bidi */ diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h index ce166ac..e807a1e 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h @@ -26,6 +26,7 @@ extern void tcm_qla2xxx_release_fabric_acl(struct se_portal_group *, struct se_n extern u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *); extern void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *); extern int tcm_qla2xxx_check_stop_free(struct se_cmd *); +extern int tcm_qla2xxx_check_release_cmd(struct se_cmd *); extern void tcm_qla2xxx_release_cmd(struct se_cmd *); extern int tcm_qla2xxx_shutdown_session(struct se_session *); extern void tcm_qla2xxx_close_session(struct se_session *); -- 1.7.2.5 -- 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