From patchwork Fri Oct 8 19:21:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarod Wilson X-Patchwork-Id: 4560 Return-path: Envelope-to: mchehab@pedra Delivery-date: Fri, 08 Oct 2010 16:21:32 -0300 Received: from mchehab by pedra with local (Exim 4.72) (envelope-from ) id 1P4IVX-0000ms-Qg for mchehab@pedra; Fri, 08 Oct 2010 16:21:32 -0300 Received: from casper.infradead.org [85.118.1.10] by pedra with IMAP (fetchmail-6.3.17) for (single-drop); Fri, 08 Oct 2010 16:21:31 -0300 (BRT) Received: from bombadil.infradead.org ([2001:4830:2446:ff00:4687:fcff:fea6:5117]) by casper.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1P4IVR-0001S4-AV for mchehab@casper.infradead.org; Fri, 08 Oct 2010 19:21:25 +0000 Received: from vger.kernel.org ([209.132.180.67]) by bombadil.infradead.org with esmtp (Exim 4.72 #1 (Red Hat Linux)) id 1P4IVP-0001JG-SH; Fri, 08 Oct 2010 19:21:24 +0000 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759458Ab0JHTVW (ORCPT + 1 other); Fri, 8 Oct 2010 15:21:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:5546 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758961Ab0JHTVV (ORCPT ); Fri, 8 Oct 2010 15:21:21 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o98JLBWp026957 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 8 Oct 2010 15:21:12 -0400 Received: from xavier.bos.redhat.com (xavier.bos.redhat.com [10.16.16.50]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id o98JLAsN014492; Fri, 8 Oct 2010 15:21:10 -0400 Received: by xavier.bos.redhat.com (Postfix, from userid 500) id D1A6781628; Fri, 8 Oct 2010 15:21:09 -0400 (EDT) Date: Fri, 8 Oct 2010 15:21:09 -0400 From: Jarod Wilson To: linux-media@vger.kernel.org Cc: lirc-list@lists.sourceforge.net, lcchen@nuvoton.com Subject: [PATCH] nuvoton-cir: add proper rx fifo overrun handling Message-ID: <20101008192109.GD5165@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Sender: Per discussion with Andy Walls on irc, rx fifo overruns are not all that uncommon on a busy system, and the initial posting of the nuvoton-cir driver doesn't handle them well enough. With this addition, we'll drain the hw fifo, attempt to process any ir pulse trains completed with that flush, then we'll issue a hw rx fifo clear and reset the raw ir sample kfifo and start over collecting raw ir data. Also slightly refactors the cir interrupt enabling so that we always get consistent flags set and only have to modify them in one place, should they need to be altered. Signed-off-by: Jarod Wilson --- drivers/media/IR/nuvoton-cir.c | 37 +++++++++++++++++++++++++++++-------- 1 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c index 1ce9359..fdb280e 100644 --- a/drivers/media/IR/nuvoton-cir.c +++ b/drivers/media/IR/nuvoton-cir.c @@ -339,6 +339,15 @@ static void nvt_clear_tx_fifo(struct nvt_dev *nvt) nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); } +/* enable RX Trigger Level Reach and Packet End interrupts */ +static void nvt_set_cir_iren(struct nvt_dev *nvt) +{ + u8 iren; + + iren = CIR_IREN_RTR | CIR_IREN_PE; + nvt_cir_reg_write(nvt, iren, CIR_IREN); +} + static void nvt_cir_regs_init(struct nvt_dev *nvt) { /* set sample limit count (PE interrupt raised when reached) */ @@ -363,8 +372,8 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) /* clear any and all stray interrupts */ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - /* and finally, enable RX Trigger Level Read and Packet End interrupts */ - nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); + /* and finally, enable interrupts */ + nvt_set_cir_iren(nvt); } static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) @@ -639,12 +648,22 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) nvt_dbg_verbose("%s done", __func__); } +static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) +{ + nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!"); + + nvt->pkts = 0; + nvt_clear_cir_fifo(nvt); + ir_raw_event_reset(nvt->rdev); +} + /* copy data from hardware rx fifo into driver buffer */ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) { unsigned long flags; u8 fifocount, val; unsigned int b_idx; + bool overrun = false; int i; /* Get count of how many bytes to read from RX FIFO */ @@ -652,11 +671,10 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) /* if we get 0xff, probably means the logical dev is disabled */ if (fifocount == 0xff) return; - /* this would suggest a fifo overrun, not good... */ + /* watch out for a fifo overrun condition */ else if (fifocount > RX_BUF_LEN) { - nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", - fifocount, RX_BUF_LEN); - return; + overrun = true; + fifocount = RX_BUF_LEN; } nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); @@ -682,6 +700,9 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) nvt_process_rx_ir_data(nvt); + if (overrun) + nvt_handle_rx_fifo_overrun(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } @@ -886,7 +907,7 @@ static void nvt_enable_cir(struct nvt_dev *nvt) nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); /* enable interrupts */ - nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); + nvt_set_cir_iren(nvt); } static void nvt_disable_cir(struct nvt_dev *nvt) @@ -1155,7 +1176,7 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_dbg("%s called", __func__); /* open interrupt */ - nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); + nvt_set_cir_iren(nvt); /* Enable CIR logical device */ nvt_efm_enable(nvt);