xref: /linux/net/bridge/br_mrp_switchdev.c (revision 40e79150c1686263e6a031d7702aec63aff31332)
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 	};
16 	int err;
17 
18 	err = switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
19 
20 	if (err && err != -EOPNOTSUPP)
21 		return err;
22 
23 	return 0;
24 }
25 
26 int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
27 {
28 	struct switchdev_obj_mrp mrp_obj = {
29 		.obj.orig_dev = br->dev,
30 		.obj.id = SWITCHDEV_OBJ_ID_MRP,
31 		.p_port = NULL,
32 		.s_port = NULL,
33 		.ring_id = mrp->ring_id,
34 	};
35 	int err;
36 
37 	err = switchdev_port_obj_del(br->dev, &mrp_obj.obj);
38 
39 	if (err && err != -EOPNOTSUPP)
40 		return err;
41 
42 	return 0;
43 }
44 
45 int br_mrp_switchdev_set_ring_role(struct net_bridge *br,
46 				   struct br_mrp *mrp,
47 				   enum br_mrp_ring_role_type role)
48 {
49 	struct switchdev_obj_ring_role_mrp mrp_role = {
50 		.obj.orig_dev = br->dev,
51 		.obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
52 		.ring_role = role,
53 		.ring_id = mrp->ring_id,
54 	};
55 	int err;
56 
57 	if (role == BR_MRP_RING_ROLE_DISABLED)
58 		err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
59 	else
60 		err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
61 
62 	return err;
63 }
64 
65 int br_mrp_switchdev_send_ring_test(struct net_bridge *br,
66 				    struct br_mrp *mrp, u32 interval,
67 				    u8 max_miss, u32 period)
68 {
69 	struct switchdev_obj_ring_test_mrp test = {
70 		.obj.orig_dev = br->dev,
71 		.obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
72 		.interval = interval,
73 		.max_miss = max_miss,
74 		.ring_id = mrp->ring_id,
75 		.period = period,
76 	};
77 	int err;
78 
79 	if (interval == 0)
80 		err = switchdev_port_obj_del(br->dev, &test.obj);
81 	else
82 		err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
83 
84 	return err;
85 }
86 
87 int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
88 				    struct br_mrp *mrp,
89 				    enum br_mrp_ring_state_type state)
90 {
91 	struct switchdev_obj_ring_state_mrp mrp_state = {
92 		.obj.orig_dev = br->dev,
93 		.obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
94 		.ring_state = state,
95 		.ring_id = mrp->ring_id,
96 	};
97 	int err;
98 
99 	err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
100 
101 	if (err && err != -EOPNOTSUPP)
102 		return err;
103 
104 	return 0;
105 }
106 
107 int br_mrp_port_switchdev_set_state(struct net_bridge_port *p,
108 				    enum br_mrp_port_state_type state)
109 {
110 	struct switchdev_attr attr = {
111 		.orig_dev = p->dev,
112 		.id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE,
113 		.u.mrp_port_state = state,
114 	};
115 	int err;
116 
117 	err = switchdev_port_attr_set(p->dev, &attr);
118 	if (err && err != -EOPNOTSUPP)
119 		br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
120 			(unsigned int)p->port_no, p->dev->name);
121 
122 	return err;
123 }
124 
125 int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
126 				   enum br_mrp_port_role_type role)
127 {
128 	struct switchdev_attr attr = {
129 		.orig_dev = p->dev,
130 		.id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
131 		.u.mrp_port_role = role,
132 	};
133 	int err;
134 
135 	err = switchdev_port_attr_set(p->dev, &attr);
136 	if (err && err != -EOPNOTSUPP)
137 		return err;
138 
139 	return 0;
140 }
141