0001
0002
0003 #include <net/switchdev.h>
0004
0005 #include "br_private_mrp.h"
0006
0007 static enum br_mrp_hw_support
0008 br_mrp_switchdev_port_obj(struct net_bridge *br,
0009 const struct switchdev_obj *obj, bool add)
0010 {
0011 int err;
0012
0013 if (add)
0014 err = switchdev_port_obj_add(br->dev, obj, NULL);
0015 else
0016 err = switchdev_port_obj_del(br->dev, obj);
0017
0018
0019
0020
0021 if (!err)
0022 return BR_MRP_HW;
0023
0024 if (err != -EOPNOTSUPP)
0025 return BR_MRP_NONE;
0026
0027
0028 return BR_MRP_SW;
0029 }
0030
0031 int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
0032 {
0033 struct switchdev_obj_mrp mrp_obj = {
0034 .obj.orig_dev = br->dev,
0035 .obj.id = SWITCHDEV_OBJ_ID_MRP,
0036 .p_port = rtnl_dereference(mrp->p_port)->dev,
0037 .s_port = rtnl_dereference(mrp->s_port)->dev,
0038 .ring_id = mrp->ring_id,
0039 .prio = mrp->prio,
0040 };
0041
0042 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0043 return 0;
0044
0045 return switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
0046 }
0047
0048 int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
0049 {
0050 struct switchdev_obj_mrp mrp_obj = {
0051 .obj.orig_dev = br->dev,
0052 .obj.id = SWITCHDEV_OBJ_ID_MRP,
0053 .p_port = NULL,
0054 .s_port = NULL,
0055 .ring_id = mrp->ring_id,
0056 };
0057
0058 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0059 return 0;
0060
0061 return switchdev_port_obj_del(br->dev, &mrp_obj.obj);
0062 }
0063
0064 enum br_mrp_hw_support
0065 br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
0066 enum br_mrp_ring_role_type role)
0067 {
0068 struct switchdev_obj_ring_role_mrp mrp_role = {
0069 .obj.orig_dev = br->dev,
0070 .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
0071 .ring_role = role,
0072 .ring_id = mrp->ring_id,
0073 .sw_backup = false,
0074 };
0075 enum br_mrp_hw_support support;
0076 int err;
0077
0078 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0079 return BR_MRP_SW;
0080
0081 support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
0082 role != BR_MRP_RING_ROLE_DISABLED);
0083 if (support != BR_MRP_SW)
0084 return support;
0085
0086
0087
0088
0089 mrp_role.sw_backup = true;
0090 if (role != BR_MRP_RING_ROLE_DISABLED)
0091 err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
0092 else
0093 err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
0094
0095 if (!err)
0096 return BR_MRP_SW;
0097
0098 return BR_MRP_NONE;
0099 }
0100
0101 enum br_mrp_hw_support
0102 br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
0103 u32 interval, u8 max_miss, u32 period,
0104 bool monitor)
0105 {
0106 struct switchdev_obj_ring_test_mrp test = {
0107 .obj.orig_dev = br->dev,
0108 .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
0109 .interval = interval,
0110 .max_miss = max_miss,
0111 .ring_id = mrp->ring_id,
0112 .period = period,
0113 .monitor = monitor,
0114 };
0115
0116 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0117 return BR_MRP_SW;
0118
0119 return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
0120 }
0121
0122 int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
0123 struct br_mrp *mrp,
0124 enum br_mrp_ring_state_type state)
0125 {
0126 struct switchdev_obj_ring_state_mrp mrp_state = {
0127 .obj.orig_dev = br->dev,
0128 .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
0129 .ring_state = state,
0130 .ring_id = mrp->ring_id,
0131 };
0132
0133 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0134 return 0;
0135
0136 return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
0137 }
0138
0139 enum br_mrp_hw_support
0140 br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
0141 u16 in_id, u32 ring_id,
0142 enum br_mrp_in_role_type role)
0143 {
0144 struct switchdev_obj_in_role_mrp mrp_role = {
0145 .obj.orig_dev = br->dev,
0146 .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
0147 .in_role = role,
0148 .in_id = mrp->in_id,
0149 .ring_id = mrp->ring_id,
0150 .i_port = rtnl_dereference(mrp->i_port)->dev,
0151 .sw_backup = false,
0152 };
0153 enum br_mrp_hw_support support;
0154 int err;
0155
0156 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0157 return BR_MRP_SW;
0158
0159 support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
0160 role != BR_MRP_IN_ROLE_DISABLED);
0161 if (support != BR_MRP_NONE)
0162 return support;
0163
0164
0165
0166
0167 mrp_role.sw_backup = true;
0168 if (role != BR_MRP_IN_ROLE_DISABLED)
0169 err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
0170 else
0171 err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
0172
0173 if (!err)
0174 return BR_MRP_SW;
0175
0176 return BR_MRP_NONE;
0177 }
0178
0179 int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
0180 enum br_mrp_in_state_type state)
0181 {
0182 struct switchdev_obj_in_state_mrp mrp_state = {
0183 .obj.orig_dev = br->dev,
0184 .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
0185 .in_state = state,
0186 .in_id = mrp->in_id,
0187 };
0188
0189 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0190 return 0;
0191
0192 return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
0193 }
0194
0195 enum br_mrp_hw_support
0196 br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
0197 u32 interval, u8 max_miss, u32 period)
0198 {
0199 struct switchdev_obj_in_test_mrp test = {
0200 .obj.orig_dev = br->dev,
0201 .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
0202 .interval = interval,
0203 .max_miss = max_miss,
0204 .in_id = mrp->in_id,
0205 .period = period,
0206 };
0207
0208 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0209 return BR_MRP_SW;
0210
0211 return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
0212 }
0213
0214 int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
0215 {
0216 struct switchdev_attr attr = {
0217 .orig_dev = p->dev,
0218 .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
0219 .u.stp_state = state,
0220 };
0221
0222 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0223 return 0;
0224
0225 return switchdev_port_attr_set(p->dev, &attr, NULL);
0226 }
0227
0228 int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
0229 enum br_mrp_port_role_type role)
0230 {
0231 struct switchdev_attr attr = {
0232 .orig_dev = p->dev,
0233 .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
0234 .u.mrp_port_role = role,
0235 };
0236
0237 if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
0238 return 0;
0239
0240 return switchdev_port_attr_set(p->dev, &attr, NULL);
0241 }