Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
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     /* In case of success just return and notify the SW that doesn't need
0019      * to do anything
0020      */
0021     if (!err)
0022         return BR_MRP_HW;
0023 
0024     if (err != -EOPNOTSUPP)
0025         return BR_MRP_NONE;
0026 
0027     /* Continue with SW backup */
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     /* If the driver can't configure to run completely the protocol in HW,
0087      * then try again to configure the HW so the SW can run the protocol.
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     /* If the driver can't configure to run completely the protocol in HW,
0165      * then try again to configure the HW so the SW can run the protocol.
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 }