From patchwork Sat Mar 18 02:04:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jasmin J." X-Patchwork-Id: 40136 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cp4t9-0002d0-AW; Sat, 18 Mar 2017 03:18:43 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.84_2/mailfrontend-6) with esmtp id 1cp4t7-0003rW-3v; Sat, 18 Mar 2017 04:18:43 +0100 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751126AbdCRDSg (ORCPT + 1 other); Fri, 17 Mar 2017 23:18:36 -0400 Received: from mail.anw.at ([195.234.101.228]:51677 "EHLO mail.anw.at" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751087AbdCRDSg (ORCPT ); Fri, 17 Mar 2017 23:18:36 -0400 Received: from [192.168.23.40] (anwhome.anw.at [195.234.103.23]) by mail.anw.at (8.14.4/8.14.4/Debian-4.1ubuntu1) with ESMTP id v2I24NI4002371 for ; Sat, 18 Mar 2017 03:04:23 +0100 To: linux-media@vger.kernel.org From: "Jasmin J." Subject: [PATCH] media/dvb-core: Race condition when writing to CAM. Message-ID: Date: Sat, 18 Mar 2017 03:04:20 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 X-Antivirus: checked in 0.018sec at mail.anw.at ([195.234.102.72]) by smf-clamd v1.2.1 - http://smfs.sf.net/ Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2017.3.18.31217 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' AT_TLD 0.1, HTML_00_01 0.05, HTML_00_10 0.05, MSGID_ADDED_BY_MTA 0.05, BODYTEXTP_SIZE_3000_LESS 0, BODY_SIZE_2000_2999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, NO_URI_HTTPS 0, __ANY_URI 0, __CT 0, __CTE 0, __CT_TEXT_PLAIN 0, __HAS_FROM 0, __HAS_LIST_ID 0, __HAS_MSGID 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MIME_VERSION 0, __MOZILLA_USER_AGENT 0, __NO_HTML_TAG_RAW 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0, __URI_NS , __USER_AGENT 0' 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). Signed-off-by: Jasmin jessich Acked-by: rjkm@metzlerbros.de Tested-by: rjkm@metzlerbros.de --- drivers/media/dvb-core/dvb_ca_en50221.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index 8d65028..0007839 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -785,6 +785,24 @@ 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 */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_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;