static int iscsi_data_xmit(struct iscsi_conn *conn)
{
	struct iscsi_task *task;
	int rc = 0;

	spin_lock_bh(&conn->session->frwd_lock);
	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
		ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
		spin_unlock_bh(&conn->session->frwd_lock);
		return -ENODATA;
	}

	if (conn->task) {
		rc = iscsi_xmit_task(conn, conn->task, false);
	        if (rc)
		        goto done;
	}

	/*
	 * process mgmt pdus like nops before commands since we should
	 * only have one nop-out as a ping from us and targets should not
	 * overflow us with nop-ins
	 */
check_mgmt:
	while (!list_empty(&conn->mgmtqueue)) {
		task = list_entry(conn->mgmtqueue.next, struct iscsi_task,
				  running);
		list_del_init(&task->running);
		if (iscsi_prep_mgmt_task(conn, task)) {
			/* regular RX path uses back_lock */
			spin_lock_bh(&conn->session->back_lock);
			__iscsi_put_task(task);
			spin_unlock_bh(&conn->session->back_lock);
			continue;
		}
		rc = iscsi_xmit_task(conn, task, false);
		if (rc)
			goto done;
	}

	/* process pending command queue */
	while (!list_empty(&conn->cmdqueue)) {
		task = list_entry(conn->cmdqueue.next, struct iscsi_task,
				  running);
		list_del_init(&task->running);
		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
			fail_scsi_task(task, DID_IMM_RETRY);
			continue;
		}
		rc = iscsi_prep_scsi_cmd_pdu(task);
		if (rc) {
			if (rc == -ENOMEM || rc == -EACCES)
				fail_scsi_task(task, DID_IMM_RETRY);
			else
				fail_scsi_task(task, DID_ABORT);
			continue;
		}
		rc = iscsi_xmit_task(conn, task, false);
		if (rc)
			goto done;
		/*
		 * we could continuously get new task requests so
		 * we need to check the mgmt queue for nops that need to
		 * be sent to aviod starvation
		 */
		if (!list_empty(&conn->mgmtqueue))
			goto check_mgmt;
	}

	while (!list_empty(&conn->requeue)) {
		/*
		 * we always do fastlogout - conn stop code will clean up.
		 */
		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
			break;

		task = list_entry(conn->requeue.next, struct iscsi_task,
				  running);

		if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
			break;

		list_del_init(&task->running);
		rc = iscsi_xmit_task(conn, task, true);
		if (rc)
			goto done;
		if (!list_empty(&conn->mgmtqueue))
			goto check_mgmt;
	}
	spin_unlock_bh(&conn->session->frwd_lock);
	return -ENODATA;

done:
	spin_unlock_bh(&conn->session->frwd_lock);
	return rc;
}
static int iscsi_data_xmit(struct iscsi_conn *conn)
{
	struct iscsi_task *task;
	int rc = 0;

	spin_lock_bh(&conn->session->frwd_lock);
	if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) {
		ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
		spin_unlock_bh(&conn->session->frwd_lock);
		return -ENODATA;
	}

	if (conn->task) {
		rc = iscsi_xmit_task(conn, conn->task, false);
	        if (rc)
		        goto done;
	}

	 
check_mgmt:
	while (!list_empty(&conn->mgmtqueue)) {
		task = list_entry(conn->mgmtqueue.next, struct iscsi_task,
				  running);
		list_del_init(&task->running);
		if (iscsi_prep_mgmt_task(conn, task)) {
			 
			spin_lock_bh(&conn->session->back_lock);
			__iscsi_put_task(task);
			spin_unlock_bh(&conn->session->back_lock);
			continue;
		}
		rc = iscsi_xmit_task(conn, task, false);
		if (rc)
			goto done;
	}

	 
	while (!list_empty(&conn->cmdqueue)) {
		task = list_entry(conn->cmdqueue.next, struct iscsi_task,
				  running);
		list_del_init(&task->running);
		if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
			fail_scsi_task(task, DID_IMM_RETRY);
			continue;
		}
		rc = iscsi_prep_scsi_cmd_pdu(task);
		if (rc) {
			if (rc == -ENOMEM || rc == -EACCES)
				fail_scsi_task(task, DID_IMM_RETRY);
			else
				fail_scsi_task(task, DID_ABORT);
			continue;
		}
		rc = iscsi_xmit_task(conn, task, false);
		if (rc)
			goto done;
		 
		if (!list_empty(&conn->mgmtqueue))
			goto check_mgmt;
	}

	while (!list_empty(&conn->requeue)) {
		 
		if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
			break;

		task = list_entry(conn->requeue.next, struct iscsi_task,
				  running);

		if (iscsi_check_tmf_restrictions(task, ISCSI_OP_SCSI_DATA_OUT))
			break;

		list_del_init(&task->running);
		rc = iscsi_xmit_task(conn, task, true);
		if (rc)
			goto done;
		if (!list_empty(&conn->mgmtqueue))
			goto check_mgmt;
	}
	spin_unlock_bh(&conn->session->frwd_lock);
	return -ENODATA;

done:
	spin_unlock_bh(&conn->session->frwd_lock);
	return rc;
}