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