aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/irda/pxaficp_ir.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-04-12 13:50:03 -0400
committerPaul Mackerras <paulus@samba.org>2007-04-12 13:50:03 -0400
commite049d1ca3094f3d1d94617f456a9961202f96e3a (patch)
treea30397ad22f2fbea268bd28fa69c60aad9dfa62a /drivers/net/irda/pxaficp_ir.c
parentedfac96a92b88d3b0b53e3f8231b74beee9ecd1d (diff)
parent80584ff3b99c36ead7e130e453b3a48b18072d18 (diff)
Merge branch 'linux-2.6' into for-2.6.22
Diffstat (limited to 'drivers/net/irda/pxaficp_ir.c')
-rw-r--r--drivers/net/irda/pxaficp_ir.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 9137e239fac2..2272156af31e 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)
321 pxa_irda_set_speed(si, si->newspeed); 321 pxa_irda_set_speed(si, si->newspeed);
322 si->newspeed = 0; 322 si->newspeed = 0;
323 } else { 323 } else {
324 int i = 64;
325
324 ICCR0 = 0; 326 ICCR0 = 0;
325 pxa_irda_fir_dma_rx_start(si); 327 pxa_irda_fir_dma_rx_start(si);
328 while ((ICSR1 & ICSR1_RNE) && i--)
329 (void)ICDR;
326 ICCR0 = ICCR0_ITR | ICCR0_RXE; 330 ICCR0 = ICCR0_ITR | ICCR0_RXE;
331
332 if (i < 0)
333 printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
327 } 334 }
328 netif_wake_queue(dev); 335 netif_wake_queue(dev);
329} 336}
330 337
331/* EIF(Error in FIFO/End in Frame) handler for FIR */ 338/* EIF(Error in FIFO/End in Frame) handler for FIR */
332static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) 339static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0)
333{ 340{
334 unsigned int len, stat, data; 341 unsigned int len, stat, data;
335 342
@@ -350,7 +357,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev)
350 } 357 }
351 if (stat & ICSR1_ROR) { 358 if (stat & ICSR1_ROR) {
352 printk(KERN_DEBUG "pxa_ir: fir receive overrun\n"); 359 printk(KERN_DEBUG "pxa_ir: fir receive overrun\n");
353 si->stats.rx_frame_errors++; 360 si->stats.rx_over_errors++;
354 } 361 }
355 } else { 362 } else {
356 si->dma_rx_buff[len++] = data; 363 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)
362 369
363 if (stat & ICSR1_EOF) { 370 if (stat & ICSR1_EOF) {
364 /* end of frame. */ 371 /* end of frame. */
365 struct sk_buff *skb = alloc_skb(len+1,GFP_ATOMIC); 372 struct sk_buff *skb;
373
374 if (icsr0 & ICSR0_FRE) {
375 printk(KERN_ERR "pxa_ir: dropping erroneous frame\n");
376 si->stats.rx_dropped++;
377 return;
378 }
379
380 skb = alloc_skb(len+1,GFP_ATOMIC);
366 if (!skb) { 381 if (!skb) {
367 printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n"); 382 printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n");
368 si->stats.rx_dropped++; 383 si->stats.rx_dropped++;
@@ -392,7 +407,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
392{ 407{
393 struct net_device *dev = dev_id; 408 struct net_device *dev = dev_id;
394 struct pxa_irda *si = netdev_priv(dev); 409 struct pxa_irda *si = netdev_priv(dev);
395 int icsr0; 410 int icsr0, i = 64;
396 411
397 /* stop RX DMA */ 412 /* stop RX DMA */
398 DCSR(si->rxdma) &= ~DCSR_RUN; 413 DCSR(si->rxdma) &= ~DCSR_RUN;
@@ -412,13 +427,18 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
412 427
413 if (icsr0 & ICSR0_EIF) { 428 if (icsr0 & ICSR0_EIF) {
414 /* An error in FIFO occured, or there is a end of frame */ 429 /* An error in FIFO occured, or there is a end of frame */
415 pxa_irda_fir_irq_eif(si, dev); 430 pxa_irda_fir_irq_eif(si, dev, icsr0);
416 } 431 }
417 432
418 ICCR0 = 0; 433 ICCR0 = 0;
419 pxa_irda_fir_dma_rx_start(si); 434 pxa_irda_fir_dma_rx_start(si);
435 while ((ICSR1 & ICSR1_RNE) && i--)
436 (void)ICDR;
420 ICCR0 = ICCR0_ITR | ICCR0_RXE; 437 ICCR0 = ICCR0_ITR | ICCR0_RXE;
421 438
439 if (i < 0)
440 printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
441
422 return IRQ_HANDLED; 442 return IRQ_HANDLED;
423} 443}
424 444