Message ID | 1279584905-15084-3-git-send-email-mchan@broadcom.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
From: "Michael Chan" <mchan@broadcom.com> Date: Mon, 19 Jul 2010 17:15:04 -0700 > smp_mb() inside bnx2_tx_avail() is used twice in the normal > bnx2_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 bnx2_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 bnx2_start_xmit() and bnx2_tx_int(), > we have the following situation: > > bnx2_start_xmit() bnx2_tx_int() > if (!bnx2_tx_avail()) > BUG(); > > ... > > if (!bnx2_tx_avail()) > netif_tx_stop_queue(); update_tx_index(); > smp_mb(); smp_mb(); > if (bnx2_tx_avail()) if (netif_tx_queue_stopped() && > netif_tx_wake_queue(); bnx2_tx_avail()) > > With smp_mb() removed from bnx2_tx_avail(), we need to add smp_mb() to > bnx2_start_xmit() as shown above to properly order netif_tx_stop_queue() > and bnx2_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 5% with 2 ports running bi-directional > 64-byte packets. > > Reviewed-by: Benjamin Li <benli@broadcom.com> > Reviewed-by: Matt Carlson <mcarlson@broadcom.com> > Signed-off-by: Michael Chan <mchan@broadcom.com> Applied. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Le lundi 19 juillet 2010 à 17:15 -0700, Michael Chan a écrit : > smp_mb() inside bnx2_tx_avail() is used twice in the normal > bnx2_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 bnx2_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 bnx2_start_xmit() and bnx2_tx_int(), > we have the following situation: > > bnx2_start_xmit() bnx2_tx_int() > if (!bnx2_tx_avail()) > BUG(); > > ... > > if (!bnx2_tx_avail()) > netif_tx_stop_queue(); update_tx_index(); > smp_mb(); smp_mb(); > if (bnx2_tx_avail()) if (netif_tx_queue_stopped() && > netif_tx_wake_queue(); bnx2_tx_avail()) > > With smp_mb() removed from bnx2_tx_avail(), we need to add smp_mb() to > bnx2_start_xmit() as shown above to properly order netif_tx_stop_queue() > and bnx2_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 5% with 2 ports running bi-directional > 64-byte packets. > > Reviewed-by: Benjamin Li <benli@broadcom.com> > Reviewed-by: Matt Carlson <mcarlson@broadcom.com> > Signed-off-by: Michael Chan <mchan@broadcom.com> > --- > drivers/net/bnx2.c | 10 +++++++++- > 1 files changed, 9 insertions(+), 1 deletions(-) > > diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c > index d44ecc3..2af570d 100644 > --- a/drivers/net/bnx2.c > +++ b/drivers/net/bnx2.c > @@ -253,7 +253,8 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) > { > u32 diff; > > - smp_mb(); > + /* Tell compiler to fetch tx_prod and tx_cons from memory. */ > + barrier(); > > /* The ring uses 256 indices for 255 entries, one of them > * needs to be skipped. > @@ -6534,6 +6535,13 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) > > if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) { > netif_tx_stop_queue(txq); > + > + /* netif_tx_stop_queue() must be done before checking > + * tx index in bnx2_tx_avail() below, because in > + * bnx2_tx_int(), we update tx index before checking for > + * netif_tx_queue_stopped(). > + */ > + smp_mb(); > if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh) > netif_tx_wake_queue(txq); > } Excellent, Is similar patch for tg3 planned ? Thanks -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Eric Dumazet wrote: > Excellent, > > Is similar patch for tg3 planned ? > Yes, this performance issue was actually first discovered when profiling a new tg3 device. So Matt should be sending out a very similar patch as part of his next patch-set. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d44ecc3..2af570d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -253,7 +253,8 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr) { u32 diff; - smp_mb(); + /* Tell compiler to fetch tx_prod and tx_cons from memory. */ + barrier(); /* The ring uses 256 indices for 255 entries, one of them * needs to be skipped. @@ -6534,6 +6535,13 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(bnx2_tx_avail(bp, txr) <= MAX_SKB_FRAGS)) { netif_tx_stop_queue(txq); + + /* netif_tx_stop_queue() must be done before checking + * tx index in bnx2_tx_avail() below, because in + * bnx2_tx_int(), we update tx index before checking for + * netif_tx_queue_stopped(). + */ + smp_mb(); if (bnx2_tx_avail(bp, txr) > bp->tx_wake_thresh) netif_tx_wake_queue(txq); }