提交 8eef5f97 编写于 作者: E Ezequiel Garcia 提交者: David S. Miller

net: mvneta: Limit the TSO segments and adjust stop/wake thresholds

Currently small MSS values may require too many TSO descriptors for
the default queue size. This commit prevents this situation by fixing
the maximum supported TSO number of segments to 100 and by setting a
minimum Tx queue size. The minimum Tx queue size is set so that at
least 2 worst-case skb can be accommodated.

In addition, the queue stop and wake thresholds values are adjusted
accordingly. The queue is stopped when there's room for only 1 worst-case
skb and waked when the number of descriptors is half that value.
Signed-off-by: NEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 9fa9379d
...@@ -251,6 +251,11 @@ ...@@ -251,6 +251,11 @@
/* Max number of Tx descriptors */ /* Max number of Tx descriptors */
#define MVNETA_MAX_TXD 532 #define MVNETA_MAX_TXD 532
/* Max number of allowed TCP segments for software TSO */
#define MVNETA_MAX_TSO_SEGS 100
#define MVNETA_MAX_SKB_DESCS (MVNETA_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)
/* descriptor aligned size */ /* descriptor aligned size */
#define MVNETA_DESC_ALIGNED_SIZE 32 #define MVNETA_DESC_ALIGNED_SIZE 32
...@@ -388,6 +393,8 @@ struct mvneta_tx_queue { ...@@ -388,6 +393,8 @@ struct mvneta_tx_queue {
* descriptor ring * descriptor ring
*/ */
int count; int count;
int tx_stop_threshold;
int tx_wake_threshold;
/* Array of transmitted skb */ /* Array of transmitted skb */
struct sk_buff **tx_skb; struct sk_buff **tx_skb;
...@@ -1309,7 +1316,7 @@ static void mvneta_txq_done(struct mvneta_port *pp, ...@@ -1309,7 +1316,7 @@ static void mvneta_txq_done(struct mvneta_port *pp,
txq->count -= tx_done; txq->count -= tx_done;
if (netif_tx_queue_stopped(nq)) { if (netif_tx_queue_stopped(nq)) {
if (txq->size - txq->count >= MAX_SKB_FRAGS + 1) if (txq->count <= txq->tx_wake_threshold)
netif_tx_wake_queue(nq); netif_tx_wake_queue(nq);
} }
} }
...@@ -1769,7 +1776,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -1769,7 +1776,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
txq->count += frags; txq->count += frags;
mvneta_txq_pend_desc_add(pp, txq, frags); mvneta_txq_pend_desc_add(pp, txq, frags);
if (txq->size - txq->count < MAX_SKB_FRAGS + 1) if (txq->count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq); netif_tx_stop_queue(nq);
u64_stats_update_begin(&stats->syncp); u64_stats_update_begin(&stats->syncp);
...@@ -2208,6 +2215,14 @@ static int mvneta_txq_init(struct mvneta_port *pp, ...@@ -2208,6 +2215,14 @@ static int mvneta_txq_init(struct mvneta_port *pp,
{ {
txq->size = pp->tx_ring_size; txq->size = pp->tx_ring_size;
/* A queue must always have room for at least one skb.
* Therefore, stop the queue when the free entries reaches
* the maximum number of descriptors per skb.
*/
txq->tx_stop_threshold = txq->size - MVNETA_MAX_SKB_DESCS;
txq->tx_wake_threshold = txq->tx_stop_threshold / 2;
/* Allocate memory for TX descriptors */ /* Allocate memory for TX descriptors */
txq->descs = dma_alloc_coherent(pp->dev->dev.parent, txq->descs = dma_alloc_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE, txq->size * MVNETA_DESC_ALIGNED_SIZE,
...@@ -2742,8 +2757,12 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev, ...@@ -2742,8 +2757,12 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,
return -EINVAL; return -EINVAL;
pp->rx_ring_size = ring->rx_pending < MVNETA_MAX_RXD ? pp->rx_ring_size = ring->rx_pending < MVNETA_MAX_RXD ?
ring->rx_pending : MVNETA_MAX_RXD; ring->rx_pending : MVNETA_MAX_RXD;
pp->tx_ring_size = ring->tx_pending < MVNETA_MAX_TXD ?
ring->tx_pending : MVNETA_MAX_TXD; pp->tx_ring_size = clamp_t(u16, ring->tx_pending,
MVNETA_MAX_SKB_DESCS * 2, MVNETA_MAX_TXD);
if (pp->tx_ring_size != ring->tx_pending)
netdev_warn(dev, "TX queue size set to %u (requested %u)\n",
pp->tx_ring_size, ring->tx_pending);
if (netif_running(dev)) { if (netif_running(dev)) {
mvneta_stop(dev); mvneta_stop(dev);
...@@ -3028,6 +3047,7 @@ static int mvneta_probe(struct platform_device *pdev) ...@@ -3028,6 +3047,7 @@ static int mvneta_probe(struct platform_device *pdev)
dev->hw_features |= dev->features; dev->hw_features |= dev->features;
dev->vlan_features |= dev->features; dev->vlan_features |= dev->features;
dev->priv_flags |= IFF_UNICAST_FLT; dev->priv_flags |= IFF_UNICAST_FLT;
dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
err = register_netdev(dev); err = register_netdev(dev);
if (err < 0) { if (err < 0) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册