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: 242151 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o98JLNRh018506 for ; Fri, 8 Oct 2010 19:21:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759458Ab0JHTVW (ORCPT ); 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 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Fri, 08 Oct 2010 19:21:24 +0000 (UTC) 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);