]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_transport.c
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / drivers / target / target_core_transport.c
index 789aa9eb0a1e590b8853a49e8f0ae137f04d3241..7fa62fc93e0b52d70ac49c67f5455a139935f55c 100644 (file)
@@ -504,7 +504,7 @@ void transport_deregister_session(struct se_session *se_sess)
         * ->acl_free_comp caller to wakeup configfs se_node_acl->acl_group
         * removal context.
         */
-       if (se_nacl && comp_nacl == true)
+       if (se_nacl && comp_nacl)
                target_put_nacl(se_nacl);
 
        transport_free_session(se_sess);
@@ -562,7 +562,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;
        }
 
@@ -687,7 +687,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 (!success) {
                INIT_WORK(&cmd->work, target_complete_failure_work);
@@ -703,6 +703,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;
@@ -736,7 +753,7 @@ void target_qf_do_work(struct work_struct *work)
        list_for_each_entry_safe(cmd, cmd_tmp, &qf_cmd_list, se_qf_node) {
                list_del(&cmd->se_qf_node);
                atomic_dec(&dev->dev_qf_count);
-               smp_mb__after_atomic_dec();
+               smp_mb__after_atomic();
 
                pr_debug("Processing %s cmd: %p QUEUE_FULL in work queue"
                        " context: %s\n", cmd->se_tfo->get_fabric_name(), cmd,
@@ -1149,7 +1166,7 @@ transport_check_alloc_task_attr(struct se_cmd *cmd)
         * Dormant to Active status.
         */
        cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id);
-       smp_mb__after_atomic_inc();
+       smp_mb__after_atomic();
        pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
                        cmd->se_ordered_id, cmd->sam_task_attr,
                        dev->transport->name);
@@ -1706,7 +1723,7 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
                return false;
        case MSG_ORDERED_TAG:
                atomic_inc(&dev->dev_ordered_sync);
-               smp_mb__after_atomic_inc();
+               smp_mb__after_atomic();
 
                pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, "
                         " se_ordered_id: %u\n",
@@ -1724,7 +1741,7 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
                 * For SIMPLE and UNTAGGED Task Attribute commands
                 */
                atomic_inc(&dev->simple_cmds);
-               smp_mb__after_atomic_inc();
+               smp_mb__after_atomic();
                break;
        }
 
@@ -1761,7 +1778,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;
        }
 
@@ -1829,7 +1846,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
 
        if (cmd->sam_task_attr == MSG_SIMPLE_TAG) {
                atomic_dec(&dev->simple_cmds);
-               smp_mb__after_atomic_dec();
+               smp_mb__after_atomic();
                dev->dev_cur_ordered_id++;
                pr_debug("Incremented dev->dev_cur_ordered_id: %u for"
                        " SIMPLE: %u\n", dev->dev_cur_ordered_id,
@@ -1841,7 +1858,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
                        cmd->se_ordered_id);
        } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
                atomic_dec(&dev->dev_ordered_sync);
-               smp_mb__after_atomic_dec();
+               smp_mb__after_atomic();
 
                dev->dev_cur_ordered_id++;
                pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
@@ -1900,7 +1917,7 @@ static void transport_handle_queue_full(
        spin_lock_irq(&dev->qf_cmd_lock);
        list_add_tail(&cmd->se_qf_node, &cmd->se_dev->qf_cmd_list);
        atomic_inc(&dev->dev_qf_count);
-       smp_mb__after_atomic_inc();
+       smp_mb__after_atomic();
        spin_unlock_irq(&cmd->se_dev->qf_cmd_lock);
 
        schedule_work(&cmd->se_dev->qf_work_queue);
@@ -2363,7 +2380,7 @@ int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
         * fabric acknowledgement that requires two target_put_sess_cmd()
         * invocations before se_cmd descriptor release.
         */
-       if (ack_kref == true) {
+       if (ack_kref) {
                kref_get(&se_cmd->cmd_kref);
                se_cmd->se_cmd_flags |= SCF_ACK_KREF;
        }
@@ -2407,6 +2424,10 @@ static void target_release_cmd_kref(struct kref *kref)
  */
 int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
 {
+       if (!se_sess) {
+               se_cmd->se_tfo->release_cmd(se_cmd);
+               return 1;
+       }
        return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref,
                        &se_sess->sess_cmd_lock);
 }
@@ -2875,7 +2896,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
                if (cmd->se_tfo->write_pending_status(cmd) != 0) {
                        cmd->transport_state |= CMD_T_ABORTED;
                        cmd->se_cmd_flags |= SCF_SEND_DELAYED_TAS;
-                       smp_mb__after_atomic_inc();
+                       smp_mb__after_atomic();
                        return;
                }
        }
@@ -2934,6 +2955,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;