diff options
-rw-r--r-- | drivers/net/r6040.c | 144 |
1 files changed, 62 insertions, 82 deletions
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 5eb057d37200..9061ec1aa4f7 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
@@ -175,7 +175,7 @@ struct r6040_private { | |||
175 | struct r6040_descriptor *tx_ring; | 175 | struct r6040_descriptor *tx_ring; |
176 | dma_addr_t rx_ring_dma; | 176 | dma_addr_t rx_ring_dma; |
177 | dma_addr_t tx_ring_dma; | 177 | dma_addr_t tx_ring_dma; |
178 | u16 tx_free_desc, rx_free_desc, phy_addr, phy_mode; | 178 | u16 tx_free_desc, phy_addr, phy_mode; |
179 | u16 mcr0, mcr1; | 179 | u16 mcr0, mcr1; |
180 | u16 switch_sig; | 180 | u16 switch_sig; |
181 | struct net_device *dev; | 181 | struct net_device *dev; |
@@ -291,27 +291,6 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, | |||
291 | desc->vndescp = desc_ring; | 291 | desc->vndescp = desc_ring; |
292 | } | 292 | } |
293 | 293 | ||
294 | /* Allocate skb buffer for rx descriptor */ | ||
295 | static void r6040_rx_buf_alloc(struct r6040_private *lp, struct net_device *dev) | ||
296 | { | ||
297 | struct r6040_descriptor *descptr; | ||
298 | |||
299 | descptr = lp->rx_insert_ptr; | ||
300 | while (lp->rx_free_desc < RX_DCNT) { | ||
301 | descptr->skb_ptr = netdev_alloc_skb(dev, MAX_BUF_SIZE); | ||
302 | |||
303 | if (!descptr->skb_ptr) | ||
304 | break; | ||
305 | descptr->buf = cpu_to_le32(pci_map_single(lp->pdev, | ||
306 | descptr->skb_ptr->data, | ||
307 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE)); | ||
308 | descptr->status = 0x8000; | ||
309 | descptr = descptr->vndescp; | ||
310 | lp->rx_free_desc++; | ||
311 | } | ||
312 | lp->rx_insert_ptr = descptr; | ||
313 | } | ||
314 | |||
315 | static void r6040_init_txbufs(struct net_device *dev) | 294 | static void r6040_init_txbufs(struct net_device *dev) |
316 | { | 295 | { |
317 | struct r6040_private *lp = netdev_priv(dev); | 296 | struct r6040_private *lp = netdev_priv(dev); |
@@ -556,71 +535,72 @@ static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
556 | static int r6040_rx(struct net_device *dev, int limit) | 535 | static int r6040_rx(struct net_device *dev, int limit) |
557 | { | 536 | { |
558 | struct r6040_private *priv = netdev_priv(dev); | 537 | struct r6040_private *priv = netdev_priv(dev); |
559 | int count; | 538 | struct r6040_descriptor *descptr = priv->rx_remove_ptr; |
560 | void __iomem *ioaddr = priv->base; | 539 | struct sk_buff *skb_ptr, *new_skb; |
540 | int count = 0; | ||
561 | u16 err; | 541 | u16 err; |
562 | 542 | ||
563 | for (count = 0; count < limit; ++count) { | 543 | /* Limit not reached and the descriptor belongs to the CPU */ |
564 | struct r6040_descriptor *descptr = priv->rx_remove_ptr; | 544 | while (count < limit && !(descptr->status & 0x8000)) { |
565 | struct sk_buff *skb_ptr; | 545 | /* Read the descriptor status */ |
566 | 546 | err = descptr->status; | |
567 | descptr = priv->rx_remove_ptr; | 547 | /* Global error status set */ |
568 | 548 | if (err & 0x0800) { | |
569 | /* Check for errors */ | 549 | /* RX dribble */ |
570 | err = ioread16(ioaddr + MLSR); | 550 | if (err & 0x0400) |
571 | if (err & 0x0400) | 551 | dev->stats.rx_frame_errors++; |
572 | dev->stats.rx_errors++; | 552 | /* Buffer lenght exceeded */ |
573 | /* RX FIFO over-run */ | 553 | if (err & 0x0200) |
574 | if (err & 0x8000) | 554 | dev->stats.rx_length_errors++; |
575 | dev->stats.rx_fifo_errors++; | 555 | /* Packet too long */ |
576 | /* RX descriptor unavailable */ | 556 | if (err & 0x0100) |
577 | if (err & 0x0080) | 557 | dev->stats.rx_length_errors++; |
578 | dev->stats.rx_frame_errors++; | 558 | /* Packet < 64 bytes */ |
579 | /* Received packet with length over buffer lenght */ | 559 | if (err & 0x0080) |
580 | if (err & 0x0020) | 560 | dev->stats.rx_length_errors++; |
581 | dev->stats.rx_over_errors++; | 561 | /* CRC error */ |
582 | /* Received packet with too long or short */ | 562 | if (err & 0x0040) { |
583 | if (err & (0x0010 | 0x0008)) | 563 | spin_lock(&priv->lock); |
584 | dev->stats.rx_length_errors++; | 564 | dev->stats.rx_crc_errors++; |
585 | /* Received packet with CRC errors */ | 565 | spin_unlock(&priv->lock); |
586 | if (err & 0x0004) { | ||
587 | spin_lock(&priv->lock); | ||
588 | dev->stats.rx_crc_errors++; | ||
589 | spin_unlock(&priv->lock); | ||
590 | } | ||
591 | |||
592 | while (priv->rx_free_desc) { | ||
593 | /* No RX packet */ | ||
594 | if (descptr->status & 0x8000) | ||
595 | break; | ||
596 | skb_ptr = descptr->skb_ptr; | ||
597 | if (!skb_ptr) { | ||
598 | printk(KERN_ERR "%s: Inconsistent RX" | ||
599 | "descriptor chain\n", | ||
600 | dev->name); | ||
601 | break; | ||
602 | } | 566 | } |
603 | descptr->skb_ptr = NULL; | 567 | goto next_descr; |
604 | skb_ptr->dev = priv->dev; | 568 | } |
605 | /* Do not count the CRC */ | 569 | |
606 | skb_put(skb_ptr, descptr->len - 4); | 570 | /* Packet successfully received */ |
607 | pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf), | 571 | new_skb = netdev_alloc_skb(dev, MAX_BUF_SIZE); |
608 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); | 572 | if (!new_skb) { |
609 | skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev); | 573 | dev->stats.rx_dropped++; |
610 | /* Send to upper layer */ | 574 | goto next_descr; |
611 | netif_receive_skb(skb_ptr); | ||
612 | dev->last_rx = jiffies; | ||
613 | dev->stats.rx_packets++; | ||
614 | dev->stats.rx_bytes += descptr->len; | ||
615 | /* To next descriptor */ | ||
616 | descptr = descptr->vndescp; | ||
617 | priv->rx_free_desc--; | ||
618 | } | 575 | } |
619 | priv->rx_remove_ptr = descptr; | 576 | skb_ptr = descptr->skb_ptr; |
577 | skb_ptr->dev = priv->dev; | ||
578 | |||
579 | /* Do not count the CRC */ | ||
580 | skb_put(skb_ptr, descptr->len - 4); | ||
581 | pci_unmap_single(priv->pdev, le32_to_cpu(descptr->buf), | ||
582 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE); | ||
583 | skb_ptr->protocol = eth_type_trans(skb_ptr, priv->dev); | ||
584 | |||
585 | /* Send to upper layer */ | ||
586 | netif_receive_skb(skb_ptr); | ||
587 | dev->last_rx = jiffies; | ||
588 | dev->stats.rx_packets++; | ||
589 | dev->stats.rx_bytes += descptr->len - 4; | ||
590 | |||
591 | /* put new skb into descriptor */ | ||
592 | descptr->skb_ptr = new_skb; | ||
593 | descptr->buf = cpu_to_le32(pci_map_single(priv->pdev, | ||
594 | descptr->skb_ptr->data, | ||
595 | MAX_BUF_SIZE, PCI_DMA_FROMDEVICE)); | ||
596 | |||
597 | next_descr: | ||
598 | /* put the descriptor back to the MAC */ | ||
599 | descptr->status = 0x8000; | ||
600 | descptr = descptr->vndescp; | ||
601 | count++; | ||
620 | } | 602 | } |
621 | /* Allocate new RX buffer */ | 603 | priv->rx_remove_ptr = descptr; |
622 | if (priv->rx_free_desc < RX_DCNT) | ||
623 | r6040_rx_buf_alloc(priv, priv->dev); | ||
624 | 604 | ||
625 | return count; | 605 | return count; |
626 | } | 606 | } |