bridge: switchdev: mrp: Implement MRP API for switchdev
[linux-block.git] / net / bridge / br_mrp_switchdev.c
CommitLineData
fadd4091
HV
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <net/switchdev.h>
4
5#include "br_private_mrp.h"
6
7int 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
26int 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
45int 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
65int 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
87int 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
107int 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
125int 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}