15fabb012SOng Boon Leong // SPDX-License-Identifier: GPL-2.0
25fabb012SOng Boon Leong /* Copyright (c) 2021, Intel Corporation. */
35fabb012SOng Boon Leong 
4bba2556eSOng Boon Leong #include <net/xdp_sock_drv.h>
5bba2556eSOng Boon Leong 
65fabb012SOng Boon Leong #include "stmmac.h"
75fabb012SOng Boon Leong #include "stmmac_xdp.h"
85fabb012SOng Boon Leong 
stmmac_xdp_enable_pool(struct stmmac_priv * priv,struct xsk_buff_pool * pool,u16 queue)9bba2556eSOng Boon Leong static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
10bba2556eSOng Boon Leong 				  struct xsk_buff_pool *pool, u16 queue)
11bba2556eSOng Boon Leong {
12bba2556eSOng Boon Leong 	struct stmmac_channel *ch = &priv->channel[queue];
13bba2556eSOng Boon Leong 	bool need_update;
14bba2556eSOng Boon Leong 	u32 frame_size;
15bba2556eSOng Boon Leong 	int err;
16bba2556eSOng Boon Leong 
17132c32eeSOng Boon Leong 	if (queue >= priv->plat->rx_queues_to_use ||
18132c32eeSOng Boon Leong 	    queue >= priv->plat->tx_queues_to_use)
19bba2556eSOng Boon Leong 		return -EINVAL;
20bba2556eSOng Boon Leong 
21bba2556eSOng Boon Leong 	frame_size = xsk_pool_get_rx_frame_size(pool);
22bba2556eSOng Boon Leong 	/* XDP ZC does not span multiple frame, make sure XSK pool buffer
23bba2556eSOng Boon Leong 	 * size can at least store Q-in-Q frame.
24bba2556eSOng Boon Leong 	 */
25bba2556eSOng Boon Leong 	if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2)
26bba2556eSOng Boon Leong 		return -EOPNOTSUPP;
27bba2556eSOng Boon Leong 
28bba2556eSOng Boon Leong 	err = xsk_pool_dma_map(pool, priv->device, STMMAC_RX_DMA_ATTR);
29bba2556eSOng Boon Leong 	if (err) {
30bba2556eSOng Boon Leong 		netdev_err(priv->dev, "Failed to map xsk pool\n");
31bba2556eSOng Boon Leong 		return err;
32bba2556eSOng Boon Leong 	}
33bba2556eSOng Boon Leong 
34bba2556eSOng Boon Leong 	need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
35bba2556eSOng Boon Leong 
36bba2556eSOng Boon Leong 	if (need_update) {
37bba2556eSOng Boon Leong 		napi_disable(&ch->rx_napi);
38132c32eeSOng Boon Leong 		napi_disable(&ch->tx_napi);
39a6451192SSong Yoong Siang 		stmmac_disable_rx_queue(priv, queue);
40a6451192SSong Yoong Siang 		stmmac_disable_tx_queue(priv, queue);
41bba2556eSOng Boon Leong 	}
42bba2556eSOng Boon Leong 
43bba2556eSOng Boon Leong 	set_bit(queue, priv->af_xdp_zc_qps);
44bba2556eSOng Boon Leong 
45bba2556eSOng Boon Leong 	if (need_update) {
46bba2556eSOng Boon Leong 		stmmac_enable_rx_queue(priv, queue);
47132c32eeSOng Boon Leong 		stmmac_enable_tx_queue(priv, queue);
48a6451192SSong Yoong Siang 		napi_enable(&ch->rxtx_napi);
49bba2556eSOng Boon Leong 
50bba2556eSOng Boon Leong 		err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
51bba2556eSOng Boon Leong 		if (err)
52bba2556eSOng Boon Leong 			return err;
53bba2556eSOng Boon Leong 	}
54bba2556eSOng Boon Leong 
55bba2556eSOng Boon Leong 	return 0;
56bba2556eSOng Boon Leong }
57bba2556eSOng Boon Leong 
stmmac_xdp_disable_pool(struct stmmac_priv * priv,u16 queue)58bba2556eSOng Boon Leong static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
59bba2556eSOng Boon Leong {
60bba2556eSOng Boon Leong 	struct stmmac_channel *ch = &priv->channel[queue];
61bba2556eSOng Boon Leong 	struct xsk_buff_pool *pool;
62bba2556eSOng Boon Leong 	bool need_update;
63bba2556eSOng Boon Leong 
64132c32eeSOng Boon Leong 	if (queue >= priv->plat->rx_queues_to_use ||
65132c32eeSOng Boon Leong 	    queue >= priv->plat->tx_queues_to_use)
66bba2556eSOng Boon Leong 		return -EINVAL;
67bba2556eSOng Boon Leong 
68bba2556eSOng Boon Leong 	pool = xsk_get_pool_from_qid(priv->dev, queue);
69bba2556eSOng Boon Leong 	if (!pool)
70bba2556eSOng Boon Leong 		return -EINVAL;
71bba2556eSOng Boon Leong 
72bba2556eSOng Boon Leong 	need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
73bba2556eSOng Boon Leong 
74bba2556eSOng Boon Leong 	if (need_update) {
75a6451192SSong Yoong Siang 		napi_disable(&ch->rxtx_napi);
76bba2556eSOng Boon Leong 		stmmac_disable_rx_queue(priv, queue);
77132c32eeSOng Boon Leong 		stmmac_disable_tx_queue(priv, queue);
78bba2556eSOng Boon Leong 		synchronize_rcu();
79bba2556eSOng Boon Leong 	}
80bba2556eSOng Boon Leong 
81bba2556eSOng Boon Leong 	xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);
82bba2556eSOng Boon Leong 
83bba2556eSOng Boon Leong 	clear_bit(queue, priv->af_xdp_zc_qps);
84bba2556eSOng Boon Leong 
85bba2556eSOng Boon Leong 	if (need_update) {
86bba2556eSOng Boon Leong 		stmmac_enable_rx_queue(priv, queue);
87132c32eeSOng Boon Leong 		stmmac_enable_tx_queue(priv, queue);
88a6451192SSong Yoong Siang 		napi_enable(&ch->rx_napi);
89a6451192SSong Yoong Siang 		napi_enable(&ch->tx_napi);
90bba2556eSOng Boon Leong 	}
91bba2556eSOng Boon Leong 
92bba2556eSOng Boon Leong 	return 0;
93bba2556eSOng Boon Leong }
94bba2556eSOng Boon Leong 
stmmac_xdp_setup_pool(struct stmmac_priv * priv,struct xsk_buff_pool * pool,u16 queue)95bba2556eSOng Boon Leong int stmmac_xdp_setup_pool(struct stmmac_priv *priv, struct xsk_buff_pool *pool,
96bba2556eSOng Boon Leong 			  u16 queue)
97bba2556eSOng Boon Leong {
98bba2556eSOng Boon Leong 	return pool ? stmmac_xdp_enable_pool(priv, pool, queue) :
99bba2556eSOng Boon Leong 		      stmmac_xdp_disable_pool(priv, queue);
100bba2556eSOng Boon Leong }
101bba2556eSOng Boon Leong 
stmmac_xdp_set_prog(struct stmmac_priv * priv,struct bpf_prog * prog,struct netlink_ext_ack * extack)1025fabb012SOng Boon Leong int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
1035fabb012SOng Boon Leong 			struct netlink_ext_ack *extack)
1045fabb012SOng Boon Leong {
1055fabb012SOng Boon Leong 	struct net_device *dev = priv->dev;
1065fabb012SOng Boon Leong 	struct bpf_prog *old_prog;
1075fabb012SOng Boon Leong 	bool need_update;
1085fabb012SOng Boon Leong 	bool if_running;
1095fabb012SOng Boon Leong 
1105fabb012SOng Boon Leong 	if_running = netif_running(dev);
1115fabb012SOng Boon Leong 
1125fabb012SOng Boon Leong 	if (prog && dev->mtu > ETH_DATA_LEN) {
1135fabb012SOng Boon Leong 		/* For now, the driver doesn't support XDP functionality with
1145fabb012SOng Boon Leong 		 * jumbo frames so we return error.
1155fabb012SOng Boon Leong 		 */
1165fabb012SOng Boon Leong 		NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
1175fabb012SOng Boon Leong 		return -EOPNOTSUPP;
1185fabb012SOng Boon Leong 	}
1195fabb012SOng Boon Leong 
120*ffb33221SWei Fang 	if (!prog)
121*ffb33221SWei Fang 		xdp_features_clear_redirect_target(dev);
122*ffb33221SWei Fang 
1235fabb012SOng Boon Leong 	need_update = !!priv->xdp_prog != !!prog;
1245fabb012SOng Boon Leong 	if (if_running && need_update)
125ac746c85SOng Boon Leong 		stmmac_xdp_release(dev);
1265fabb012SOng Boon Leong 
1275fabb012SOng Boon Leong 	old_prog = xchg(&priv->xdp_prog, prog);
1285fabb012SOng Boon Leong 	if (old_prog)
1295fabb012SOng Boon Leong 		bpf_prog_put(old_prog);
1305fabb012SOng Boon Leong 
1315fabb012SOng Boon Leong 	/* Disable RX SPH for XDP operation */
1325fabb012SOng Boon Leong 	priv->sph = priv->sph_cap && !stmmac_xdp_is_enabled(priv);
1335fabb012SOng Boon Leong 
1345fabb012SOng Boon Leong 	if (if_running && need_update)
135ac746c85SOng Boon Leong 		stmmac_xdp_open(dev);
1365fabb012SOng Boon Leong 
137*ffb33221SWei Fang 	if (prog)
138*ffb33221SWei Fang 		xdp_features_set_redirect_target(dev, false);
139*ffb33221SWei Fang 
1405fabb012SOng Boon Leong 	return 0;
1415fabb012SOng Boon Leong }
142