BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bal_release/src/lib/librscmgr/Makefile b/bal_release/src/lib/librscmgr/Makefile
new file mode 100644
index 0000000..d94cd45
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/Makefile
@@ -0,0 +1,37 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+MOD_NAME = rscmgr
+MOD_TYPE = lib
+MOD_DEPS = dev_log cli os_cli bal_api
+srcs = rsc_mgr.c rsc_mgr_common.c rsc_mgr_cli.c
+
+# XXX To break a circular dependency, we should avoid adding bal_core to MOD_DEPS
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../core/main
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr.c b/bal_release/src/lib/librscmgr/rsc_mgr.c
new file mode 100644
index 0000000..bd8afec
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr.c
@@ -0,0 +1,922 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#include <bcmolt_host_api.h>
+#include <bcm_dev_log.h>
+#include <bal_objs.h>
+#include <bal_api.h>
+#include <bal_cli.h>
+#include <bcmolt_math.h>
+#include <bcm_topo.h>
+#include "rsc_mgr_common.h"
+#include "rsc_mgr.h"
+
+#define GPON_NUM_OF_ALLOC_IDS 1024
+#define XGPON_NUM_OF_ALLOC_IDS 2048
+
+#define GPON_NUM_OF_GEM_PORT_IDS_PER_PON 4096
+#define XGPON_NUM_OF_GEM_PORT_IDS_PER_PON 8192
+
+#define RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id) \
+ ((first_data_alloc_id) + (bcmolt_pon_alloc_id)(RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids - 1))
+#define RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id) ( \
+ ((alloc_id) >= (first_data_alloc_id) && (alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id)))
+#define RSC_MGR_ALLOC_ID_IS_VALID(pon_id, alloc_id, first_data_alloc_id) ( \
+ ((alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DEFAULT(pon_id)) || \
+ RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id))
+
+#define RSC_MGR_GEM_PORT_ID_LAST_DEFAULT(pon_id) ((bcmolt_pon_gem_port_id)(bcm_topo_pon_get_max_num_of_onus(pon_id) - 1))
+#define RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id) \
+ ((first_data_port_id) + (bcmolt_pon_gem_port_id)(RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports - bcm_topo_pon_get_max_num_of_onus(pon_id) - 1))
+#define RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id) ( \
+ ((gem_port_id) >= (first_data_port_id) && (gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id)))
+#define RSC_MGR_GEM_PORT_ID_IS_VALID(pon_id, gem_port_id, first_data_port_id) ( \
+ ((gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DEFAULT(pon_id)) || \
+ RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id))
+
+#define RSC_MGR_FOR_EACH_ALLOC_INDEX(pon_id, alloc_index) \
+ for (alloc_index = (bcmolt_pon_alloc_index)0; alloc_index < (bcmolt_pon_alloc_index)RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids; alloc_index++)
+
+#define RSC_MGR_FOR_EACH_GEM_INDEX(pon_id, gem_port_index) \
+ for (gem_port_index = 0; (bcmolt_pon_gem_port_index)gem_port_index < (bcmolt_pon_gem_port_index)RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports; gem_port_index++)
+
+#define RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(tm_sched_auto_index) \
+ for (tm_sched_auto_index = 0; (bcmbal_tm_sched_id_index)tm_sched_auto_index < (bcmbal_tm_sched_id_index)tm_context.num_of_tm_sched_auto_key_ids; tm_sched_auto_index++)
+
+/* Because GEM port 0 .. 127 are used for OMCI, we can start allocating from 128. But due to a bug in Maple A0, 128 .. 159 must not be used. So we start from 256. */
+#define MIN_BASE_GEM_PORT_ID_GPON 256
+
+#define NUM_OF_TM_SCHED_AUTO_KEY_IDS 2048
+#define MIN_BASE_TM_SCHED_AUTO_ID 2048
+
+
+rsc_mgr_context_t rsc_mgr_context;
+rsc_mgr_tm_context tm_context;
+
+
+static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id);
+static bcmos_errno rsc_mgr_obj_get(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_obj **obj, dev_log_id log_id);
+static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data);
+static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data);
+
+
+static bcmos_bool rsc_mgr_is_valid_data_alloc_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_alloc_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return (rsc_mgr_obj_id)(bcmolt_pon_alloc_id)RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, min_data_obj_id);
+}
+
+static bcmos_bool rsc_mgr_is_valid_data_gem_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_gem_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return (rsc_mgr_obj_id)(bcmolt_pon_gem_port_id)RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, min_data_obj_id);
+}
+static bcmos_bool rsc_mgr_is_valid_data_tm_sched_auto_id(rsc_mgr_obj_id id)
+{
+ return (id >= MIN_BASE_TM_SCHED_AUTO_ID && id < MIN_BASE_TM_SCHED_AUTO_ID + NUM_OF_TM_SCHED_AUTO_KEY_IDS);
+}
+
+static bcmos_bool rsc_mgr_is_valid_data_tm_sched_auto_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return rsc_mgr_is_valid_data_tm_sched_auto_id(id);
+}
+
+static rsc_mgr_obj_id rsc_mgr_get_last_data_tm_sched_auto_id_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
+{
+ return (rsc_mgr_obj_id)(min_data_obj_id + NUM_OF_TM_SCHED_AUTO_KEY_IDS - 1);
+}
+
+
+static bcmos_errno rsc_mgr_obj_alloc(bcmbal_intf_id access_int_id, rsc_mgr_obj_id *obj_id, uint32_t range_size, rsc_mgr_obj_type type, rsc_mgr_obj_rsc *obj_rsc, void *user_data, dev_log_id log_id)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+
+ if (range_size < RSC_MGR_MIN_RANGE_SIZE || range_size > RSC_MGR_MAX_RANGE_SIZE)
+ {
+ BCM_LOG(ERROR, log_id, "Range size must be in the range %u .. %u\n", RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE);
+ return BCM_ERR_PARM;
+ }
+
+ if (*obj_id)
+ {
+ rc = rsc_mgr_obj_get(access_int_id, *obj_id, obj_rsc, &obj, log_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ if (obj->range_size != range_size)
+ {
+ BCM_LOG(ERROR, log_id, "When reusing a range of %ss, range size (%d) must be exactly the same as the range from creation (%u)\n",
+ obj_rsc->obj_name, range_size, obj->range_size);
+ return BCM_ERR_PARM;
+ }
+
+ if (obj->type != type)
+ {
+ BCM_LOG(ERROR, log_id, "When reusing %ss, type (%d) must be exactly the same as the type from creation (%u)\n",
+ obj_rsc->obj_name, type, obj->type);
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ rsc_mgr_obj *base_obj;
+ rsc_mgr_obj *last_obj;
+ rsc_mgr_obj *obj_iter;
+
+ /* Find the first free range that fits ("first-fit" algorithm). */
+ TAILQ_FOREACH(obj_iter, &obj_rsc->free_objs, list)
+ {
+ if (range_size <= obj_iter->range_size)
+ break;
+ }
+ if (!obj_iter)
+ {
+ BCM_LOG(ERROR, log_id, "No free %ss\n", obj_rsc->obj_name);
+ return BCM_ERR_NORES;
+ }
+ *obj_id = obj_iter->id;
+
+ if (range_size < obj_iter->range_size)
+ {
+ /* Insert a smaller range (decrease by 'range_size') to the list of free objects. It will replace the old free range. */
+ base_obj = &obj_iter[range_size];
+ last_obj = &obj_iter[obj_iter->range_size - 1];
+ TAILQ_INSERT_HEAD(&obj_rsc->free_objs, base_obj, list);
+ base_obj->range_size = obj_iter->range_size - range_size;
+ last_obj->base_obj = base_obj;
+ }
+
+ /* Move 'range_size' objects from the list of free objects to the list of allocated objects. */
+ base_obj = obj_iter;
+ last_obj = &obj_iter[range_size - 1];
+ TAILQ_REMOVE(&obj_rsc->free_objs, base_obj, list);
+ TAILQ_INSERT_HEAD(&obj_rsc->allocated_objs, base_obj, list);
+ base_obj->range_size = range_size;
+ base_obj->type = type;
+ last_obj->base_obj = base_obj;
+
+ obj = obj_iter;
+ /* since new object, initialize the user data list */
+ TAILQ_INIT(&obj->user_data_list);
+
+ }
+ obj->ref_count++;
+
+ /** store user data (flow entry pointer) in a linked list inside the object */
+ rsc_mgr_obj_store_user_data(obj, user_data);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_obj_free(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, void *user_data, dev_log_id log_id)
+{
+ rsc_mgr_obj *obj;
+ rsc_mgr_obj *last_obj;
+ bcmos_errno rc;
+
+ rc = rsc_mgr_obj_get(access_int_id, obj_id, obj_rsc, &obj, log_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ obj->ref_count--;
+ /** remove user data (flow entry pointer) from the linked list inside the object */
+ rsc_mgr_obj_remove_user_data(obj, user_data);
+
+ if (!obj->ref_count)
+ {
+ rsc_mgr_obj *next_obj = NULL;
+ rsc_mgr_obj *prev_obj = NULL;
+
+ /* Validate that going to the next object won't overflow the array. */
+ if (obj < &obj_rsc->objs[obj_rsc->num_of_objs - 1] && &obj[obj->range_size] <= &obj_rsc->objs[obj_rsc->num_of_objs - 1])
+ {
+ /* Check if the next ID is in the free list (according to its reference count).
+ * If true -> we can merge obj's range with the next range. */
+ if (!obj[obj->range_size].ref_count)
+ next_obj = &obj[obj->range_size];
+ }
+
+ /* Validate that going to the base of the previous range won't underflow the array. */
+ if (obj > obj_rsc->objs)
+ {
+ /* Check if the base ID of the previous range is in the free list (according to the base ID's reference count).
+ * If true -> we can merge obj's range with the previous range. */
+ if (obj[-1].base_obj && !obj[-1].base_obj->ref_count)
+ prev_obj = obj[-1].base_obj;
+ }
+
+ /* First remove the object from the allocated linked list. */
+ TAILQ_REMOVE(&obj_rsc->allocated_objs, obj, list);
+ last_obj = &obj[obj->range_size - 1];
+ obj->type = RSC_MGR_OBJ_TYPE_INVALID; /* Clear type. */
+ if (next_obj && !prev_obj)
+ {
+ /* Merge only with next range. */
+ TAILQ_INSERT_BEFORE(next_obj, obj, list);
+ TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
+ obj->range_size += next_obj->range_size;
+ last_obj->base_obj = NULL;
+ next_obj->range_size = 0;
+ last_obj = &obj[obj->range_size - 1];
+ last_obj->base_obj = obj;
+ }
+ else if (!next_obj && prev_obj)
+ {
+ /* Merge only with previous range. */
+ prev_obj->range_size += obj->range_size;
+ obj->range_size = 0;
+ last_obj->base_obj = prev_obj;
+ }
+ else if (next_obj && prev_obj)
+ {
+ /* Merge with both next and previous ranges. */
+ prev_obj->range_size += obj->range_size + next_obj->range_size;
+ obj->range_size = 0;
+ next_obj->range_size = 0;
+ TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
+ last_obj->base_obj = NULL;
+ last_obj = &prev_obj[prev_obj->range_size - 1];
+ last_obj->base_obj = prev_obj;
+ }
+ else
+ {
+ /* No merge at all. */
+ TAILQ_INSERT_TAIL(&obj_rsc->free_objs, obj, list);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_obj_get(bcmbal_intf_id access_int_id, rsc_mgr_obj_id obj_id, rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_obj **obj, dev_log_id log_id)
+{
+ bcmos_errno rc;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ if (!obj_rsc->is_valid_data_obj_id_cb(access_int_id, obj_id, obj_rsc->min_data_obj_id))
+ {
+ BCM_LOG(ERROR, log_id, "%s must be in the range %u .. %u\n",
+ obj_rsc->obj_name, obj_rsc->min_data_obj_id, obj_rsc->get_last_data_obj_id_cb(access_int_id, obj_rsc->min_data_obj_id));
+ return BCM_ERR_PARM;
+ }
+
+ *obj = &obj_rsc->objs[obj_id - obj_rsc->min_data_obj_id];
+ /* Only base object must have its reference count > 0. */
+ if (!(*obj)->ref_count)
+ {
+ BCM_LOG(ERROR, log_id, "%s hasn't been allocated before\n", obj_rsc->obj_name);
+ return BCM_ERR_PARM;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/** @brief stores user passed in data in the linked list inside the obj */
+static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data)
+{
+ rsc_mgr_user_data_entry *user_data_entry = NULL;
+
+ if (NULL == user_data)
+ return BCM_ERR_OK;
+
+ user_data_entry = bcmos_calloc(sizeof(rsc_mgr_user_data_entry));
+ user_data_entry->user_data = user_data;
+ TAILQ_INSERT_HEAD(&obj->user_data_list, user_data_entry, next);
+
+ return BCM_ERR_OK;
+}
+
+/** @brief removes user data from the linked list inside the obj */
+static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data)
+{
+ rsc_mgr_user_data_entry *user_data_entry = NULL, *user_data_entry_tmp;
+
+ if (NULL == user_data)
+ return BCM_ERR_OK;
+
+ TAILQ_FOREACH_SAFE(user_data_entry, &obj->user_data_list, next, user_data_entry_tmp)
+ {
+ if (user_data == user_data_entry->user_data)
+ break;
+ }
+ TAILQ_REMOVE(&obj->user_data_list, user_data_entry, next);
+
+ user_data_entry->user_data = NULL;
+ bcmos_free(user_data_entry);
+
+ return BCM_ERR_OK;
+}
+
+/** @brief iterator to iterate through the user data list in obj
+ * @note the assumption is if a NULL is returned, then caller code stop the iteration.
+ * */
+static void *rsc_mgr_obj_get_next_user_data(rsc_mgr_obj *obj, void **curr_user_data_entry, void **next_user_data_entry)
+{
+ if (NULL == *curr_user_data_entry)
+ {
+ *curr_user_data_entry = TAILQ_FIRST(&obj->user_data_list);
+ if (*curr_user_data_entry)
+ {
+ *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*curr_user_data_entry), next);
+ return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
+ }
+ }
+ else
+ {
+ *curr_user_data_entry = *next_user_data_entry;
+ if (*next_user_data_entry)
+ {
+ *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*next_user_data_entry), next);
+ return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Alloc ID (aggregation port ID) */
+static bcmos_errno _rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id)
+{
+ bcmolt_pon_alloc_index alloc_index;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
+ {
+ bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
+ bcmolt_gpon_ni_cfg_id failed_prop;
+
+ BCMOLT_CFG_PROP_SET(&gpon_ni_cfg, gpon_ni, min_data_alloc_id, min_data_agg_port_id);
+ if (!bcmolt_gpon_ni_cfg_data_bounds_check(&gpon_ni_cfg.data, (1ULL << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+ bcmolt_xgpon_ni_cfg_id failed_prop;
+
+ BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_alloc_id, min_data_agg_port_id);
+ if (!bcmolt_xgpon_ni_cfg_data_bounds_check(&xgpon_ni_cfg.data, (1ULL << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
+ return BCM_ERR_PARM;
+ }
+ }
+
+ if (!TAILQ_EMPTY(&topo_context->alloc_ids.allocated_objs))
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal alloc ID cannot be set when there are allocated alloc IDs\n");
+ return BCM_ERR_STATE;
+ }
+
+ topo_context->alloc_ids.min_data_obj_id = (rsc_mgr_obj_id)min_data_agg_port_id;
+ RSC_MGR_FOR_EACH_ALLOC_INDEX(access_int_id, alloc_index)
+ topo_context->alloc_ids.objs[alloc_index].id = topo_context->alloc_ids.min_data_obj_id + alloc_index;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id)
+{
+ bcmos_errno rc;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ return _rsc_mgr_access_int_base_alloc_id_set(access_int_id, min_data_agg_port_id);
+}
+
+
+static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id)
+{
+ bcmos_errno rc;
+
+ rc = rsc_mgr_init_validate();
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+ return rc;
+ }
+
+ if (!bcm_topo_pon_is_valid(access_int_id))
+ return BCM_ERR_PARM;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_alloc_validate_non_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id topo_context_gem_port,
+ bcmbal_service_port_id req_gem_port, uint32_t range_size, rsc_mgr_obj_type type,
+ dev_log_id log_id)
+{
+ if (topo_context_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID && req_gem_port && req_gem_port != topo_context_gem_port)
+ {
+ BCM_LOG(ERROR, log_id, "Access interface already has %s service port ID=%u configured\n", RSC_MGR_OBJ_TYPE_STR(type), topo_context_gem_port);
+ return BCM_ERR_ALREADY;
+ }
+
+ if (range_size > 1)
+ {
+ BCM_LOG(ERROR, log_id, "Range bigger than 1 for %s GEM port is not allowed\n", RSC_MGR_OBJ_TYPE_STR(type));
+ return BCM_ERR_PARM;
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_alloc_id_alloc(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id *agg_port_id, uint32_t range_size, void *user_data)
+{
+ bcmos_errno rc;
+ rsc_mgr_obj_id obj_id = *agg_port_id;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_ALLOC_ID, &topo_context->alloc_ids, user_data, topo_context->log_id);
+ *agg_port_id = obj_id;
+
+ return rc;
+}
+
+bcmos_errno rsc_mgr_alloc_id_free(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void *user_data)
+{
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ if (!bcm_topo_pon_is_valid(access_int_id))
+ return BCM_ERR_PARM;
+
+ return rsc_mgr_obj_free(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, user_data, topo_context->log_id);
+}
+
+bcmos_errno rsc_mgr_alloc_id_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, uint32_t *ref_count)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ *ref_count = obj->ref_count;
+
+ return BCM_ERR_OK;
+}
+
+/** @brief iterates through user data list of an alloc id object */
+void *rsc_mgr_alloc_id_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void **curr_user_data_entry, void **next_user_data_entry)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
+ if (rc != BCM_ERR_OK)
+ return NULL;
+
+ return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry);
+}
+
+/* GEM (service port ID) */
+static bcmos_errno _rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
+{
+ bcmolt_pon_gem_port_index gem_index;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
+ {
+ bcmolt_gpon_gem_port_cfg gpon_gem_port_cfg = { .key.gem_port_id = min_data_svc_port_id };
+ bcmolt_gpon_gem_port_key_id failed_prop;
+
+ if (!bcmolt_gpon_gem_port_key_bounds_check(&gpon_gem_port_cfg.key, 1ULL << BCMOLT_GPON_GEM_PORT_KEY_ID_GEM_PORT_ID, &failed_prop) ||
+ min_data_svc_port_id < MIN_BASE_GEM_PORT_ID_GPON)
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+ bcmolt_xgpon_ni_cfg_id failed_prop;
+
+ BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_gem_port_id, min_data_svc_port_id);
+ if (!bcmolt_xgpon_ni_cfg_data_bounds_check(&xgpon_ni_cfg.data, 1ULL << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_GEM_PORT_ID, &failed_prop))
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
+ return BCM_ERR_PARM;
+ }
+ }
+
+ if (!TAILQ_EMPTY(&topo_context->gems.allocated_objs))
+ {
+ BCM_LOG(ERROR, topo_context->log_id, "Minimal GEM port cannot be set when there are allocated GEM ports\n");
+ return BCM_ERR_STATE;
+ }
+
+ topo_context->gems.min_data_obj_id = (rsc_mgr_obj_id)min_data_svc_port_id;
+ RSC_MGR_FOR_EACH_GEM_INDEX(access_int_id, gem_index)
+ topo_context->gems.objs[gem_index].id = topo_context->gems.min_data_obj_id + gem_index;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
+{
+ bcmos_errno rc;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ return _rsc_mgr_access_int_base_gem_set(access_int_id, min_data_svc_port_id);
+}
+
+static bcmos_errno _rsc_mgr_base_tm_sched_auto_id_set (bcmbal_tm_sched_id min_tm_sched_auto_id)
+{
+ bcmbal_tm_sched_id_index i;
+
+
+ if (!TAILQ_EMPTY(&tm_context.tm_sched_auto_key_ids.allocated_objs))
+ {
+ BCM_LOG(ERROR, tm_context.log_id, "Minimal tm node auto id cannot be set when there are allocated ids \n");
+ return BCM_ERR_STATE;
+ }
+
+ tm_context.tm_sched_auto_key_ids.min_data_obj_id = (rsc_mgr_obj_id)min_tm_sched_auto_id;
+ RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(i)
+ {
+ tm_context.tm_sched_auto_key_ids.objs[i].id = tm_context.tm_sched_auto_key_ids.min_data_obj_id + i;
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno rsc_mgr_gem_alloc_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = NULL;
+ rsc_mgr_obj_id obj_id = *svc_port_id;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST, &topo_context->gems, user_data, topo_context->log_id);
+ *svc_port_id = obj_id;
+
+ return rc;
+}
+
+
+bcmos_errno rsc_mgr_gem_alloc_multicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = NULL;
+ rsc_mgr_obj_id obj_id = *svc_port_id;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ rc = rsc_mgr_alloc_validate_non_unicast(access_int_id, topo_context->multicast_gem_port, *svc_port_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST, topo_context->log_id);
+
+ if (topo_context->multicast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
+ obj_id = topo_context->multicast_gem_port; /* This will cause the reference count of the multicast GEM to increase. */
+#endif
+
+ rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST, &topo_context->gems, user_data, topo_context->log_id);
+ *svc_port_id = obj_id;
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ if (!rc)
+ RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = *svc_port_id;
+#endif
+
+ return rc;
+}
+
+bcmos_errno rsc_mgr_gem_alloc_broadcast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data)
+{
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = NULL;
+ rsc_mgr_obj_id obj_id = *svc_port_id;
+
+ rc = rsc_mgr_alloc_validate_common(access_int_id);
+ if (BCM_ERR_OK != rc)
+ return rc;
+
+ topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+ rc = rsc_mgr_alloc_validate_non_unicast(access_int_id, topo_context->broadcast_gem_port, *svc_port_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST, topo_context->log_id);
+
+ if (topo_context->broadcast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
+ obj_id = topo_context->broadcast_gem_port; /* This will cause the reference count of the broadcast GEM to increase. */
+#endif
+
+ rc = rsc_mgr_obj_alloc(access_int_id, &obj_id, range_size, RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST, &topo_context->gems, user_data, topo_context->log_id);
+ *svc_port_id = obj_id;
+
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+ if (!rc)
+ RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->broadcast_gem_port = *svc_port_id;
+#endif
+
+ return rc;
+}
+
+bcmos_errno rsc_mgr_gem_free(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void *user_data)
+{
+ bcmos_errno rc;
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ rsc_mgr_topo_pon_context *topo_context;
+#endif
+
+ if (!bcm_topo_pon_is_valid(access_int_id))
+ return BCM_ERR_PARM;
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+#endif
+
+ rc = rsc_mgr_obj_free(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, user_data, topo_context->log_id);
+
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ if (!rc && topo_context->multicast_gem_port == svc_port_id)
+ RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+#endif
+
+ return rc;
+}
+
+bcmos_errno rsc_mgr_gem_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, uint32_t *ref_count)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ *ref_count = obj->ref_count;
+
+ return BCM_ERR_OK;
+}
+
+/** @brief iterates through user data list of a gem object */
+void *rsc_mgr_gem_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void **curr_user_data_entry, void **next_user_data_entry)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+
+ rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
+ if (rc != BCM_ERR_OK)
+ return NULL;
+
+ return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry);
+}
+
+
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_alloc(bcmbal_tm_sched_id *tm_sched_id)
+{
+ bcmos_errno rc;
+ rsc_mgr_obj_id obj_id = *tm_sched_id;
+
+ rc = rsc_mgr_init_validate();
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+ return rc;
+ }
+
+ /* Allocate a new object. */
+ rc = rsc_mgr_obj_alloc(0, &obj_id, 1, RSC_MGR_OBJ_TYPE_TM_SCHED, &tm_context.tm_sched_auto_key_ids, NULL, tm_context.log_id);
+ *tm_sched_id = obj_id;
+
+ return rc;
+}
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_free(bcmbal_tm_sched_id tm_sched_id)
+{
+ bcmos_errno rc;
+
+ rc = rsc_mgr_obj_free(0, (rsc_mgr_obj_id)tm_sched_id, &tm_context.tm_sched_auto_key_ids, NULL, tm_context.log_id);
+
+ return rc;
+}
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_get_ref_count(bcmbal_tm_sched_id tm_sched_id, uint32_t *ref_count)
+{
+ rsc_mgr_obj *obj;
+ bcmos_errno rc;
+
+ rc = rsc_mgr_obj_get(0, (rsc_mgr_obj_id)tm_sched_id, &tm_context.tm_sched_auto_key_ids, &obj, tm_context.log_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ *ref_count = obj->ref_count;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_bool _rsc_mgr_tm_sched_id_validate(bcmbal_tm_sched_id tm_sched_key_id)
+{
+ return (!rsc_mgr_is_valid_data_tm_sched_auto_id(tm_sched_key_id));
+}
+
+static void rsc_mgr_init_obj_rsc(rsc_mgr_obj_rsc *obj_rsc, rsc_mgr_is_valid_data_obj_id_cb_t is_valid_data_obj_id_cb,
+ rsc_mgr_get_last_data_obj_id_cb_t get_last_data_obj_id_cb, uint32_t num_of_objs, const char *obj_name)
+{
+ rsc_mgr_obj *obj;
+
+ obj_rsc->obj_name = obj_name;
+ obj_rsc->is_valid_data_obj_id_cb = is_valid_data_obj_id_cb;
+ obj_rsc->get_last_data_obj_id_cb = get_last_data_obj_id_cb;
+ TAILQ_INIT(&obj_rsc->free_objs);
+ TAILQ_INIT(&obj_rsc->allocated_objs);
+ obj_rsc->objs = bcmos_calloc(num_of_objs * sizeof(*obj_rsc->objs));
+ obj_rsc->num_of_objs = num_of_objs;
+
+ /* Insert a first entry to the list of free objects. */
+ obj = &obj_rsc->objs[0];
+ obj->range_size = num_of_objs;
+ TAILQ_INSERT_HEAD(&obj_rsc->free_objs, obj, list);
+}
+
+static void rsc_mgr_uninit_obj_rsc(rsc_mgr_obj_rsc *obj_rsc)
+{
+ bcmos_free(obj_rsc->objs);
+}
+
+bcmos_errno rsc_mgr_mac_init(void)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_devid device_id;
+ uint32_t pon_id;
+ rsc_mgr_topo_pon_context *topo_context, *old_topo_context;
+
+ do
+ {
+ rc = rsc_mgr_init_validate();
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was not initialized");
+ break;
+ }
+ BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
+ {
+ old_topo_context = bcm_topo_pon_get_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR);
+ if (old_topo_context)
+ {
+ bcmos_free(old_topo_context);
+ }
+ topo_context = bcmos_calloc(sizeof(*topo_context));
+ if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
+ {
+ topo_context->num_of_alloc_ids = GPON_NUM_OF_ALLOC_IDS;
+ topo_context->num_of_gem_ports = GPON_NUM_OF_GEM_PORT_IDS_PER_PON;
+ }
+ else
+ {
+ topo_context->num_of_alloc_ids = XGPON_NUM_OF_ALLOC_IDS;
+ topo_context->num_of_gem_ports = XGPON_NUM_OF_GEM_PORT_IDS_PER_PON;
+ }
+ topo_context->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+ topo_context->broadcast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
+ bcm_topo_pon_set_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR, topo_context);
+#ifdef ENABLE_LOG
+ snprintf(topo_context->log_id_name, sizeof(topo_context->log_id_name), "RSC_MGR%u", pon_id);
+ topo_context->log_id = bcm_dev_log_id_register(topo_context->log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(topo_context->log_id == DEV_LOG_INVALID_ID);
+#endif
+ rsc_mgr_init_obj_rsc(&topo_context->alloc_ids, rsc_mgr_is_valid_data_alloc_id_cb, rsc_mgr_get_last_data_alloc_id_cb,
+ RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids, "alloc ID");
+ rsc_mgr_init_obj_rsc(&topo_context->gems, rsc_mgr_is_valid_data_gem_cb, rsc_mgr_get_last_data_gem_cb,
+ RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports, "GEM port");
+
+ if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
+ {
+ bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
+
+ bcmolt_gpon_ni_cfg_data_set_default(&gpon_ni_cfg.data, 1 << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
+ _rsc_mgr_access_int_base_alloc_id_set(pon_id, gpon_ni_cfg.data.min_data_alloc_id);
+
+ _rsc_mgr_access_int_base_gem_set(pon_id, MIN_BASE_GEM_PORT_ID_GPON);
+ }
+ else
+ {
+ bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
+
+ bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
+ _rsc_mgr_access_int_base_alloc_id_set(pon_id, xgpon_ni_cfg.data.min_data_alloc_id);
+
+ bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_GEM_PORT_ID);
+ _rsc_mgr_access_int_base_gem_set(pon_id, xgpon_ni_cfg.data.min_data_gem_port_id);
+ }
+ }
+
+ }while(0);
+ return rc;
+}
+
+bcmos_errno rsc_mgr_init(void)
+{
+ if (rsc_mgr_init_validate() == BCM_ERR_OK)
+ {
+ BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was already initialized");
+ return BCM_ERR_OK;
+ }
+
+#ifdef ENABLE_LOG
+ if (rsc_mgr_log_id == DEV_LOG_INVALID_ID)
+ {
+ rsc_mgr_log_id = bcm_dev_log_id_register("RSC_MGR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(rsc_mgr_log_id == DEV_LOG_INVALID_ID);
+ }
+#endif
+
+ /*Init the tm object*/
+ tm_context.num_of_tm_sched_auto_key_ids = NUM_OF_TM_SCHED_AUTO_KEY_IDS;
+ snprintf(tm_context.log_id_name , sizeof(tm_context.log_id_name) , "RSC_MGR_TM");
+ tm_context.log_id = bcm_dev_log_id_register(tm_context.log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(tm_context.log_id == DEV_LOG_INVALID_ID);
+
+ rsc_mgr_init_obj_rsc(&tm_context.tm_sched_auto_key_ids, rsc_mgr_is_valid_data_tm_sched_auto_id_cb, rsc_mgr_get_last_data_tm_sched_auto_id_cb,
+ tm_context.num_of_tm_sched_auto_key_ids, "TM node auto id");
+
+ _rsc_mgr_base_tm_sched_auto_id_set(MIN_BASE_TM_SCHED_AUTO_ID);
+
+ rsc_mgr_context.is_initialized = BCMOS_TRUE;
+ return BCM_ERR_OK;
+}
+
+void rsc_mgr_uninit(void)
+{
+ bcmolt_devid device_id;
+ uint32_t pon_id;
+
+ if (!rsc_mgr_context.is_initialized)
+ return;
+
+ BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
+ {
+ rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(pon_id);
+
+ rsc_mgr_uninit_obj_rsc(&topo_context->gems);
+ rsc_mgr_uninit_obj_rsc(&topo_context->alloc_ids);
+ }
+ rsc_mgr_context.is_initialized = BCMOS_FALSE;
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr.h b/bal_release/src/lib/librscmgr/rsc_mgr.h
new file mode 100644
index 0000000..072d37e
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#ifndef _RSC_MGR_H_
+#define _RSC_MGR_H_
+
+#include <bal_objs.h>
+
+/* Alloc ID (aggregation port ID) */
+bcmos_errno rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id);
+bcmos_errno rsc_mgr_alloc_id_alloc(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id *agg_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_alloc_id_free(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void *user_data);
+bcmos_errno rsc_mgr_alloc_id_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, uint32_t *ref_count);
+void* rsc_mgr_alloc_id_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void **curr_user_data_entry, void **next_user_data_entry);
+
+
+/* GEM (service port ID) */
+bcmos_errno rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id);
+bcmos_errno rsc_mgr_gem_alloc_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_alloc_multicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_alloc_broadcast(bcmbal_intf_id access_int_id, bcmbal_service_port_id *svc_port_id, uint32_t range_size, void *user_data);
+bcmos_errno rsc_mgr_gem_free(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void *user_data);
+bcmos_errno rsc_mgr_gem_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, uint32_t *ref_count);
+void* rsc_mgr_gem_get_next_user_data(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void **curr_user_data_entry, void **next_user_data_entry);
+
+bcmos_errno _rsc_mgr_tm_sched_auto_id_alloc(bcmbal_tm_sched_id *tm_sched_key_id);
+bcmos_errno _rsc_mgr_tm_sched_auto_id_free(bcmbal_tm_sched_id tm_sched_key_id);
+bcmos_errno _rsc_mgr_tm_sched_auto_id_get_ref_count(bcmbal_tm_sched_id tm_sched_key_id, uint32_t *ref_count);
+bcmos_bool _rsc_mgr_tm_sched_id_validate(bcmbal_tm_sched_id tm_sched_key_id);
+
+bcmos_errno rsc_mgr_mac_init(void);
+bcmos_errno rsc_mgr_init(void);
+void rsc_mgr_uninit(void);
+
+#endif
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_cli.c b/bal_release/src/lib/librscmgr/rsc_mgr_cli.c
new file mode 100644
index 0000000..7584741
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_cli.c
@@ -0,0 +1,315 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#include <bcm_dev_log.h>
+#include <bcmcli.h>
+#include <bal_objs.h>
+#include <bal_api.h>
+#include <bcm_topo.h>
+#include "rsc_mgr.h"
+#include "rsc_mgr_common.h"
+#include "rsc_mgr_cli.h"
+
+static bcmos_errno rsc_mgr_cli_cmd_init(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ return rsc_mgr_init();
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_base_alloc_id_set(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmbal_aggregation_port_id min_data_agg_port_id = (bcmbal_aggregation_port_id)bcmcli_find_named_parm(session, "min_data_agg_port_id")->value.unumber;
+
+ return rsc_mgr_access_int_base_alloc_id_set(access_int_id, min_data_agg_port_id);
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_base_gem_set(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmbal_service_port_id min_data_svc_port_id = (bcmbal_service_port_id)bcmcli_find_named_parm(session, "min_data_svc_port_id")->value.unumber;
+
+ return rsc_mgr_access_int_base_gem_set(access_int_id, min_data_svc_port_id);
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_alloc_id_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmcli_cmd_parm *agg_port_id_parm = bcmcli_find_named_parm(session, "agg_port_id");
+ bcmbal_aggregation_port_id agg_port_id = 0;
+ uint32_t range_size = (uint32_t)bcmcli_find_named_parm(session, "range_size")->value.unumber;
+ uint32_t ref_count;
+ bcmos_errno rc;
+
+ if (agg_port_id_parm)
+ agg_port_id = (bcmbal_aggregation_port_id)agg_port_id_parm->value.unumber;
+
+ rc = rsc_mgr_alloc_id_alloc(access_int_id, &agg_port_id, range_size, NULL);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ rc = rsc_mgr_alloc_id_get_ref_count(access_int_id, agg_port_id, &ref_count);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcmcli_session_print(session, "Allocated alloc ID=%u (ref_count=%u)\n", agg_port_id, ref_count);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_alloc_id_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmbal_aggregation_port_id agg_port_id = (bcmbal_aggregation_port_id)bcmcli_find_named_parm(session, "agg_port_id")->value.unumber;
+ uint32_t ref_count;
+ bcmos_errno rc;
+
+ rc = rsc_mgr_alloc_id_get_ref_count(access_int_id, agg_port_id, &ref_count);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ rc = rsc_mgr_alloc_id_free(access_int_id, agg_port_id, NULL);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcmcli_session_print(session, "Freed alloc ID=%u (ref_count=%u)\n", agg_port_id, ref_count - 1);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_gem_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmcli_cmd_parm *svc_port_id_parm = bcmcli_find_named_parm(session, "svc_port_id");
+ bcmbal_service_port_id svc_port_id = 0;
+ uint32_t range_size = (uint32_t)bcmcli_find_named_parm(session, "range_size")->value.unumber;
+ rsc_mgr_obj_type gem_type = (rsc_mgr_obj_type)bcmcli_find_named_parm(session, "gem_type")->value.enum_val;
+ uint32_t ref_count;
+ bcmos_errno rc;
+
+ if (svc_port_id_parm)
+ svc_port_id = (bcmbal_service_port_id)svc_port_id_parm->value.unumber;
+
+ if (RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST == gem_type)
+ rc = rsc_mgr_gem_alloc_multicast(access_int_id, &svc_port_id, range_size, NULL);
+ else if (RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST == gem_type)
+ rc = rsc_mgr_gem_alloc_broadcast(access_int_id, &svc_port_id, range_size, NULL);
+ else
+ rc = rsc_mgr_gem_alloc_unicast(access_int_id, &svc_port_id, range_size, NULL);
+
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ rc = rsc_mgr_gem_get_ref_count(access_int_id, svc_port_id, &ref_count);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcmcli_session_print(session, "Allocated GEM port=%u (ref_count=%u)\n", svc_port_id, ref_count);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_gem_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+ bcmbal_service_port_id svc_port_id = (bcmbal_service_port_id)bcmcli_find_named_parm(session, "svc_port_id")->value.unumber;
+ uint32_t ref_count;
+ bcmos_errno rc;
+
+ rc = rsc_mgr_gem_get_ref_count(access_int_id, svc_port_id, &ref_count);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ rc = rsc_mgr_gem_free(access_int_id, svc_port_id, NULL);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcmcli_session_print(session, "Freed GEM port=%u (ref_count=%u)\n", svc_port_id, ref_count - 1);
+
+ return BCM_ERR_OK;
+}
+/*allocates a new tm node auto id
+no inputs parameters are used */
+static bcmos_errno rsc_mgr_cli_cmd_tm_sched_auto_alloc(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_tm_sched_id tm_sched_auto_id = 0;
+ bcmos_errno rc;
+
+ rc = _rsc_mgr_tm_sched_auto_id_alloc(&tm_sched_auto_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+
+ bcmcli_session_print(session, "Allocated TM SCHED AUTO ID %u \n", tm_sched_auto_id);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_tm_sched_auto_free(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_tm_sched_id tm_sched_auto_id = (bcmbal_tm_sched_id)bcmcli_find_named_parm(session, "tm_sched_auto_id")->value.unumber;
+ uint32_t ref_count;
+ bcmos_errno rc;
+
+ rc = _rsc_mgr_tm_sched_auto_id_get_ref_count(tm_sched_auto_id, &ref_count);
+
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ rc = _rsc_mgr_tm_sched_auto_id_free(tm_sched_auto_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcmcli_session_print(session, "Freed TM NODE AUTO ID %u (ref_count=%u)\n", tm_sched_auto_id, ref_count - 1);
+
+ return BCM_ERR_OK;
+}
+
+static void rsc_mgr_show_objs_list(bcmcli_session *session, bcmbal_intf_id access_int_id, rsc_mgr_obj_rsc *obj_rsc,
+ rsc_mgr_obj_list *obj_list)
+{
+ rsc_mgr_obj *obj_iter;
+
+ TAILQ_FOREACH(obj_iter, obj_list, list)
+ {
+ if (obj_iter->range_size == 1)
+ {
+ bcmcli_session_print(session, "\t%s=%u (obj_type=%s, ref_count=%u)\n",
+ obj_rsc->obj_name, obj_iter->id, RSC_MGR_OBJ_TYPE_STR(obj_iter->type), obj_iter->ref_count);
+ }
+ else
+ {
+ bcmcli_session_print(session, "\t%s=%u .. %u (obj_type=%s, ref_count=%u)\n",
+ obj_rsc->obj_name, obj_iter->id, obj_iter->id + obj_iter->range_size - 1, RSC_MGR_OBJ_TYPE_STR(obj_iter->type), obj_iter->ref_count);
+ }
+ }
+}
+
+static void rsc_mgr_show_objs(bcmcli_session *session, bcmbal_intf_id access_int_id, rsc_mgr_obj_rsc *obj_rsc)
+{
+ bcmcli_session_print(session, "Base data %s=%u\n", obj_rsc->obj_name, obj_rsc->min_data_obj_id);
+ bcmcli_session_print(session, "Allocated %ss:\n", obj_rsc->obj_name);
+ rsc_mgr_show_objs_list(session, access_int_id, obj_rsc, &obj_rsc->allocated_objs);
+ bcmcli_session_print(session, "Free %ss:\n", obj_rsc->obj_name);
+ rsc_mgr_show_objs_list(session, access_int_id, obj_rsc, &obj_rsc->free_objs);
+}
+
+static bcmos_errno rsc_mgr_show(bcmcli_session *session, bcmbal_intf_id access_int_id)
+{
+ bcmos_errno rc;
+ rsc_mgr_topo_pon_context *topo_context;
+
+ rc = rsc_mgr_init_validate();
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
+ return rc;
+ }
+
+ if (!bcm_topo_pon_is_valid(access_int_id))
+ return BCM_ERR_PARM;
+
+ topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
+ rsc_mgr_show_objs(session, access_int_id, &topo_context->alloc_ids);
+ rsc_mgr_show_objs(session, access_int_id, &topo_context->gems);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno rsc_mgr_cli_cmd_show(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcmbal_intf_id access_int_id = (bcmbal_intf_id)bcmcli_find_named_parm(session, "key.access_int_id")->value.unumber;
+
+ return rsc_mgr_show(session, access_int_id);
+}
+
+void rsc_mgr_cli_init(bcmcli_entry *cli_dir)
+{
+ bcmcli_entry *dbg_dir;
+
+ static bcmcli_enum_val rsc_mgr_cli_enum_gem_type_table[] =
+ {
+ { .name = "unicast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST },
+ { .name = "multicast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST },
+ { .name = "broadcast", .val = RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST },
+ BCMCLI_ENUM_LAST
+ };
+
+ dbg_dir = bcmcli_dir_add(cli_dir, "rsc_mgr", "BAL resource manager API access", BCMCLI_ACCESS_ADMIN, NULL);
+
+ BCMCLI_MAKE_CMD(dbg_dir, "init", "Initialize resource manager for a specific access terminal", rsc_mgr_cli_cmd_init,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "base_alloc_id_set", "Set the base alloc ID for an access interface", rsc_mgr_cli_cmd_base_alloc_id_set,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("min_data_agg_port_id", "minimal data aggregation port ID", BCMCLI_PARM_UNUMBER, 0));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "base_gem_set", "Set the base GEM port for an access interface", rsc_mgr_cli_cmd_base_gem_set,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("min_data_svc_port_id", "minimal data service port ID", BCMCLI_PARM_UNUMBER, 0));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "alloc_id_alloc", "Allocate an alloc ID range or reuse an existing alloc ID range", rsc_mgr_cli_cmd_alloc_id_alloc,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("agg_port_id", "aggregation port ID (if omitted a new alloc ID is allocated, otherwise we reuse an existing alloc ID)",
+ BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL),
+ BCMCLI_MAKE_PARM_RANGE("range_size", "range size", BCMCLI_PARM_UNUMBER, 0, RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "alloc_id_free", "Free an alloc ID range", rsc_mgr_cli_cmd_alloc_id_free,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("agg_port_id", "base of alloc ID range", BCMCLI_PARM_UNUMBER, 0));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "gem_alloc", "Allocate a GEM port range or reuse an existing GEM port range", rsc_mgr_cli_cmd_gem_alloc,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("svc_port_id", "service port ID (if omitted a new GEM port is allocated, otherwise we reuse an existing GEM port)",
+ BCMCLI_PARM_UNUMBER, BCMCLI_PARM_FLAG_OPTIONAL),
+ BCMCLI_MAKE_PARM_RANGE("range_size", "range size", BCMCLI_PARM_UNUMBER, 0, RSC_MGR_MIN_RANGE_SIZE, RSC_MGR_MAX_RANGE_SIZE),
+ BCMCLI_MAKE_PARM_ENUM("gem_type", "GEM type", rsc_mgr_cli_enum_gem_type_table, 0));
+
+ BCMCLI_MAKE_CMD(dbg_dir, "gem_free", "Free a GEM port range", rsc_mgr_cli_cmd_gem_free,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0),
+ BCMCLI_MAKE_PARM("svc_port_id", "base of GEM port range", BCMCLI_PARM_UNUMBER, 0));
+
+ BCMCLI_MAKE_CMD_NOPARM(dbg_dir, "tm_sched_auto_id_alloc", "Allocate a tm node auto id or reuse an existing id", rsc_mgr_cli_cmd_tm_sched_auto_alloc);
+
+ BCMCLI_MAKE_CMD(dbg_dir, "tm_sched_auto_id_free", "Free a tm node auto id", rsc_mgr_cli_cmd_tm_sched_auto_free,
+ BCMCLI_MAKE_PARM("tm_sched_auto_id", "tm node auto id to be free", BCMCLI_PARM_UNUMBER, 0));
+
+
+ BCMCLI_MAKE_CMD(dbg_dir, "show", "Show the database of the resource manager", rsc_mgr_cli_cmd_show,
+ BCMCLI_MAKE_PARM_RANGE("key.access_term_id", "access terminal identifier", BCMCLI_PARM_UNUMBER, 0, 0, MAX_SUPPORTED_OLTS),
+ BCMCLI_MAKE_PARM("key.access_int_id", "access interface identifier", BCMCLI_PARM_UNUMBER, 0));
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_cli.h b/bal_release/src/lib/librscmgr/rsc_mgr_cli.h
new file mode 100644
index 0000000..7d9085c
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_cli.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#ifndef _RSC_MGR_CLI_H_
+#define _RSC_MGR_CLI_H_
+
+#include <bcmcli.h>
+
+void rsc_mgr_cli_init(bcmcli_entry *cli_dir);
+
+#endif
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_common.c b/bal_release/src/lib/librscmgr/rsc_mgr_common.c
new file mode 100644
index 0000000..71bcee9
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_common.c
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#include <bcm_topo.h>
+#include "rsc_mgr_common.h"
+
+#ifdef ENABLE_LOG
+dev_log_id rsc_mgr_log_id = DEV_LOG_INVALID_ID;
+#endif
+
+bcmos_errno rsc_mgr_init_validate(void)
+{
+ if (!rsc_mgr_context.is_initialized)
+ {
+#ifdef ENABLE_LOG
+ if (rsc_mgr_log_id == DEV_LOG_INVALID_ID)
+ {
+ rsc_mgr_log_id = bcm_dev_log_id_register("RSC_MGR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(rsc_mgr_log_id == DEV_LOG_INVALID_ID);
+ }
+#endif
+ return BCM_ERR_STATE;
+ }
+
+ if (!bcm_topo_is_initialized())
+ {
+ BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager cannot be called before topology is initialized\n");
+ return BCM_ERR_STATE;
+ }
+
+ return BCM_ERR_OK;
+}
+
diff --git a/bal_release/src/lib/librscmgr/rsc_mgr_common.h b/bal_release/src/lib/librscmgr/rsc_mgr_common.h
new file mode 100644
index 0000000..4d19176
--- /dev/null
+++ b/bal_release/src/lib/librscmgr/rsc_mgr_common.h
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#ifndef _RSC_MGR_COMMON_H_
+#define _RSC_MGR_COMMON_H_
+
+#include <bcmolt_host_api.h>
+#include <bcm_dev_log.h>
+#include <bal_objs.h>
+#include <bcmolt_math.h>
+
+#define RSC_MGR_MIN_RANGE_SIZE 1
+#define RSC_MGR_MAX_RANGE_SIZE 8
+
+#define RSC_MGR_PON_TOPO_CONTEXT(pon_id) ((rsc_mgr_topo_pon_context *)bcm_topo_pon_get_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR))
+
+typedef enum rsc_mgr_obj_type
+{
+ RSC_MGR_OBJ_TYPE_INVALID = 0,
+ RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST,
+ RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST,
+ RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST,
+ RSC_MGR_OBJ_TYPE_ALLOC_ID,
+ RSC_MGR_OBJ_TYPE_TM_SCHED,
+} rsc_mgr_obj_type;
+
+#define RSC_MGR_OBJ_TYPE_STR(_type) \
+ ((_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_UNICAST ? "gem_port_unicast":\
+ (_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_MULTICAST ? "gem_port_multicast":\
+ (_type) == RSC_MGR_OBJ_TYPE_GEM_PORT_BROADCAST ? "gem_port_broadcast":\
+ (_type) == RSC_MGR_OBJ_TYPE_ALLOC_ID ? "alloc_id":\
+ (_type) == RSC_MGR_OBJ_TYPE_TM_SCHED ? "tm_sched":"invalid")
+
+
+typedef struct
+{
+ bcmos_bool is_initialized;
+} rsc_mgr_context_t;
+
+extern rsc_mgr_context_t rsc_mgr_context;
+
+/** @brief container for storing user data */
+typedef struct rsc_mgr_user_data_entry
+{
+ TAILQ_ENTRY(rsc_mgr_user_data_entry) next;
+ void *user_data;
+} rsc_mgr_user_data_entry;
+
+/** @brief linked list of flow entries sharing the same GEM port or Alloc Id */
+typedef TAILQ_HEAD(, rsc_mgr_user_data_entry) shared_obj_user_data_list;
+
+/* An object ID can be either alloc ID or GEM port. */
+typedef uint32_t rsc_mgr_obj_id;
+
+/* An element for an object linked list. */
+typedef struct rsc_mgr_obj
+{
+ TAILQ_ENTRY(rsc_mgr_obj) list;
+ struct rsc_mgr_obj *base_obj; /* The last object of a range points to the base object of the range. */
+ rsc_mgr_obj_id id;
+ uint32_t ref_count;
+ uint32_t range_size;
+ rsc_mgr_obj_type type;
+ shared_obj_user_data_list user_data_list; /* this stores a list of flows sharing the same gem or alloc id object */
+} rsc_mgr_obj;
+
+typedef TAILQ_HEAD(, rsc_mgr_obj) rsc_mgr_obj_list;
+
+typedef bcmos_bool (*rsc_mgr_is_valid_data_obj_id_cb_t)(bcmolt_pon_ni pon_id, rsc_mgr_obj_id id, rsc_mgr_obj_id min_data_obj_id);
+typedef rsc_mgr_obj_id (*rsc_mgr_get_last_data_obj_id_cb_t)(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id);
+
+typedef struct
+{
+ const char *obj_name;
+ rsc_mgr_is_valid_data_obj_id_cb_t is_valid_data_obj_id_cb;
+ rsc_mgr_get_last_data_obj_id_cb_t get_last_data_obj_id_cb;
+ rsc_mgr_obj_list free_objs;
+ rsc_mgr_obj_list allocated_objs;
+ rsc_mgr_obj *objs; /* Dynamically allocated */
+ uint32_t num_of_objs;
+ rsc_mgr_obj_id min_data_obj_id;
+} rsc_mgr_obj_rsc;
+
+typedef struct
+{
+ rsc_mgr_obj_rsc alloc_ids;
+ rsc_mgr_obj_rsc gems;
+ uint16_t num_of_alloc_ids;
+ uint16_t num_of_gem_ports;
+#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
+ uint16_t multicast_gem_port; /* For validation purposes (validate there is no more than a single multicast GEM port per PON). */
+#endif
+#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
+ uint16_t broadcast_gem_port; /* For validation purposes (validate there is no more than a single broadcast GEM port per PON). */
+#endif
+#ifdef ENABLE_LOG
+ dev_log_id log_id;
+ char log_id_name[MAX_DEV_LOG_ID_NAME];
+#endif
+} rsc_mgr_topo_pon_context;
+
+typedef struct
+{
+ rsc_mgr_obj_rsc tm_sched_auto_key_ids;
+ uint16_t num_of_tm_sched_auto_key_ids;
+#ifdef ENABLE_LOG
+ dev_log_id log_id;
+ char log_id_name[MAX_DEV_LOG_ID_NAME];
+#endif
+
+} rsc_mgr_tm_context;
+#ifdef ENABLE_LOG
+extern dev_log_id rsc_mgr_log_id;
+#endif
+
+bcmos_errno rsc_mgr_init_validate(void);
+
+#endif
+