diff options
| -rw-r--r-- | 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 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 */ |
| 332 | static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev) | 339 | static 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 | ||
