diff options
Diffstat (limited to 'net/core/xdp.c')
-rw-r--r-- | net/core/xdp.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/net/core/xdp.c b/net/core/xdp.c new file mode 100644 index 000000000000..097a0f74e004 --- /dev/null +++ b/net/core/xdp.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* net/core/xdp.c | ||
2 | * | ||
3 | * Copyright (c) 2017 Jesper Dangaard Brouer, Red Hat Inc. | ||
4 | * Released under terms in GPL version 2. See COPYING. | ||
5 | */ | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/mm.h> | ||
8 | |||
9 | #include <net/xdp.h> | ||
10 | |||
11 | #define REG_STATE_NEW 0x0 | ||
12 | #define REG_STATE_REGISTERED 0x1 | ||
13 | #define REG_STATE_UNREGISTERED 0x2 | ||
14 | #define REG_STATE_UNUSED 0x3 | ||
15 | |||
16 | void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq) | ||
17 | { | ||
18 | /* Simplify driver cleanup code paths, allow unreg "unused" */ | ||
19 | if (xdp_rxq->reg_state == REG_STATE_UNUSED) | ||
20 | return; | ||
21 | |||
22 | WARN(!(xdp_rxq->reg_state == REG_STATE_REGISTERED), "Driver BUG"); | ||
23 | |||
24 | xdp_rxq->reg_state = REG_STATE_UNREGISTERED; | ||
25 | xdp_rxq->dev = NULL; | ||
26 | } | ||
27 | EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg); | ||
28 | |||
29 | static void xdp_rxq_info_init(struct xdp_rxq_info *xdp_rxq) | ||
30 | { | ||
31 | memset(xdp_rxq, 0, sizeof(*xdp_rxq)); | ||
32 | } | ||
33 | |||
34 | /* Returns 0 on success, negative on failure */ | ||
35 | int xdp_rxq_info_reg(struct xdp_rxq_info *xdp_rxq, | ||
36 | struct net_device *dev, u32 queue_index) | ||
37 | { | ||
38 | if (xdp_rxq->reg_state == REG_STATE_UNUSED) { | ||
39 | WARN(1, "Driver promised not to register this"); | ||
40 | return -EINVAL; | ||
41 | } | ||
42 | |||
43 | if (xdp_rxq->reg_state == REG_STATE_REGISTERED) { | ||
44 | WARN(1, "Missing unregister, handled but fix driver"); | ||
45 | xdp_rxq_info_unreg(xdp_rxq); | ||
46 | } | ||
47 | |||
48 | if (!dev) { | ||
49 | WARN(1, "Missing net_device from driver"); | ||
50 | return -ENODEV; | ||
51 | } | ||
52 | |||
53 | /* State either UNREGISTERED or NEW */ | ||
54 | xdp_rxq_info_init(xdp_rxq); | ||
55 | xdp_rxq->dev = dev; | ||
56 | xdp_rxq->queue_index = queue_index; | ||
57 | |||
58 | xdp_rxq->reg_state = REG_STATE_REGISTERED; | ||
59 | return 0; | ||
60 | } | ||
61 | EXPORT_SYMBOL_GPL(xdp_rxq_info_reg); | ||
62 | |||
63 | void xdp_rxq_info_unused(struct xdp_rxq_info *xdp_rxq) | ||
64 | { | ||
65 | xdp_rxq->reg_state = REG_STATE_UNUSED; | ||
66 | } | ||
67 | EXPORT_SYMBOL_GPL(xdp_rxq_info_unused); | ||
68 | |||
69 | bool xdp_rxq_info_is_reg(struct xdp_rxq_info *xdp_rxq) | ||
70 | { | ||
71 | return (xdp_rxq->reg_state == REG_STATE_REGISTERED); | ||
72 | } | ||
73 | EXPORT_SYMBOL_GPL(xdp_rxq_info_is_reg); | ||