ARM: SAMSUNG: adc: make waitq part of client structure

Moved local waitq instance from s3c_adc_read function to s3c_adc_client
structure which is global. This makes the ADC operation more robust and
ensure there is no memory corruption.

Occasional cases (during stress test) found src_adc_read function
woke up and exited before completing last action (spinlock restore) in the
__wake_up function which is part of ADC IRQ handler. This caused memory
corruption and found subsequent function crashed due to this.

BUG=chromeos-partner:14648
TEST=Ran ADC stress test for several hours
 cd /sys/devices/platform/ncp15wb473.0/
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&
 while true; do cat temp1_input > /dev/null; done&

Change-Id: I52730669b2537cae32b8f4ef94750d8723c4cd6a
Signed-off-by: Sunil Mazhavanchery <sunilm@samsung.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/34504
Commit-Ready: Doug Anderson <dianders@chromium.org>
Reviewed-by: Doug Anderson <dianders@chromium.org>
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index a049213..15cc07d 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -52,7 +52,7 @@
 struct s3c_adc_client {
 	struct platform_device	*pdev;
 	struct list_head	 pend;
-	wait_queue_head_t	*wait;
+	wait_queue_head_t	 wait;
 
 	unsigned int		 nr_samples;
 	int			 result;
@@ -254,7 +254,7 @@
 			     unsigned v, unsigned u, unsigned *left)
 {
 	client->result = v;
-	wake_up(client->wait);
+	wake_up(&client->wait);
 }
 
 /* Get the result out of the client with locking.
@@ -277,7 +277,6 @@
 int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
 {
 	unsigned long flags;
-	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
 	int ret;
 
 	/* Lock around access of client members.  Technically all that's really
@@ -287,7 +286,6 @@
 	 */
 	spin_lock_irqsave(&adc_dev->lock, flags);
 	client->convert_cb = s3c_convert_done;
-	client->wait = &wake;
 	client->result = -1;
 	spin_unlock_irqrestore(&adc_dev->lock, flags);
 
@@ -295,7 +293,7 @@
 	if (ret < 0)
 		goto exit;
 
-	wait_event_timeout(wake, s3c_get_result(client) >= 0, HZ / 2);
+	wait_event_timeout(client->wait, s3c_get_result(client) >= 0, HZ / 2);
 	ret = s3c_get_result(client);
 
 	if (ret < 0) {
@@ -308,7 +306,6 @@
 	 * a pointer to the client anymore.
 	 */
 	client->convert_cb = NULL;
-	client->wait = NULL;
 
 	return ret;
 }
@@ -347,6 +344,7 @@
 	client->is_ts = is_ts;
 	client->select_cb = select;
 	client->convert_cb = conv;
+	init_waitqueue_head(&client->wait);
 
 	return client;
 }