Skip to content

Commit

Permalink
[ARM] 4295/2: Fix error-handling in pxaficp_ir.c (version 2)
Browse files Browse the repository at this point in the history
This patch addresses the following issues with the pxa2xx FIr driver:

1. increment overrun error counter and not frame error counter on ICSR1_ROR bit set in ICSR1.
2. drop frames reported with the frame error from the IC.
3. when resetting the receiver and preparing it for the next DMA in pxa_irda_fir_irq() actually clear the Rx FIFO. See description in Table 11-2 in PXA270 Developer's Manual of the RXE bit.

Correction added in version 2: clearing the IC Rx FIFO also has to be done in pxa_irda_fir_dma_tx_irq()

Signed-off-by: G. Liakhovetski <gl@dsa-ac.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Guennadi Liakhovetski authored and Russell King committed Apr 1, 2007
1 parent 6c330ba commit 9a4d93d
Showing 1 changed file with 25 additions and 5 deletions.
30 changes: 25 additions & 5 deletions drivers/net/irda/pxaficp_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,22 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
pxa_irda_set_speed(si, si->newspeed);
si->newspeed = 0;
} else {
int i = 64;

ICCR0 = 0;
pxa_irda_fir_dma_rx_start(si);
while ((ICSR1 & ICSR1_RNE) && i--)
(void)ICDR;
ICCR0 = ICCR0_ITR | ICCR0_RXE;

if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
}
netif_wake_queue(dev);
}

/* EIF(Error in FIFO/End in Frame) handler for FIR */
static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0)
{
unsigned int len, stat, data;

Expand All @@ -350,7 +357,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
}
if (stat & ICSR1_ROR) {
printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
si->stats.rx_frame_errors++;
si->stats.rx_over_errors++;
}
} else {
si->dma_rx_buff[len++] = data;
Expand All @@ -362,7 +369,15 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)

if (stat & ICSR1_EOF) {
/* end of frame. */
struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC);
struct sk_buff *skb;

if (icsr0 & ICSR0_FRE) {
printk(KERN_ERR "pxa_ir: dropping erroneous frame\n");
si->stats.rx_dropped++;
return;
}

skb = alloc_skb(len+1,GFP_ATOMIC);
if (!skb) {
printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
si->stats.rx_dropped++;
Expand Down Expand Up @@ -392,7 +407,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct pxa_irda *si = netdev_priv(dev);
int icsr0;
int icsr0, i = 64;

/* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN;
Expand All @@ -412,13 +427,18 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)

if (icsr0 & ICSR0_EIF) {
/* An error in FIFO occured, or there is a end of frame */
pxa_irda_fir_irq_eif(si, dev);
pxa_irda_fir_irq_eif(si, dev, icsr0);
}

ICCR0 = 0;
pxa_irda_fir_dma_rx_start(si);
while ((ICSR1 & ICSR1_RNE) && i--)
(void)ICDR;
ICCR0 = ICCR0_ITR | ICCR0_RXE;

if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");

return IRQ_HANDLED;
}

Expand Down

0 comments on commit 9a4d93d

Please sign in to comment.