|
@@ -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);
|