diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2010-08-02 07:26:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-02 18:46:31 -0400 |
commit | f65aac166fe10b96e64c233980a3522fc50fbecf (patch) | |
tree | be56c446c8fd596a47d0c5c62a339f19a71a5fb9 /drivers/net/tg3.c | |
parent | 67b284d476bcb3d100e946da23d6cf9acfd0465c (diff) |
tg3: Improve small packet performance
smp_mb() inside tg3_tx_avail() is used twice in the normal
tg3_start_xmit() path (see illustration below). The full memory
barrier is only necessary during race conditions with tx completion.
We can speed up the tx path by replacing smp_mb() in tg3_tx_avail()
with a compiler barrier. The compiler barrier is to force the
compiler to fetch the tx_prod and tx_cons from memory.
In the race condition between tg3_start_xmit() and tg3_tx(),
we have the following situation:
tg3_start_xmit() tg3_tx()
if (!tg3_tx_avail())
BUG();
...
if (!tg3_tx_avail())
netif_tx_stop_queue(); update_tx_index();
smp_mb(); smp_mb();
if (tg3_tx_avail()) if (netif_tx_queue_stopped() &&
netif_tx_wake_queue(); tg3_tx_avail())
With smp_mb() removed from tg3_tx_avail(), we need to add smp_mb() to
tg3_start_xmit() as shown above to properly order netif_tx_stop_queue()
and tg3_tx_avail() to check the ring index. If it is not strictly
ordered, the tx queue can be stopped forever.
This improves performance by about 3% with 2 ports running
bi-directional 64-byte packets.
Reviewed-by: Benjamin Li <benli@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 32e3a3de4c6d..820a7ddd7e09 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4386,7 +4386,8 @@ static void tg3_tx_recover(struct tg3 *tp) | |||
4386 | 4386 | ||
4387 | static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) | 4387 | static inline u32 tg3_tx_avail(struct tg3_napi *tnapi) |
4388 | { | 4388 | { |
4389 | smp_mb(); | 4389 | /* Tell compiler to fetch tx indices from memory. */ |
4390 | barrier(); | ||
4390 | return tnapi->tx_pending - | 4391 | return tnapi->tx_pending - |
4391 | ((tnapi->tx_prod - tnapi->tx_cons) & (TG3_TX_RING_SIZE - 1)); | 4392 | ((tnapi->tx_prod - tnapi->tx_cons) & (TG3_TX_RING_SIZE - 1)); |
4392 | } | 4393 | } |
@@ -5670,6 +5671,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, | |||
5670 | tnapi->tx_prod = entry; | 5671 | tnapi->tx_prod = entry; |
5671 | if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { | 5672 | if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { |
5672 | netif_tx_stop_queue(txq); | 5673 | netif_tx_stop_queue(txq); |
5674 | |||
5675 | /* netif_tx_stop_queue() must be done before checking | ||
5676 | * checking tx index in tg3_tx_avail() below, because in | ||
5677 | * tg3_tx(), we update tx index before checking for | ||
5678 | * netif_tx_queue_stopped(). | ||
5679 | */ | ||
5680 | smp_mb(); | ||
5673 | if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) | 5681 | if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) |
5674 | netif_tx_wake_queue(txq); | 5682 | netif_tx_wake_queue(txq); |
5675 | } | 5683 | } |
@@ -5715,6 +5723,13 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) | |||
5715 | /* Estimate the number of fragments in the worst case */ | 5723 | /* Estimate the number of fragments in the worst case */ |
5716 | if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) { | 5724 | if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) { |
5717 | netif_stop_queue(tp->dev); | 5725 | netif_stop_queue(tp->dev); |
5726 | |||
5727 | /* netif_tx_stop_queue() must be done before checking | ||
5728 | * checking tx index in tg3_tx_avail() below, because in | ||
5729 | * tg3_tx(), we update tx index before checking for | ||
5730 | * netif_tx_queue_stopped(). | ||
5731 | */ | ||
5732 | smp_mb(); | ||
5718 | if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est) | 5733 | if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est) |
5719 | return NETDEV_TX_BUSY; | 5734 | return NETDEV_TX_BUSY; |
5720 | 5735 | ||
@@ -5950,6 +5965,13 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, | |||
5950 | tnapi->tx_prod = entry; | 5965 | tnapi->tx_prod = entry; |
5951 | if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { | 5966 | if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) { |
5952 | netif_tx_stop_queue(txq); | 5967 | netif_tx_stop_queue(txq); |
5968 | |||
5969 | /* netif_tx_stop_queue() must be done before checking | ||
5970 | * checking tx index in tg3_tx_avail() below, because in | ||
5971 | * tg3_tx(), we update tx index before checking for | ||
5972 | * netif_tx_queue_stopped(). | ||
5973 | */ | ||
5974 | smp_mb(); | ||
5953 | if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) | 5975 | if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)) |
5954 | netif_tx_wake_queue(txq); | 5976 | netif_tx_wake_queue(txq); |
5955 | } | 5977 | } |