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_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp, 111 u16 in_id, u32 ring_id, 112 enum br_mrp_in_role_type role) 113 { 114 struct switchdev_obj_in_role_mrp mrp_role = { 115 .obj.orig_dev = br->dev, 116 .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP, 117 .in_role = role, 118 .in_id = mrp->in_id, 119 .ring_id = mrp->ring_id, 120 .i_port = rtnl_dereference(mrp->i_port)->dev, 121 }; 122 int err; 123 124 if (role == BR_MRP_IN_ROLE_DISABLED) 125 err = switchdev_port_obj_del(br->dev, &mrp_role.obj); 126 else 127 err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL); 128 129 return err; 130 } 131 132 int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp, 133 enum br_mrp_in_state_type state) 134 { 135 struct switchdev_obj_in_state_mrp mrp_state = { 136 .obj.orig_dev = br->dev, 137 .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP, 138 .in_state = state, 139 .in_id = mrp->in_id, 140 }; 141 int err; 142 143 err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL); 144 145 if (err && err != -EOPNOTSUPP) 146 return err; 147 148 return 0; 149 } 150 151 int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp, 152 u32 interval, u8 max_miss, u32 period) 153 { 154 struct switchdev_obj_in_test_mrp test = { 155 .obj.orig_dev = br->dev, 156 .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP, 157 .interval = interval, 158 .max_miss = max_miss, 159 .in_id = mrp->in_id, 160 .period = period, 161 }; 162 int err; 163 164 if (interval == 0) 165 err = switchdev_port_obj_del(br->dev, &test.obj); 166 else 167 err = switchdev_port_obj_add(br->dev, &test.obj, NULL); 168 169 return err; 170 } 171 172 int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, 173 enum br_mrp_port_state_type state) 174 { 175 struct switchdev_attr attr = { 176 .orig_dev = p->dev, 177 .id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE, 178 .u.mrp_port_state = state, 179 }; 180 int err; 181 182 err = switchdev_port_attr_set(p->dev, &attr); 183 if (err && err != -EOPNOTSUPP) 184 br_warn(p->br, "error setting offload MRP state on port %u(%s)\n", 185 (unsigned int)p->port_no, p->dev->name); 186 187 return err; 188 } 189 190 int br_mrp_port_switchdev_set_role(struct net_bridge_port *p, 191 enum br_mrp_port_role_type role) 192 { 193 struct switchdev_attr attr = { 194 .orig_dev = p->dev, 195 .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, 196 .u.mrp_port_role = role, 197 }; 198 int err; 199 200 err = switchdev_port_attr_set(p->dev, &attr); 201 if (err && err != -EOPNOTSUPP) 202 return err; 203 204 return 0; 205 } 206