blob: 4fc020ebdeab807bf199b77a5d524781456aa893 [file] [log] [blame]
/******************************************************************************
*
* <:copyright-BRCM:2016:DUAL/GPL:standard
*
* Copyright (c) 2016 Broadcom
* All Rights Reserved
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed
* to you under the terms of the GNU General Public License version 2
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
* with the following added to such license:
*
* As a special exception, the copyright holders of this software give
* you permission to link this software with independent modules, and
* to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module.
* An independent module is a module which is not derived from this
* software. The special exception does not apply to any modifications
* of the software.
*
* Not withstanding the above, under no circumstances may you combine
* this software in any way with any other Broadcom software provided
* under a license other than the GPL, without Broadcom's express prior
* written consent.
*
* :>
*
*****************************************************************************/
/**
* @file bal_switch_group.c
* @brief BAL Switch util functions that handle group requests
* @addtogroup sw_util
*/
/*@{*/
#include <bal_common.h>
#include <bcm_dev_log.h>
#include <bal_msg.h>
#include "bcmos_errno.h"
#include "bal_switch_util.h" /* include bal_util.msg.h for bal_util_oper_group */
#include "group_fsm.h" /* for struct group_inst */
#include "bal_dpp_group.h"
#include "bal_switch_acc_term.h"
#ifdef TEST_SW_UTIL_LOOPBACK
/* nothing to check in loop back mode */
bcmos_errno sw_util_group_info_validate(void *p_msg)
{
return BCM_ERR_OK;
}
#else
/**
* @brief The group check function validate the group parameters from the core
*
* @param p_msg A pointer to the group object to validate
* @return error code
*/
bcmos_errno sw_util_group_info_validate(void *p_msg)
{
bcmbal_group_cfg *p_grp = (bcmbal_group_cfg *)p_msg;
int i, num_of_pon;
if (p_grp == NULL)
{
BCM_LOG(ERROR, log_id_sw_util,
" No group specified during validation\n" );
return BCM_ERR_PARM;
}
/* if members field is set, make sure the PON interfaces are valid */
if (BCMBAL_CFG_PROP_IS_SET(p_grp, group, members))
{
num_of_pon = bal_bcm_pon_inf_map_size_get();
for(i=0; i<p_grp->data.members.len; i++)
{
bcmbal_group_member_info *p_member = &p_grp->data.members.val[i];
if (p_member->intf_id >= num_of_pon)
{
BCM_LOG(ERROR, log_id_sw_util,
" invalid group member with pon id = %d\n", p_member->intf_id );
return BCM_ERR_PARM;
}
}
}
/* member action is not supported yet */
return BCM_ERR_OK;
}
/**
* @brief The group remove function program switch to release resource that have
* been allocated during the group add operation.
*
* @param p_group_inst A pointer to the group instance being referenced
* @return error code
*/
static bcmos_errno bal_sw_util_group_remove(group_inst *p_group_inst)
{
bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
bcmos_errno ret = BCM_ERR_OK;
int unit;
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util,
" Got a group remove request - group_id=%d \n", p_group->key.group_id);
/* remove must have at least one member */
if(p_group->data.members.len == 0)
{
BCM_LOG(ERROR, log_id_sw_util, "group remove request must have at least one member\n");
return BCM_ERR_PARM;
}
unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
dev_type = bal_bcm_dev_type_get(unit);
/* call the group add function based on device type */
if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
ret = bal_sw_util_dpp_group_rem(unit, p_group);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group remove: 0x%x\n", dev_type );
ret = BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " Return group remove request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
/**
* @brief The group add function program switch to add a member interface to the group
*
* @param p_group_inst A pointer to the group instance being referenced
* @return error code
*/
static bcmos_errno bal_sw_util_group_add(group_inst *p_group_inst)
{
bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
bcmos_errno ret = BCM_ERR_OK;
int unit;
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util,
" Got a group add request - group_id=%d \n", p_group->key.group_id);
/* add must have at least one member */
if(p_group->data.members.len == 0)
{
BCM_LOG(ERROR, log_id_sw_util, "group add request must have at least one member\n");
return BCM_ERR_PARM;
}
unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
dev_type = bal_bcm_dev_type_get(unit);
/* call the group add function based on device type */
if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
ret = bal_sw_util_dpp_group_add(unit, p_group);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group add: 0x%x\n", dev_type );
ret = BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " Return group add request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
/**
* @brief The group set function program switch to replace member interfaces of a group
*
* @param p_group_inst A pointer to the group instance being referenced
* @return error code
*/
static bcmos_errno bal_sw_util_group_set(group_inst *p_group_inst)
{
bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
bcmos_errno ret = BCM_ERR_OK;
int unit;
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util,
" Got a group set request - group_id=%d \n", p_group->key.group_id);
if(p_group->data.members.len == 0)
{
unit = bal_bcm_dft_dev_get();
}
else
{
unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
}
dev_type = bal_bcm_dev_type_get(unit);
/* call the group set function based on device type */
if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
ret = bal_sw_util_dpp_group_set(unit, p_group);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group set: 0x%x\n", dev_type );
ret = BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " Return group set request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
/**
* @brief The group create function program switch to create an empty group
*
* @param p_group_inst A pointer to the group instance being referenced
* @return error code
*/
static bcmos_errno bal_sw_util_group_create(group_inst *p_group_inst)
{
bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
bcmos_errno ret = BCM_ERR_OK;
int unit;
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util,
" Got a group create request - group_id=%d \n", p_group->key.group_id);
/* For now, only one switch device for a system. If multiple devices support is required,
need to loop through all devices to create the group */
unit = bal_bcm_dft_dev_get();
dev_type = bal_bcm_dev_type_get(unit);
/* call the group create function based on device type */
if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
if( NULL == bal_sw_util_dpp_group_create(unit, p_group))
{
BCM_LOG(ERROR, log_id_sw_util, " switch group create failed\n");
ret = BCM_ERR_INTERNAL;
}
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group create: 0x%x\n", dev_type );
ret = BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " Return group create request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
/**
* @brief The group destroy function program switch to release all resource used in a group
*
* @param p_group_inst A pointer to the group instance being referenced
* @return error code
*/
static bcmos_errno bal_sw_util_group_destroy(group_inst *p_group_inst)
{
bcmbal_group_cfg *p_group = &p_group_inst->current_group_info;
bcmos_errno ret = BCM_ERR_OK;
int unit;
uint32_t dev_type;
BCM_LOG(INFO, log_id_sw_util,
" Got a group destroy request - group_id=%d \n", p_group->key.group_id);
/* For now, only one switch device for a system. If multiple devices support is required,
need to loop through all devices to create the group */
unit = bal_bcm_dft_dev_get();
dev_type = bal_bcm_dev_type_get(unit);
/* call the group destroy function based on device type */
if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
{
ret = bal_sw_util_dpp_group_destroy(unit, p_group);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group destroy: 0x%x\n", dev_type );
ret = BCM_ERR_INTERNAL;
}
BCM_LOG(INFO, log_id_sw_util, " Return group destroy request with %d on device 0x%x\n", ret, dev_type );
return ret;
}
static uint32_t g_group_inited = 0;
#endif
/**
* @brief SWITCH module: group SET handler
*
* This routine is called by group_fsm in the BAL core upon
* SET request for group object.
*
* @param p_group_inst Pointer to group instance
* @param opt_type Operation type on group instance
*
* @return bcmos_errno
*/
bcmos_errno sw_util_group_set(group_inst *p_group_inst, bal_util_oper_group opt_type)
{
bcmos_errno ret = BCM_ERR_OK;
#ifndef TEST_SW_UTIL_LOOPBACK
bal_sw_util_vsi_list_init();
if (g_group_inited == 0)
{
/* initialized the internal group link list */
bal_sw_util_dpp_group_list_init();
g_group_inited = 1;
}
if(p_group_inst == NULL)
{
BCM_LOG(ERROR, log_id_sw_util, "group set request with NULL pointer to the group instance\n");
return BCM_ERR_PARM;
}
if (opt_type == BAL_UTIL_OPER_GROUP_CREATE)
{
ret = bal_sw_util_group_create(p_group_inst);
}
else if (opt_type == BAL_UTIL_OPER_GROUP_ADD)
{
ret = bal_sw_util_group_add(p_group_inst);
}
else if( BAL_UTIL_OPER_GROUP_REMOVE == opt_type )
{
ret = bal_sw_util_group_remove(p_group_inst);
}
else if( BAL_UTIL_OPER_GROUP_SET == opt_type )
{
ret = bal_sw_util_group_set(p_group_inst);
}
else if( BAL_UTIL_OPER_GROUP_DESTROY == opt_type )
{
ret = bal_sw_util_group_destroy(p_group_inst);
}
else
{
BCM_LOG(ERROR, log_id_sw_util, "Only CREATE/ADD/REMOVE/SET/DESTROY request is supported for GROUP object\n");
return BCM_ERR_NOT_SUPPORTED;
}
#else
BCM_LOG(INFO, log_id_sw_util, "dummy group %s SUCCESS\n",
BCMBAL_UTIL_GROUP_OPER_STR_GET(opt_type));
#endif
return ret;
}
/**
* @brief SWITCH module: group clean up function
*
* This routine is called from the bal_switch_util() when Core calls the finish function.
*
* @return bcmos_errno
*/
bcmos_errno sw_util_group_finish()
{
bcmos_errno ret = BCM_ERR_OK;
#ifndef TEST_SW_UTIL_LOOPBACK
if (g_group_inited)
{
/* release the internal group link list */
bal_sw_util_dpp_group_list_finish();
g_group_inited = 0;
}
#endif
return ret;
}
/*@}*/