Commit 7b1eea1a authored by Ioana Ciocoi Radulescu's avatar Ioana Ciocoi Radulescu Committed by David S. Miller

dpaa2-eth: Allow XDP header adjustments

Reserve XDP_PACKET_HEADROOM bytes in Rx buffers to allow XDP
programs to increase frame header size.
Signed-off-by: default avatarIoana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7e273a8e
...@@ -216,11 +216,15 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv, ...@@ -216,11 +216,15 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv,
xdp.data = vaddr + dpaa2_fd_get_offset(fd); xdp.data = vaddr + dpaa2_fd_get_offset(fd);
xdp.data_end = xdp.data + dpaa2_fd_get_len(fd); xdp.data_end = xdp.data + dpaa2_fd_get_len(fd);
xdp.data_hard_start = xdp.data; xdp.data_hard_start = xdp.data - XDP_PACKET_HEADROOM;
xdp_set_data_meta_invalid(&xdp); xdp_set_data_meta_invalid(&xdp);
xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp); xdp_act = bpf_prog_run_xdp(xdp_prog, &xdp);
/* xdp.data pointer may have changed */
dpaa2_fd_set_offset(fd, xdp.data - vaddr);
dpaa2_fd_set_len(fd, xdp.data_end - xdp.data);
switch (xdp_act) { switch (xdp_act) {
case XDP_PASS: case XDP_PASS:
break; break;
...@@ -1483,7 +1487,7 @@ static bool xdp_mtu_valid(struct dpaa2_eth_priv *priv, int mtu) ...@@ -1483,7 +1487,7 @@ static bool xdp_mtu_valid(struct dpaa2_eth_priv *priv, int mtu)
mfl = DPAA2_ETH_L2_MAX_FRM(mtu); mfl = DPAA2_ETH_L2_MAX_FRM(mtu);
linear_mfl = DPAA2_ETH_RX_BUF_SIZE - DPAA2_ETH_RX_HWA_SIZE - linear_mfl = DPAA2_ETH_RX_BUF_SIZE - DPAA2_ETH_RX_HWA_SIZE -
dpaa2_eth_rx_head_room(priv); dpaa2_eth_rx_head_room(priv) - XDP_PACKET_HEADROOM;
if (mfl > linear_mfl) { if (mfl > linear_mfl) {
netdev_warn(priv->net_dev, "Maximum MTU for XDP is %d\n", netdev_warn(priv->net_dev, "Maximum MTU for XDP is %d\n",
...@@ -1537,6 +1541,32 @@ static int dpaa2_eth_change_mtu(struct net_device *dev, int new_mtu) ...@@ -1537,6 +1541,32 @@ static int dpaa2_eth_change_mtu(struct net_device *dev, int new_mtu)
return 0; return 0;
} }
static int update_rx_buffer_headroom(struct dpaa2_eth_priv *priv, bool has_xdp)
{
struct dpni_buffer_layout buf_layout = {0};
int err;
err = dpni_get_buffer_layout(priv->mc_io, 0, priv->mc_token,
DPNI_QUEUE_RX, &buf_layout);
if (err) {
netdev_err(priv->net_dev, "dpni_get_buffer_layout failed\n");
return err;
}
/* Reserve extra headroom for XDP header size changes */
buf_layout.data_head_room = dpaa2_eth_rx_head_room(priv) +
(has_xdp ? XDP_PACKET_HEADROOM : 0);
buf_layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM;
err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
DPNI_QUEUE_RX, &buf_layout);
if (err) {
netdev_err(priv->net_dev, "dpni_set_buffer_layout failed\n");
return err;
}
return 0;
}
static int setup_xdp(struct net_device *dev, struct bpf_prog *prog) static int setup_xdp(struct net_device *dev, struct bpf_prog *prog)
{ {
struct dpaa2_eth_priv *priv = netdev_priv(dev); struct dpaa2_eth_priv *priv = netdev_priv(dev);
...@@ -1560,11 +1590,18 @@ static int setup_xdp(struct net_device *dev, struct bpf_prog *prog) ...@@ -1560,11 +1590,18 @@ static int setup_xdp(struct net_device *dev, struct bpf_prog *prog)
if (up) if (up)
dpaa2_eth_stop(dev); dpaa2_eth_stop(dev);
/* While in xdp mode, enforce a maximum Rx frame size based on MTU */ /* While in xdp mode, enforce a maximum Rx frame size based on MTU.
* Also, when switching between xdp/non-xdp modes we need to reconfigure
* our Rx buffer layout. Buffer pool was drained on dpaa2_eth_stop,
* so we are sure no old format buffers will be used from now on.
*/
if (need_update) { if (need_update) {
err = set_rx_mfl(priv, dev->mtu, !!prog); err = set_rx_mfl(priv, dev->mtu, !!prog);
if (err) if (err)
goto out_err; goto out_err;
err = update_rx_buffer_headroom(priv, !!prog);
if (err)
goto out_err;
} }
old = xchg(&priv->xdp_prog, prog); old = xchg(&priv->xdp_prog, prog);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment