137 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3#include <linux/bpf.h>4#include <linux/bpf_trace.h>5#include <linux/filter.h>6 7#include "lan966x_main.h"8 9static int lan966x_xdp_setup(struct net_device *dev, struct netdev_bpf *xdp)10{11 struct lan966x_port *port = netdev_priv(dev);12 struct lan966x *lan966x = port->lan966x;13 struct bpf_prog *old_prog;14 bool old_xdp, new_xdp;15 int err;16 17 if (!lan966x->fdma) {18 NL_SET_ERR_MSG_MOD(xdp->extack,19 "Allow to set xdp only when using fdma");20 return -EOPNOTSUPP;21 }22 23 old_xdp = lan966x_xdp_present(lan966x);24 old_prog = xchg(&port->xdp_prog, xdp->prog);25 new_xdp = lan966x_xdp_present(lan966x);26 27 if (old_xdp == new_xdp)28 goto out;29 30 err = lan966x_fdma_reload_page_pool(lan966x);31 if (err) {32 xchg(&port->xdp_prog, old_prog);33 return err;34 }35 36out:37 if (old_prog)38 bpf_prog_put(old_prog);39 40 return 0;41}42 43int lan966x_xdp(struct net_device *dev, struct netdev_bpf *xdp)44{45 switch (xdp->command) {46 case XDP_SETUP_PROG:47 return lan966x_xdp_setup(dev, xdp);48 default:49 return -EINVAL;50 }51}52 53int lan966x_xdp_xmit(struct net_device *dev,54 int n,55 struct xdp_frame **frames,56 u32 flags)57{58 struct lan966x_port *port = netdev_priv(dev);59 int nxmit = 0;60 61 for (int i = 0; i < n; ++i) {62 struct xdp_frame *xdpf = frames[i];63 int err;64 65 err = lan966x_fdma_xmit_xdpf(port, xdpf, 0);66 if (err)67 break;68 69 nxmit++;70 }71 72 return nxmit;73}74 75int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len)76{77 struct bpf_prog *xdp_prog = port->xdp_prog;78 struct lan966x *lan966x = port->lan966x;79 struct xdp_buff xdp;80 u32 act;81 82 xdp_init_buff(&xdp, PAGE_SIZE << lan966x->rx.page_order,83 &port->xdp_rxq);84 xdp_prepare_buff(&xdp, page_address(page),85 IFH_LEN_BYTES + XDP_PACKET_HEADROOM,86 data_len - IFH_LEN_BYTES, false);87 act = bpf_prog_run_xdp(xdp_prog, &xdp);88 switch (act) {89 case XDP_PASS:90 return FDMA_PASS;91 case XDP_TX:92 return lan966x_fdma_xmit_xdpf(port, page,93 data_len - IFH_LEN_BYTES) ?94 FDMA_DROP : FDMA_TX;95 case XDP_REDIRECT:96 if (xdp_do_redirect(port->dev, &xdp, xdp_prog))97 return FDMA_DROP;98 99 return FDMA_REDIRECT;100 default:101 bpf_warn_invalid_xdp_action(port->dev, xdp_prog, act);102 fallthrough;103 case XDP_ABORTED:104 trace_xdp_exception(port->dev, xdp_prog, act);105 fallthrough;106 case XDP_DROP:107 return FDMA_DROP;108 }109}110 111bool lan966x_xdp_present(struct lan966x *lan966x)112{113 for (int p = 0; p < lan966x->num_phys_ports; ++p) {114 if (!lan966x->ports[p])115 continue;116 117 if (lan966x_xdp_port_present(lan966x->ports[p]))118 return true;119 }120 121 return false;122}123 124int lan966x_xdp_port_init(struct lan966x_port *port)125{126 struct lan966x *lan966x = port->lan966x;127 128 return xdp_rxq_info_reg(&port->xdp_rxq, port->dev, 0,129 lan966x->napi.napi_id);130}131 132void lan966x_xdp_port_deinit(struct lan966x_port *port)133{134 if (xdp_rxq_info_is_reg(&port->xdp_rxq))135 xdp_rxq_info_unreg(&port->xdp_rxq);136}137