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