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