Dear Sir. have any suggestion?
Best Regards. 2015-06-05 18:09 GMT+08:00 Mingyu Li <igv...@gmail.com>: > 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 <n...@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 <igv...@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 >> > >
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel