msm: ipc: Fix potential AB-BA deadlock

In kernel QMI, while receiving responses continuously, there is a
classic out-of-order(AB-BA) deadlock scenario between IPC router and
Kernel QMI interface. The scenario is as below:

  1) IPC Router receives the message for kernel QMI port and acquires the
     corresponding port's port_rx_q_lock and then calls the notify
     function for that port which tries to acquire the handle_lock of the
     port.

  2) Kernel QMI interface, that runs independent of IPC Router activities,
     tries to send a message and acquires handle_lock for the port and
     tries to acquire the port's port_rx_q_lock to read the response from
     the port.

  3) This creates a classic AB-BA deadlock because port_rx_q_lock is
     locked at step 1 and handle_lock is acquired at step 2.

Fix the deadlock.

Change-Id: I532cff30b445e11baa715a570e5e853d9b71bab3
Signed-off-by: Zaheerulla Meer <zmeer@codeaurora.org>
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 21baa06..e66afeb 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -464,6 +464,7 @@
 			    struct rr_packet *pkt, int clone)
 {
 	struct rr_packet *temp_pkt = pkt;
+	void (*notify)(unsigned event, void *priv);
 
 	if (unlikely(!port_ptr || !pkt))
 		return -EINVAL;
@@ -482,9 +483,10 @@
 	wake_lock(&port_ptr->port_rx_wake_lock);
 	list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q);
 	wake_up(&port_ptr->port_rx_wait_q);
-	if (port_ptr->notify)
-		port_ptr->notify(MSM_IPC_ROUTER_READ_CB, port_ptr->priv);
+	notify = port_ptr->notify;
 	mutex_unlock(&port_ptr->port_rx_q_lock_lhb3);
+	if (notify)
+		notify(MSM_IPC_ROUTER_READ_CB, port_ptr->priv);
 	return 0;
 }