<div dir="ltr"><div>Dear Sir.<br><br></div><div>have any suggestion?<br></div><div><br></div>Best Regards.<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-06-05 18:09 GMT+08:00 Mingyu Li <span dir="ltr"><<a href="mailto:igvtee@gmail.com" target="_blank">igvtee@gmail.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>this feature i reference tg3.c driver at function tg3_start_xmit.<br></div><div>it says therer is a small possibility that start_xmit will miss it<br></div><div>and cause the queue to be stopped forever.<br></div><div><br></div>below is the tg3 drivers code<br></div>=== function tg3_tx ===<br>        tnapi->tx_cons = sw_idx;<br><br>        /* Need to make the tx_cons update visible to tg3_start_xmit()<br>         * before checking for netif_queue_stopped().  Without the<br>         * memory barrier, there is a small possibility that tg3_start_xmit()<br>         * will miss it and cause the queue to be stopped forever.<br>         */<br>        smp_mb();<br><br>        if (unlikely(netif_tx_queue_stopped(txq) &&<br>                     (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) {<br>                __netif_tx_lock(txq, smp_processor_id());<br>                if (netif_tx_queue_stopped(txq) &&<br>                    (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))<br>                        netif_tx_wake_queue(txq);<br>                __netif_tx_unlock(txq);<br>        }<br><br>=== tg3_start_xmit ===<br>        budget = tg3_tx_avail(tnapi);<br>        <br>        /* We are running in BH disabled context with netif_tx_lock<br>         * and TX reclaim runs via tp->napi.poll inside of a software<br>         * interrupt.  Furthermore, IRQ processing runs lockless so we have<br>         * no IRQ context deadlocks to worry about either.  Rejoice!<br>         */<br>        if (unlikely(budget <= (skb_shinfo(skb)->nr_frags + 1))) {<br>                if (!netif_tx_queue_stopped(txq)) {<br>                        netif_tx_stop_queue(txq);<br>                <br>                        /* This is a hard error, log it. */<br>                        netdev_err(dev,<br>                                   "BUG! Tx Ring full when queue awake!\n");<br>                }       <br>                return NETDEV_TX_BUSY;<br>        }<br><br></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">2015-06-05 16:40 GMT+08:00 Felix Fietkau <span dir="ltr"><<a href="mailto:nbd@openwrt.org" target="_blank">nbd@openwrt.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>On 2015-06-02 15:06, michael lee wrote:<br>
> use pktgen to verify on rt3662. can improve transmit rate.<br>
> pkt_size 1500<br>
> burst 1 : 807Mb/sec<br>
> burst 8 : 984Mb/sec<br>
><br>
> pkt_size 60<br>
> burst 1 : 57Mb/sec<br>
> burst 8 : 236Mb/sec<br>
><br>
> Signed-off-by: michael lee <<a href="mailto:igvtee@gmail.com" target="_blank">igvtee@gmail.com</a>><br>
> ---<br>
>  .../drivers/net/ethernet/ralink/ralink_soc_eth.c   | 51 +++++++++++++---------<br>
>  .../drivers/net/ethernet/ralink/ralink_soc_eth.h   |  2 +<br>
>  2 files changed, 33 insertions(+), 20 deletions(-)<br>
><br>
> 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<br>
> index b2304bb..4b39825 100644<br>
> --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c<br>
> +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c<br>
> @@ -337,6 +337,8 @@ static int fe_alloc_tx(struct fe_priv *priv)<br>
>       struct fe_tx_ring *ring = &priv->tx_ring;<br>
><br>
>       ring->tx_free_idx = 0;<br>
> +     ring->tx_next_idx = 0;<br>
> +     ring->tx_thresh = max((unsigned long)ring->tx_ring_size >> 2, MAX_SKB_FRAGS);<br>
><br>
>       ring->tx_buf = kcalloc(ring->tx_ring_size, sizeof(*ring->tx_buf),<br>
>                       GFP_KERNEL);<br>
> @@ -525,8 +527,16 @@ static int fe_vlan_rx_kill_vid(struct net_device *dev,<br>
>       return 0;<br>
>  }<br>
><br>
> +static inline u32 fe_empty_txd(struct fe_tx_ring *ring)<br>
> +{<br>
> +     barrier();<br>
</div></div>What is this barrier for?<br>
<span><br>
> +     return (u32)(ring->tx_ring_size -<br>
> +                     ((ring->tx_next_idx - ring->tx_free_idx) &<br>
> +                      (ring->tx_ring_size - 1)));<br>
> +}<br>
> +<br>
>  static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev,<br>
> -             int idx, int tx_num, struct fe_tx_ring *ring)<br>
> +             int tx_num, struct fe_tx_ring *ring)<br>
>  {<br>
>       struct fe_priv *priv = netdev_priv(dev);<br>
>       struct skb_frag_struct *frag;<br>
</span><span>> @@ -649,14 +659,22 @@ static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev,<br>
>       netdev_sent_queue(dev, skb->len);<br>
>       skb_tx_timestamp(skb);<br>
><br>
> -     j = NEXT_TX_DESP_IDX(j);<br>
> +     ring->tx_next_idx = NEXT_TX_DESP_IDX(j);<br>
>       wmb();<br>
> -     fe_reg_w32(j, FE_REG_TX_CTX_IDX0);<br>
> +     if (unlikely(fe_empty_txd(ring) <= ring->tx_thresh)) {<br>
> +             netif_stop_queue(dev);<br>
> +             smp_mb();<br>
> +             if (unlikely(fe_empty_txd(ring) > ring->tx_thresh))<br>
> +                     netif_wake_queue(dev);<br>
</span>Why do that queue wake check here, when it's already being done during<br>
tx cleanup.<br>
<div><div><br>
> +     }<br>
> +<br>
> +     if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || !skb->xmit_more)<br>
> +             fe_reg_w32(ring->tx_next_idx, FE_REG_TX_CTX_IDX0);<br>
><br>
>       return 0;<br>
><br>
>  err_dma:<br>
> -     j = idx;<br>
> +     j = ring->tx_next_idx;<br>
>       for (i = 0; i < tx_num; i++) {<br>
>               ptxd = &ring->tx_dma[j];<br>
>               tx_buf = &ring->tx_buf[j];<br>
<br>
</div></div><span><font color="#888888">- Felix<br>
</font></span></blockquote></div><br></div>
</div></div></blockquote></div><br></div>