The dev->dma_mask usually points to dev->coherent_dma_mask. This is an
issue as setting both of them will override the other. This is
problematic here as the PPv2 driver uses a 32-bit-mask for coherent
accesses (txq, rxq, bm) and a 40-bit mask for all other accesses due to
an hardware limitation.

This can lead to a memory remap for all dma_map_single() calls when
dealing with memory above 4GB.

Fixes: 2067e0a13cfe ("net: mvpp2: set dma mask and coherent dma mask on PPv2.2")
Reported-by: Stefan Chulski <stef...@marvell.com>
Signed-off-by: Antoine Tenart <antoine.ten...@free-electrons.com>
---
 drivers/net/ethernet/marvell/mvpp2.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/net/ethernet/marvell/mvpp2.c 
b/drivers/net/ethernet/marvell/mvpp2.c
index dd0ee2691c86..7024d4dbb461 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -7969,9 +7969,25 @@ static int mvpp2_probe(struct platform_device *pdev)
        priv->tclk = clk_get_rate(priv->pp_clk);
 
        if (priv->hw_version == MVPP22) {
+               /* If dma_mask points to coherent_dma_mask, setting both will
+                * override the value of the other. This is problematic as the
+                * PPv2 driver uses a 32-bit-mask for coherent accesses (txq,
+                * rxq, bm) and a 40-bit mask for all other accesses.
+                */
+               if (pdev->dev.dma_mask == &pdev->dev.coherent_dma_mask) {
+                       pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
+                                                         
sizeof(*pdev->dev.dma_mask),
+                                                         GFP_KERNEL);
+                       if (!pdev->dev.dma_mask) {
+                               err = -ENOMEM;
+                               goto err_mg_clk;
+                       }
+               }
+
                err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
                if (err)
                        goto err_mg_clk;
+
                /* Sadly, the BM pools all share the same register to
                 * store the high 32 bits of their address. So they
                 * must all have the same high 32 bits, which forces
-- 
2.13.5

Reply via email to