Merge tag 'gpio-v5.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-2.6-microblaze.git] / net / bridge / br_mrp_switchdev.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <net/switchdev.h>
4
5 #include "br_private_mrp.h"
6
7 int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
8 {
9         struct switchdev_obj_mrp mrp_obj = {
10                 .obj.orig_dev = br->dev,
11                 .obj.id = SWITCHDEV_OBJ_ID_MRP,
12                 .p_port = rtnl_dereference(mrp->p_port)->dev,
13                 .s_port = rtnl_dereference(mrp->s_port)->dev,
14                 .ring_id = mrp->ring_id,
15                 .prio = mrp->prio,
16         };
17         int err;
18
19         err = switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
20
21         if (err && err != -EOPNOTSUPP)
22                 return err;
23
24         return 0;
25 }
26
27 int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
28 {
29         struct switchdev_obj_mrp mrp_obj = {
30                 .obj.orig_dev = br->dev,
31                 .obj.id = SWITCHDEV_OBJ_ID_MRP,
32                 .p_port = NULL,
33                 .s_port = NULL,
34                 .ring_id = mrp->ring_id,
35         };
36         int err;
37
38         err = switchdev_port_obj_del(br->dev, &mrp_obj.obj);
39
40         if (err && err != -EOPNOTSUPP)
41                 return err;
42
43         return 0;
44 }
45
46 int br_mrp_switchdev_set_ring_role(struct net_bridge *br,
47                                    struct br_mrp *mrp,
48                                    enum br_mrp_ring_role_type role)
49 {
50         struct switchdev_obj_ring_role_mrp mrp_role = {
51                 .obj.orig_dev = br->dev,
52                 .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
53                 .ring_role = role,
54                 .ring_id = mrp->ring_id,
55         };
56         int err;
57
58         if (role == BR_MRP_RING_ROLE_DISABLED)
59                 err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
60         else
61                 err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
62
63         return err;
64 }
65
66 int br_mrp_switchdev_send_ring_test(struct net_bridge *br,
67                                     struct br_mrp *mrp, u32 interval,
68                                     u8 max_miss, u32 period,
69                                     bool monitor)
70 {
71         struct switchdev_obj_ring_test_mrp test = {
72                 .obj.orig_dev = br->dev,
73                 .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
74                 .interval = interval,
75                 .max_miss = max_miss,
76                 .ring_id = mrp->ring_id,
77                 .period = period,
78                 .monitor = monitor,
79         };
80         int err;
81
82         if (interval == 0)
83                 err = switchdev_port_obj_del(br->dev, &test.obj);
84         else
85                 err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
86
87         return err;
88 }
89
90 int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
91                                     struct br_mrp *mrp,
92                                     enum br_mrp_ring_state_type state)
93 {
94         struct switchdev_obj_ring_state_mrp mrp_state = {
95                 .obj.orig_dev = br->dev,
96                 .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
97                 .ring_state = state,
98                 .ring_id = mrp->ring_id,
99         };
100         int err;
101
102         err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
103
104         if (err && err != -EOPNOTSUPP)
105                 return err;
106
107         return 0;
108 }
109
110 int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
111                                  u16 in_id, u32 ring_id,
112                                  enum br_mrp_in_role_type role)
113 {
114         struct switchdev_obj_in_role_mrp mrp_role = {
115                 .obj.orig_dev = br->dev,
116                 .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
117                 .in_role = role,
118                 .in_id = mrp->in_id,
119                 .ring_id = mrp->ring_id,
120                 .i_port = rtnl_dereference(mrp->i_port)->dev,
121         };
122         int err;
123
124         if (role == BR_MRP_IN_ROLE_DISABLED)
125                 err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
126         else
127                 err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
128
129         return err;
130 }
131
132 int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
133                                   enum br_mrp_in_state_type state)
134 {
135         struct switchdev_obj_in_state_mrp mrp_state = {
136                 .obj.orig_dev = br->dev,
137                 .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
138                 .in_state = state,
139                 .in_id = mrp->in_id,
140         };
141         int err;
142
143         err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
144
145         if (err && err != -EOPNOTSUPP)
146                 return err;
147
148         return 0;
149 }
150
151 int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
152                                   u32 interval, u8 max_miss, u32 period)
153 {
154         struct switchdev_obj_in_test_mrp test = {
155                 .obj.orig_dev = br->dev,
156                 .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
157                 .interval = interval,
158                 .max_miss = max_miss,
159                 .in_id = mrp->in_id,
160                 .period = period,
161         };
162         int err;
163
164         if (interval == 0)
165                 err = switchdev_port_obj_del(br->dev, &test.obj);
166         else
167                 err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
168
169         return err;
170 }
171
172 int br_mrp_port_switchdev_set_state(struct net_bridge_port *p,
173                                     enum br_mrp_port_state_type state)
174 {
175         struct switchdev_attr attr = {
176                 .orig_dev = p->dev,
177                 .id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE,
178                 .u.mrp_port_state = state,
179         };
180         int err;
181
182         err = switchdev_port_attr_set(p->dev, &attr);
183         if (err && err != -EOPNOTSUPP)
184                 br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
185                         (unsigned int)p->port_no, p->dev->name);
186
187         return err;
188 }
189
190 int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
191                                    enum br_mrp_port_role_type role)
192 {
193         struct switchdev_attr attr = {
194                 .orig_dev = p->dev,
195                 .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
196                 .u.mrp_port_role = role,
197         };
198         int err;
199
200         err = switchdev_port_attr_set(p->dev, &attr);
201         if (err && err != -EOPNOTSUPP)
202                 return err;
203
204         return 0;
205 }