diff options
| -rw-r--r-- | drivers/media/dvb/dvb-usb/anysee.c | 38 |
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 | ||
| 121 | error_unlock: | ||
| 96 | mutex_unlock(&anysee_usb_mutex); | 122 | mutex_unlock(&anysee_usb_mutex); |
| 97 | 123 | ||
| 98 | return ret; | 124 | return ret; |
