Merge tag 'tty-4.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[linux-2.6-microblaze.git] / net / core / xdp.c
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);