summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_transport.c74
1 files changed, 26 insertions, 48 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index dd9c87f62d76..db139133f708 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -66,7 +66,6 @@ struct kmem_cache *t10_alua_lu_gp_mem_cache;
struct kmem_cache *t10_alua_tg_pt_gp_cache;
struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
-static int transport_generic_write_pending(struct se_cmd *);
static int transport_processing_thread(void *param);
static void transport_complete_task_attr(struct se_cmd *cmd);
static void transport_handle_queue_full(struct se_cmd *cmd,
@@ -2487,23 +2486,39 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
atomic_inc(&cmd->t_fe_count);
/*
- * For WRITEs, let the fabric know its buffer is ready.
- *
- * The command will be added to the execution queue after its write
- * data has arrived.
- *
- * Everything else but a WRITE, add the command to the execution queue.
+ * If this command is not a write we can execute it right here,
+ * for write buffers we need to notify the fabric driver first
+ * and let it call back once the write buffers are ready.
*/
target_add_to_state_list(cmd);
- if (cmd->data_direction == DMA_TO_DEVICE)
- return transport_generic_write_pending(cmd);
- target_execute_cmd(cmd);
- return 0;
+ if (cmd->data_direction != DMA_TO_DEVICE) {
+ target_execute_cmd(cmd);
+ return 0;
+ }
+
+ spin_lock_irq(&cmd->t_state_lock);
+ cmd->t_state = TRANSPORT_WRITE_PENDING;
+ spin_unlock_irq(&cmd->t_state_lock);
+
+ transport_cmd_check_stop(cmd, false);
+
+ ret = cmd->se_tfo->write_pending(cmd);
+ if (ret == -EAGAIN || ret == -ENOMEM)
+ goto queue_full;
+
+ if (ret < 0)
+ return ret;
+ return 1;
out_fail:
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
return -EINVAL;
+queue_full:
+ pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
+ cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
+ transport_handle_queue_full(cmd, cmd->se_dev);
+ return 0;
}
EXPORT_SYMBOL(transport_generic_new_cmd);
@@ -2519,43 +2534,6 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
}
}
-static int transport_generic_write_pending(struct se_cmd *cmd)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&cmd->t_state_lock, flags);
- cmd->t_state = TRANSPORT_WRITE_PENDING;
- spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
- /*
- * Clear the se_cmd for WRITE_PENDING status in order to set
- * CMD_T_ACTIVE so that transport_generic_handle_data can be called
- * from HW target mode interrupt code. This is safe to be called
- * with remove_from_lists false before the cmd->se_tfo->write_pending
- * because the se_cmd->se_lun pointer is not being cleared.
- */
- transport_cmd_check_stop(cmd, false);
-
- /*
- * Call the fabric write_pending function here to let the
- * frontend know that WRITE buffers are ready.
- */
- ret = cmd->se_tfo->write_pending(cmd);
- if (ret == -EAGAIN || ret == -ENOMEM)
- goto queue_full;
- else if (ret < 0)
- return ret;
-
- return 1;
-
-queue_full:
- pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
- cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
- transport_handle_queue_full(cmd, cmd->se_dev);
- return 0;
-}
-
void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
{
if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {