V4L/DVB (8331): cx18: Add locking for struct cx18 GPIO state variables

cx18: Add locking for struct cx18 GPIO state variables in
anticpation of adding IR microcontroller reset support for
use by external IR modules.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index e73de62..22434aa 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -421,6 +421,7 @@
 	mutex_init(&cx->serialize_lock);
 	mutex_init(&cx->i2c_bus_lock[0]);
 	mutex_init(&cx->i2c_bus_lock[1]);
+	mutex_init(&cx->gpio_lock);
 
 	spin_lock_init(&cx->lock);
 	spin_lock_init(&cx->dma_reg_lock);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index b78d0e3..45e31b0 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -427,6 +427,7 @@
 	/* gpio */
 	u32 gpio_dir;
 	u32 gpio_val;
+	struct mutex gpio_lock;
 
 	/* v4l2 and User settings */
 
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
index 089bad6..d753a40 100644
--- a/drivers/media/video/cx18/cx18-gpio.c
+++ b/drivers/media/video/cx18/cx18-gpio.c
@@ -69,6 +69,7 @@
 	/* Assuming that the masks are a subset of the bits in gpio_dir */
 
 	/* Assert */
+	mutex_lock(&cx->gpio_lock);
 	cx->gpio_val =
 		(cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask);
 	gpio_write(cx);
@@ -79,10 +80,12 @@
 		(cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask);
 	gpio_write(cx);
 	schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery));
+	mutex_unlock(&cx->gpio_lock);
 }
 
 void cx18_gpio_init(struct cx18 *cx)
 {
+	mutex_lock(&cx->gpio_lock);
 	cx->gpio_dir = cx->card->gpio_init.direction;
 	cx->gpio_val = cx->card->gpio_init.initial_value;
 
@@ -91,14 +94,17 @@
 		cx->gpio_val |= 1 << cx->card->xceive_pin;
 	}
 
-	if (cx->gpio_dir == 0)
+	if (cx->gpio_dir == 0) {
+		mutex_unlock(&cx->gpio_lock);
 		return;
+	}
 
 	CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
 		   read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2),
 		   read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2));
 
 	gpio_write(cx);
+	mutex_unlock(&cx->gpio_lock);
 }
 
 /* Xceive tuner reset function */
@@ -112,13 +118,16 @@
 		return 0;
 	CX18_DEBUG_INFO("Resetting tuner\n");
 
+	mutex_lock(&cx->gpio_lock);
 	cx->gpio_val &= ~(1 << cx->card->xceive_pin);
-
 	gpio_write(cx);
+	mutex_unlock(&cx->gpio_lock);
 	schedule_timeout_interruptible(msecs_to_jiffies(1));
 
+	mutex_lock(&cx->gpio_lock);
 	cx->gpio_val |= 1 << cx->card->xceive_pin;
 	gpio_write(cx);
+	mutex_unlock(&cx->gpio_lock);
 	schedule_timeout_interruptible(msecs_to_jiffies(1));
 	return 0;
 }
@@ -151,8 +160,10 @@
 		return -EINVAL;
 	}
 	if (mask) {
+		mutex_lock(&cx->gpio_lock);
 		cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
 		gpio_write(cx);
+		mutex_unlock(&cx->gpio_lock);
 	}
 	return 0;
 }
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 6eaf77b..146a4b8 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -716,8 +716,10 @@
 	cx18_get_audio_input(cx, cx->audio_input, &audin);
 	CX18_INFO("Video Input: %s\n", vidin.name);
 	CX18_INFO("Audio Input: %s\n", audin.name);
+	mutex_lock(&cx->gpio_lock);
 	CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
 		cx->gpio_dir, cx->gpio_val);
+	mutex_unlock(&cx->gpio_lock);
 	CX18_INFO("Tuner: %s\n",
 		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
 	cx2341x_log_status(&cx->params, cx->name);