From patchwork Sun May 7 21:23:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jasmin J." X-Patchwork-Id: 41187 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from ) id 1d7UIh-0004Sr-PP; Sun, 07 May 2017 22:05:11 +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-8) with esmtp id 1d7UIQ-0000Lc-kr; Mon, 08 May 2017 00:05:11 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756196AbdEGWEu (ORCPT + 1 other); Sun, 7 May 2017 18:04:50 -0400 Received: from mail.anw.at ([195.234.101.228]:35906 "EHLO mail.anw.at" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756148AbdEGWEt (ORCPT ); Sun, 7 May 2017 18:04:49 -0400 X-Greylist: delayed 595 seconds by postgrey-1.27 at vger.kernel.org; Sun, 07 May 2017 18:04:26 EDT Received: from hoppel.217.196.72.190 (anwhome.anw.at [195.234.103.23]) by mail.anw.at (8.14.4/8.14.4/Debian-4.1ubuntu1) with ESMTP id v47LNeGL026475; Sun, 7 May 2017 23:23:44 +0200 From: "Jasmin J." To: linux-media@vger.kernel.org Cc: mchehab@s-opensource.com, max.kellermann@gmail.com, jasmin@anw.at Subject: [PATCH 04/11] [media] dvb-core/dvb_ca_en50221.c: Refactored dvb_ca_en50221_thread Date: Sun, 7 May 2017 23:23:27 +0200 Message-Id: <1494192214-20082-5-git-send-email-jasmin@anw.at> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1494192214-20082-1-git-send-email-jasmin@anw.at> References: <1494192214-20082-1-git-send-email-jasmin@anw.at> X-Antivirus: checked in 0.108sec 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: 2016.11.22.95719 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' AT_TLD 0.1, MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_10000_PLUS 0, ECARD_WORD 0, IN_REP_TO 0, LEGITIMATE_SIGNS 0, MSG_THREAD 0, MULTIPLE_REAL_RCPTS 0, NO_URI_HTTPS 0, REFERENCES 0, __ANY_URI 0, __FROM_DOMAIN_IN_ANY_CC2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_LIST_ID 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __IN_REP_TO 0, __LEGIT_LIST_HEADER 0, __LINES_OF_YELLING 0, __MIME_TEXT_ONLY 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MULTIPLE_RCPTS_CC_X2 0, __NO_HTML_TAG_RAW 0, __REFERENCES 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0, __URI_NS ' From: Jasmin Jessich Refactored "dvb_ca_en50221_thread" by moving the state machine into the new function "dvb_ca_en50221_thread_state_machine". This reduces the thread function size and reduces the structural complexity and of course gives us more space to meet the line length goal in the new function. Signed-off-by: Jasmin Jessich --- drivers/media/dvb-core/dvb_ca_en50221.c | 338 +++++++++++++++++--------------- 1 file changed, 176 insertions(+), 162 deletions(-) diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index ba30bcf4..cc1d1d1 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -1055,204 +1055,218 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) /** - * Kernel thread which monitors CA slots for CAM changes, and performs data transfers. + * Thread state machine for one CA slot to perform the data transfer. + * + * @ca: CA instance. + * @slot: Slot to process. */ -static int dvb_ca_en50221_thread(void *data) +static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca, + int slot) { - struct dvb_ca_private *ca = data; - int slot; int flags; int status; int pktcount; void *rxbuf; - dprintk("%s\n", __func__); - - /* choose the correct initial delay */ - dvb_ca_en50221_thread_update_delay(ca); - - /* main loop */ - while (!kthread_should_stop()) { - /* sleep for a bit */ - if (!ca->wakeup) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ca->delay); - if (kthread_should_stop()) - return 0; - } - ca->wakeup = 0; + struct dvb_ca_slot *sl = &ca->slot_info[slot]; - /* go through all the slots processing them */ - for (slot = 0; slot < ca->slot_count; slot++) { - struct dvb_ca_slot *sl = &ca->slot_info[slot]; + mutex_lock(&sl->slot_lock); - mutex_lock(&sl->slot_lock); + // check the CAM status + deal with CAMCHANGEs + while (dvb_ca_en50221_check_camstatus(ca, slot)) { + /* clear down an old CI slot if necessary */ + if (sl->slot_state != SLOT_STAT_NONE) + dvb_ca_en50221_slot_shutdown(ca, slot); - // check the cam status + deal with CAMCHANGEs - while (dvb_ca_en50221_check_camstatus(ca, slot)) { - /* clear down an old CI slot if necessary */ - if (sl->slot_state != SLOT_STAT_NONE) - dvb_ca_en50221_slot_shutdown(ca, slot); + /* if a CAM is NOW present, initialise it */ + if (sl->camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { + sl->slot_state = SLOT_STAT_UNINIT; + } - /* if a CAM is NOW present, initialise it */ - if (sl->camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) { - sl->slot_state = SLOT_STAT_UNINIT; - } + /* we've handled one CAMCHANGE */ + dvb_ca_en50221_thread_update_delay(ca); + atomic_dec(&sl->camchange_count); + } - /* we've handled one CAMCHANGE */ - dvb_ca_en50221_thread_update_delay(ca); - atomic_dec(&sl->camchange_count); - } + // CAM state machine + switch (sl->slot_state) { + case SLOT_STAT_NONE: + case SLOT_STAT_INVALID: + // no action needed + break; - // CAM state machine - switch (sl->slot_state) { - case SLOT_STAT_NONE: - case SLOT_STAT_INVALID: - // no action needed - break; + case SLOT_STAT_UNINIT: + sl->slot_state = SLOT_STAT_WAITREADY; + ca->pub->slot_reset(ca->pub, slot); + sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); + break; - case SLOT_STAT_UNINIT: - sl->slot_state = SLOT_STAT_WAITREADY; - ca->pub->slot_reset(ca->pub, slot); - sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); - break; + case SLOT_STAT_WAITREADY: + if (time_after(jiffies, sl->timeout)) { + pr_err("dvb_ca adaptor %d: PC card did not respond :(\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + // no other action needed; will automatically change state when ready + break; - case SLOT_STAT_WAITREADY: - if (time_after(jiffies, sl->timeout)) { - pr_err("dvb_ca adaptor %d: PC card did not respond :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; + case SLOT_STAT_VALIDATE: + if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { + /* we need this extra check for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && + (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, slot, 0); + if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + sl->slot_state = SLOT_STAT_NONE; dvb_ca_en50221_thread_update_delay(ca); break; } - // no other action needed; will automatically change state when ready - break; + } - case SLOT_STAT_VALIDATE: - if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { - /* we need this extra check for annoying interfaces like the budget-av */ - if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && - (ca->pub->poll_slot_status)) { - status = ca->pub->poll_slot_status(ca->pub, slot, 0); - if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { - sl->slot_state = SLOT_STAT_NONE; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - } - - pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { - pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - if (ca->pub->write_cam_control(ca->pub, slot, - CTRLIF_COMMAND, CMDREG_RS) != 0) { - pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - dprintk("DVB CAM validated successfully\n"); + pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { + pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + if (ca->pub->write_cam_control(ca->pub, slot, + CTRLIF_COMMAND, CMDREG_RS) != 0) { + pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } + dprintk("DVB CAM validated successfully\n"); - sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); - sl->slot_state = SLOT_STAT_WAITFR; - ca->wakeup = 1; - break; + sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); + sl->slot_state = SLOT_STAT_WAITFR; + ca->wakeup = 1; + break; - case SLOT_STAT_WAITFR: - if (time_after(jiffies, sl->timeout)) { - pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } + case SLOT_STAT_WAITFR: + if (time_after(jiffies, sl->timeout)) { + pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); + break; + } - flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); - if (flags & STATREG_FR) { - sl->slot_state = SLOT_STAT_LINKINIT; - ca->wakeup = 1; - } - break; + flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); + if (flags & STATREG_FR) { + sl->slot_state = SLOT_STAT_LINKINIT; + ca->wakeup = 1; + } + break; - case SLOT_STAT_LINKINIT: - if (dvb_ca_en50221_link_init(ca, slot) != 0) { - /* we need this extra check for annoying interfaces like the budget-av */ - if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && - (ca->pub->poll_slot_status)) { - status = ca->pub->poll_slot_status(ca->pub, slot, 0); - if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { - sl->slot_state = SLOT_STAT_NONE; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - } - - pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_UNINIT; + case SLOT_STAT_LINKINIT: + if (dvb_ca_en50221_link_init(ca, slot) != 0) { + /* we need this extra check for annoying interfaces like the budget-av */ + if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && + (ca->pub->poll_slot_status)) { + status = ca->pub->poll_slot_status(ca->pub, slot, 0); + if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { + sl->slot_state = SLOT_STAT_NONE; dvb_ca_en50221_thread_update_delay(ca); break; } + } - if (sl->rx_buffer.data == NULL) { - rxbuf = vmalloc(RX_BUFFER_SIZE); - if (rxbuf == NULL) { - pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", - ca->dvbdev->adapter->num); - sl->slot_state = SLOT_STAT_INVALID; - dvb_ca_en50221_thread_update_delay(ca); - break; - } - dvb_ringbuffer_init(&sl->rx_buffer, rxbuf, RX_BUFFER_SIZE); - } + pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", + ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_UNINIT; + dvb_ca_en50221_thread_update_delay(ca); + break; + } - ca->pub->slot_ts_enable(ca->pub, slot); - sl->slot_state = SLOT_STAT_RUNNING; - dvb_ca_en50221_thread_update_delay(ca); - pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", + if (sl->rx_buffer.data == NULL) { + rxbuf = vmalloc(RX_BUFFER_SIZE); + if (rxbuf == NULL) { + pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num); + sl->slot_state = SLOT_STAT_INVALID; + dvb_ca_en50221_thread_update_delay(ca); break; + } + dvb_ringbuffer_init(&sl->rx_buffer, rxbuf, RX_BUFFER_SIZE); + } - case SLOT_STAT_RUNNING: - if (!ca->open) - break; + ca->pub->slot_ts_enable(ca->pub, slot); + sl->slot_state = SLOT_STAT_RUNNING; + dvb_ca_en50221_thread_update_delay(ca); + pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", + ca->dvbdev->adapter->num); + break; - // poll slots for data - pktcount = 0; - while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { - if (!ca->open) - break; - - /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ - if (dvb_ca_en50221_check_camstatus(ca, slot)) { - // we dont want to sleep on the next iteration so we can handle the cam change - ca->wakeup = 1; - break; - } - - /* check if we've hit our limit this time */ - if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { - // dont sleep; there is likely to be more data to read - ca->wakeup = 1; - break; - } - } + case SLOT_STAT_RUNNING: + if (!ca->open) + break; + + // poll slots for data + pktcount = 0; + while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { + if (!ca->open) + break; + + /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ + if (dvb_ca_en50221_check_camstatus(ca, slot)) { + // we dont want to sleep on the next iteration so we can handle the cam change + ca->wakeup = 1; break; } - mutex_unlock(&sl->slot_lock); + /* check if we've hit our limit this time */ + if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { + // dont sleep; there is likely to be more data to read + ca->wakeup = 1; + break; + } } + break; + } + + mutex_unlock(&sl->slot_lock); +} + + + +/** + * Kernel thread which monitors CA slots for CAM changes, and performs data transfers. + */ +static int dvb_ca_en50221_thread(void *data) +{ + struct dvb_ca_private *ca = data; + int slot; + + dprintk("%s\n", __func__); + + /* choose the correct initial delay */ + dvb_ca_en50221_thread_update_delay(ca); + + /* main loop */ + while (!kthread_should_stop()) { + /* sleep for a bit */ + if (!ca->wakeup) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(ca->delay); + if (kthread_should_stop()) + return 0; + } + ca->wakeup = 0; + + /* go through all the slots processing them */ + for (slot = 0; slot < ca->slot_count; slot++) + dvb_ca_en50221_thread_state_machine(ca, slot); } return 0;