Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-microblaze.git] / drivers / target / target_core_transport.c
index 7e35edd..14c6f2b 100644 (file)
@@ -736,8 +736,7 @@ 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);
+       transport_generic_request_failure(cmd, cmd->sense_reason);
 }
 
 /*
@@ -855,7 +854,8 @@ static bool target_cmd_interrupted(struct se_cmd *cmd)
 }
 
 /* May be called from interrupt context so must not sleep. */
-void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
+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;
@@ -865,6 +865,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
                return;
 
        cmd->scsi_status = scsi_status;
+       cmd->sense_reason = sense_reason;
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        switch (cmd->scsi_status) {
@@ -886,13 +887,21 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
        INIT_WORK(&cmd->work, success ? target_complete_ok_work :
                  target_complete_failure_work);
 
-       if (wwn->cmd_compl_affinity == SE_COMPL_AFFINITY_CPUID)
+       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);
 }
+EXPORT_SYMBOL(target_complete_cmd_with_sense);
+
+void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
+{
+       target_complete_cmd_with_sense(cmd, scsi_status, scsi_status ?
+                             TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE :
+                             TCM_NO_SENSE);
+}
 EXPORT_SYMBOL(target_complete_cmd);
 
 void target_set_cmd_data_length(struct se_cmd *cmd, int length)
@@ -2003,7 +2012,6 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_ADDRESS_OUT_OF_RANGE:
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
-       case TCM_CHECK_CONDITION_NOT_READY:
        case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
        case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
        case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
@@ -2013,6 +2021,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_TOO_MANY_SEGMENT_DESCS:
        case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
        case TCM_INVALID_FIELD_IN_COMMAND_IU:
+       case TCM_ALUA_TG_PT_STANDBY:
+       case TCM_ALUA_TG_PT_UNAVAILABLE:
+       case TCM_ALUA_STATE_TRANSITION:
+       case TCM_ALUA_OFFLINE:
                break;
        case TCM_OUT_OF_RESOURCES:
                cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -3277,9 +3289,6 @@ static const struct sense_detail sense_detail_table[] = {
        [TCM_CHECK_CONDITION_UNIT_ATTENTION] = {
                .key = UNIT_ATTENTION,
        },
-       [TCM_CHECK_CONDITION_NOT_READY] = {
-               .key = NOT_READY,
-       },
        [TCM_MISCOMPARE_VERIFY] = {
                .key = MISCOMPARE,
                .asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */
@@ -3340,6 +3349,26 @@ static const struct sense_detail sense_detail_table[] = {
                .asc = 0x0e,
                .ascq = 0x03, /* INVALID FIELD IN COMMAND INFORMATION UNIT */
        },
+       [TCM_ALUA_TG_PT_STANDBY] = {
+               .key = NOT_READY,
+               .asc = 0x04,
+               .ascq = ASCQ_04H_ALUA_TG_PT_STANDBY,
+       },
+       [TCM_ALUA_TG_PT_UNAVAILABLE] = {
+               .key = NOT_READY,
+               .asc = 0x04,
+               .ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE,
+       },
+       [TCM_ALUA_STATE_TRANSITION] = {
+               .key = NOT_READY,
+               .asc = 0x04,
+               .ascq = ASCQ_04H_ALUA_STATE_TRANSITION,
+       },
+       [TCM_ALUA_OFFLINE] = {
+               .key = NOT_READY,
+               .asc = 0x04,
+               .ascq = ASCQ_04H_ALUA_OFFLINE,
+       },
 };
 
 /**
@@ -3374,11 +3403,8 @@ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
                        cmd->scsi_status = SAM_STAT_BUSY;
                        return;
                }
-       } else if (sd->asc == 0) {
-               WARN_ON_ONCE(cmd->scsi_asc == 0);
-               asc = cmd->scsi_asc;
-               ascq = cmd->scsi_ascq;
        } else {
+               WARN_ON_ONCE(sd->asc == 0);
                asc = sd->asc;
                ascq = sd->ascq;
        }