Skip to content

Commit

Permalink
[media] dib0700: protect the dib0700 buffer access
Browse files Browse the repository at this point in the history
This patch protects the common buffer access inside the dib0700 in order
to manage concurrent access. This protection is done using mutex.

Cc: Mauro Carvalho Chehab <mchehab@redhat.com>
Cc: Florian Mickler <florian@mickler.org>
Cc: stable@kernel.org
Signed-off-by: Javier Marcet <javier@marcet.info>
Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
[mchehab@redhat.com: dprint requires 3 arguments. Replaced by dib_info]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Olivier Grenie authored and Mauro Carvalho Chehab committed Aug 6, 2011
1 parent 79fcce3 commit bff469f
Showing 1 changed file with 72 additions and 9 deletions.
81 changes: 72 additions & 9 deletions drivers/media/dvb/dvb-usb/dib0700_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
struct dib0700_state *st = d->priv;
int ret;

if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
REQUEST_GET_VERSION,
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
Expand All @@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
if (fwtype != NULL)
*fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) |
(st->buf[14] << 8) | st->buf[15];
mutex_unlock(&d->usb_mutex);
return ret;
}

Expand Down Expand Up @@ -108,14 +114,20 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
{
struct dib0700_state *st = d->priv;
s16 ret;
int ret;

if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_SET_GPIO;
st->buf[1] = gpio;
st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);

ret = dib0700_ctrl_wr(d, st->buf, 3);

mutex_unlock(&d->usb_mutex);
return ret;
}

Expand All @@ -125,13 +137,19 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
int ret;

if (st->fw_version >= 0x10201) {
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_SET_USB_XFER_LEN;
st->buf[1] = (nb_ts_packets >> 8) & 0xff;
st->buf[2] = nb_ts_packets & 0xff;

deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);

ret = dib0700_ctrl_wr(d, st->buf, 3);
mutex_unlock(&d->usb_mutex);
} else {
deb_info("this firmware does not allow to change the USB xfer len\n");
ret = -EIO;
Expand Down Expand Up @@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,

} else {
/* Write request */
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}
st->buf[0] = REQUEST_NEW_I2C_WRITE;
st->buf[1] = msg[i].addr << 1;
st->buf[2] = (en_start << 7) | (en_stop << 6) |
Expand All @@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
USB_TYPE_VENDOR | USB_DIR_OUT,
0, 0, st->buf, msg[i].len + 4,
USB_CTRL_GET_TIMEOUT);
mutex_unlock(&d->usb_mutex);
if (result < 0) {
deb_info("i2c write error (status = %d)\n", result);
break;
Expand All @@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,

if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

for (i = 0; i < num; i++) {
/* fill in the address */
Expand Down Expand Up @@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
break;
}
}
mutex_unlock(&d->usb_mutex);
mutex_unlock(&d->i2c_mutex);

return i;
Expand Down Expand Up @@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
{
struct dib0700_state *st = d->priv;
s16 ret;
int ret;

if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_SET_CLOCK;
st->buf[1] = (en_pll << 7) | (pll_src << 6) |
Expand All @@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
st->buf[9] = dsuScaler & 0xff; /* LSB */

ret = dib0700_ctrl_wr(d, st->buf, 10);
mutex_unlock(&d->usb_mutex);

return ret;
}
Expand All @@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
{
struct dib0700_state *st = d->priv;
u16 divider;
int ret;

if (scl_kHz == 0)
return -EINVAL;

if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_SET_I2C_PARAM;
divider = (u16) (30000 / scl_kHz);
st->buf[1] = 0;
Expand All @@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
return dib0700_ctrl_wr(d, st->buf, 8);

ret = dib0700_ctrl_wr(d, st->buf, 8);
mutex_unlock(&d->usb_mutex);

return ret;
}


Expand Down Expand Up @@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
}
}

if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_ENABLE_VIDEO;
/* this bit gives a kind of command,
* rather than enabling something or not */
Expand Down Expand Up @@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)

deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);

return dib0700_ctrl_wr(adap->dev, st->buf, 4);
ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
mutex_unlock(&adap->dev->usb_mutex);

return ret;
}

int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
Expand All @@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
struct dib0700_state *st = d->priv;
int new_proto, ret;

if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
deb_info("could not acquire lock");
return 0;
}

st->buf[0] = REQUEST_SET_RC;
st->buf[1] = 0;
st->buf[2] = 0;
Expand All @@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
else if (rc_type == RC_TYPE_NEC)
new_proto = 0;
else if (rc_type == RC_TYPE_RC6) {
if (st->fw_version < 0x10200)
return -EINVAL;
if (st->fw_version < 0x10200) {
ret = -EINVAL;
goto out;
}

new_proto = 2;
} else
return -EINVAL;
} else {
ret = -EINVAL;
goto out;
}

st->buf[1] = new_proto;

ret = dib0700_ctrl_wr(d, st->buf, 3);
if (ret < 0) {
err("ir protocol setup failed");
return ret;
goto out;
}

d->props.rc.core.protocol = rc_type;

out:
mutex_unlock(&d->usb_mutex);
return ret;
}

Expand Down

0 comments on commit bff469f

Please sign in to comment.