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 9 static 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 15 if (!lan966x->fdma) { 16 NL_SET_ERR_MSG_MOD(xdp->extack, 17 "Allow to set xdp only when using fdma"); 18 return -EOPNOTSUPP; 19 } 20 21 old_prog = xchg(&port->xdp_prog, xdp->prog); 22 if (old_prog) 23 bpf_prog_put(old_prog); 24 25 return 0; 26 } 27 28 int lan966x_xdp(struct net_device *dev, struct netdev_bpf *xdp) 29 { 30 switch (xdp->command) { 31 case XDP_SETUP_PROG: 32 return lan966x_xdp_setup(dev, xdp); 33 default: 34 return -EINVAL; 35 } 36 } 37 38 int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len) 39 { 40 struct bpf_prog *xdp_prog = port->xdp_prog; 41 struct lan966x *lan966x = port->lan966x; 42 struct xdp_buff xdp; 43 u32 act; 44 45 xdp_init_buff(&xdp, PAGE_SIZE << lan966x->rx.page_order, 46 &port->xdp_rxq); 47 xdp_prepare_buff(&xdp, page_address(page), IFH_LEN_BYTES, 48 data_len - IFH_LEN_BYTES, false); 49 act = bpf_prog_run_xdp(xdp_prog, &xdp); 50 switch (act) { 51 case XDP_PASS: 52 return FDMA_PASS; 53 default: 54 bpf_warn_invalid_xdp_action(port->dev, xdp_prog, act); 55 fallthrough; 56 case XDP_ABORTED: 57 trace_xdp_exception(port->dev, xdp_prog, act); 58 fallthrough; 59 case XDP_DROP: 60 return FDMA_DROP; 61 } 62 } 63 64 int lan966x_xdp_port_init(struct lan966x_port *port) 65 { 66 struct lan966x *lan966x = port->lan966x; 67 68 return xdp_rxq_info_reg(&port->xdp_rxq, port->dev, 0, 69 lan966x->napi.napi_id); 70 } 71 72 void lan966x_xdp_port_deinit(struct lan966x_port *port) 73 { 74 if (xdp_rxq_info_is_reg(&port->xdp_rxq)) 75 xdp_rxq_info_unreg(&port->xdp_rxq); 76 } 77