dpaa_eth: try to move the data in place for the A050385 erratum
authorCamelia Groza <camelia.groza@nxp.com>
Thu, 4 Feb 2021 16:49:28 +0000 (18:49 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 6 Feb 2021 03:58:34 +0000 (19:58 -0800)
The XDP frame's headroom might be large enough to accommodate the
xdpf backpointer as well as shifting the data to an aligned address.

Try this first before resorting to allocating a new buffer and copying
the data.

Suggested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
Acked-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Acked-by: Madalin Bucur <madalin.bucur@oss.nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c

index 2a2c7db..6faa20b 100644 (file)
@@ -2180,8 +2180,9 @@ static int dpaa_a050385_wa_xdpf(struct dpaa_priv *priv,
                                struct xdp_frame **init_xdpf)
 {
        struct xdp_frame *new_xdpf, *xdpf = *init_xdpf;
-       void *new_buff;
+       void *new_buff, *aligned_data;
        struct page *p;
+       u32 data_shift;
        int headroom;
 
        /* Check the data alignment and make sure the headroom is large
@@ -2198,6 +2199,23 @@ static int dpaa_a050385_wa_xdpf(struct dpaa_priv *priv,
                return 0;
        }
 
+       /* Try to move the data inside the buffer just enough to align it and
+        * store the xdpf backpointer. If the available headroom isn't large
+        * enough, resort to allocating a new buffer and copying the data.
+        */
+       aligned_data = PTR_ALIGN_DOWN(xdpf->data, DPAA_FD_DATA_ALIGNMENT);
+       data_shift = xdpf->data - aligned_data;
+
+       /* The XDP frame's headroom needs to be large enough to accommodate
+        * shifting the data as well as storing the xdpf backpointer.
+        */
+       if (xdpf->headroom  >= data_shift + priv->tx_headroom) {
+               memmove(aligned_data, xdpf->data, xdpf->len);
+               xdpf->data = aligned_data;
+               xdpf->headroom = priv->tx_headroom;
+               return 0;
+       }
+
        /* The new xdp_frame is stored in the new buffer. Reserve enough space
         * in the headroom for storing it along with the driver's private
         * info. The headroom needs to be aligned to DPAA_FD_DATA_ALIGNMENT to