This patch merges the cmd completion functions so there is a common code path. Signed-off-by: Mike Christie <mchristi@xxxxxxxxxx> --- drivers/target/target_core_transport.c | 156 +++++++++++---------------------- 1 file changed, 49 insertions(+), 107 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 6aee378..faad7b4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -68,7 +68,7 @@ static void transport_handle_queue_full(struct se_cmd *cmd, struct se_device *dev, int err, bool write_pending); static int transport_put_cmd(struct se_cmd *cmd); -static void target_complete_ok_work(struct work_struct *work); +static void target_complete_cmd_work(struct work_struct *work); int init_se_kmem_caches(void) { @@ -670,14 +670,6 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) transport_put_cmd(cmd); } -static void target_complete_failure_work(struct work_struct *work) -{ - struct se_cmd *cmd = container_of(work, struct se_cmd, work); - - transport_generic_request_failure(cmd, - TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE); -} - /* * Used when asking transport to copy Sense Data from the underlying * Linux/SCSI struct scsi_cmnd @@ -721,24 +713,10 @@ void transport_copy_sense_to_cmd(struct se_cmd *cmd, unsigned char *sense) void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) { - int success; unsigned long flags; - cmd->scsi_status = scsi_status; spin_lock_irqsave(&cmd->t_state_lock, flags); - switch (cmd->scsi_status) { - case SAM_STAT_CHECK_CONDITION: - if (cmd->se_cmd_flags & SCF_TASK_SENSE) - success = 1; - else - success = 0; - break; - default: - success = 1; - break; - } - /* * Check for case where an explicit ABORT_TASK has been received * and transport_wait_for_tasks() will be waiting for completion.. @@ -748,12 +726,9 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) spin_unlock_irqrestore(&cmd->t_state_lock, flags); complete_all(&cmd->t_transport_stop_comp); return; - } else if (!success) { - INIT_WORK(&cmd->work, target_complete_failure_work); - } else { - INIT_WORK(&cmd->work, target_complete_ok_work); } + INIT_WORK(&cmd->work, target_complete_cmd_work); cmd->t_state = TRANSPORT_COMPLETE; cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE); spin_unlock_irqrestore(&cmd->t_state_lock, flags); @@ -1678,19 +1653,8 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, void transport_generic_request_failure(struct se_cmd *cmd, sense_reason_t sense_reason) { - int ret = 0, post_ret = 0; - - /* - * For SAM Task Attribute emulation for failed struct se_cmd - */ - transport_complete_task_attr(cmd); - /* - * Handle special case for COMPARE_AND_WRITE failure, where the - * callback is expected to drop the per device ->caw_sem. - */ - if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && - cmd->transport_complete_callback) - cmd->transport_complete_callback(cmd, false, &post_ret); + u8 scsi_status = SAM_STAT_CHECK_CONDITION; + unsigned long flags; if (transport_check_aborted_status(cmd, 1)) return; @@ -1737,7 +1701,7 @@ void transport_generic_request_failure(struct se_cmd *cmd, * * Uses linux/include/scsi/scsi.h SAM status codes defs */ - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; + scsi_status = SAM_STAT_RESERVATION_CONFLICT; /* * For UA Interlock Code 11b, a RESERVATION CONFLICT will * establish a UNIT ATTENTION with PREVIOUS RESERVATION @@ -1751,11 +1715,8 @@ void transport_generic_request_failure(struct se_cmd *cmd, cmd->orig_fe_lun, 0x2C, ASCQ_2CH_PREVIOUS_RESERVATION_CONFLICT_STATUS); } - trace_target_cmd_complete(cmd); - ret = cmd->se_tfo->queue_status(cmd); - if (ret) - goto queue_full; - goto check_stop; + + goto queue_completion; default: pr_err("Unknown transport error for CDB 0x%02x: %d\n", cmd->t_task_cdb[0], sense_reason); @@ -1763,17 +1724,12 @@ void transport_generic_request_failure(struct se_cmd *cmd, break; } - ret = transport_send_check_condition_and_sense(cmd, sense_reason); - if (ret) - goto queue_full; - -check_stop: - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; + spin_lock_irqsave(&cmd->t_state_lock, flags); + transport_setup_sense(cmd, sense_reason); + spin_unlock_irqrestore(&cmd->t_state_lock, flags); -queue_full: - transport_handle_queue_full(cmd, cmd->se_dev, ret, false); +queue_completion: + target_complete_cmd(cmd, scsi_status); } EXPORT_SYMBOL(transport_generic_request_failure); @@ -2119,10 +2075,10 @@ static bool target_read_prot_action(struct se_cmd *cmd) return false; } -static void target_complete_ok_work(struct work_struct *work) +static void target_complete_cmd_work(struct work_struct *work) { struct se_cmd *cmd = container_of(work, struct se_cmd, work); - int ret; + int ret = 0; /* * Check if we need to move delayed/dormant tasks from cmds on the @@ -2139,20 +2095,6 @@ static void target_complete_ok_work(struct work_struct *work) schedule_work(&cmd->se_dev->qf_work_queue); /* - * Check if we need to send a sense buffer from - * the struct se_cmd in question. - */ - if (cmd->se_cmd_flags & SCF_TASK_SENSE) { - WARN_ON(!cmd->scsi_status); - ret = transport_send_check_condition_and_sense(cmd, 0); - if (ret) - goto queue_full; - - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; - } - /* * Check for a callback, used by amongst other things * XDWRITE_READ_10 and COMPARE_AND_WRITE emulation. */ @@ -2161,22 +2103,33 @@ static void target_complete_ok_work(struct work_struct *work) bool caw = (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE); bool zero_dl = !(cmd->data_length); int post_ret = 0; + bool good = !(cmd->scsi_status); + + if (good || caw) { + rc = cmd->transport_complete_callback(cmd, good, + &post_ret); + if (!rc && !post_ret) { + if (caw && zero_dl) + goto queue_rsp; + + return; + } else if (rc && good) { + transport_setup_sense(cmd, rc); + } + } + } - rc = cmd->transport_complete_callback(cmd, true, &post_ret); - if (!rc && !post_ret) { - if (caw && zero_dl) - goto queue_rsp; - - return; - } else if (rc) { - ret = transport_send_check_condition_and_sense(cmd, rc); - if (ret) - goto queue_full; + if (transport_check_aborted_status(cmd, 1)) + return; - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; - } + /* + * Check if we need to send a sense buffer from + * the struct se_cmd in question. + */ + if (cmd->se_cmd_flags & SCF_TASK_SENSE) { + WARN_ON(!cmd->scsi_status); + ret = transport_send_check_condition_and_sense(cmd, 0); + goto done; } queue_rsp: @@ -2195,18 +2148,11 @@ static void target_complete_ok_work(struct work_struct *work) if (target_read_prot_action(cmd)) { ret = transport_send_check_condition_and_sense(cmd, cmd->pi_err); - if (ret) - goto queue_full; - - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; + break; } trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_data_in(cmd); - if (ret) - goto queue_full; break; case DMA_TO_DEVICE: atomic_long_add(cmd->data_length, @@ -2218,8 +2164,6 @@ static void target_complete_ok_work(struct work_struct *work) atomic_long_add(cmd->data_length, &cmd->se_lun->lun_stats.tx_data_octets); ret = cmd->se_tfo->queue_data_in(cmd); - if (ret) - goto queue_full; break; } /* Fall through for DMA_TO_DEVICE */ @@ -2227,22 +2171,20 @@ static void target_complete_ok_work(struct work_struct *work) queue_status: trace_target_cmd_complete(cmd); ret = cmd->se_tfo->queue_status(cmd); - if (ret) - goto queue_full; break; default: break; } - transport_lun_remove_cmd(cmd); - transport_cmd_check_stop_to_fabric(cmd); - return; - -queue_full: - pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p," - " data_direction: %d\n", cmd, cmd->data_direction); - - transport_handle_queue_full(cmd, cmd->se_dev, ret, false); +done: + if (ret) { + pr_debug("Handling complete_ok QUEUE_FULL: se_cmd: %p," + " data_direction: %d\n", cmd, cmd->data_direction); + transport_handle_queue_full(cmd, cmd->se_dev, ret, false); + } else { + transport_lun_remove_cmd(cmd); + transport_cmd_check_stop_to_fabric(cmd); + } } void target_free_sgl(struct scatterlist *sgl, int nents) -- 1.8.3.1 -- 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