return false;
}
+static void target_complete(struct se_cmd *cmd, int success)
+{
+ struct se_wwn *wwn = cmd->se_sess->se_tpg->se_tpg_wwn;
+ struct se_dev_attrib *da;
+ u8 compl_type;
+ int cpu;
+
+ if (!wwn) {
+ cpu = cmd->cpuid;
+ goto queue_work;
+ }
+
+ da = &cmd->se_dev->dev_attrib;
+ if (da->complete_type == TARGET_FABRIC_DEFAULT_COMPL)
+ compl_type = wwn->wwn_tf->tf_ops->default_compl_type;
+ else if (da->complete_type == TARGET_DIRECT_SUBMIT &&
+ wwn->wwn_tf->tf_ops->direct_compl_supp)
+ compl_type = TARGET_DIRECT_COMPL;
+ else
+ compl_type = TARGET_QUEUE_COMPL;
+
+ if (compl_type == TARGET_DIRECT_COMPL) {
+ /*
+ * Failure handling and processing secondary stages of
+ * complex commands can be too heavy to handle from the
+ * fabric driver so always defer.
+ */
+ if (success && !cmd->transport_complete_callback) {
+ target_complete_ok_work(&cmd->work);
+ return;
+ }
+
+ compl_type = TARGET_QUEUE_COMPL;
+ }
+
+queue_work:
+ INIT_WORK(&cmd->work, success ? target_complete_ok_work :
+ target_complete_failure_work);
+
+ if (!wwn || wwn->cmd_compl_affinity == SE_COMPL_AFFINITY_CPUID)
+ cpu = cmd->cpuid;
+ else
+ cpu = wwn->cmd_compl_affinity;
+
+ queue_work_on(cpu, target_completion_wq, &cmd->work);
+}
+
/* May be called from interrupt context so must not sleep. */
void target_complete_cmd_with_sense(struct se_cmd *cmd, u8 scsi_status,
sense_reason_t sense_reason)
{
- struct se_wwn *wwn = cmd->se_sess->se_tpg->se_tpg_wwn;
- int success, cpu;
unsigned long flags;
+ int success;
if (target_cmd_interrupted(cmd))
return;
cmd->transport_state |= (CMD_T_COMPLETE | CMD_T_ACTIVE);
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
- INIT_WORK(&cmd->work, success ? target_complete_ok_work :
- target_complete_failure_work);
-
- if (!wwn || wwn->cmd_compl_affinity == SE_COMPL_AFFINITY_CPUID)
- cpu = cmd->cpuid;
- else
- cpu = wwn->cmd_compl_affinity;
-
- queue_work_on(cpu, target_completion_wq, &cmd->work);
+ target_complete(cmd, success);
}
EXPORT_SYMBOL(target_complete_cmd_with_sense);
/* Peripheral Device Text Identification Information */
#define PD_TEXT_ID_INFO_LEN 256
+enum target_compl_type {
+ /* Use the fabric driver's default completion type */
+ TARGET_FABRIC_DEFAULT_COMPL,
+ /* Complete from the backend calling context */
+ TARGET_DIRECT_COMPL,
+ /* Defer completion to the LIO workqueue */
+ TARGET_QUEUE_COMPL,
+};
+
enum target_submit_type {
/* Use the fabric driver's default submission type */
TARGET_FABRIC_DEFAULT_SUBMIT,
u32 atomic_granularity;
u32 atomic_max_with_boundary;
u32 atomic_max_boundary;
+ u8 complete_type;
u8 submit_type;
struct se_device *da_dev;
struct config_group da_group;
* its entirety before a command is aborted.
*/
unsigned int write_pending_must_be_called:1;
+ /*
+ * Set this if the driver does not require calling queue_data_in
+ * queue_status and check_stop_free from a worker thread when
+ * completing successful commands.
+ */
+ unsigned int direct_compl_supp:1;
/*
* Set this if the driver supports submitting commands to the backend
* from target_submit/target_submit_cmd.
*/
unsigned int direct_submit_supp:1;
- /*
- * Set this to a target_submit_type value.
- */
+ /* Set this to a target_submit_type value. */
u8 default_submit_type;
+ /* Set this to the target_compl_type value. */
+ u8 default_compl_type;
};
int target_register_template(const struct target_core_fabric_ops *fo);