e78653b
From: Olivier Grenie <olivier.grenie@dibcom.fr>
e78653b
Date: Mon, 1 Aug 2011 15:45:58 +0000 (-0300)
e78653b
Subject: [media] dib0700: protect the dib0700 buffer access
e78653b
X-Git-Tag: next-20110927~67^2~4^2~224
e78653b
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fnext%2Flinux-next.git;a=commitdiff_plain;h=bff469f4167fdabfe15294f375577d7eadbaa1bb
e78653b
e78653b
[media] dib0700: protect the dib0700 buffer access
e78653b
e78653b
This patch protects the common buffer access inside the dib0700 in order
e78653b
to manage concurrent access. This protection is done using mutex.
e78653b
e78653b
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
e78653b
Cc: Florian Mickler <florian@mickler.org>
e78653b
Cc: stable@kernel.org
e78653b
Signed-off-by: Javier Marcet <javier@marcet.info>
e78653b
Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
e78653b
Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
e78653b
[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info]
e78653b
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
e78653b
---
e78653b
e78653b
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
e78653b
index 5eb91b4..a224e94 100644
e78653b
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
e78653b
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
e78653b
@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
e78653b
 	struct dib0700_state *st = d->priv;
e78653b
 	int ret;
e78653b
 
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
+
e78653b
 	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
e78653b
 				  REQUEST_GET_VERSION,
e78653b
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
e78653b
@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
e78653b
 	if (fwtype != NULL)
e78653b
 		*fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
e78653b
 			(st->buf[14] << 8) | st->buf[15];
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
 	return ret;
e78653b
 }
e78653b
 
e78653b
@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
e78653b
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
e78653b
 {
e78653b
 	struct dib0700_state *st = d->priv;
e78653b
-	s16 ret;
e78653b
+	int ret;
e78653b
+
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
 
e78653b
 	st->buf[0] = REQUEST_SET_GPIO;
e78653b
 	st->buf[1] = gpio;
e78653b
@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_
e78653b
 
e78653b
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
e78653b
 
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
 	return ret;
e78653b
 }
e78653b
 
e78653b
@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
e78653b
 	int ret;
e78653b
 
e78653b
 	if (st->fw_version >= 0x10201) {
e78653b
+		if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+			deb_info("could not acquire lock");
e78653b
+			return 0;
e78653b
+		}
e78653b
+
e78653b
 		st->buf[0] = REQUEST_SET_USB_XFER_LEN;
e78653b
 		st->buf[1] = (nb_ts_packets >> 8) & 0xff;
e78653b
 		st->buf[2] = nb_ts_packets & 0xff;
e78653b
@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
e78653b
 		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
e78653b
 
e78653b
 		ret = dib0700_ctrl_wr(d, st->buf, 3);
e78653b
+		mutex_unlock(&d->usb_mutex);
e78653b
 	} else {
e78653b
 		deb_info("this firmware does not allow to change the USB xfer len\n");
e78653b
 		ret = -EIO;
e78653b
@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
e78653b
 
e78653b
 		} else {
e78653b
 			/* Write request */
e78653b
+			if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+				deb_info("could not acquire lock");
e78653b
+				return 0;
e78653b
+			}
e78653b
 			st->buf[0] = REQUEST_NEW_I2C_WRITE;
e78653b
 			st->buf[1] = msg[i].addr << 1;
e78653b
 			st->buf[2] = (en_start << 7) | (en_stop << 6) |
e78653b
@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
e78653b
 						 USB_TYPE_VENDOR | USB_DIR_OUT,
e78653b
 						 0, 0, st->buf, msg[i].len + 4,
e78653b
 						 USB_CTRL_GET_TIMEOUT);
e78653b
+			mutex_unlock(&d->usb_mutex);
e78653b
 			if (result < 0) {
e78653b
 				deb_info("i2c write error (status = %d)\n", result);
e78653b
 				break;
e78653b
@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
e78653b
 
e78653b
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
e78653b
 		return -EAGAIN;
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
 
e78653b
 	for (i = 0; i < num; i++) {
e78653b
 		/* fill in the address */
e78653b
@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
e78653b
 				break;
e78653b
 		}
e78653b
 	}
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
 	mutex_unlock(&d->i2c_mutex);
e78653b
 
e78653b
 	return i;
e78653b
@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
e78653b
 	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
e78653b
 {
e78653b
 	struct dib0700_state *st = d->priv;
e78653b
-	s16 ret;
e78653b
+	int ret;
e78653b
+
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
 
e78653b
 	st->buf[0] = REQUEST_SET_CLOCK;
e78653b
 	st->buf[1] = (en_pll << 7) | (pll_src << 6) |
e78653b
@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
e78653b
 	st->buf[9] =  dsuScaler         & 0xff; /* LSB */
e78653b
 
e78653b
 	ret = dib0700_ctrl_wr(d, st->buf, 10);
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
 
e78653b
 	return ret;
e78653b
 }
e78653b
@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
e78653b
 {
e78653b
 	struct dib0700_state *st = d->priv;
e78653b
 	u16 divider;
e78653b
+	int ret;
e78653b
 
e78653b
 	if (scl_kHz == 0)
e78653b
 		return -EINVAL;
e78653b
 
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
+
e78653b
 	st->buf[0] = REQUEST_SET_I2C_PARAM;
e78653b
 	divider = (u16) (30000 / scl_kHz);
e78653b
 	st->buf[1] = 0;
e78653b
@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
e78653b
 	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
e78653b
 		(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
e78653b
 		st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
e78653b
-	return dib0700_ctrl_wr(d, st->buf, 8);
e78653b
+
e78653b
+	ret = dib0700_ctrl_wr(d, st->buf, 8);
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
+
e78653b
+	return ret;
e78653b
 }
e78653b
 
e78653b
 
e78653b
@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
e78653b
 		}
e78653b
 	}
e78653b
 
e78653b
+	if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
+
e78653b
 	st->buf[0] = REQUEST_ENABLE_VIDEO;
e78653b
 	/* this bit gives a kind of command,
e78653b
 	 * rather than enabling something or not */
e78653b
@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
e78653b
 
e78653b
 	deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
e78653b
 
e78653b
-	return dib0700_ctrl_wr(adap->dev, st->buf, 4);
e78653b
+	ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
e78653b
+	mutex_unlock(&adap->dev->usb_mutex);
e78653b
+
e78653b
+	return ret;
e78653b
 }
e78653b
 
e78653b
 int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
e78653b
@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
e78653b
 	struct dib0700_state *st = d->priv;
e78653b
 	int new_proto, ret;
e78653b
 
e78653b
+	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
e78653b
+		deb_info("could not acquire lock");
e78653b
+		return 0;
e78653b
+	}
e78653b
+
e78653b
 	st->buf[0] = REQUEST_SET_RC;
e78653b
 	st->buf[1] = 0;
e78653b
 	st->buf[2] = 0;
e78653b
@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
e78653b
 	else if (rc_type == RC_TYPE_NEC)
e78653b
 		new_proto = 0;
e78653b
 	else if (rc_type == RC_TYPE_RC6) {
e78653b
-		if (st->fw_version < 0x10200)
e78653b
-			return -EINVAL;
e78653b
+		if (st->fw_version < 0x10200) {
e78653b
+			ret = -EINVAL;
e78653b
+			goto out;
e78653b
+		}
e78653b
 
e78653b
 		new_proto = 2;
e78653b
-	} else
e78653b
-		return -EINVAL;
e78653b
+	} else {
e78653b
+		ret = -EINVAL;
e78653b
+		goto out;
e78653b
+	}
e78653b
 
e78653b
 	st->buf[1] = new_proto;
e78653b
 
e78653b
 	ret = dib0700_ctrl_wr(d, st->buf, 3);
e78653b
 	if (ret < 0) {
e78653b
 		err("ir protocol setup failed");
e78653b
-		return ret;
e78653b
+		goto out;
e78653b
 	}
e78653b
 
e78653b
 	d->props.rc.core.protocol = rc_type;
e78653b
 
e78653b
+out:
e78653b
+	mutex_unlock(&d->usb_mutex);
e78653b
 	return ret;
e78653b
 }
e78653b