1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2022 Gerhard Engleder <gerhard@engleder-embedded.com> */
3
4 #include <linux/if_vlan.h>
5 #include <net/xdp_sock_drv.h>
6
7 #include "tsnep.h"
8
tsnep_xdp_setup_prog(struct tsnep_adapter * adapter,struct bpf_prog * prog,struct netlink_ext_ack * extack)9 int tsnep_xdp_setup_prog(struct tsnep_adapter *adapter, struct bpf_prog *prog,
10 struct netlink_ext_ack *extack)
11 {
12 struct bpf_prog *old_prog;
13
14 old_prog = xchg(&adapter->xdp_prog, prog);
15 if (old_prog)
16 bpf_prog_put(old_prog);
17
18 return 0;
19 }
20
tsnep_xdp_enable_pool(struct tsnep_adapter * adapter,struct xsk_buff_pool * pool,u16 queue_id)21 static int tsnep_xdp_enable_pool(struct tsnep_adapter *adapter,
22 struct xsk_buff_pool *pool, u16 queue_id)
23 {
24 struct tsnep_queue *queue;
25 int retval;
26
27 if (queue_id >= adapter->num_rx_queues ||
28 queue_id >= adapter->num_tx_queues)
29 return -EINVAL;
30
31 queue = &adapter->queue[queue_id];
32 if (queue->rx->queue_index != queue_id ||
33 queue->tx->queue_index != queue_id) {
34 netdev_err(adapter->netdev,
35 "XSK support only for TX/RX queue pairs\n");
36
37 return -EOPNOTSUPP;
38 }
39
40 retval = xsk_pool_dma_map(pool, adapter->dmadev,
41 DMA_ATTR_SKIP_CPU_SYNC);
42 if (retval) {
43 netdev_err(adapter->netdev, "failed to map XSK pool\n");
44
45 return retval;
46 }
47
48 retval = tsnep_enable_xsk(queue, pool);
49 if (retval) {
50 xsk_pool_dma_unmap(pool, DMA_ATTR_SKIP_CPU_SYNC);
51
52 return retval;
53 }
54
55 return 0;
56 }
57
tsnep_xdp_disable_pool(struct tsnep_adapter * adapter,u16 queue_id)58 static int tsnep_xdp_disable_pool(struct tsnep_adapter *adapter, u16 queue_id)
59 {
60 struct xsk_buff_pool *pool;
61 struct tsnep_queue *queue;
62
63 if (queue_id >= adapter->num_rx_queues ||
64 queue_id >= adapter->num_tx_queues)
65 return -EINVAL;
66
67 pool = xsk_get_pool_from_qid(adapter->netdev, queue_id);
68 if (!pool)
69 return -EINVAL;
70
71 queue = &adapter->queue[queue_id];
72
73 tsnep_disable_xsk(queue);
74
75 xsk_pool_dma_unmap(pool, DMA_ATTR_SKIP_CPU_SYNC);
76
77 return 0;
78 }
79
tsnep_xdp_setup_pool(struct tsnep_adapter * adapter,struct xsk_buff_pool * pool,u16 queue_id)80 int tsnep_xdp_setup_pool(struct tsnep_adapter *adapter,
81 struct xsk_buff_pool *pool, u16 queue_id)
82 {
83 return pool ? tsnep_xdp_enable_pool(adapter, pool, queue_id) :
84 tsnep_xdp_disable_pool(adapter, queue_id);
85 }
86