Skip to content

Commit ae680bc

Browse files
camelia-groza-NXPkuba-moo
authored andcommitted
dpaa_eth: implement the A050385 erratum workaround for XDP
For XDP TX, even tough we start out with correctly aligned buffers, the XDP program might change the data's alignment. For REDIRECT, we have no control over the alignment either. Create a new workaround for xdp_frame structures to verify the erratum conditions and move the data to a fresh buffer if necessary. Create a new xdp_frame for managing the new buffer and free the old one using the XDP API. Due to alignment constraints, all frames have a 256 byte headroom that is offered fully to XDP under the erratum. If the XDP program uses all of it, the data needs to be move to make room for the xdpf backpointer. Disable the metadata support since the information can be lost. Acked-by: Madalin Bucur <[email protected]> Signed-off-by: Camelia Groza <[email protected]> Reviewed-by: Maciej Fijalkowski <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d7af044 commit ae680bc

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

drivers/net/ethernet/freescale/dpaa/dpaa_eth.c

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,6 +2171,52 @@ static int dpaa_a050385_wa_skb(struct net_device *net_dev, struct sk_buff **s)
21712171

21722172
return 0;
21732173
}
2174+
2175+
static int dpaa_a050385_wa_xdpf(struct dpaa_priv *priv,
2176+
struct xdp_frame **init_xdpf)
2177+
{
2178+
struct xdp_frame *new_xdpf, *xdpf = *init_xdpf;
2179+
void *new_buff;
2180+
struct page *p;
2181+
2182+
/* Check the data alignment and make sure the headroom is large
2183+
* enough to store the xdpf backpointer. Use an aligned headroom
2184+
* value.
2185+
*
2186+
* Due to alignment constraints, we give XDP access to the full 256
2187+
* byte frame headroom. If the XDP program uses all of it, copy the
2188+
* data to a new buffer and make room for storing the backpointer.
2189+
*/
2190+
if (PTR_IS_ALIGNED(xdpf->data, DPAA_A050385_ALIGN) &&
2191+
xdpf->headroom >= priv->tx_headroom) {
2192+
xdpf->headroom = priv->tx_headroom;
2193+
return 0;
2194+
}
2195+
2196+
p = dev_alloc_pages(0);
2197+
if (unlikely(!p))
2198+
return -ENOMEM;
2199+
2200+
/* Copy the data to the new buffer at a properly aligned offset */
2201+
new_buff = page_address(p);
2202+
memcpy(new_buff + priv->tx_headroom, xdpf->data, xdpf->len);
2203+
2204+
/* Create an XDP frame around the new buffer in a similar fashion
2205+
* to xdp_convert_buff_to_frame.
2206+
*/
2207+
new_xdpf = new_buff;
2208+
new_xdpf->data = new_buff + priv->tx_headroom;
2209+
new_xdpf->len = xdpf->len;
2210+
new_xdpf->headroom = priv->tx_headroom;
2211+
new_xdpf->frame_sz = DPAA_BP_RAW_SIZE;
2212+
new_xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
2213+
2214+
/* Release the initial buffer */
2215+
xdp_return_frame_rx_napi(xdpf);
2216+
2217+
*init_xdpf = new_xdpf;
2218+
return 0;
2219+
}
21742220
#endif
21752221

21762222
static netdev_tx_t
@@ -2407,6 +2453,15 @@ static int dpaa_xdp_xmit_frame(struct net_device *net_dev,
24072453
percpu_priv = this_cpu_ptr(priv->percpu_priv);
24082454
percpu_stats = &percpu_priv->stats;
24092455

2456+
#ifdef CONFIG_DPAA_ERRATUM_A050385
2457+
if (unlikely(fman_has_errata_a050385())) {
2458+
if (dpaa_a050385_wa_xdpf(priv, &xdpf)) {
2459+
err = -ENOMEM;
2460+
goto out_error;
2461+
}
2462+
}
2463+
#endif
2464+
24102465
if (xdpf->headroom < DPAA_TX_PRIV_DATA_SIZE) {
24112466
err = -EINVAL;
24122467
goto out_error;
@@ -2480,14 +2535,33 @@ static u32 dpaa_run_xdp(struct dpaa_priv *priv, struct qm_fd *fd, void *vaddr,
24802535
xdp.frame_sz = DPAA_BP_RAW_SIZE - DPAA_TX_PRIV_DATA_SIZE;
24812536
xdp.rxq = &dpaa_fq->xdp_rxq;
24822537

2538+
/* We reserve a fixed headroom of 256 bytes under the erratum and we
2539+
* offer it all to XDP programs to use. If no room is left for the
2540+
* xdpf backpointer on TX, we will need to copy the data.
2541+
* Disable metadata support since data realignments might be required
2542+
* and the information can be lost.
2543+
*/
2544+
#ifdef CONFIG_DPAA_ERRATUM_A050385
2545+
if (unlikely(fman_has_errata_a050385())) {
2546+
xdp_set_data_meta_invalid(&xdp);
2547+
xdp.data_hard_start = vaddr;
2548+
xdp.frame_sz = DPAA_BP_RAW_SIZE;
2549+
}
2550+
#endif
2551+
24832552
xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp);
24842553

24852554
/* Update the length and the offset of the FD */
24862555
qm_fd_set_contig(fd, xdp.data - vaddr, xdp.data_end - xdp.data);
24872556

24882557
switch (xdp_act) {
24892558
case XDP_PASS:
2559+
#ifdef CONFIG_DPAA_ERRATUM_A050385
2560+
*xdp_meta_len = xdp_data_meta_unsupported(&xdp) ? 0 :
2561+
xdp.data - xdp.data_meta;
2562+
#else
24902563
*xdp_meta_len = xdp.data - xdp.data_meta;
2564+
#endif
24912565
break;
24922566
case XDP_TX:
24932567
/* We can access the full headroom when sending the frame
@@ -3191,10 +3265,16 @@ static u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl,
31913265
*/
31923266
headroom = (u16)(bl[port].priv_data_size + DPAA_HWA_SIZE);
31933267

3194-
if (port == RX)
3268+
if (port == RX) {
3269+
#ifdef CONFIG_DPAA_ERRATUM_A050385
3270+
if (unlikely(fman_has_errata_a050385()))
3271+
headroom = XDP_PACKET_HEADROOM;
3272+
#endif
3273+
31953274
return ALIGN(headroom, DPAA_FD_RX_DATA_ALIGNMENT);
3196-
else
3275+
} else {
31973276
return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT);
3277+
}
31983278
}
31993279

32003280
static int dpaa_eth_probe(struct platform_device *pdev)

0 commit comments

Comments
 (0)