brintos

brintos / linux-shallow public Read only

0
0
Text · 2.8 KiB · 9ee61db Raw
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