diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 09c7c1b0fd05..cc1cb456ab8a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -766,6 +766,30 @@ static void ipa3_transport_irq_cmd_ack(void *user1, int user2)
 	complete(&desc->xfer_done);
 }
 
+/**
+ * ipa3_transport_irq_cmd_ack_free - callback function which will be
+ * called by SPS/GSI driver after an immediate command is complete.
+ * This function will also free the completion object once it is done.
+ * @tag_comp: pointer to the completion object
+ * @ignored: parameter not used
+ *
+ * Complete the immediate commands completion object, this will release the
+ * thread which waits on this completion object (ipa3_send_cmd())
+ */
+static void ipa3_transport_irq_cmd_ack_free(void *tag_comp, int ignored)
+{
+	struct ipa3_tag_completion *comp = tag_comp;
+
+	if (!comp) {
+		IPAERR("comp is NULL\n");
+		return;
+	}
+
+	complete(&comp->comp);
+	if (atomic_dec_return(&comp->cnt) == 0)
+		kfree(comp);
+}
+
 /**
  * ipa3_send_cmd - send immediate commands
  * @num_desc:	number of descriptors within the desc struct
@@ -778,7 +802,58 @@ static void ipa3_transport_irq_cmd_ack(void *user1, int user2)
  */
 int ipa3_send_cmd(u16 num_desc, struct ipa3_desc *descr)
 {
-	return ipa3_send_cmd_timeout(num_desc, descr, 0);
+	struct ipa3_desc *desc;
+	int i, result = 0;
+	struct ipa3_sys_context *sys;
+	int ep_idx;
+
+	for (i = 0; i < num_desc; i++)
+		IPADBG("sending imm cmd %d\n", descr[i].opcode);
+
+	ep_idx = ipa3_get_ep_mapping(IPA_CLIENT_APPS_CMD_PROD);
+	if (-1 == ep_idx) {
+		IPAERR("Client %u is not mapped\n",
+			IPA_CLIENT_APPS_CMD_PROD);
+		return -EFAULT;
+	}
+
+	sys = ipa3_ctx->ep[ep_idx].sys;
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+
+	if (num_desc == 1) {
+		init_completion(&descr->xfer_done);
+
+		if (descr->callback || descr->user1)
+			WARN_ON(1);
+
+		descr->callback = ipa3_transport_irq_cmd_ack;
+		descr->user1 = descr;
+		if (ipa3_send_one(sys, descr, true)) {
+			IPAERR("fail to send immediate command\n");
+			result = -EFAULT;
+			goto bail;
+		}
+		wait_for_completion(&descr->xfer_done);
+	} else {
+		desc = &descr[num_desc - 1];
+		init_completion(&desc->xfer_done);
+
+		if (desc->callback || desc->user1)
+			WARN_ON(1);
+
+		desc->callback = ipa3_transport_irq_cmd_ack;
+		desc->user1 = desc;
+		if (ipa3_send(sys, num_desc, descr, true)) {
+			IPAERR("fail to send multiple immediate command set\n");
+			result = -EFAULT;
+			goto bail;
+		}
+		wait_for_completion(&desc->xfer_done);
+	}
+
+bail:
+		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+		return result;
 }
 
 /**
@@ -800,6 +875,7 @@ int ipa3_send_cmd_timeout(u16 num_desc, struct ipa3_desc *descr, u32 timeout)
 	struct ipa3_sys_context *sys;
 	int ep_idx;
 	int completed;
+	struct ipa3_tag_completion *comp;
 
 	for (i = 0; i < num_desc; i++)
 		IPADBG("sending imm cmd %d\n", descr[i].opcode);
@@ -810,55 +886,56 @@ int ipa3_send_cmd_timeout(u16 num_desc, struct ipa3_desc *descr, u32 timeout)
 			IPA_CLIENT_APPS_CMD_PROD);
 		return -EFAULT;
 	}
+
+	comp = kzalloc(sizeof(*comp), GFP_ATOMIC);
+	if (!comp) {
+		IPAERR("no mem\n");
+		return -ENOMEM;
+	}
+	init_completion(&comp->comp);
+
+	/* completion needs to be released from both here and in ack callback */
+	atomic_set(&comp->cnt, 2);
+
 	sys = ipa3_ctx->ep[ep_idx].sys;
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
 	if (num_desc == 1) {
-		init_completion(&descr->xfer_done);
-
 		if (descr->callback || descr->user1)
 			WARN_ON(1);
 
-		descr->callback = ipa3_transport_irq_cmd_ack;
-		descr->user1 = descr;
+		descr->callback = ipa3_transport_irq_cmd_ack_free;
+		descr->user1 = comp;
 		if (ipa3_send_one(sys, descr, true)) {
 			IPAERR("fail to send immediate command\n");
+			kfree(comp);
 			result = -EFAULT;
 			goto bail;
 		}
-		if (timeout) {
-			completed = wait_for_completion_timeout(
-				&descr->xfer_done, msecs_to_jiffies(timeout));
-			if (!completed)
-				IPADBG("timeout waiting for imm-cmd ACK\n");
-		} else {
-			wait_for_completion(&descr->xfer_done);
-		}
 	} else {
 		desc = &descr[num_desc - 1];
-		init_completion(&desc->xfer_done);
 
 		if (desc->callback || desc->user1)
 			WARN_ON(1);
 
-		desc->callback = ipa3_transport_irq_cmd_ack;
-		desc->user1 = desc;
+		desc->callback = ipa3_transport_irq_cmd_ack_free;
+		desc->user1 = comp;
 		if (ipa3_send(sys, num_desc, descr, true)) {
 			IPAERR("fail to send multiple immediate command set\n");
+			kfree(comp);
 			result = -EFAULT;
 			goto bail;
 		}
-		if (timeout) {
-			completed = wait_for_completion_timeout(
-				&desc->xfer_done, msecs_to_jiffies(timeout));
-			if (!completed)
-				IPADBG("timeout waiting for imm-cmd ACK\n");
-		} else {
-			wait_for_completion(&desc->xfer_done);
-		}
-
 	}
 
+	completed = wait_for_completion_timeout(
+		&comp->comp, msecs_to_jiffies(timeout));
+	if (!completed)
+		IPADBG("timeout waiting for imm-cmd ACK\n");
+
+	if (atomic_dec_return(&comp->cnt) == 0)
+		kfree(comp);
+
 bail:
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	return result;