18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <net/switchdev.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include "br_private_mrp.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciint br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp) 88c2ecf20Sopenharmony_ci{ 98c2ecf20Sopenharmony_ci struct switchdev_obj_mrp mrp_obj = { 108c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 118c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_MRP, 128c2ecf20Sopenharmony_ci .p_port = rtnl_dereference(mrp->p_port)->dev, 138c2ecf20Sopenharmony_ci .s_port = rtnl_dereference(mrp->s_port)->dev, 148c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 158c2ecf20Sopenharmony_ci .prio = mrp->prio, 168c2ecf20Sopenharmony_ci }; 178c2ecf20Sopenharmony_ci int err; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL); 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 228c2ecf20Sopenharmony_ci return err; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci return 0; 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ciint br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct switchdev_obj_mrp mrp_obj = { 308c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 318c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_MRP, 328c2ecf20Sopenharmony_ci .p_port = NULL, 338c2ecf20Sopenharmony_ci .s_port = NULL, 348c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 358c2ecf20Sopenharmony_ci }; 368c2ecf20Sopenharmony_ci int err; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci err = switchdev_port_obj_del(br->dev, &mrp_obj.obj); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 418c2ecf20Sopenharmony_ci return err; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return 0; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ciint br_mrp_switchdev_set_ring_role(struct net_bridge *br, 478c2ecf20Sopenharmony_ci struct br_mrp *mrp, 488c2ecf20Sopenharmony_ci enum br_mrp_ring_role_type role) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct switchdev_obj_ring_role_mrp mrp_role = { 518c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 528c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP, 538c2ecf20Sopenharmony_ci .ring_role = role, 548c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 558c2ecf20Sopenharmony_ci }; 568c2ecf20Sopenharmony_ci int err; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (role == BR_MRP_RING_ROLE_DISABLED) 598c2ecf20Sopenharmony_ci err = switchdev_port_obj_del(br->dev, &mrp_role.obj); 608c2ecf20Sopenharmony_ci else 618c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return err; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciint br_mrp_switchdev_send_ring_test(struct net_bridge *br, 678c2ecf20Sopenharmony_ci struct br_mrp *mrp, u32 interval, 688c2ecf20Sopenharmony_ci u8 max_miss, u32 period, 698c2ecf20Sopenharmony_ci bool monitor) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct switchdev_obj_ring_test_mrp test = { 728c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 738c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_RING_TEST_MRP, 748c2ecf20Sopenharmony_ci .interval = interval, 758c2ecf20Sopenharmony_ci .max_miss = max_miss, 768c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 778c2ecf20Sopenharmony_ci .period = period, 788c2ecf20Sopenharmony_ci .monitor = monitor, 798c2ecf20Sopenharmony_ci }; 808c2ecf20Sopenharmony_ci int err; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (interval == 0) 838c2ecf20Sopenharmony_ci err = switchdev_port_obj_del(br->dev, &test.obj); 848c2ecf20Sopenharmony_ci else 858c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &test.obj, NULL); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return err; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ciint br_mrp_switchdev_set_ring_state(struct net_bridge *br, 918c2ecf20Sopenharmony_ci struct br_mrp *mrp, 928c2ecf20Sopenharmony_ci enum br_mrp_ring_state_type state) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct switchdev_obj_ring_state_mrp mrp_state = { 958c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 968c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_RING_STATE_MRP, 978c2ecf20Sopenharmony_ci .ring_state = state, 988c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 998c2ecf20Sopenharmony_ci }; 1008c2ecf20Sopenharmony_ci int err; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 1058c2ecf20Sopenharmony_ci return err; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci return 0; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ciint br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp, 1118c2ecf20Sopenharmony_ci u16 in_id, u32 ring_id, 1128c2ecf20Sopenharmony_ci enum br_mrp_in_role_type role) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct switchdev_obj_in_role_mrp mrp_role = { 1158c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 1168c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP, 1178c2ecf20Sopenharmony_ci .in_role = role, 1188c2ecf20Sopenharmony_ci .in_id = mrp->in_id, 1198c2ecf20Sopenharmony_ci .ring_id = mrp->ring_id, 1208c2ecf20Sopenharmony_ci .i_port = rtnl_dereference(mrp->i_port)->dev, 1218c2ecf20Sopenharmony_ci }; 1228c2ecf20Sopenharmony_ci int err; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (role == BR_MRP_IN_ROLE_DISABLED) 1258c2ecf20Sopenharmony_ci err = switchdev_port_obj_del(br->dev, &mrp_role.obj); 1268c2ecf20Sopenharmony_ci else 1278c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return err; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ciint br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp, 1338c2ecf20Sopenharmony_ci enum br_mrp_in_state_type state) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct switchdev_obj_in_state_mrp mrp_state = { 1368c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 1378c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_IN_STATE_MRP, 1388c2ecf20Sopenharmony_ci .in_state = state, 1398c2ecf20Sopenharmony_ci .in_id = mrp->in_id, 1408c2ecf20Sopenharmony_ci }; 1418c2ecf20Sopenharmony_ci int err; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 1468c2ecf20Sopenharmony_ci return err; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ciint br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp, 1528c2ecf20Sopenharmony_ci u32 interval, u8 max_miss, u32 period) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci struct switchdev_obj_in_test_mrp test = { 1558c2ecf20Sopenharmony_ci .obj.orig_dev = br->dev, 1568c2ecf20Sopenharmony_ci .obj.id = SWITCHDEV_OBJ_ID_IN_TEST_MRP, 1578c2ecf20Sopenharmony_ci .interval = interval, 1588c2ecf20Sopenharmony_ci .max_miss = max_miss, 1598c2ecf20Sopenharmony_ci .in_id = mrp->in_id, 1608c2ecf20Sopenharmony_ci .period = period, 1618c2ecf20Sopenharmony_ci }; 1628c2ecf20Sopenharmony_ci int err; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci if (interval == 0) 1658c2ecf20Sopenharmony_ci err = switchdev_port_obj_del(br->dev, &test.obj); 1668c2ecf20Sopenharmony_ci else 1678c2ecf20Sopenharmony_ci err = switchdev_port_obj_add(br->dev, &test.obj, NULL); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return err; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciint br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct switchdev_attr attr = { 1758c2ecf20Sopenharmony_ci .orig_dev = p->dev, 1768c2ecf20Sopenharmony_ci .id = SWITCHDEV_ATTR_ID_PORT_STP_STATE, 1778c2ecf20Sopenharmony_ci .u.stp_state = state, 1788c2ecf20Sopenharmony_ci }; 1798c2ecf20Sopenharmony_ci int err; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci err = switchdev_port_attr_set(p->dev, &attr); 1828c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 1838c2ecf20Sopenharmony_ci br_warn(p->br, "error setting offload MRP state on port %u(%s)\n", 1848c2ecf20Sopenharmony_ci (unsigned int)p->port_no, p->dev->name); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return err; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ciint br_mrp_port_switchdev_set_role(struct net_bridge_port *p, 1908c2ecf20Sopenharmony_ci enum br_mrp_port_role_type role) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci struct switchdev_attr attr = { 1938c2ecf20Sopenharmony_ci .orig_dev = p->dev, 1948c2ecf20Sopenharmony_ci .id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, 1958c2ecf20Sopenharmony_ci .u.mrp_port_role = role, 1968c2ecf20Sopenharmony_ci }; 1978c2ecf20Sopenharmony_ci int err; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci err = switchdev_port_attr_set(p->dev, &attr); 2008c2ecf20Sopenharmony_ci if (err && err != -EOPNOTSUPP) 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 205