^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <net/switchdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include "br_private_mrp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) struct switchdev_obj_mrp mrp_obj = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) .obj.id = SWITCHDEV_OBJ_ID_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) .p_port = rtnl_dereference(mrp->p_port)->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) .s_port = rtnl_dereference(mrp->s_port)->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) .prio = mrp->prio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) err = switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct switchdev_obj_mrp mrp_obj = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .obj.id = SWITCHDEV_OBJ_ID_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .p_port = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) .s_port = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) err = switchdev_port_obj_del(br->dev, &mrp_obj.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int br_mrp_switchdev_set_ring_role(struct net_bridge *br,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct br_mrp *mrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) enum br_mrp_ring_role_type role)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct switchdev_obj_ring_role_mrp mrp_role = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .ring_role = role,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (role == BR_MRP_RING_ROLE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int br_mrp_switchdev_send_ring_test(struct net_bridge *br,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct br_mrp *mrp, u32 interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u8 max_miss, u32 period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) bool monitor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct switchdev_obj_ring_test_mrp test = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .interval = interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .max_miss = max_miss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .period = period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .monitor = monitor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (interval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) err = switchdev_port_obj_del(br->dev, &test.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct br_mrp *mrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) enum br_mrp_ring_state_type state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct switchdev_obj_ring_state_mrp mrp_state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .ring_state = state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u16 in_id, u32 ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) enum br_mrp_in_role_type role)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct switchdev_obj_in_role_mrp mrp_role = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .in_role = role,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .in_id = mrp->in_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .ring_id = mrp->ring_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .i_port = rtnl_dereference(mrp->i_port)->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (role == BR_MRP_IN_ROLE_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) enum br_mrp_in_state_type state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct switchdev_obj_in_state_mrp mrp_state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .in_state = state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .in_id = mrp->in_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u32 interval, u8 max_miss, u32 period)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct switchdev_obj_in_test_mrp test = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .obj.orig_dev = br->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .interval = interval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .max_miss = max_miss,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .in_id = mrp->in_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .period = period,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (interval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) err = switchdev_port_obj_del(br->dev, &test.obj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct switchdev_attr attr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .orig_dev = p->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .u.stp_state = state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) err = switchdev_port_attr_set(p->dev, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) (unsigned int)p->port_no, p->dev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) enum br_mrp_port_role_type role)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct switchdev_attr attr = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .orig_dev = p->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .u.mrp_port_role = role,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) err = switchdev_port_attr_set(p->dev, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (err && err != -EOPNOTSUPP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }