msm: smd_tty: smd_tty_open to wait until SMD channel is fully open

smd_tty_open waits with timeout for SMD channel to be fully open
before returning.

CRs-Fixed: 296382
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 2a0dcfc..bfc4150 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -56,6 +56,8 @@
 	void *pil;
 	int in_reset;
 	int in_reset_updated;
+	int is_open;
+	wait_queue_head_t ch_opened_wait_queue;
 	spinlock_t reset_lock;
 };
 
@@ -176,6 +178,8 @@
 		spin_lock_irqsave(&info->reset_lock, flags);
 		info->in_reset = 0;
 		info->in_reset_updated = 1;
+		info->is_open = 1;
+		wake_up_interruptible(&info->ch_opened_wait_queue);
 		spin_unlock_irqrestore(&info->reset_lock, flags);
 		break;
 
@@ -183,6 +187,8 @@
 		spin_lock_irqsave(&info->reset_lock, flags);
 		info->in_reset = 1;
 		info->in_reset_updated = 1;
+		info->is_open = 0;
+		wake_up_interruptible(&info->ch_opened_wait_queue);
 		spin_unlock_irqrestore(&info->reset_lock, flags);
 		/* schedule task to send TTY_BREAK */
 		tasklet_hi_schedule(&info->tty_tsklt);
@@ -281,6 +287,23 @@
 							smd_ch_edge[n],
 							&info->ch, info,
 							smd_tty_notify);
+			if (res < 0) {
+				pr_err("%s: %s open failed %d\n", __func__,
+					smd_ch_name[n], res);
+				goto release_pil;
+			}
+
+			res = wait_event_interruptible_timeout(
+				info->ch_opened_wait_queue,
+				info->is_open, (2 * HZ));
+			if (res == 0)
+				res = -ETIMEDOUT;
+			if (res < 0) {
+				pr_err("%s: wait for %s smd_open failed %d\n",
+					__func__, smd_ch_name[n], res);
+				goto release_pil;
+			}
+			res = 0;
 		}
 	}
 
@@ -505,6 +528,8 @@
 	smd_tty[0].driver.driver.name = smd_ch_name[0];
 	smd_tty[0].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[0].reset_lock);
+	smd_tty[0].is_open = 0;
+	init_waitqueue_head(&smd_tty[0].ch_opened_wait_queue);
 	/*
 	 * DS port is opened in the kernel starting with 8660 fusion.
 	 * Only register the platform driver for targets older than that.
@@ -524,6 +549,8 @@
 	smd_tty[1].driver.driver.name = smd_ch_name[1];
 	smd_tty[1].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[1].reset_lock);
+	smd_tty[1].is_open = 0;
+	init_waitqueue_head(&smd_tty[1].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[1].driver);
 	if (ret)
 		goto unreg0;
@@ -531,6 +558,8 @@
 	smd_tty[2].driver.driver.name = smd_ch_name[2];
 	smd_tty[2].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[2].reset_lock);
+	smd_tty[2].is_open = 0;
+	init_waitqueue_head(&smd_tty[2].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[2].driver);
 	if (ret)
 		goto unreg1;
@@ -538,6 +567,8 @@
 	smd_tty[3].driver.driver.name = smd_ch_name[3];
 	smd_tty[3].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[3].reset_lock);
+	smd_tty[3].is_open = 0;
+	init_waitqueue_head(&smd_tty[3].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[3].driver);
 	if (ret)
 		goto unreg2;
@@ -545,6 +576,8 @@
 	smd_tty[7].driver.driver.name = smd_ch_name[7];
 	smd_tty[7].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[7].reset_lock);
+	smd_tty[7].is_open = 0;
+	init_waitqueue_head(&smd_tty[7].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[7].driver);
 	if (ret)
 		goto unreg3;
@@ -552,6 +585,8 @@
 	smd_tty[21].driver.driver.name = smd_ch_name[21];
 	smd_tty[21].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[21].reset_lock);
+	smd_tty[21].is_open = 0;
+	init_waitqueue_head(&smd_tty[21].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[21].driver);
 	if (ret)
 		goto unreg7;
@@ -559,6 +594,8 @@
 	smd_tty[27].driver.driver.name = smd_ch_name[27];
 	smd_tty[27].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[27].reset_lock);
+	smd_tty[27].is_open = 0;
+	init_waitqueue_head(&smd_tty[27].ch_opened_wait_queue);
 	ret = platform_driver_register(&smd_tty[27].driver);
 	if (ret)
 		goto unreg21;
@@ -566,6 +603,8 @@
 	smd_tty[36].driver.driver.name = "LOOPBACK_TTY";
 	smd_tty[36].driver.driver.owner = THIS_MODULE;
 	spin_lock_init(&smd_tty[36].reset_lock);
+	smd_tty[36].is_open = 0;
+	init_waitqueue_head(&smd_tty[36].ch_opened_wait_queue);
 	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
 	ret = platform_driver_register(&smd_tty[36].driver);
 	if (ret)