aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/aeroflex/greth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/aeroflex/greth.c')
-rw-r--r--drivers/net/ethernet/aeroflex/greth.c86
1 files changed, 48 insertions, 38 deletions
diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c
index 23578dfee249..3005155e412b 100644
--- a/drivers/net/ethernet/aeroflex/greth.c
+++ b/drivers/net/ethernet/aeroflex/greth.c
@@ -123,6 +123,12 @@ static inline void greth_enable_tx(struct greth_private *greth)
123 GRETH_REGORIN(greth->regs->control, GRETH_TXEN); 123 GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
124} 124}
125 125
126static inline void greth_enable_tx_and_irq(struct greth_private *greth)
127{
128 wmb(); /* BDs must been written to memory before enabling TX */
129 GRETH_REGORIN(greth->regs->control, GRETH_TXEN | GRETH_TXI);
130}
131
126static inline void greth_disable_tx(struct greth_private *greth) 132static inline void greth_disable_tx(struct greth_private *greth)
127{ 133{
128 GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN); 134 GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
@@ -447,29 +453,30 @@ out:
447 return err; 453 return err;
448} 454}
449 455
456static inline u16 greth_num_free_bds(u16 tx_last, u16 tx_next)
457{
458 if (tx_next < tx_last)
459 return (tx_last - tx_next) - 1;
460 else
461 return GRETH_TXBD_NUM - (tx_next - tx_last) - 1;
462}
450 463
451static netdev_tx_t 464static netdev_tx_t
452greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev) 465greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
453{ 466{
454 struct greth_private *greth = netdev_priv(dev); 467 struct greth_private *greth = netdev_priv(dev);
455 struct greth_bd *bdp; 468 struct greth_bd *bdp;
456 u32 status = 0, dma_addr, ctrl; 469 u32 status, dma_addr;
457 int curr_tx, nr_frags, i, err = NETDEV_TX_OK; 470 int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
458 unsigned long flags; 471 unsigned long flags;
472 u16 tx_last;
459 473
460 nr_frags = skb_shinfo(skb)->nr_frags; 474 nr_frags = skb_shinfo(skb)->nr_frags;
475 tx_last = greth->tx_last;
476 rmb(); /* tx_last is updated by the poll task */
461 477
462 /* Clean TX Ring */ 478 if (greth_num_free_bds(tx_last, greth->tx_next) < nr_frags + 1) {
463 greth_clean_tx_gbit(dev);
464
465 if (greth->tx_free < nr_frags + 1) {
466 spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
467 ctrl = GRETH_REGLOAD(greth->regs->control);
468 /* Enable TX IRQ only if not already in poll() routine */
469 if (ctrl & GRETH_RXI)
470 GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
471 netif_stop_queue(dev); 479 netif_stop_queue(dev);
472 spin_unlock_irqrestore(&greth->devlock, flags);
473 err = NETDEV_TX_BUSY; 480 err = NETDEV_TX_BUSY;
474 goto out; 481 goto out;
475 } 482 }
@@ -488,6 +495,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
488 /* Linear buf */ 495 /* Linear buf */
489 if (nr_frags != 0) 496 if (nr_frags != 0)
490 status = GRETH_TXBD_MORE; 497 status = GRETH_TXBD_MORE;
498 else
499 status = GRETH_BD_IE;
491 500
492 if (skb->ip_summed == CHECKSUM_PARTIAL) 501 if (skb->ip_summed == CHECKSUM_PARTIAL)
493 status |= GRETH_TXBD_CSALL; 502 status |= GRETH_TXBD_CSALL;
@@ -545,14 +554,12 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
545 554
546 /* Enable the descriptor chain by enabling the first descriptor */ 555 /* Enable the descriptor chain by enabling the first descriptor */
547 bdp = greth->tx_bd_base + greth->tx_next; 556 bdp = greth->tx_bd_base + greth->tx_next;
548 greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN); 557 greth_write_bd(&bdp->stat,
549 greth->tx_next = curr_tx; 558 greth_read_bd(&bdp->stat) | GRETH_BD_EN);
550 greth->tx_free -= nr_frags + 1;
551
552 wmb();
553 559
554 spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/ 560 spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
555 greth_enable_tx(greth); 561 greth->tx_next = curr_tx;
562 greth_enable_tx_and_irq(greth);
556 spin_unlock_irqrestore(&greth->devlock, flags); 563 spin_unlock_irqrestore(&greth->devlock, flags);
557 564
558 return NETDEV_TX_OK; 565 return NETDEV_TX_OK;
@@ -648,7 +655,6 @@ static void greth_clean_tx(struct net_device *dev)
648 if (greth->tx_free > 0) { 655 if (greth->tx_free > 0) {
649 netif_wake_queue(dev); 656 netif_wake_queue(dev);
650 } 657 }
651
652} 658}
653 659
654static inline void greth_update_tx_stats(struct net_device *dev, u32 stat) 660static inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
@@ -670,20 +676,22 @@ static void greth_clean_tx_gbit(struct net_device *dev)
670{ 676{
671 struct greth_private *greth; 677 struct greth_private *greth;
672 struct greth_bd *bdp, *bdp_last_frag; 678 struct greth_bd *bdp, *bdp_last_frag;
673 struct sk_buff *skb; 679 struct sk_buff *skb = NULL;
674 u32 stat; 680 u32 stat;
675 int nr_frags, i; 681 int nr_frags, i;
682 u16 tx_last;
676 683
677 greth = netdev_priv(dev); 684 greth = netdev_priv(dev);
685 tx_last = greth->tx_last;
678 686
679 while (greth->tx_free < GRETH_TXBD_NUM) { 687 while (tx_last != greth->tx_next) {
680 688
681 skb = greth->tx_skbuff[greth->tx_last]; 689 skb = greth->tx_skbuff[tx_last];
682 690
683 nr_frags = skb_shinfo(skb)->nr_frags; 691 nr_frags = skb_shinfo(skb)->nr_frags;
684 692
685 /* We only clean fully completed SKBs */ 693 /* We only clean fully completed SKBs */
686 bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags); 694 bdp_last_frag = greth->tx_bd_base + SKIP_TX(tx_last, nr_frags);
687 695
688 GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX); 696 GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
689 mb(); 697 mb();
@@ -692,14 +700,14 @@ static void greth_clean_tx_gbit(struct net_device *dev)
692 if (stat & GRETH_BD_EN) 700 if (stat & GRETH_BD_EN)
693 break; 701 break;
694 702
695 greth->tx_skbuff[greth->tx_last] = NULL; 703 greth->tx_skbuff[tx_last] = NULL;
696 704
697 greth_update_tx_stats(dev, stat); 705 greth_update_tx_stats(dev, stat);
698 dev->stats.tx_bytes += skb->len; 706 dev->stats.tx_bytes += skb->len;
699 707
700 bdp = greth->tx_bd_base + greth->tx_last; 708 bdp = greth->tx_bd_base + tx_last;
701 709
702 greth->tx_last = NEXT_TX(greth->tx_last); 710 tx_last = NEXT_TX(tx_last);
703 711
704 dma_unmap_single(greth->dev, 712 dma_unmap_single(greth->dev,
705 greth_read_bd(&bdp->addr), 713 greth_read_bd(&bdp->addr),
@@ -708,21 +716,26 @@ static void greth_clean_tx_gbit(struct net_device *dev)
708 716
709 for (i = 0; i < nr_frags; i++) { 717 for (i = 0; i < nr_frags; i++) {
710 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 718 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
711 bdp = greth->tx_bd_base + greth->tx_last; 719 bdp = greth->tx_bd_base + tx_last;
712 720
713 dma_unmap_page(greth->dev, 721 dma_unmap_page(greth->dev,
714 greth_read_bd(&bdp->addr), 722 greth_read_bd(&bdp->addr),
715 skb_frag_size(frag), 723 skb_frag_size(frag),
716 DMA_TO_DEVICE); 724 DMA_TO_DEVICE);
717 725
718 greth->tx_last = NEXT_TX(greth->tx_last); 726 tx_last = NEXT_TX(tx_last);
719 } 727 }
720 greth->tx_free += nr_frags+1;
721 dev_kfree_skb(skb); 728 dev_kfree_skb(skb);
722 } 729 }
730 if (skb) { /* skb is set only if the above while loop was entered */
731 wmb();
732 greth->tx_last = tx_last;
723 733
724 if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1))) 734 if (netif_queue_stopped(dev) &&
725 netif_wake_queue(dev); 735 (greth_num_free_bds(tx_last, greth->tx_next) >
736 (MAX_SKB_FRAGS+1)))
737 netif_wake_queue(dev);
738 }
726} 739}
727 740
728static int greth_rx(struct net_device *dev, int limit) 741static int greth_rx(struct net_device *dev, int limit)
@@ -965,16 +978,12 @@ static int greth_poll(struct napi_struct *napi, int budget)
965 greth = container_of(napi, struct greth_private, napi); 978 greth = container_of(napi, struct greth_private, napi);
966 979
967restart_txrx_poll: 980restart_txrx_poll:
968 if (netif_queue_stopped(greth->netdev)) {
969 if (greth->gbit_mac)
970 greth_clean_tx_gbit(greth->netdev);
971 else
972 greth_clean_tx(greth->netdev);
973 }
974
975 if (greth->gbit_mac) { 981 if (greth->gbit_mac) {
982 greth_clean_tx_gbit(greth->netdev);
976 work_done += greth_rx_gbit(greth->netdev, budget - work_done); 983 work_done += greth_rx_gbit(greth->netdev, budget - work_done);
977 } else { 984 } else {
985 if (netif_queue_stopped(greth->netdev))
986 greth_clean_tx(greth->netdev);
978 work_done += greth_rx(greth->netdev, budget - work_done); 987 work_done += greth_rx(greth->netdev, budget - work_done);
979 } 988 }
980 989
@@ -983,7 +992,8 @@ restart_txrx_poll:
983 spin_lock_irqsave(&greth->devlock, flags); 992 spin_lock_irqsave(&greth->devlock, flags);
984 993
985 ctrl = GRETH_REGLOAD(greth->regs->control); 994 ctrl = GRETH_REGLOAD(greth->regs->control);
986 if (netif_queue_stopped(greth->netdev)) { 995 if ((greth->gbit_mac && (greth->tx_last != greth->tx_next)) ||
996 (!greth->gbit_mac && netif_queue_stopped(greth->netdev))) {
987 GRETH_REGSAVE(greth->regs->control, 997 GRETH_REGSAVE(greth->regs->control,
988 ctrl | GRETH_TXI | GRETH_RXI); 998 ctrl | GRETH_TXI | GRETH_RXI);
989 mask = GRETH_INT_RX | GRETH_INT_RE | 999 mask = GRETH_INT_RX | GRETH_INT_RE |