Merge branch 'linux-linaro-lsk' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / drivers / target / target_core_transport.c
index 21e315874a5472503dfe1ba010dea1236993b553..dcc5daa0ff1c551bf8970dfa417f1cb983d0063c 100644 (file)
@@ -488,7 +488,7 @@ static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists)
 
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-               complete(&cmd->t_transport_stop_comp);
+               complete_all(&cmd->t_transport_stop_comp);
                return 1;
        }
 
@@ -617,7 +617,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
        if (cmd->transport_state & CMD_T_ABORTED &&
            cmd->transport_state & CMD_T_STOP) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               complete(&cmd->t_transport_stop_comp);
+               complete_all(&cmd->t_transport_stop_comp);
                return;
        } else if (cmd->transport_state & CMD_T_FAILED) {
                INIT_WORK(&cmd->work, target_complete_failure_work);
@@ -633,6 +633,23 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 }
 EXPORT_SYMBOL(target_complete_cmd);
 
+void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
+{
+       if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
+               if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
+                       cmd->residual_count += cmd->data_length - length;
+               } else {
+                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
+                       cmd->residual_count = cmd->data_length - length;
+               }
+
+               cmd->data_length = length;
+       }
+
+       target_complete_cmd(cmd, scsi_status);
+}
+EXPORT_SYMBOL(target_complete_cmd_with_length);
+
 static void target_add_to_state_list(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
@@ -1688,7 +1705,7 @@ void target_execute_cmd(struct se_cmd *cmd)
                        cmd->se_tfo->get_task_tag(cmd));
 
                spin_unlock_irq(&cmd->t_state_lock);
-               complete(&cmd->t_transport_stop_comp);
+               complete_all(&cmd->t_transport_stop_comp);
                return;
        }
 
@@ -1771,8 +1788,7 @@ static void transport_complete_qf(struct se_cmd *cmd)
 
        if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
                ret = cmd->se_tfo->queue_status(cmd);
-               if (ret)
-                       goto out;
+               goto out;
        }
 
        switch (cmd->data_direction) {
@@ -2112,7 +2128,7 @@ transport_generic_new_cmd(struct se_cmd *cmd)
         * and let it call back once the write buffers are ready.
         */
        target_add_to_state_list(cmd);
-       if (cmd->data_direction != DMA_TO_DEVICE) {
+       if (cmd->data_direction != DMA_TO_DEVICE || cmd->data_length == 0) {
                target_execute_cmd(cmd);
                return 0;
        }
@@ -2877,6 +2893,12 @@ static void target_tmr_work(struct work_struct *work)
 int transport_generic_handle_tmr(
        struct se_cmd *cmd)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       cmd->transport_state |= CMD_T_ACTIVE;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
        INIT_WORK(&cmd->work, target_tmr_work);
        queue_work(cmd->se_dev->tmr_wq, &cmd->work);
        return 0;