diff options
author | Olivier Grenie <olivier.grenie@dibcom.fr> | 2011-08-01 11:45:58 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-08-06 08:31:36 -0400 |
commit | bff469f4167fdabfe15294f375577d7eadbaa1bb (patch) | |
tree | 2f89dde514f48ee94958408fbbe1db9c8d4741cf | |
parent | 79fcce3230b140f7675f8529ee53fe2f9644f902 (diff) |
[media] dib0700: protect the dib0700 buffer access
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>
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_core.c | 81 |
1 files changed, 72 insertions, 9 deletions
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index 5eb91b4f8fd0..a224e94325b7 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c | |||
@@ -30,6 +30,11 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | |||
30 | struct dib0700_state *st = d->priv; | 30 | struct dib0700_state *st = d->priv; |
31 | int ret; | 31 | int ret; |
32 | 32 | ||
33 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
34 | deb_info("could not acquire lock"); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
33 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), | 38 | ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), |
34 | REQUEST_GET_VERSION, | 39 | REQUEST_GET_VERSION, |
35 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | 40 | USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, |
@@ -46,6 +51,7 @@ int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, | |||
46 | if (fwtype != NULL) | 51 | if (fwtype != NULL) |
47 | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | | 52 | *fwtype = (st->buf[12] << 24) | (st->buf[13] << 16) | |
48 | (st->buf[14] << 8) | st->buf[15]; | 53 | (st->buf[14] << 8) | st->buf[15]; |
54 | mutex_unlock(&d->usb_mutex); | ||
49 | return ret; | 55 | return ret; |
50 | } | 56 | } |
51 | 57 | ||
@@ -108,7 +114,12 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen | |||
108 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) | 114 | int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val) |
109 | { | 115 | { |
110 | struct dib0700_state *st = d->priv; | 116 | struct dib0700_state *st = d->priv; |
111 | s16 ret; | 117 | int ret; |
118 | |||
119 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
120 | deb_info("could not acquire lock"); | ||
121 | return 0; | ||
122 | } | ||
112 | 123 | ||
113 | st->buf[0] = REQUEST_SET_GPIO; | 124 | st->buf[0] = REQUEST_SET_GPIO; |
114 | st->buf[1] = gpio; | 125 | st->buf[1] = gpio; |
@@ -116,6 +127,7 @@ int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_ | |||
116 | 127 | ||
117 | ret = dib0700_ctrl_wr(d, st->buf, 3); | 128 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
118 | 129 | ||
130 | mutex_unlock(&d->usb_mutex); | ||
119 | return ret; | 131 | return ret; |
120 | } | 132 | } |
121 | 133 | ||
@@ -125,6 +137,11 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) | |||
125 | int ret; | 137 | int ret; |
126 | 138 | ||
127 | if (st->fw_version >= 0x10201) { | 139 | if (st->fw_version >= 0x10201) { |
140 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
141 | deb_info("could not acquire lock"); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
128 | st->buf[0] = REQUEST_SET_USB_XFER_LEN; | 145 | st->buf[0] = REQUEST_SET_USB_XFER_LEN; |
129 | st->buf[1] = (nb_ts_packets >> 8) & 0xff; | 146 | st->buf[1] = (nb_ts_packets >> 8) & 0xff; |
130 | st->buf[2] = nb_ts_packets & 0xff; | 147 | st->buf[2] = nb_ts_packets & 0xff; |
@@ -132,6 +149,7 @@ static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets) | |||
132 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); | 149 | deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets); |
133 | 150 | ||
134 | ret = dib0700_ctrl_wr(d, st->buf, 3); | 151 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
152 | mutex_unlock(&d->usb_mutex); | ||
135 | } else { | 153 | } else { |
136 | deb_info("this firmware does not allow to change the USB xfer len\n"); | 154 | deb_info("this firmware does not allow to change the USB xfer len\n"); |
137 | ret = -EIO; | 155 | ret = -EIO; |
@@ -208,6 +226,10 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
208 | 226 | ||
209 | } else { | 227 | } else { |
210 | /* Write request */ | 228 | /* Write request */ |
229 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
230 | deb_info("could not acquire lock"); | ||
231 | return 0; | ||
232 | } | ||
211 | st->buf[0] = REQUEST_NEW_I2C_WRITE; | 233 | st->buf[0] = REQUEST_NEW_I2C_WRITE; |
212 | st->buf[1] = msg[i].addr << 1; | 234 | st->buf[1] = msg[i].addr << 1; |
213 | st->buf[2] = (en_start << 7) | (en_stop << 6) | | 235 | st->buf[2] = (en_start << 7) | (en_stop << 6) | |
@@ -227,6 +249,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
227 | USB_TYPE_VENDOR | USB_DIR_OUT, | 249 | USB_TYPE_VENDOR | USB_DIR_OUT, |
228 | 0, 0, st->buf, msg[i].len + 4, | 250 | 0, 0, st->buf, msg[i].len + 4, |
229 | USB_CTRL_GET_TIMEOUT); | 251 | USB_CTRL_GET_TIMEOUT); |
252 | mutex_unlock(&d->usb_mutex); | ||
230 | if (result < 0) { | 253 | if (result < 0) { |
231 | deb_info("i2c write error (status = %d)\n", result); | 254 | deb_info("i2c write error (status = %d)\n", result); |
232 | break; | 255 | break; |
@@ -249,6 +272,10 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
249 | 272 | ||
250 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 273 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
251 | return -EAGAIN; | 274 | return -EAGAIN; |
275 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
276 | deb_info("could not acquire lock"); | ||
277 | return 0; | ||
278 | } | ||
252 | 279 | ||
253 | for (i = 0; i < num; i++) { | 280 | for (i = 0; i < num; i++) { |
254 | /* fill in the address */ | 281 | /* fill in the address */ |
@@ -279,6 +306,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, | |||
279 | break; | 306 | break; |
280 | } | 307 | } |
281 | } | 308 | } |
309 | mutex_unlock(&d->usb_mutex); | ||
282 | mutex_unlock(&d->i2c_mutex); | 310 | mutex_unlock(&d->i2c_mutex); |
283 | 311 | ||
284 | return i; | 312 | return i; |
@@ -337,7 +365,12 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | |||
337 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) | 365 | u16 pll_loopdiv, u16 free_div, u16 dsuScaler) |
338 | { | 366 | { |
339 | struct dib0700_state *st = d->priv; | 367 | struct dib0700_state *st = d->priv; |
340 | s16 ret; | 368 | int ret; |
369 | |||
370 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
371 | deb_info("could not acquire lock"); | ||
372 | return 0; | ||
373 | } | ||
341 | 374 | ||
342 | st->buf[0] = REQUEST_SET_CLOCK; | 375 | st->buf[0] = REQUEST_SET_CLOCK; |
343 | st->buf[1] = (en_pll << 7) | (pll_src << 6) | | 376 | st->buf[1] = (en_pll << 7) | (pll_src << 6) | |
@@ -352,6 +385,7 @@ static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll, | |||
352 | st->buf[9] = dsuScaler & 0xff; /* LSB */ | 385 | st->buf[9] = dsuScaler & 0xff; /* LSB */ |
353 | 386 | ||
354 | ret = dib0700_ctrl_wr(d, st->buf, 10); | 387 | ret = dib0700_ctrl_wr(d, st->buf, 10); |
388 | mutex_unlock(&d->usb_mutex); | ||
355 | 389 | ||
356 | return ret; | 390 | return ret; |
357 | } | 391 | } |
@@ -360,10 +394,16 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) | |||
360 | { | 394 | { |
361 | struct dib0700_state *st = d->priv; | 395 | struct dib0700_state *st = d->priv; |
362 | u16 divider; | 396 | u16 divider; |
397 | int ret; | ||
363 | 398 | ||
364 | if (scl_kHz == 0) | 399 | if (scl_kHz == 0) |
365 | return -EINVAL; | 400 | return -EINVAL; |
366 | 401 | ||
402 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
403 | deb_info("could not acquire lock"); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
367 | st->buf[0] = REQUEST_SET_I2C_PARAM; | 407 | st->buf[0] = REQUEST_SET_I2C_PARAM; |
368 | divider = (u16) (30000 / scl_kHz); | 408 | divider = (u16) (30000 / scl_kHz); |
369 | st->buf[1] = 0; | 409 | st->buf[1] = 0; |
@@ -379,7 +419,11 @@ int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz) | |||
379 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", | 419 | deb_info("setting I2C speed: %04x %04x %04x (%d kHz).", |
380 | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | | 420 | (st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) | |
381 | st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); | 421 | st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz); |
382 | return dib0700_ctrl_wr(d, st->buf, 8); | 422 | |
423 | ret = dib0700_ctrl_wr(d, st->buf, 8); | ||
424 | mutex_unlock(&d->usb_mutex); | ||
425 | |||
426 | return ret; | ||
383 | } | 427 | } |
384 | 428 | ||
385 | 429 | ||
@@ -515,6 +559,11 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
515 | } | 559 | } |
516 | } | 560 | } |
517 | 561 | ||
562 | if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) { | ||
563 | deb_info("could not acquire lock"); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
518 | st->buf[0] = REQUEST_ENABLE_VIDEO; | 567 | st->buf[0] = REQUEST_ENABLE_VIDEO; |
519 | /* this bit gives a kind of command, | 568 | /* this bit gives a kind of command, |
520 | * rather than enabling something or not */ | 569 | * rather than enabling something or not */ |
@@ -548,7 +597,10 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) | |||
548 | 597 | ||
549 | deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); | 598 | deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]); |
550 | 599 | ||
551 | return dib0700_ctrl_wr(adap->dev, st->buf, 4); | 600 | ret = dib0700_ctrl_wr(adap->dev, st->buf, 4); |
601 | mutex_unlock(&adap->dev->usb_mutex); | ||
602 | |||
603 | return ret; | ||
552 | } | 604 | } |
553 | 605 | ||
554 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | 606 | int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) |
@@ -557,6 +609,11 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
557 | struct dib0700_state *st = d->priv; | 609 | struct dib0700_state *st = d->priv; |
558 | int new_proto, ret; | 610 | int new_proto, ret; |
559 | 611 | ||
612 | if (mutex_lock_interruptible(&d->usb_mutex) < 0) { | ||
613 | deb_info("could not acquire lock"); | ||
614 | return 0; | ||
615 | } | ||
616 | |||
560 | st->buf[0] = REQUEST_SET_RC; | 617 | st->buf[0] = REQUEST_SET_RC; |
561 | st->buf[1] = 0; | 618 | st->buf[1] = 0; |
562 | st->buf[2] = 0; | 619 | st->buf[2] = 0; |
@@ -567,23 +624,29 @@ int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
567 | else if (rc_type == RC_TYPE_NEC) | 624 | else if (rc_type == RC_TYPE_NEC) |
568 | new_proto = 0; | 625 | new_proto = 0; |
569 | else if (rc_type == RC_TYPE_RC6) { | 626 | else if (rc_type == RC_TYPE_RC6) { |
570 | if (st->fw_version < 0x10200) | 627 | if (st->fw_version < 0x10200) { |
571 | return -EINVAL; | 628 | ret = -EINVAL; |
629 | goto out; | ||
630 | } | ||
572 | 631 | ||
573 | new_proto = 2; | 632 | new_proto = 2; |
574 | } else | 633 | } else { |
575 | return -EINVAL; | 634 | ret = -EINVAL; |
635 | goto out; | ||
636 | } | ||
576 | 637 | ||
577 | st->buf[1] = new_proto; | 638 | st->buf[1] = new_proto; |
578 | 639 | ||
579 | ret = dib0700_ctrl_wr(d, st->buf, 3); | 640 | ret = dib0700_ctrl_wr(d, st->buf, 3); |
580 | if (ret < 0) { | 641 | if (ret < 0) { |
581 | err("ir protocol setup failed"); | 642 | err("ir protocol setup failed"); |
582 | return ret; | 643 | goto out; |
583 | } | 644 | } |
584 | 645 | ||
585 | d->props.rc.core.protocol = rc_type; | 646 | d->props.rc.core.protocol = rc_type; |
586 | 647 | ||
648 | out: | ||
649 | mutex_unlock(&d->usb_mutex); | ||
587 | return ret; | 650 | return ret; |
588 | } | 651 | } |
589 | 652 | ||