msm: smd_pkt: Add packet arrival wakelock

While handling the incoming packets from remote subsystems, delay the
system suspension by holding a wakelock with a timeout value of 2 seconds.
This will allow the user-space clients to process the incoming packets
before the system goes to suspend.

CRs-Fixed: 335782
Change-Id: Idea2fd490a52a8bfd7b97cad7e784a6782a0cf8f
Signed-off-by: Eric Holmberg <eholmber@codeaurora.org>
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 8023129..63c5fef 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -31,6 +31,7 @@
 #include <linux/msm_smd_pkt.h>
 #include <linux/poll.h>
 #include <asm/ioctls.h>
+#include <linux/wakelock.h>
 
 #include <mach/msm_smd.h>
 #include <mach/peripheral-loader.h>
@@ -45,6 +46,7 @@
 #define LOOPBACK_INX (NUM_SMD_PKT_PORTS - 1)
 
 #define DEVICE_NAME "smdpkt"
+#define WAKELOCK_TIMEOUT (2*HZ)
 
 struct smd_pkt_dev {
 	struct cdev cdev;
@@ -70,7 +72,8 @@
 	int has_reset;
 	int do_reset_notification;
 	struct completion ch_allocated;
-
+	struct wake_lock pa_wake_lock;		/* Packet Arrival Wake lock*/
+	struct work_struct packet_arrival_work;
 } *smd_pkt_devp[NUM_SMD_PKT_PORTS];
 
 struct class *smd_pkt_classp;
@@ -183,6 +186,19 @@
 
 }
 
+static void packet_arrival_worker(struct work_struct *work)
+{
+	struct smd_pkt_dev *smd_pkt_devp;
+
+	smd_pkt_devp = container_of(work, struct smd_pkt_dev,
+				    packet_arrival_work);
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	if (smd_pkt_devp->ch)
+		wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
+				  WAKELOCK_TIMEOUT);
+	mutex_unlock(&smd_pkt_devp->ch_lock);
+}
+
 static long smd_pkt_ioctl(struct file *file, unsigned int cmd,
 					     unsigned long arg)
 {
@@ -421,6 +437,7 @@
 
 	/* here we have a packet of size sz ready */
 	wake_up(&smd_pkt_devp->ch_read_wait_queue);
+	schedule_work(&smd_pkt_devp->packet_arrival_work);
 	D(KERN_ERR "%s: after wake_up\n", __func__);
 }
 
@@ -579,6 +596,10 @@
 	if (!smd_pkt_devp)
 		return -EINVAL;
 
+	wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
+			smd_pkt_dev_name[smd_pkt_devp->i]);
+	INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
+
 	file->private_data = smd_pkt_devp;
 
 	mutex_lock(&smd_pkt_devp->ch_lock);
@@ -665,6 +686,9 @@
 out:
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 
+	if (r < 0)
+		wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+
 	return r;
 }
 
@@ -690,6 +714,7 @@
 
 	smd_pkt_devp->has_reset = 0;
 	smd_pkt_devp->do_reset_notification = 0;
+	wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
 
 	return r;
 }