diff mbox

rtl28xxu: fix control message flaws

Message ID 1444495530-1674-1-git-send-email-crope@iki.fi (mailing list archive)
State New, archived
Headers show

Commit Message

Antti Palosaari Oct. 10, 2015, 4:45 p.m. UTC
Add lock to prevent concurrent access for control message as control
message function uses shared buffer. Without the lock there may be
remote control polling which messes the buffer causing IO errors.
Increase buffer size and add check for maximum supported message
length.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=103391
Fixes: c56222a6b25c ("[media] rtl28xxu: move usb buffers to state")
Cc: <stable@vger.kernel.org> # 4.0+
Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 15 +++++++++++++--
 drivers/media/usb/dvb-usb-v2/rtl28xxu.h |  2 +-
 2 files changed, 14 insertions(+), 3 deletions(-)

Comments

Daniel Glöckner Oct. 14, 2015, 10:11 p.m. UTC | #1
On Sat, Oct 10, 2015 at 07:45:30PM +0300, Antti Palosaari wrote:
> Add lock to prevent concurrent access for control message as control
> message function uses shared buffer. Without the lock there may be
> remote control polling which messes the buffer causing IO errors.

This patch fixes the Problems I had with my Astrometa stick's I2C bus
locking up at the end of each dvbv5-scan run until it is disconnected.
There is another source of IO errors in the current driver, though.
The delayed work closing the I2C gate to the tuner is often executed
after rtl2832_power_ctrl has disabled the PLL. This will cause the
USB transfer accessing the gate control register to fail with -EPIPE.

Best regards,

  Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Antti Palosaari Oct. 15, 2015, 6:54 a.m. UTC | #2
On 10/15/2015 01:11 AM, Daniel Glöckner wrote:
> On Sat, Oct 10, 2015 at 07:45:30PM +0300, Antti Palosaari wrote:
>> Add lock to prevent concurrent access for control message as control
>> message function uses shared buffer. Without the lock there may be
>> remote control polling which messes the buffer causing IO errors.
>
> This patch fixes the Problems I had with my Astrometa stick's I2C bus
> locking up at the end of each dvbv5-scan run until it is disconnected.
> There is another source of IO errors in the current driver, though.
> The delayed work closing the I2C gate to the tuner is often executed
> after rtl2832_power_ctrl has disabled the PLL. This will cause the
> USB transfer accessing the gate control register to fail with -EPIPE.

I saw that few times too, but it does not cause any other harm than 
error printing. It went away when canceled that delayed gate closing 
timer during demod sleep. But that was device which doesn't have slave 
demod at all, so it does not apply to your case as integrated demod 
sleep is not called at all. I think some callback which does opposite 
than "enable_slave_ts()" is needed. Like "disable_slave_ts()" which 
kills that timer before demod is powered off.

regards
Antti
Benjamin Larsson Nov. 6, 2015, 11:15 p.m. UTC | #3
On 10/10/2015 06:45 PM, Antti Palosaari wrote:
> Add lock to prevent concurrent access for control message as control
> message function uses shared buffer. Without the lock there may be
> remote control polling which messes the buffer causing IO errors.
> Increase buffer size and add check for maximum supported message
> length.
>

This patch made at least one of my devices work. Before my log was full 
of errors.

Totally unrelated I do get a fail on loading the firmware. Just retrying 
made it work eventually.

[  143.286498] mn88473 19-0018: downloading firmware from file 
'dvb-demod-mn88473-01.fw'
[  143.551497] mn88473 19-0018: firmware download failed=-32
[  143.826792] rtl2832 19-0010: i2c reg read failed -32
[  143.903215] mn88473 19-0018: downloading firmware from file 
'dvb-demod-mn88473-01.fw'
[  144.345554] mn88473 19-0018: firmware download failed=-32
[  331.060613] mn88473 19-0018: downloading firmware from file 
'dvb-demod-mn88473-01.fw'
[  331.477234] mn88473 19-0018: firmware download failed=-32
[  354.997771] rtl2832 19-0010: i2c reg read failed -32
[  358.591754] mn88473 19-0018: downloading firmware from file 
'dvb-demod-mn88473-01.fw'
[  359.115582] mn88473 19-0018: firmware parity check succeeded=0x20

MvH
Benjamin Larsson
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index c3cac4c..197a4f2 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -34,6 +34,14 @@  static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 	unsigned int pipe;
 	u8 requesttype;
 
+	mutex_lock(&d->usb_mutex);
+
+	if (req->size > sizeof(dev->buf)) {
+		dev_err(&d->intf->dev, "too large message %u\n", req->size);
+		ret = -EINVAL;
+		goto err_mutex_unlock;
+	}
+
 	if (req->index & CMD_WR_FLAG) {
 		/* write */
 		memcpy(dev->buf, req->data, req->size);
@@ -50,14 +58,17 @@  static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 	dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
 			req->index, dev->buf, req->size);
 	if (ret < 0)
-		goto err;
+		goto err_mutex_unlock;
 
 	/* read request, copy returned data to return buf */
 	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
 		memcpy(req->data, dev->buf, req->size);
 
+	mutex_unlock(&d->usb_mutex);
+
 	return 0;
-err:
+err_mutex_unlock:
+	mutex_unlock(&d->usb_mutex);
 	dev_dbg(&d->intf->dev, "failed=%d\n", ret);
 	return ret;
 }
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 9f6115a..1380629 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -71,7 +71,7 @@ 
 
 
 struct rtl28xxu_dev {
-	u8 buf[28];
+	u8 buf[128];
 	u8 chip_id;
 	u8 tuner;
 	char *tuner_name;