aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2012-01-21 09:19:29 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-01-26 11:46:09 -0500
commitcf427952adcee0210e64b77ae7de9c8f256cce5c (patch)
tree1a10d40bf9b5207b4a04dea36b5eb90ffa81ed4c /drivers
parent3e9caa525147e28d032a8e413d9797c21cbaf88c (diff)
[media] anysee: repeat failed USB control messages
Control message load increased heavily after CI/CAM support due to dvb_ca_en50221. It looks like CI/CAM drops to non-working state easily after error is returned to its callbacks. Due to that, add some logic to avoid errors repeating failed messages. Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/dvb/dvb-usb/anysee.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index cf0c318d6989..03c28655af1b 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
58 u8 *rbuf, u8 rlen) 58 u8 *rbuf, u8 rlen)
59{ 59{
60 struct anysee_state *state = d->priv; 60 struct anysee_state *state = d->priv;
61 int act_len, ret; 61 int act_len, ret, i;
62 u8 buf[64]; 62 u8 buf[64];
63 63
64 memcpy(&buf[0], sbuf, slen); 64 memcpy(&buf[0], sbuf, slen);
@@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
73 /* We need receive one message more after dvb_usb_generic_rw due 73 /* We need receive one message more after dvb_usb_generic_rw due
74 to weird transaction flow, which is 1 x send + 2 x receive. */ 74 to weird transaction flow, which is 1 x send + 2 x receive. */
75 ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0); 75 ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
76 if (!ret) { 76 if (ret)
77 goto error_unlock;
78
79 /* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
80 * (EPIPE, Broken pipe). Function supports currently msleep() as a
81 * parameter but I would not like to use it, since according to
82 * Documentation/timers/timers-howto.txt it should not be used such
83 * short, under < 20ms, sleeps. Repeating failed message would be
84 * better choice as not to add unwanted delays...
85 * Fixing that correctly is one of those or both;
86 * 1) use repeat if possible
87 * 2) add suitable delay
88 */
89
90 /* get answer, retry few times if error returned */
91 for (i = 0; i < 3; i++) {
77 /* receive 2nd answer */ 92 /* receive 2nd answer */
78 ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 93 ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
79 d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf), 94 d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
80 &act_len, 2000); 95 &act_len, 2000);
81 if (ret) 96
82 err("%s: recv bulk message failed: %d", __func__, ret); 97 if (ret) {
83 else { 98 deb_info("%s: recv bulk message failed: %d",
99 __func__, ret);
100 } else {
84 deb_xfer("<<< "); 101 deb_xfer("<<< ");
85 debug_dump(buf, rlen, deb_xfer); 102 debug_dump(buf, rlen, deb_xfer);
86 103
87 if (buf[63] != 0x4f) 104 if (buf[63] != 0x4f)
88 deb_info("%s: cmd failed\n", __func__); 105 deb_info("%s: cmd failed\n", __func__);
106
107 break;
89 } 108 }
90 } 109 }
91 110
111 if (ret) {
112 /* all retries failed, it is fatal */
113 err("%s: recv bulk message failed: %d", __func__, ret);
114 goto error_unlock;
115 }
116
92 /* read request, copy returned data to return buf */ 117 /* read request, copy returned data to return buf */
93 if (!ret && rbuf && rlen) 118 if (rbuf && rlen)
94 memcpy(rbuf, buf, rlen); 119 memcpy(rbuf, buf, rlen);
95 120
121error_unlock:
96 mutex_unlock(&anysee_usb_mutex); 122 mutex_unlock(&anysee_usb_mutex);
97 123
98 return ret; 124 return ret;