2020-04-26 16:22:04 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
# include <net/switchdev.h>
# include "br_private_mrp.h"
int br_mrp_switchdev_add ( struct net_bridge * br , struct br_mrp * mrp )
{
struct switchdev_obj_mrp mrp_obj = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_MRP ,
. p_port = rtnl_dereference ( mrp - > p_port ) - > dev ,
. s_port = rtnl_dereference ( mrp - > s_port ) - > dev ,
. ring_id = mrp - > ring_id ,
2020-05-30 21:09:47 +03:00
. prio = mrp - > prio ,
2020-04-26 16:22:04 +03:00
} ;
int err ;
err = switchdev_port_obj_add ( br - > dev , & mrp_obj . obj , NULL ) ;
if ( err & & err ! = - EOPNOTSUPP )
return err ;
return 0 ;
}
int br_mrp_switchdev_del ( struct net_bridge * br , struct br_mrp * mrp )
{
struct switchdev_obj_mrp mrp_obj = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_MRP ,
. p_port = NULL ,
. s_port = NULL ,
. ring_id = mrp - > ring_id ,
} ;
int err ;
err = switchdev_port_obj_del ( br - > dev , & mrp_obj . obj ) ;
if ( err & & err ! = - EOPNOTSUPP )
return err ;
return 0 ;
}
int br_mrp_switchdev_set_ring_role ( struct net_bridge * br ,
struct br_mrp * mrp ,
enum br_mrp_ring_role_type role )
{
struct switchdev_obj_ring_role_mrp mrp_role = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP ,
. ring_role = role ,
. ring_id = mrp - > ring_id ,
} ;
int err ;
if ( role = = BR_MRP_RING_ROLE_DISABLED )
err = switchdev_port_obj_del ( br - > dev , & mrp_role . obj ) ;
else
err = switchdev_port_obj_add ( br - > dev , & mrp_role . obj , NULL ) ;
return err ;
}
int br_mrp_switchdev_send_ring_test ( struct net_bridge * br ,
struct br_mrp * mrp , u32 interval ,
2020-05-30 21:09:48 +03:00
u8 max_miss , u32 period ,
bool monitor )
2020-04-26 16:22:04 +03:00
{
struct switchdev_obj_ring_test_mrp test = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_RING_TEST_MRP ,
. interval = interval ,
. max_miss = max_miss ,
. ring_id = mrp - > ring_id ,
. period = period ,
2020-05-30 21:09:48 +03:00
. monitor = monitor ,
2020-04-26 16:22:04 +03:00
} ;
int err ;
if ( interval = = 0 )
err = switchdev_port_obj_del ( br - > dev , & test . obj ) ;
else
err = switchdev_port_obj_add ( br - > dev , & test . obj , NULL ) ;
return err ;
}
int br_mrp_switchdev_set_ring_state ( struct net_bridge * br ,
struct br_mrp * mrp ,
enum br_mrp_ring_state_type state )
{
struct switchdev_obj_ring_state_mrp mrp_state = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_RING_STATE_MRP ,
. ring_state = state ,
. ring_id = mrp - > ring_id ,
} ;
int err ;
err = switchdev_port_obj_add ( br - > dev , & mrp_state . obj , NULL ) ;
if ( err & & err ! = - EOPNOTSUPP )
return err ;
return 0 ;
}
2020-07-14 10:34:53 +03:00
int br_mrp_switchdev_set_in_role ( struct net_bridge * br , struct br_mrp * mrp ,
u16 in_id , u32 ring_id ,
enum br_mrp_in_role_type role )
{
struct switchdev_obj_in_role_mrp mrp_role = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_IN_ROLE_MRP ,
. in_role = role ,
. in_id = mrp - > in_id ,
. ring_id = mrp - > ring_id ,
. i_port = rtnl_dereference ( mrp - > i_port ) - > dev ,
} ;
int err ;
if ( role = = BR_MRP_IN_ROLE_DISABLED )
err = switchdev_port_obj_del ( br - > dev , & mrp_role . obj ) ;
else
err = switchdev_port_obj_add ( br - > dev , & mrp_role . obj , NULL ) ;
return err ;
}
int br_mrp_switchdev_set_in_state ( struct net_bridge * br , struct br_mrp * mrp ,
enum br_mrp_in_state_type state )
{
struct switchdev_obj_in_state_mrp mrp_state = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_IN_STATE_MRP ,
. in_state = state ,
. in_id = mrp - > in_id ,
} ;
int err ;
err = switchdev_port_obj_add ( br - > dev , & mrp_state . obj , NULL ) ;
if ( err & & err ! = - EOPNOTSUPP )
return err ;
return 0 ;
}
int br_mrp_switchdev_send_in_test ( struct net_bridge * br , struct br_mrp * mrp ,
u32 interval , u8 max_miss , u32 period )
{
struct switchdev_obj_in_test_mrp test = {
. obj . orig_dev = br - > dev ,
. obj . id = SWITCHDEV_OBJ_ID_IN_TEST_MRP ,
. interval = interval ,
. max_miss = max_miss ,
. in_id = mrp - > in_id ,
. period = period ,
} ;
int err ;
if ( interval = = 0 )
err = switchdev_port_obj_del ( br - > dev , & test . obj ) ;
else
err = switchdev_port_obj_add ( br - > dev , & test . obj , NULL ) ;
return err ;
}
2020-04-26 16:22:04 +03:00
int br_mrp_port_switchdev_set_state ( struct net_bridge_port * p ,
enum br_mrp_port_state_type state )
{
struct switchdev_attr attr = {
. orig_dev = p - > dev ,
. id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE ,
. u . mrp_port_state = state ,
} ;
int err ;
err = switchdev_port_attr_set ( p - > dev , & attr ) ;
if ( err & & err ! = - EOPNOTSUPP )
br_warn ( p - > br , " error setting offload MRP state on port %u(%s) \n " ,
( unsigned int ) p - > port_no , p - > dev - > name ) ;
return err ;
}
int br_mrp_port_switchdev_set_role ( struct net_bridge_port * p ,
enum br_mrp_port_role_type role )
{
struct switchdev_attr attr = {
. orig_dev = p - > dev ,
. id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE ,
. u . mrp_port_role = role ,
} ;
int err ;
err = switchdev_port_attr_set ( p - > dev , & attr ) ;
if ( err & & err ! = - EOPNOTSUPP )
return err ;
return 0 ;
}