On 2015-02-19 11:21, Antti Seppälä wrote:
On 19 February 2015 at 11:43, Benjamin Larsson <benjamin@xxxxxxxxxxxx> wrote:
On 2015-02-19 10:13, Antti Seppälä wrote:
It seems that currently the firmware download on the mn88472 is
somehow wrong for my Astrometa HD-901T2.
Reducing the download chunk size (mn88472_config.i2c_wr_max) to 2
makes the firmware download consistently succeed.
Hi, try adding the workaround patch I sent for this.
[PATCH 1/3] rtl28xxu: lower the rc poll time to mitigate i2c transfer errors
I now see that it hasn't been merged. But I have been running with this
patch for a few months now without any major issues.
The patch really did improve firmware loading. Weird...
Even with it I still get occasional i2c errors from r820t:
[ 15.874402] r820t 8-003a: r820t_write: i2c wr failed=-32 reg=0a len=1: da
[ 81.455517] r820t 8-003a: r820t_read: i2c rd failed=-32 reg=00
len=4: 69 74 e6 df
[ 99.949702] r820t 8-003a: r820t_read: i2c rd failed=-32 reg=00
len=4: 69 74 e6 df
These errors seem to appear more often if I'm reading the signal
strength values using e.g. femon.
Br,
-Antti
This patch implements a retry logic. If a transfer fails it will convert
it to 1 byte transfers. This will not work when loading the nm88472
firmware as everything is loaded through the 0xf6 register.
I think we might need something like this to get the Astrometa working
reliably.
Based on usb logs from the windows driver one can see that they only
send 1 byte at a time so they can retry all transfers. So this issue
seems to be related to the rtl2832p bridge chip and how much i2c traffic
is generated.
MvH
Benjamin Larsson
>From 5962cf8fafdfe98138fd69beb4d0b5d2a7af5732 Mon Sep 17 00:00:00 2001
From: Benjamin Larsson <benjamin@xxxxxxxxxxxx>
Date: Thu, 20 Nov 2014 00:50:02 +0100
Subject: [PATCH] rtl28xxu: implement i2c transfer retry logic
Cc: Linux Media Mailing List <linux-media@xxxxxxxxxxxxxxx>
This is needed for Astrometa hardware. Retry counts up to 6 has been
observered before the i2c transfer succeded.
Signed-off-by: Benjamin Larsson <benjamin@xxxxxxxxxxxx>
---
drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 4af8a61..4d321ae 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -185,6 +185,8 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
struct dvb_usb_device *d = i2c_get_adapdata(adap);
struct rtl28xxu_priv *priv = d->priv;
struct rtl28xxu_req req;
+ u8 rb_buf[2];
+ int i, retry_cnt;
/*
* It is not known which are real I2C bus xfer limits, but testing
@@ -273,6 +275,33 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
req.size = msg[0].len-1;
req.data = &msg[0].buf[1];
ret = rtl28xxu_ctrl_msg(d, &req);
+
+ /* Astrometa hardware needs a retry for some failed transfers.
+ * Just send one byte at the time.
+ * Retry max 10 times for each transfer.
+ */
+ if (ret) {
+ req.size = 1;
+ req.data = rb_buf;
+
+ dev_dbg(&d->udev->dev, "%s: transfer of %d bytes failed\n", __func__, msg[0].len-1);
+ rb_buf[0] = msg[0].buf[0];
+
+ for (i=0 ; i<msg[0].len-1 ; i++) {
+ retry_cnt = 0;
+ req.value = ((msg[0].buf[0]+i) << 8) | (msg[0].addr << 1);
+ rb_buf[0] = msg[0].buf[i+1];
+
+ do {
+ dev_dbg(&d->udev->dev, "%s: byte: %d retry: %d\n", __func__, i, retry_cnt);
+ ret = rtl28xxu_ctrl_msg(d, &req);
+ retry_cnt++;
+ if (retry_cnt > 10)
+ goto err_mutex_unlock;
+
+ } while (ret);
+ }
+ }
} else {
/* method 3 - new I2C */
req.value = (msg[0].addr << 1);
--
1.9.1