| From foo@baz Thu Mar 22 14:57:32 CET 2018 |
| From: Jasmin J <jasmin@anw.at> |
| Date: Fri, 17 Mar 2017 23:04:20 -0300 |
| Subject: [media] media/dvb-core: Race condition when writing to CAM |
| |
| From: Jasmin J <jasmin@anw.at> |
| |
| |
| [ Upstream commit e7080d4471d805d921a9ea21b32f911a91e248cb ] |
| |
| 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). |
| |
| [mchehab@s-opensource.com: make checkpatch happy] |
| |
| Signed-off-by: Jasmin jessich <jasmin@anw.at> |
| Tested-by: Ralph Metzler <rjkm@metzlerbros.de> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/media/dvb-core/dvb_ca_en50221.c | 23 +++++++++++++++++++++++ |
| 1 file changed, 23 insertions(+) |
| |
| --- a/drivers/media/dvb-core/dvb_ca_en50221.c |
| +++ b/drivers/media/dvb-core/dvb_ca_en50221.c |
| @@ -750,6 +750,29 @@ static int dvb_ca_en50221_write_data(str |
| 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; |