linux/net/bridge/br_mrp_switchdev.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2
   3#include <net/switchdev.h>
   4
   5#include "br_private_mrp.h"
   6
   7static enum br_mrp_hw_support
   8br_mrp_switchdev_port_obj(struct net_bridge *br,
   9                          const struct switchdev_obj *obj, bool add)
  10{
  11        int err;
  12
  13        if (add)
  14                err = switchdev_port_obj_add(br->dev, obj, NULL);
  15        else
  16                err = switchdev_port_obj_del(br->dev, obj);
  17
  18        /* In case of success just return and notify the SW that doesn't need
  19         * to do anything
  20         */
  21        if (!err)
  22                return BR_MRP_HW;
  23
  24        if (err != -EOPNOTSUPP)
  25                return BR_MRP_NONE;
  26
  27        /* Continue with SW backup */
  28        return BR_MRP_SW;
  29}
  30
  31int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
  32{
  33        struct switchdev_obj_mrp mrp_obj = {
  34                .obj.orig_dev = br->dev,
  35                .obj.id = SWITCHDEV_OBJ_ID_MRP,
  36                .p_port = rtnl_dereference(mrp->p_port)->dev,
  37                .s_port = rtnl_dereference(mrp->s_port)->dev,
  38                .ring_id = mrp->ring_id,
  39                .prio = mrp->prio,
  40        };
  41
  42        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  43                return 0;
  44
  45        return switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
  46}
  47
  48int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
  49{
  50        struct switchdev_obj_mrp mrp_obj = {
  51                .obj.orig_dev = br->dev,
  52                .obj.id = SWITCHDEV_OBJ_ID_MRP,
  53                .p_port = NULL,
  54                .s_port = NULL,
  55                .ring_id = mrp->ring_id,
  56        };
  57
  58        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  59                return 0;
  60
  61        return switchdev_port_obj_del(br->dev, &mrp_obj.obj);
  62}
  63
  64enum br_mrp_hw_support
  65br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
  66                               enum br_mrp_ring_role_type role)
  67{
  68        struct switchdev_obj_ring_role_mrp mrp_role = {
  69                .obj.orig_dev = br->dev,
  70                .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
  71                .ring_role = role,
  72                .ring_id = mrp->ring_id,
  73                .sw_backup = false,
  74        };
  75        enum br_mrp_hw_support support;
  76        int err;
  77
  78        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
  79                return BR_MRP_SW;
  80
  81        support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
  82                                            role != BR_MRP_RING_ROLE_DISABLED);
  83        if (support != BR_MRP_SW)
  84                return support;
  85
  86        /* If the driver can't configure to run completely the protocol in HW,
  87         * then try again to configure the HW so the SW can run the protocol.
  88         */
  89        mrp_role.sw_backup = true;
  90        if (role != BR_MRP_RING_ROLE_DISABLED)
  91                err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
  92        else
  93                err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
  94
  95        if (!err)
  96                return BR_MRP_SW;
  97
  98        return BR_MRP_NONE;
  99}
 100
 101enum br_mrp_hw_support
 102br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
 103                                u32 interval, u8 max_miss, u32 period,
 104                                bool monitor)
 105{
 106        struct switchdev_obj_ring_test_mrp test = {
 107                .obj.orig_dev = br->dev,
 108                .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
 109                .interval = interval,
 110                .max_miss = max_miss,
 111                .ring_id = mrp->ring_id,
 112                .period = period,
 113                .monitor = monitor,
 114        };
 115
 116        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 117                return BR_MRP_SW;
 118
 119        return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
 120}
 121
 122int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
 123                                    struct br_mrp *mrp,
 124                                    enum br_mrp_ring_state_type state)
 125{
 126        struct switchdev_obj_ring_state_mrp mrp_state = {
 127                .obj.orig_dev = br->dev,
 128                .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
 129                .ring_state = state,
 130                .ring_id = mrp->ring_id,
 131        };
 132
 133        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 134                return 0;
 135
 136        return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
 137}
 138
 139enum br_mrp_hw_support
 140br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
 141                             u16 in_id, u32 ring_id,
 142                             enum br_mrp_in_role_type role)
 143{
 144        struct switchdev_obj_in_role_mrp mrp_role = {
 145                .obj.orig_dev = br->dev,
 146                .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
 147                .in_role = role,
 148                .in_id = mrp->in_id,
 149                .ring_id = mrp->ring_id,
 150                .i_port = rtnl_dereference(mrp->i_port)->dev,
 151                .sw_backup = false,
 152        };
 153        enum br_mrp_hw_support support;
 154        int err;
 155
 156        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 157                return BR_MRP_SW;
 158
 159        support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
 160                                            role != BR_MRP_IN_ROLE_DISABLED);
 161        if (support != BR_MRP_NONE)
 162                return support;
 163
 164        /* If the driver can't configure to run completely the protocol in HW,
 165         * then try again to configure the HW so the SW can run the protocol.
 166         */
 167        mrp_role.sw_backup = true;
 168        if (role != BR_MRP_IN_ROLE_DISABLED)
 169                err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
 170        else
 171                err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
 172
 173        if (!err)
 174                return BR_MRP_SW;
 175
 176        return BR_MRP_NONE;
 177}
 178
 179int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
 180                                  enum br_mrp_in_state_type state)
 181{
 182        struct switchdev_obj_in_state_mrp mrp_state = {
 183                .obj.orig_dev = br->dev,
 184                .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
 185                .in_state = state,
 186                .in_id = mrp->in_id,
 187        };
 188
 189        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 190                return 0;
 191
 192        return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
 193}
 194
 195enum br_mrp_hw_support
 196br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
 197                              u32 interval, u8 max_miss, u32 period)
 198{
 199        struct switchdev_obj_in_test_mrp test = {
 200                .obj.orig_dev = br->dev,
 201                .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
 202                .interval = interval,
 203                .max_miss = max_miss,
 204                .in_id = mrp->in_id,
 205                .period = period,
 206        };
 207
 208        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 209                return BR_MRP_SW;
 210
 211        return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
 212}
 213
 214int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
 215{
 216        struct switchdev_attr attr = {
 217                .orig_dev = p->dev,
 218                .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
 219                .u.stp_state = state,
 220        };
 221
 222        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 223                return 0;
 224
 225        return switchdev_port_attr_set(p->dev, &attr, NULL);
 226}
 227
 228int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
 229                                   enum br_mrp_port_role_type role)
 230{
 231        struct switchdev_attr attr = {
 232                .orig_dev = p->dev,
 233                .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
 234                .u.mrp_port_role = role,
 235        };
 236
 237        if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
 238                return 0;
 239
 240        return switchdev_port_attr_set(p->dev, &attr, NULL);
 241}
 242