Skip to content

Commit

Permalink
Merge branch 'mvneta'
Browse files Browse the repository at this point in the history
Ezequiel Garcia says:

====================
ethernet: marvell: After-TSO fixes

This patchset consists of different fixes and improvements in the mvneta
and mv643xx_eth drivers. The most important change is the one that allows
to support small MSS values (see patches 2 and 6).

This is done following the Solarflare driver (see commit 7e6d06f).

While doing this some other fixes were spotted and so they are included.

Finally, notice that the TSO support introduced a wrong DMA unmapping
of the TSO header buffers, so patches 4 and 8 provide a couple patches to
fix that in the drivers.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 2, 2014
2 parents 688cea8 + b926260 commit f7b4e71
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 37 deletions.
76 changes: 51 additions & 25 deletions drivers/net/ethernet/marvell/mv643xx_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,13 @@ static char mv643xx_eth_driver_version[] = "1.4";

#define TSO_HEADER_SIZE 128

/* Max number of allowed TCP segments for software TSO */
#define MV643XX_MAX_TSO_SEGS 100
#define MV643XX_MAX_SKB_DESCS (MV643XX_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)

#define IS_TSO_HEADER(txq, addr) \
((addr >= txq->tso_hdrs_dma) && \
(addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE))
/*
* RX/TX descriptors.
*/
Expand Down Expand Up @@ -348,6 +355,9 @@ struct tx_queue {
int tx_curr_desc;
int tx_used_desc;

int tx_stop_threshold;
int tx_wake_threshold;

char *tso_hdrs;
dma_addr_t tso_hdrs_dma;

Expand Down Expand Up @@ -497,7 +507,7 @@ static void txq_maybe_wake(struct tx_queue *txq)

if (netif_tx_queue_stopped(nq)) {
__netif_tx_lock(nq, smp_processor_id());
if (txq->tx_ring_size - txq->tx_desc_count >= MAX_SKB_FRAGS + 1)
if (txq->tx_desc_count <= txq->tx_wake_threshold)
netif_tx_wake_queue(nq);
__netif_tx_unlock(nq);
}
Expand Down Expand Up @@ -897,7 +907,8 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
}
}

static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb,
struct net_device *dev)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
int nr_frags = skb_shinfo(skb)->nr_frags;
Expand All @@ -910,11 +921,15 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb)
cmd_sts = 0;
l4i_chk = 0;

if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) {
if (net_ratelimit())
netdev_err(dev, "tx queue full?!\n");
return -EBUSY;
}

ret = skb_tx_csum(mp, skb, &l4i_chk, &cmd_sts, skb->len);
if (ret) {
dev_kfree_skb_any(skb);
if (ret)
return ret;
}
cmd_sts |= TX_FIRST_DESC | GEN_CRC | BUFFER_OWNED_BY_DMA;

tx_index = txq->tx_curr_desc++;
Expand Down Expand Up @@ -967,36 +982,26 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
nq = netdev_get_tx_queue(dev, queue);

if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
txq->tx_dropped++;
netdev_printk(KERN_DEBUG, dev,
"failed to linearize skb with tiny unaligned fragment\n");
return NETDEV_TX_BUSY;
}

if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) {
if (net_ratelimit())
netdev_err(dev, "tx queue full?!\n");
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}

length = skb->len;

if (skb_is_gso(skb))
ret = txq_submit_tso(txq, skb, dev);
else
ret = txq_submit_skb(txq, skb);
ret = txq_submit_skb(txq, skb, dev);
if (!ret) {
int entries_left;

txq->tx_bytes += length;
txq->tx_packets++;

entries_left = txq->tx_ring_size - txq->tx_desc_count;
if (entries_left < MAX_SKB_FRAGS + 1)
if (txq->tx_desc_count >= txq->tx_stop_threshold)
netif_tx_stop_queue(nq);
} else if (ret == -EBUSY) {
return NETDEV_TX_BUSY;
} else {
txq->tx_dropped++;
dev_kfree_skb_any(skb);
}

return NETDEV_TX_OK;
Expand Down Expand Up @@ -1070,8 +1075,9 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
mp->dev->stats.tx_errors++;
}

dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
desc->byte_cnt, DMA_TO_DEVICE);
if (!IS_TSO_HEADER(txq, desc->buf_ptr))
dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr,
desc->byte_cnt, DMA_TO_DEVICE);
dev_kfree_skb(skb);
}

Expand Down Expand Up @@ -1614,7 +1620,11 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er)
return -EINVAL;

mp->rx_ring_size = er->rx_pending < 4096 ? er->rx_pending : 4096;
mp->tx_ring_size = er->tx_pending < 4096 ? er->tx_pending : 4096;
mp->tx_ring_size = clamp_t(unsigned int, er->tx_pending,
MV643XX_MAX_SKB_DESCS * 2, 4096);
if (mp->tx_ring_size != er->tx_pending)
netdev_warn(dev, "TX queue size set to %u (requested %u)\n",
mp->tx_ring_size, er->tx_pending);

if (netif_running(dev)) {
mv643xx_eth_stop(dev);
Expand Down Expand Up @@ -1990,6 +2000,13 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)

txq->tx_ring_size = mp->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->tx_ring_size - MV643XX_MAX_SKB_DESCS;
txq->tx_wake_threshold = txq->tx_stop_threshold / 2;

txq->tx_desc_count = 0;
txq->tx_curr_desc = 0;
txq->tx_used_desc = 0;
Expand Down Expand Up @@ -2849,6 +2866,7 @@ static void set_params(struct mv643xx_eth_private *mp,
struct mv643xx_eth_platform_data *pd)
{
struct net_device *dev = mp->dev;
unsigned int tx_ring_size;

if (is_valid_ether_addr(pd->mac_addr))
memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
Expand All @@ -2863,9 +2881,16 @@ static void set_params(struct mv643xx_eth_private *mp,

mp->rxq_count = pd->rx_queue_count ? : 1;

mp->tx_ring_size = DEFAULT_TX_QUEUE_SIZE;
tx_ring_size = DEFAULT_TX_QUEUE_SIZE;
if (pd->tx_queue_size)
mp->tx_ring_size = pd->tx_queue_size;
tx_ring_size = pd->tx_queue_size;

mp->tx_ring_size = clamp_t(unsigned int, tx_ring_size,
MV643XX_MAX_SKB_DESCS * 2, 4096);
if (mp->tx_ring_size != tx_ring_size)
netdev_warn(dev, "TX queue size set to %u (requested %u)\n",
mp->tx_ring_size, tx_ring_size);

mp->tx_desc_sram_addr = pd->tx_sram_addr;
mp->tx_desc_sram_size = pd->tx_sram_size;

Expand Down Expand Up @@ -3092,6 +3117,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev->hw_features = dev->features;

dev->priv_flags |= IFF_UNICAST_FLT;
dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;

SET_NETDEV_DEV(dev, &pdev->dev);

Expand Down
46 changes: 34 additions & 12 deletions drivers/net/ethernet/marvell/mvneta.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,6 @@
#define MVNETA_RX_COAL_PKTS 32
#define MVNETA_RX_COAL_USEC 100

/* Napi polling weight */
#define MVNETA_RX_POLL_WEIGHT 64

/* The two bytes Marvell header. Either contains a special value used
* by Marvell switches when a specific hardware mode is enabled (not
* supported by this driver) or is filled automatically by zeroes on
Expand Down Expand Up @@ -254,6 +251,11 @@
/* Max number of Tx descriptors */
#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 */
#define MVNETA_DESC_ALIGNED_SIZE 32

Expand All @@ -262,6 +264,10 @@
ETH_HLEN + ETH_FCS_LEN, \
MVNETA_CPU_D_CACHE_LINE_SIZE)

#define IS_TSO_HEADER(txq, addr) \
((addr >= txq->tso_hdrs_phys) && \
(addr < txq->tso_hdrs_phys + txq->size * TSO_HEADER_SIZE))

#define MVNETA_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD)

struct mvneta_pcpu_stats {
Expand Down Expand Up @@ -391,6 +397,8 @@ struct mvneta_tx_queue {
* descriptor ring
*/
int count;
int tx_stop_threshold;
int tx_wake_threshold;

/* Array of transmitted skb */
struct sk_buff **tx_skb;
Expand Down Expand Up @@ -1287,11 +1295,12 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,

mvneta_txq_inc_get(txq);

if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
dma_unmap_single(pp->dev->dev.parent,
tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
if (!skb)
continue;

dma_unmap_single(pp->dev->dev.parent, tx_desc->buf_phys_addr,
tx_desc->data_size, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
}
}
Expand All @@ -1312,7 +1321,7 @@ static void mvneta_txq_done(struct mvneta_port *pp,
txq->count -= tx_done;

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);
}
}
Expand Down Expand Up @@ -1639,7 +1648,7 @@ static int mvneta_tx_tso(struct sk_buff *skb, struct net_device *dev,
*/
for (i = desc_count - 1; i >= 0; i--) {
struct mvneta_tx_desc *tx_desc = txq->descs + i;
if (!(tx_desc->command & MVNETA_TXD_F_DESC))
if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr))
dma_unmap_single(pp->dev->dev.parent,
tx_desc->buf_phys_addr,
tx_desc->data_size,
Expand Down Expand Up @@ -1772,7 +1781,7 @@ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
txq->count += 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);

u64_stats_update_begin(&stats->syncp);
Expand Down Expand Up @@ -2211,6 +2220,14 @@ static int mvneta_txq_init(struct mvneta_port *pp,
{
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 */
txq->descs = dma_alloc_coherent(pp->dev->dev.parent,
txq->size * MVNETA_DESC_ALIGNED_SIZE,
Expand Down Expand Up @@ -2745,8 +2762,12 @@ static int mvneta_ethtool_set_ringparam(struct net_device *dev,
return -EINVAL;
pp->rx_ring_size = 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)) {
mvneta_stop(dev);
Expand Down Expand Up @@ -3025,12 +3046,13 @@ static int mvneta_probe(struct platform_device *pdev)
if (dram_target_info)
mvneta_conf_mbus_windows(pp, dram_target_info);

netif_napi_add(dev, &pp->napi, mvneta_poll, MVNETA_RX_POLL_WEIGHT);
netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT);

dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
dev->hw_features |= dev->features;
dev->vlan_features |= dev->features;
dev->priv_flags |= IFF_UNICAST_FLT;
dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;

err = register_netdev(dev);
if (err < 0) {
Expand Down

0 comments on commit f7b4e71

Please sign in to comment.