dpaa2-eth: increase the needed headroom to account for alignment
authorIoana Ciornei <ioana.ciornei@nxp.com>
Fri, 24 Nov 2023 10:28:04 +0000 (12:28 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 26 Nov 2023 15:18:57 +0000 (15:18 +0000)
Increase the needed headroom to account for a 64 byte alignment
restriction which, with this patch, we make mandatory on the Tx path.
The case in which the amount of headroom needed is not available is
already handled by the driver which instead sends a S/G frame with the
first buffer only holding the SW and HW annotation areas.

Without this patch, we can empirically see data corruption happening
between Tx and Tx confirmation which sometimes leads to the SW
annotation area being overwritten.

Since this is an old IP where the hardware team cannot help to
understand the underlying behavior, we make the Tx alignment mandatory
for all frames to avoid the crash on Tx conf. Also, remove the comment
that suggested that this is just an optimization.

This patch also sets the needed_headroom net device field to the usual
value that the driver would need on the Tx path:
- 64 bytes for the software annotation area
- 64 bytes to account for a 64 byte aligned buffer address

Fixes: 6e2387e8f19e ("staging: fsl-dpaa2/eth: Add Freescale DPAA2 Ethernet driver")
Closes: https://lore.kernel.org/netdev/aa784d0c-85eb-4e5d-968b-c8f74fa86be6@gin.de/
Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h

index 15bab41cee48dfa13b25cd3c145d4df726ea6018..774377db0b4bdd3a413dd999b40a0ee6263ebe0d 100644 (file)
@@ -1073,14 +1073,12 @@ static int dpaa2_eth_build_single_fd(struct dpaa2_eth_priv *priv,
        dma_addr_t addr;
 
        buffer_start = skb->data - dpaa2_eth_needed_headroom(skb);
-
-       /* If there's enough room to align the FD address, do it.
-        * It will help hardware optimize accesses.
-        */
        aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN,
                                  DPAA2_ETH_TX_BUF_ALIGN);
        if (aligned_start >= skb->head)
                buffer_start = aligned_start;
+       else
+               return -ENOMEM;
 
        /* Store a backpointer to the skb at the beginning of the buffer
         * (in the private data area) such that we can release it
@@ -4967,6 +4965,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
        if (err)
                goto err_dl_port_add;
 
+       net_dev->needed_headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN;
+
        err = register_netdev(net_dev);
        if (err < 0) {
                dev_err(dev, "register_netdev() failed\n");
index bfb6c96c3b2f081d8fc428f036213327faa5a3a0..834cba8c3a416390578484ff7075b4626b0d2525 100644 (file)
@@ -740,7 +740,7 @@ static inline bool dpaa2_eth_rx_pause_enabled(u64 link_options)
 
 static inline unsigned int dpaa2_eth_needed_headroom(struct sk_buff *skb)
 {
-       unsigned int headroom = DPAA2_ETH_SWA_SIZE;
+       unsigned int headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN;
 
        /* If we don't have an skb (e.g. XDP buffer), we only need space for
         * the software annotation area