| /****************************************************************************** |
| * |
| * <: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; |
| } |
| /*@}*/ |
| |
| |