aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <gl@dsa-ac.de>2007-03-30 03:49:55 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-04-01 17:38:01 -0400
commit9a4d93d49d140c196020a1bae339efcf211cac03 (patch)
treef2a7baa89513ad8c988b23b647d8d9bc95b78fd7 /drivers/net
parent6c330ba72c45007a9ef681396925c22d11029008 (diff)
[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 <gl@dsa-ac.de> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/net')
-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