Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9a4d93d49d140c196020a1bae339efcf211cac03
Commit:     9a4d93d49d140c196020a1bae339efcf211cac03
Parent:     6c330ba72c45007a9ef681396925c22d11029008
Author:     Guennadi Liakhovetski <[EMAIL PROTECTED]>
AuthorDate: Fri Mar 30 08:49:55 2007 +0100
Committer:  Russell King <[EMAIL PROTECTED]>
CommitDate: Sun Apr 1 22:38:01 2007 +0100

    [ARM] 4295/2: Fix error-handling in pxaficp_ir.c (version 2)
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Russell King <[EMAIL PROTECTED]>
---
 drivers/net/irda/pxaficp_ir.c |   30 +++++++++++++++++++++++++-----
 1 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 9137e23..2272156 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -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;
 
@@ -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;
@@ -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++;
@@ -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;
@@ -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;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to