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;
 
                        }
                        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;
 
        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++;
 {
        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;
 
        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;
 }