aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarod Wilson <jarod@redhat.com>2010-10-08 15:16:23 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-20 23:18:32 -0400
commitfbdc781c6ba9742b475ca9979007ea12bed0d044 (patch)
tree92f3de4e320eca636f5f517a9f6931f76f1c7ea0
parent6d2f5c27880c2c72e35432eae10c7a74251050c0 (diff)
[media] nuvoton-cir: add proper rx fifo overrun handling
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 <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/IR/nuvoton-cir.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c
index 1ce93599ff56..fdb280ed01ce 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)
339 nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); 339 nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON);
340} 340}
341 341
342/* enable RX Trigger Level Reach and Packet End interrupts */
343static void nvt_set_cir_iren(struct nvt_dev *nvt)
344{
345 u8 iren;
346
347 iren = CIR_IREN_RTR | CIR_IREN_PE;
348 nvt_cir_reg_write(nvt, iren, CIR_IREN);
349}
350
342static void nvt_cir_regs_init(struct nvt_dev *nvt) 351static void nvt_cir_regs_init(struct nvt_dev *nvt)
343{ 352{
344 /* set sample limit count (PE interrupt raised when reached) */ 353 /* set sample limit count (PE interrupt raised when reached) */
@@ -363,8 +372,8 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
363 /* clear any and all stray interrupts */ 372 /* clear any and all stray interrupts */
364 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); 373 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
365 374
366 /* and finally, enable RX Trigger Level Read and Packet End interrupts */ 375 /* and finally, enable interrupts */
367 nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); 376 nvt_set_cir_iren(nvt);
368} 377}
369 378
370static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) 379static 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)
639 nvt_dbg_verbose("%s done", __func__); 648 nvt_dbg_verbose("%s done", __func__);
640} 649}
641 650
651static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
652{
653 nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!");
654
655 nvt->pkts = 0;
656 nvt_clear_cir_fifo(nvt);
657 ir_raw_event_reset(nvt->rdev);
658}
659
642/* copy data from hardware rx fifo into driver buffer */ 660/* copy data from hardware rx fifo into driver buffer */
643static void nvt_get_rx_ir_data(struct nvt_dev *nvt) 661static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
644{ 662{
645 unsigned long flags; 663 unsigned long flags;
646 u8 fifocount, val; 664 u8 fifocount, val;
647 unsigned int b_idx; 665 unsigned int b_idx;
666 bool overrun = false;
648 int i; 667 int i;
649 668
650 /* Get count of how many bytes to read from RX FIFO */ 669 /* 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)
652 /* if we get 0xff, probably means the logical dev is disabled */ 671 /* if we get 0xff, probably means the logical dev is disabled */
653 if (fifocount == 0xff) 672 if (fifocount == 0xff)
654 return; 673 return;
655 /* this would suggest a fifo overrun, not good... */ 674 /* watch out for a fifo overrun condition */
656 else if (fifocount > RX_BUF_LEN) { 675 else if (fifocount > RX_BUF_LEN) {
657 nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", 676 overrun = true;
658 fifocount, RX_BUF_LEN); 677 fifocount = RX_BUF_LEN;
659 return;
660 } 678 }
661 679
662 nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); 680 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)
682 700
683 nvt_process_rx_ir_data(nvt); 701 nvt_process_rx_ir_data(nvt);
684 702
703 if (overrun)
704 nvt_handle_rx_fifo_overrun(nvt);
705
685 spin_unlock_irqrestore(&nvt->nvt_lock, flags); 706 spin_unlock_irqrestore(&nvt->nvt_lock, flags);
686} 707}
687 708
@@ -886,7 +907,7 @@ static void nvt_enable_cir(struct nvt_dev *nvt)
886 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); 907 nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
887 908
888 /* enable interrupts */ 909 /* enable interrupts */
889 nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); 910 nvt_set_cir_iren(nvt);
890} 911}
891 912
892static void nvt_disable_cir(struct nvt_dev *nvt) 913static void nvt_disable_cir(struct nvt_dev *nvt)
@@ -1155,7 +1176,7 @@ static int nvt_resume(struct pnp_dev *pdev)
1155 nvt_dbg("%s called", __func__); 1176 nvt_dbg("%s called", __func__);
1156 1177
1157 /* open interrupt */ 1178 /* open interrupt */
1158 nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); 1179 nvt_set_cir_iren(nvt);
1159 1180
1160 /* Enable CIR logical device */ 1181 /* Enable CIR logical device */
1161 nvt_efm_enable(nvt); 1182 nvt_efm_enable(nvt);