diff options
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 3db422b6666b..d653b5a19e77 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -337,6 +337,10 @@ struct tx_queue { | |||
337 | dma_addr_t tx_desc_dma; | 337 | dma_addr_t tx_desc_dma; |
338 | int tx_desc_area_size; | 338 | int tx_desc_area_size; |
339 | struct sk_buff **tx_skb; | 339 | struct sk_buff **tx_skb; |
340 | |||
341 | unsigned long tx_packets; | ||
342 | unsigned long tx_bytes; | ||
343 | unsigned long tx_dropped; | ||
340 | }; | 344 | }; |
341 | 345 | ||
342 | struct mv643xx_eth_private { | 346 | struct mv643xx_eth_private { |
@@ -347,8 +351,6 @@ struct mv643xx_eth_private { | |||
347 | 351 | ||
348 | int phy_addr; | 352 | int phy_addr; |
349 | 353 | ||
350 | spinlock_t lock; | ||
351 | |||
352 | struct mib_counters mib_counters; | 354 | struct mib_counters mib_counters; |
353 | struct work_struct tx_timeout_task; | 355 | struct work_struct tx_timeout_task; |
354 | struct mii_if_info mii; | 356 | struct mii_if_info mii; |
@@ -453,10 +455,12 @@ static void txq_maybe_wake(struct tx_queue *txq) | |||
453 | struct mv643xx_eth_private *mp = txq_to_mp(txq); | 455 | struct mv643xx_eth_private *mp = txq_to_mp(txq); |
454 | struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); | 456 | struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); |
455 | 457 | ||
456 | spin_lock(&mp->lock); | 458 | if (netif_tx_queue_stopped(nq)) { |
457 | if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) | 459 | __netif_tx_lock(nq, smp_processor_id()); |
458 | netif_tx_wake_queue(nq); | 460 | if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1) |
459 | spin_unlock(&mp->lock); | 461 | netif_tx_wake_queue(nq); |
462 | __netif_tx_unlock(nq); | ||
463 | } | ||
460 | } | 464 | } |
461 | 465 | ||
462 | 466 | ||
@@ -785,28 +789,24 @@ static void txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb) | |||
785 | static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) | 789 | static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) |
786 | { | 790 | { |
787 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 791 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
788 | struct net_device_stats *stats = &dev->stats; | ||
789 | int queue; | 792 | int queue; |
790 | struct tx_queue *txq; | 793 | struct tx_queue *txq; |
791 | struct netdev_queue *nq; | 794 | struct netdev_queue *nq; |
792 | int entries_left; | 795 | int entries_left; |
793 | 796 | ||
797 | queue = skb_get_queue_mapping(skb); | ||
798 | txq = mp->txq + queue; | ||
799 | nq = netdev_get_tx_queue(dev, queue); | ||
800 | |||
794 | if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { | 801 | if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) { |
795 | stats->tx_dropped++; | 802 | txq->tx_dropped++; |
796 | dev_printk(KERN_DEBUG, &dev->dev, | 803 | dev_printk(KERN_DEBUG, &dev->dev, |
797 | "failed to linearize skb with tiny " | 804 | "failed to linearize skb with tiny " |
798 | "unaligned fragment\n"); | 805 | "unaligned fragment\n"); |
799 | return NETDEV_TX_BUSY; | 806 | return NETDEV_TX_BUSY; |
800 | } | 807 | } |
801 | 808 | ||
802 | queue = skb_get_queue_mapping(skb); | ||
803 | txq = mp->txq + queue; | ||
804 | nq = netdev_get_tx_queue(dev, queue); | ||
805 | |||
806 | spin_lock(&mp->lock); | ||
807 | |||
808 | if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { | 809 | if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) { |
809 | spin_unlock(&mp->lock); | ||
810 | if (net_ratelimit()) | 810 | if (net_ratelimit()) |
811 | dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n"); | 811 | dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n"); |
812 | kfree_skb(skb); | 812 | kfree_skb(skb); |
@@ -814,16 +814,14 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
814 | } | 814 | } |
815 | 815 | ||
816 | txq_submit_skb(txq, skb); | 816 | txq_submit_skb(txq, skb); |
817 | stats->tx_bytes += skb->len; | 817 | txq->tx_bytes += skb->len; |
818 | stats->tx_packets++; | 818 | txq->tx_packets++; |
819 | dev->trans_start = jiffies; | 819 | dev->trans_start = jiffies; |
820 | 820 | ||
821 | entries_left = txq->tx_ring_size - txq->tx_desc_count; | 821 | entries_left = txq->tx_ring_size - txq->tx_desc_count; |
822 | if (entries_left < MAX_SKB_FRAGS + 1) | 822 | if (entries_left < MAX_SKB_FRAGS + 1) |
823 | netif_tx_stop_queue(nq); | 823 | netif_tx_stop_queue(nq); |
824 | 824 | ||
825 | spin_unlock(&mp->lock); | ||
826 | |||
827 | return NETDEV_TX_OK; | 825 | return NETDEV_TX_OK; |
828 | } | 826 | } |
829 | 827 | ||
@@ -832,10 +830,11 @@ static int mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
832 | static void txq_kick(struct tx_queue *txq) | 830 | static void txq_kick(struct tx_queue *txq) |
833 | { | 831 | { |
834 | struct mv643xx_eth_private *mp = txq_to_mp(txq); | 832 | struct mv643xx_eth_private *mp = txq_to_mp(txq); |
833 | struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); | ||
835 | u32 hw_desc_ptr; | 834 | u32 hw_desc_ptr; |
836 | u32 expected_ptr; | 835 | u32 expected_ptr; |
837 | 836 | ||
838 | spin_lock(&mp->lock); | 837 | __netif_tx_lock(nq, smp_processor_id()); |
839 | 838 | ||
840 | if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index)) | 839 | if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index)) |
841 | goto out; | 840 | goto out; |
@@ -848,7 +847,7 @@ static void txq_kick(struct tx_queue *txq) | |||
848 | txq_enable(txq); | 847 | txq_enable(txq); |
849 | 848 | ||
850 | out: | 849 | out: |
851 | spin_unlock(&mp->lock); | 850 | __netif_tx_unlock(nq); |
852 | 851 | ||
853 | mp->work_tx_end &= ~(1 << txq->index); | 852 | mp->work_tx_end &= ~(1 << txq->index); |
854 | } | 853 | } |
@@ -856,9 +855,10 @@ out: | |||
856 | static int txq_reclaim(struct tx_queue *txq, int budget, int force) | 855 | static int txq_reclaim(struct tx_queue *txq, int budget, int force) |
857 | { | 856 | { |
858 | struct mv643xx_eth_private *mp = txq_to_mp(txq); | 857 | struct mv643xx_eth_private *mp = txq_to_mp(txq); |
858 | struct netdev_queue *nq = netdev_get_tx_queue(mp->dev, txq->index); | ||
859 | int reclaimed; | 859 | int reclaimed; |
860 | 860 | ||
861 | spin_lock(&mp->lock); | 861 | __netif_tx_lock(nq, smp_processor_id()); |
862 | 862 | ||
863 | reclaimed = 0; | 863 | reclaimed = 0; |
864 | while (reclaimed < budget && txq->tx_desc_count > 0) { | 864 | while (reclaimed < budget && txq->tx_desc_count > 0) { |
@@ -897,9 +897,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
897 | } | 897 | } |
898 | 898 | ||
899 | /* | 899 | /* |
900 | * Drop mp->lock while we free the skb. | 900 | * Drop tx queue lock while we free the skb. |
901 | */ | 901 | */ |
902 | spin_unlock(&mp->lock); | 902 | __netif_tx_unlock(nq); |
903 | 903 | ||
904 | if (cmd_sts & TX_FIRST_DESC) | 904 | if (cmd_sts & TX_FIRST_DESC) |
905 | dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); | 905 | dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); |
@@ -909,14 +909,14 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
909 | if (skb) | 909 | if (skb) |
910 | dev_kfree_skb(skb); | 910 | dev_kfree_skb(skb); |
911 | 911 | ||
912 | spin_lock(&mp->lock); | 912 | __netif_tx_lock(nq, smp_processor_id()); |
913 | } | 913 | } |
914 | 914 | ||
915 | __netif_tx_unlock(nq); | ||
916 | |||
915 | if (reclaimed < budget) | 917 | if (reclaimed < budget) |
916 | mp->work_tx &= ~(1 << txq->index); | 918 | mp->work_tx &= ~(1 << txq->index); |
917 | 919 | ||
918 | spin_unlock(&mp->lock); | ||
919 | |||
920 | return reclaimed; | 920 | return reclaimed; |
921 | } | 921 | } |
922 | 922 | ||
@@ -1123,7 +1123,31 @@ static int smi_reg_write(struct mv643xx_eth_private *mp, unsigned int addr, | |||
1123 | } | 1123 | } |
1124 | 1124 | ||
1125 | 1125 | ||
1126 | /* mib counters *************************************************************/ | 1126 | /* statistics ***************************************************************/ |
1127 | static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) | ||
1128 | { | ||
1129 | struct mv643xx_eth_private *mp = netdev_priv(dev); | ||
1130 | struct net_device_stats *stats = &dev->stats; | ||
1131 | unsigned long tx_packets = 0; | ||
1132 | unsigned long tx_bytes = 0; | ||
1133 | unsigned long tx_dropped = 0; | ||
1134 | int i; | ||
1135 | |||
1136 | for (i = 0; i < mp->txq_count; i++) { | ||
1137 | struct tx_queue *txq = mp->txq + i; | ||
1138 | |||
1139 | tx_packets += txq->tx_packets; | ||
1140 | tx_bytes += txq->tx_bytes; | ||
1141 | tx_dropped += txq->tx_dropped; | ||
1142 | } | ||
1143 | |||
1144 | stats->tx_packets = tx_packets; | ||
1145 | stats->tx_bytes = tx_bytes; | ||
1146 | stats->tx_dropped = tx_dropped; | ||
1147 | |||
1148 | return stats; | ||
1149 | } | ||
1150 | |||
1127 | static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) | 1151 | static inline u32 mib_read(struct mv643xx_eth_private *mp, int offset) |
1128 | { | 1152 | { |
1129 | return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); | 1153 | return rdl(mp, MIB_COUNTERS(mp->port_num) + offset); |
@@ -1355,6 +1379,7 @@ static void mv643xx_eth_get_ethtool_stats(struct net_device *dev, | |||
1355 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1379 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1356 | int i; | 1380 | int i; |
1357 | 1381 | ||
1382 | mv643xx_eth_get_stats(dev); | ||
1358 | mib_counters_update(mp); | 1383 | mib_counters_update(mp); |
1359 | 1384 | ||
1360 | for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { | 1385 | for (i = 0; i < ARRAY_SIZE(mv643xx_eth_stats); i++) { |
@@ -2138,6 +2163,7 @@ static int mv643xx_eth_stop(struct net_device *dev) | |||
2138 | free_irq(dev->irq, dev); | 2163 | free_irq(dev->irq, dev); |
2139 | 2164 | ||
2140 | port_reset(mp); | 2165 | port_reset(mp); |
2166 | mv643xx_eth_get_stats(dev); | ||
2141 | mib_counters_update(mp); | 2167 | mib_counters_update(mp); |
2142 | 2168 | ||
2143 | for (i = 0; i < mp->rxq_count; i++) | 2169 | for (i = 0; i < mp->rxq_count; i++) |
@@ -2585,8 +2611,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2585 | set_params(mp, pd); | 2611 | set_params(mp, pd); |
2586 | dev->real_num_tx_queues = mp->txq_count; | 2612 | dev->real_num_tx_queues = mp->txq_count; |
2587 | 2613 | ||
2588 | spin_lock_init(&mp->lock); | ||
2589 | |||
2590 | mib_counters_clear(mp); | 2614 | mib_counters_clear(mp); |
2591 | INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); | 2615 | INIT_WORK(&mp->tx_timeout_task, tx_timeout_task); |
2592 | 2616 | ||
@@ -2612,6 +2636,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev) | |||
2612 | BUG_ON(!res); | 2636 | BUG_ON(!res); |
2613 | dev->irq = res->start; | 2637 | dev->irq = res->start; |
2614 | 2638 | ||
2639 | dev->get_stats = mv643xx_eth_get_stats; | ||
2615 | dev->hard_start_xmit = mv643xx_eth_xmit; | 2640 | dev->hard_start_xmit = mv643xx_eth_xmit; |
2616 | dev->open = mv643xx_eth_open; | 2641 | dev->open = mv643xx_eth_open; |
2617 | dev->stop = mv643xx_eth_stop; | 2642 | dev->stop = mv643xx_eth_stop; |