[OpenWrt-Devel] [PATCH] [ 4/5] ramips: add xmit_more support
Mingyu Li
igvtee at gmail.com
Fri Jun 5 06:09:53 EDT 2015
this feature i reference tg3.c driver at function tg3_start_xmit.
it says therer is a small possibility that start_xmit will miss it
and cause the queue to be stopped forever.
below is the tg3 drivers code
=== function tg3_tx ===
tnapi->tx_cons = sw_idx;
/* Need to make the tx_cons update visible to tg3_start_xmit()
* before checking for netif_queue_stopped(). Without the
* memory barrier, there is a small possibility that
tg3_start_xmit()
* will miss it and cause the queue to be stopped forever.
*/
smp_mb();
if (unlikely(netif_tx_queue_stopped(txq) &&
(tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) {
__netif_tx_lock(txq, smp_processor_id());
if (netif_tx_queue_stopped(txq) &&
(tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))
netif_tx_wake_queue(txq);
__netif_tx_unlock(txq);
}
=== tg3_start_xmit ===
budget = tg3_tx_avail(tnapi);
/* We are running in BH disabled context with netif_tx_lock
* and TX reclaim runs via tp->napi.poll inside of a software
* interrupt. Furthermore, IRQ processing runs lockless so we have
* no IRQ context deadlocks to worry about either. Rejoice!
*/
if (unlikely(budget <= (skb_shinfo(skb)->nr_frags + 1))) {
if (!netif_tx_queue_stopped(txq)) {
netif_tx_stop_queue(txq);
/* This is a hard error, log it. */
netdev_err(dev,
"BUG! Tx Ring full when queue awake!\n");
}
return NETDEV_TX_BUSY;
}
2015-06-05 16:40 GMT+08:00 Felix Fietkau <nbd at openwrt.org>:
> On 2015-06-02 15:06, michael lee wrote:
> > use pktgen to verify on rt3662. can improve transmit rate.
> > pkt_size 1500
> > burst 1 : 807Mb/sec
> > burst 8 : 984Mb/sec
> >
> > pkt_size 60
> > burst 1 : 57Mb/sec
> > burst 8 : 236Mb/sec
> >
> > Signed-off-by: michael lee <igvtee at gmail.com>
> > ---
> > .../drivers/net/ethernet/ralink/ralink_soc_eth.c | 51
> +++++++++++++---------
> > .../drivers/net/ethernet/ralink/ralink_soc_eth.h | 2 +
> > 2 files changed, 33 insertions(+), 20 deletions(-)
> >
> > diff --git
> a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c
> b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c
> > index b2304bb..4b39825 100644
> > ---
> a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c
> > +++
> b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c
> > @@ -337,6 +337,8 @@ static int fe_alloc_tx(struct fe_priv *priv)
> > struct fe_tx_ring *ring = &priv->tx_ring;
> >
> > ring->tx_free_idx = 0;
> > + ring->tx_next_idx = 0;
> > + ring->tx_thresh = max((unsigned long)ring->tx_ring_size >> 2,
> MAX_SKB_FRAGS);
> >
> > ring->tx_buf = kcalloc(ring->tx_ring_size, sizeof(*ring->tx_buf),
> > GFP_KERNEL);
> > @@ -525,8 +527,16 @@ static int fe_vlan_rx_kill_vid(struct net_device
> *dev,
> > return 0;
> > }
> >
> > +static inline u32 fe_empty_txd(struct fe_tx_ring *ring)
> > +{
> > + barrier();
> What is this barrier for?
>
> > + return (u32)(ring->tx_ring_size -
> > + ((ring->tx_next_idx - ring->tx_free_idx) &
> > + (ring->tx_ring_size - 1)));
> > +}
> > +
> > static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev,
> > - int idx, int tx_num, struct fe_tx_ring *ring)
> > + int tx_num, struct fe_tx_ring *ring)
> > {
> > struct fe_priv *priv = netdev_priv(dev);
> > struct skb_frag_struct *frag;
> > @@ -649,14 +659,22 @@ static int fe_tx_map_dma(struct sk_buff *skb,
> struct net_device *dev,
> > netdev_sent_queue(dev, skb->len);
> > skb_tx_timestamp(skb);
> >
> > - j = NEXT_TX_DESP_IDX(j);
> > + ring->tx_next_idx = NEXT_TX_DESP_IDX(j);
> > wmb();
> > - fe_reg_w32(j, FE_REG_TX_CTX_IDX0);
> > + if (unlikely(fe_empty_txd(ring) <= ring->tx_thresh)) {
> > + netif_stop_queue(dev);
> > + smp_mb();
> > + if (unlikely(fe_empty_txd(ring) > ring->tx_thresh))
> > + netif_wake_queue(dev);
> Why do that queue wake check here, when it's already being done during
> tx cleanup.
>
> > + }
> > +
> > + if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) ||
> !skb->xmit_more)
> > + fe_reg_w32(ring->tx_next_idx, FE_REG_TX_CTX_IDX0);
> >
> > return 0;
> >
> > err_dma:
> > - j = idx;
> > + j = ring->tx_next_idx;
> > for (i = 0; i < tx_num; i++) {
> > ptxd = &ring->tx_dma[j];
> > tx_buf = &ring->tx_buf[j];
>
> - Felix
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/openwrt-devel/attachments/20150605/7c0c41dd/attachment.htm>
-------------- next part --------------
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list