Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf427952 authored by Antti Palosaari's avatar Antti Palosaari Committed by Mauro Carvalho Chehab
Browse files

[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: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 3e9caa52
Loading
Loading
Loading
Loading
+32 −6
Original line number Original line Diff line number Diff line
@@ -58,7 +58,7 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
	u8 *rbuf, u8 rlen)
	u8 *rbuf, u8 rlen)
{
{
	struct anysee_state *state = d->priv;
	struct anysee_state *state = d->priv;
	int act_len, ret;
	int act_len, ret, i;
	u8 buf[64];
	u8 buf[64];


	memcpy(&buf[0], sbuf, slen);
	memcpy(&buf[0], sbuf, slen);
@@ -73,26 +73,52 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
	/* We need receive one message more after dvb_usb_generic_rw due
	/* We need receive one message more after dvb_usb_generic_rw due
	   to weird transaction flow, which is 1 x send + 2 x receive. */
	   to weird transaction flow, which is 1 x send + 2 x receive. */
	ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
	ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
	if (!ret) {
	if (ret)
		goto error_unlock;

	/* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
	 * (EPIPE, Broken pipe). Function supports currently msleep() as a
	 * parameter but I would not like to use it, since according to
	 * Documentation/timers/timers-howto.txt it should not be used such
	 * short, under < 20ms, sleeps. Repeating failed message would be
	 * better choice as not to add unwanted delays...
	 * Fixing that correctly is one of those or both;
	 * 1) use repeat if possible
	 * 2) add suitable delay
	 */

	/* get answer, retry few times if error returned */
	for (i = 0; i < 3; i++) {
		/* receive 2nd answer */
		/* receive 2nd answer */
		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
			d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
			d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
			&act_len, 2000);
			&act_len, 2000);
		if (ret)

			err("%s: recv bulk message failed: %d", __func__, ret);
		if (ret) {
		else {
			deb_info("%s: recv bulk message failed: %d",
					__func__, ret);
		} else {
			deb_xfer("<<< ");
			deb_xfer("<<< ");
			debug_dump(buf, rlen, deb_xfer);
			debug_dump(buf, rlen, deb_xfer);


			if (buf[63] != 0x4f)
			if (buf[63] != 0x4f)
				deb_info("%s: cmd failed\n", __func__);
				deb_info("%s: cmd failed\n", __func__);

			break;
		}
	}
	}

	if (ret) {
		/* all retries failed, it is fatal */
		err("%s: recv bulk message failed: %d", __func__, ret);
		goto error_unlock;
	}
	}


	/* read request, copy returned data to return buf */
	/* read request, copy returned data to return buf */
	if (!ret && rbuf && rlen)
	if (rbuf && rlen)
		memcpy(rbuf, buf, rlen);
		memcpy(rbuf, buf, rlen);


error_unlock:
	mutex_unlock(&anysee_usb_mutex);
	mutex_unlock(&anysee_usb_mutex);


	return ret;
	return ret;