Skip to content

Commit

Permalink
[media] media/dvb-core: Race condition when writing to CAM
Browse files Browse the repository at this point in the history
It started with a sporadic message in syslog: "CAM tried to send a
buffer larger than the ecount size" This message is not the fault
itself, but a consecutive fault, after a read error from the CAM. This
happens only on several CAMs, several hardware, and of course sporadic.

It is a consecutive fault, if the last read from the CAM did fail. I
guess this will not happen on all CAMs, but at least it did on mine.
There was a write error to the CAM and during the re-initialization
procedure, the CAM finished the last read, although it got a RS.

The write error to the CAM happened because a race condition between HC
write, checking DA and FR.

This patch added an additional check for DA(RE), just after checking FR.
It is important to read the CAMs status register again, to give the CAM
the necessary time for a proper reaction to HC. Please note the
description within the source code (patch below).

[[email protected]: make checkpatch happy]

Signed-off-by: Jasmin jessich <[email protected]>
Tested-by: Ralph Metzler <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
jasmin-j authored and mchehab committed Apr 17, 2017
1 parent b73bb2a commit e7080d4
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions drivers/media/dvb-core/dvb_ca_en50221.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,29 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
goto exit;
}

/*
* It may need some time for the CAM to settle down, or there might
* be a race condition between the CAM, writing HC and our last
* check for DA. This happens, if the CAM asserts DA, just after
* checking DA before we are setting HC. In this case it might be
* a bug in the CAM to keep the FR bit, the lower layer/HW
* communication requires a longer timeout or the CAM needs more
* time internally. But this happens in reality!
* We need to read the status from the HW again and do the same
* we did for the previous check for DA
*/
status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
if (status < 0)
goto exit;

if (status & (STATUSREG_DA | STATUSREG_RE)) {
if (status & STATUSREG_DA)
dvb_ca_en50221_thread_wakeup(ca);

status = -EAGAIN;
goto exit;
}

/* send the amount of data */
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
goto exit;
Expand Down

0 comments on commit e7080d4

Please sign in to comment.