Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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}