[PATCH net-next 2/6] net: mvpp2: disable TSO if its buffers cannot be allocated

From: Antoine Tenart
Date: Thu Dec 07 2017 - 03:50:25 EST


This patch changes the PPv2 behaviour when the TSO specific headers
cannot be allocated. In such cases the driver was previously failing and
the interface wasn't enabled while only the TSO feature is disabled now
and a warning message is shown.

Such memory allocation failures can happen when DMA_CMA is enabled and
CMA_SIZE_MBYTES is too small (ie. its default value).

Signed-off-by: Antoine Tenart <antoine.tenart@xxxxxxxxxxxxxxxxxx>
---
drivers/net/ethernet/marvell/mvpp2.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index d67f40ee63b3..2f86358614a6 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -5735,6 +5735,8 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
u32 val;
int cpu, desc, desc_per_txq, tx_port_num;
struct mvpp2_txq_pcpu *txq_pcpu;
+ struct net_device *dev = port->dev;
+ bool tso = dev->features & NETIF_F_TSO;

txq->size = port->tx_ring_size;

@@ -5807,13 +5809,41 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
txq_pcpu->stop_threshold = txq->size - MVPP2_MAX_SKB_DESCS;
txq_pcpu->wake_threshold = txq_pcpu->stop_threshold / 2;

+ if (!tso)
+ continue;
+
txq_pcpu->tso_headers =
dma_alloc_coherent(port->dev->dev.parent,
txq_pcpu->size * TSO_HEADER_SIZE,
&txq_pcpu->tso_headers_dma,
GFP_KERNEL);
if (!txq_pcpu->tso_headers)
- return -ENOMEM;
+ tso = false;
+ }
+
+ /* TSO was enabled but not enough memory is available to allocate the
+ * TSO specific buffers. Free the successfully allocated buffers, warn
+ * the user and disable TSO.
+ */
+ if ((dev->features & NETIF_F_TSO) && !tso)
+ goto cleanup_tso;
+
+ return 0;
+
+cleanup_tso:
+ dev->features &= ~NETIF_F_TSO;
+ netdev_warn(dev, "TSO disabled\n");
+
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+
+ if (txq_pcpu->tso_headers)
+ dma_free_coherent(port->dev->dev.parent,
+ txq_pcpu->size * TSO_HEADER_SIZE,
+ txq_pcpu->tso_headers,
+ txq_pcpu->tso_headers_dma);
+
+ txq_pcpu->tso_headers = NULL;
}

return 0;
--
2.14.3