105821b53020b8d9af9759b52b3d4ba23450ddc9
[linux-2.6-microblaze.git] / drivers / net / ethernet / stmicro / stmmac / stmmac_xdp.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021, Intel Corporation. */
3
4 #include <net/xdp_sock_drv.h>
5
6 #include "stmmac.h"
7 #include "stmmac_xdp.h"
8
9 static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
10                                   struct xsk_buff_pool *pool, u16 queue)
11 {
12         struct stmmac_channel *ch = &priv->channel[queue];
13         bool need_update;
14         u32 frame_size;
15         int err;
16
17         if (queue >= priv->plat->rx_queues_to_use ||
18             queue >= priv->plat->tx_queues_to_use)
19                 return -EINVAL;
20
21         frame_size = xsk_pool_get_rx_frame_size(pool);
22         /* XDP ZC does not span multiple frame, make sure XSK pool buffer
23          * size can at least store Q-in-Q frame.
24          */
25         if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2)
26                 return -EOPNOTSUPP;
27
28         err = xsk_pool_dma_map(pool, priv->device, STMMAC_RX_DMA_ATTR);
29         if (err) {
30                 netdev_err(priv->dev, "Failed to map xsk pool\n");
31                 return err;
32         }
33
34         need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
35
36         if (need_update) {
37                 stmmac_disable_rx_queue(priv, queue);
38                 stmmac_disable_tx_queue(priv, queue);
39                 napi_disable(&ch->rx_napi);
40                 napi_disable(&ch->tx_napi);
41         }
42
43         set_bit(queue, priv->af_xdp_zc_qps);
44
45         if (need_update) {
46                 napi_enable(&ch->rxtx_napi);
47                 stmmac_enable_rx_queue(priv, queue);
48                 stmmac_enable_tx_queue(priv, queue);
49
50                 err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
51                 if (err)
52                         return err;
53         }
54
55         return 0;
56 }
57
58 static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
59 {
60         struct stmmac_channel *ch = &priv->channel[queue];
61         struct xsk_buff_pool *pool;
62         bool need_update;
63
64         if (queue >= priv->plat->rx_queues_to_use ||
65             queue >= priv->plat->tx_queues_to_use)
66                 return -EINVAL;
67
68         pool = xsk_get_pool_from_qid(priv->dev, queue);
69         if (!pool)
70                 return -EINVAL;
71
72         need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
73
74         if (need_update) {
75                 stmmac_disable_rx_queue(priv, queue);
76                 stmmac_disable_tx_queue(priv, queue);
77                 synchronize_rcu();
78                 napi_disable(&ch->rxtx_napi);
79         }
80
81         xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);
82
83         clear_bit(queue, priv->af_xdp_zc_qps);
84
85         if (need_update) {
86                 napi_enable(&ch->rx_napi);
87                 napi_enable(&ch->tx_napi);
88                 stmmac_enable_rx_queue(priv, queue);
89                 stmmac_enable_tx_queue(priv, queue);
90         }
91
92         return 0;
93 }
94
95 int stmmac_xdp_setup_pool(struct stmmac_priv *priv, struct xsk_buff_pool *pool,
96                           u16 queue)
97 {
98         return pool ? stmmac_xdp_enable_pool(priv, pool, queue) :
99                       stmmac_xdp_disable_pool(priv, queue);
100 }
101
102 int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog,
103                         struct netlink_ext_ack *extack)
104 {
105         struct net_device *dev = priv->dev;
106         struct bpf_prog *old_prog;
107         bool need_update;
108         bool if_running;
109
110         if_running = netif_running(dev);
111
112         if (prog && dev->mtu > ETH_DATA_LEN) {
113                 /* For now, the driver doesn't support XDP functionality with
114                  * jumbo frames so we return error.
115                  */
116                 NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
117                 return -EOPNOTSUPP;
118         }
119
120         need_update = !!priv->xdp_prog != !!prog;
121         if (if_running && need_update)
122                 stmmac_release(dev);
123
124         old_prog = xchg(&priv->xdp_prog, prog);
125         if (old_prog)
126                 bpf_prog_put(old_prog);
127
128         /* Disable RX SPH for XDP operation */
129         priv->sph = priv->sph_cap && !stmmac_xdp_is_enabled(priv);
130
131         if (if_running && need_update)
132                 stmmac_open(dev);
133
134         return 0;
135 }