Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/bridge/br_mrp_switchdev.c
26288 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#include <net/switchdev.h>
4
5
#include "br_private_mrp.h"
6
7
static enum br_mrp_hw_support
8
br_mrp_switchdev_port_obj(struct net_bridge *br,
9
const struct switchdev_obj *obj, bool add)
10
{
11
int err;
12
13
if (add)
14
err = switchdev_port_obj_add(br->dev, obj, NULL);
15
else
16
err = switchdev_port_obj_del(br->dev, obj);
17
18
/* In case of success just return and notify the SW that doesn't need
19
* to do anything
20
*/
21
if (!err)
22
return BR_MRP_HW;
23
24
if (err != -EOPNOTSUPP)
25
return BR_MRP_NONE;
26
27
/* Continue with SW backup */
28
return BR_MRP_SW;
29
}
30
31
int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
32
{
33
struct switchdev_obj_mrp mrp_obj = {
34
.obj.orig_dev = br->dev,
35
.obj.id = SWITCHDEV_OBJ_ID_MRP,
36
.p_port = rtnl_dereference(mrp->p_port)->dev,
37
.s_port = rtnl_dereference(mrp->s_port)->dev,
38
.ring_id = mrp->ring_id,
39
.prio = mrp->prio,
40
};
41
42
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
43
return 0;
44
45
return switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
46
}
47
48
int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
49
{
50
struct switchdev_obj_mrp mrp_obj = {
51
.obj.orig_dev = br->dev,
52
.obj.id = SWITCHDEV_OBJ_ID_MRP,
53
.p_port = NULL,
54
.s_port = NULL,
55
.ring_id = mrp->ring_id,
56
};
57
58
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
59
return 0;
60
61
return switchdev_port_obj_del(br->dev, &mrp_obj.obj);
62
}
63
64
enum br_mrp_hw_support
65
br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
66
enum br_mrp_ring_role_type role)
67
{
68
struct switchdev_obj_ring_role_mrp mrp_role = {
69
.obj.orig_dev = br->dev,
70
.obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
71
.ring_role = role,
72
.ring_id = mrp->ring_id,
73
.sw_backup = false,
74
};
75
enum br_mrp_hw_support support;
76
int err;
77
78
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
79
return BR_MRP_SW;
80
81
support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
82
role != BR_MRP_RING_ROLE_DISABLED);
83
if (support != BR_MRP_SW)
84
return support;
85
86
/* If the driver can't configure to run completely the protocol in HW,
87
* then try again to configure the HW so the SW can run the protocol.
88
*/
89
mrp_role.sw_backup = true;
90
if (role != BR_MRP_RING_ROLE_DISABLED)
91
err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
92
else
93
err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
94
95
if (!err)
96
return BR_MRP_SW;
97
98
return BR_MRP_NONE;
99
}
100
101
enum br_mrp_hw_support
102
br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
103
u32 interval, u8 max_miss, u32 period,
104
bool monitor)
105
{
106
struct switchdev_obj_ring_test_mrp test = {
107
.obj.orig_dev = br->dev,
108
.obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
109
.interval = interval,
110
.max_miss = max_miss,
111
.ring_id = mrp->ring_id,
112
.period = period,
113
.monitor = monitor,
114
};
115
116
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
117
return BR_MRP_SW;
118
119
return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
120
}
121
122
int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
123
struct br_mrp *mrp,
124
enum br_mrp_ring_state_type state)
125
{
126
struct switchdev_obj_ring_state_mrp mrp_state = {
127
.obj.orig_dev = br->dev,
128
.obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
129
.ring_state = state,
130
.ring_id = mrp->ring_id,
131
};
132
133
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
134
return 0;
135
136
return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
137
}
138
139
enum br_mrp_hw_support
140
br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
141
u16 in_id, u32 ring_id,
142
enum br_mrp_in_role_type role)
143
{
144
struct switchdev_obj_in_role_mrp mrp_role = {
145
.obj.orig_dev = br->dev,
146
.obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
147
.in_role = role,
148
.in_id = mrp->in_id,
149
.ring_id = mrp->ring_id,
150
.i_port = rtnl_dereference(mrp->i_port)->dev,
151
.sw_backup = false,
152
};
153
enum br_mrp_hw_support support;
154
int err;
155
156
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
157
return BR_MRP_SW;
158
159
support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
160
role != BR_MRP_IN_ROLE_DISABLED);
161
if (support != BR_MRP_NONE)
162
return support;
163
164
/* If the driver can't configure to run completely the protocol in HW,
165
* then try again to configure the HW so the SW can run the protocol.
166
*/
167
mrp_role.sw_backup = true;
168
if (role != BR_MRP_IN_ROLE_DISABLED)
169
err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
170
else
171
err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
172
173
if (!err)
174
return BR_MRP_SW;
175
176
return BR_MRP_NONE;
177
}
178
179
int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
180
enum br_mrp_in_state_type state)
181
{
182
struct switchdev_obj_in_state_mrp mrp_state = {
183
.obj.orig_dev = br->dev,
184
.obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
185
.in_state = state,
186
.in_id = mrp->in_id,
187
};
188
189
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
190
return 0;
191
192
return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
193
}
194
195
enum br_mrp_hw_support
196
br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
197
u32 interval, u8 max_miss, u32 period)
198
{
199
struct switchdev_obj_in_test_mrp test = {
200
.obj.orig_dev = br->dev,
201
.obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
202
.interval = interval,
203
.max_miss = max_miss,
204
.in_id = mrp->in_id,
205
.period = period,
206
};
207
208
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
209
return BR_MRP_SW;
210
211
return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
212
}
213
214
int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
215
{
216
struct switchdev_attr attr = {
217
.orig_dev = p->dev,
218
.id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
219
.u.stp_state = state,
220
};
221
222
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
223
return 0;
224
225
return switchdev_port_attr_set(p->dev, &attr, NULL);
226
}
227
228
int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
229
enum br_mrp_port_role_type role)
230
{
231
struct switchdev_attr attr = {
232
.orig_dev = p->dev,
233
.id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
234
.u.mrp_port_role = role,
235
};
236
237
if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
238
return 0;
239
240
return switchdev_port_attr_set(p->dev, &attr, NULL);
241
}
242
243