msm: bam_dmux: send powerdown ack to A2

When bam_dmux disconnects to the bam hardware in response to the A2
powering down, send an ack back to the A2 signaling that bam_dmux got
the powerdown signal and processed it.

This change optimizes the response time for back-to-back shutdown and
powerup sequences instead of requiring a hard coded delay in the A2 state
machine.

Change-Id: Ie1699abb060f0c0ecd144060ec62955da9439288
Signed-off-by: Jeffrey Hugo <jhugo@codeaurora.org>
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 7b9bdac..4dac062 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -205,6 +205,7 @@
 
 /* A2 power collaspe */
 #define UL_TIMEOUT_DELAY 1000	/* in ms */
+#define ENABLE_DISCONNECT_ACK	0x1
 static void toggle_apps_ack(void);
 static void reconnect_to_bam(void);
 static void disconnect_to_bam(void);
@@ -237,6 +238,7 @@
 static DEFINE_SPINLOCK(wakelock_reference_lock);
 static int wakelock_reference_count;
 static int a2_pc_disabled_wakelock_skipped;
+static int disconnect_ack;
 /* End A2 power collaspe */
 
 /* subsystem restart */
@@ -308,9 +310,10 @@
 	 * W: 1 = Uplink Wait-for-ack
 	 * A: 1 = Uplink ACK received
 	 * #: >=1 On-demand uplink vote
+	 * D: 1 = Disconnect ACK active
 	 */
 	len += scnprintf(buff, sizeof(buff),
-		"<DMUX> %u.%09lu %c%c%c%c %c%c%c%c%d ",
+		"<DMUX> %u.%09lu %c%c%c%c %c%c%c%c%d%c ",
 		(unsigned)t_now, nanosec_rem,
 		a2_pc_disabled ? 'D' : 'd',
 		in_global_reset ? 'R' : 'r',
@@ -320,7 +323,8 @@
 		bam_is_connected ?  'U' : 'u',
 		wait_for_ack ? 'W' : 'w',
 		ul_wakeup_ack_completion.done ? 'A' : 'a',
-		atomic_read(&ul_ondemand_vote)
+		atomic_read(&ul_ondemand_vote),
+		disconnect_ack ? 'D' : 'd'
 		);
 
 	va_start(arg_list, fmt);
@@ -547,6 +551,10 @@
 		bam_dmux_log("%s: opening cid %d PC enabled\n", __func__,
 				rx_hdr->ch_id);
 		handle_bam_mux_cmd_open(rx_hdr);
+		if (rx_hdr->reserved & ENABLE_DISCONNECT_ACK) {
+			bam_dmux_log("%s: activating disconnect ack\n");
+			disconnect_ack = 1;
+		}
 		dev_kfree_skb_any(rx_skb);
 		break;
 	case BAM_MUX_HDR_CMD_OPEN_NO_A2_PC:
@@ -1256,6 +1264,7 @@
 			"\tW: 1 = Uplink Wait-for-ack\n"
 			"\tA: 1 = Uplink ACK received\n"
 			"\t#: >=1 On-demand uplink vote\n"
+			"\tD: 1 = Disconnect ACK active\n"
 				);
 		buff += i;
 	}
@@ -1681,6 +1690,9 @@
 	bam_rx_pool_len = 0;
 	mutex_unlock(&bam_rx_pool_mutexlock);
 
+	if (disconnect_ack)
+		toggle_apps_ack();
+
 	verify_tx_queue_is_empty(__func__);
 }
 
@@ -1785,6 +1797,7 @@
 	ul_powerdown_finish();
 	a2_pc_disabled = 0;
 	a2_pc_disabled_wakelock_skipped = 0;
+	disconnect_ack = 0;
 
 	/* Cleanup Channel States */
 	for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {