xref: /openbmc/linux/net/bridge/br_mrp_switchdev.c (revision 55fd7e02)
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_port_switchdev_set_state(struct net_bridge_port *p,
111 				    enum br_mrp_port_state_type state)
112 {
113 	struct switchdev_attr attr = {
114 		.orig_dev = p->dev,
115 		.id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE,
116 		.u.mrp_port_state = state,
117 	};
118 	int err;
119 
120 	err = switchdev_port_attr_set(p->dev, &attr);
121 	if (err && err != -EOPNOTSUPP)
122 		br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
123 			(unsigned int)p->port_no, p->dev->name);
124 
125 	return err;
126 }
127 
128 int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
129 				   enum br_mrp_port_role_type role)
130 {
131 	struct switchdev_attr attr = {
132 		.orig_dev = p->dev,
133 		.id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
134 		.u.mrp_port_role = role,
135 	};
136 	int err;
137 
138 	err = switchdev_port_attr_set(p->dev, &attr);
139 	if (err && err != -EOPNOTSUPP)
140 		return err;
141 
142 	return 0;
143 }
144