blob: bd8afec2bf50b376b9a97f7488291cfa0ae374e7 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32#include <bcmolt_host_api.h>
33#include <bcm_dev_log.h>
34#include <bal_objs.h>
35#include <bal_api.h>
36#include <bal_cli.h>
37#include <bcmolt_math.h>
38#include <bcm_topo.h>
39#include "rsc_mgr_common.h"
40#include "rsc_mgr.h"
41
42#define GPON_NUM_OF_ALLOC_IDS 1024
43#define XGPON_NUM_OF_ALLOC_IDS 2048
44
45#define GPON_NUM_OF_GEM_PORT_IDS_PER_PON 4096
46#define XGPON_NUM_OF_GEM_PORT_IDS_PER_PON 8192
47
48#define RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id) \
49 ((first_data_alloc_id) + (bcmolt_pon_alloc_id)(RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids - 1))
50#define RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id) ( \
51 ((alloc_id) >= (first_data_alloc_id) && (alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, first_data_alloc_id)))
52#define RSC_MGR_ALLOC_ID_IS_VALID(pon_id, alloc_id, first_data_alloc_id) ( \
53 ((alloc_id) <= RSC_MGR_ALLOC_ID_LAST_DEFAULT(pon_id)) || \
54 RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, alloc_id, first_data_alloc_id))
55
56#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))
57#define RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id) \
58 ((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))
59#define RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id) ( \
60 ((gem_port_id) >= (first_data_port_id) && (gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, first_data_port_id)))
61#define RSC_MGR_GEM_PORT_ID_IS_VALID(pon_id, gem_port_id, first_data_port_id) ( \
62 ((gem_port_id) <= RSC_MGR_GEM_PORT_ID_LAST_DEFAULT(pon_id)) || \
63 RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, gem_port_id, first_data_port_id))
64
65#define RSC_MGR_FOR_EACH_ALLOC_INDEX(pon_id, alloc_index) \
66 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++)
67
68#define RSC_MGR_FOR_EACH_GEM_INDEX(pon_id, gem_port_index) \
69 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++)
70
71#define RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(tm_sched_auto_index) \
72 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++)
73
74/* 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. */
75#define MIN_BASE_GEM_PORT_ID_GPON 256
76
77#define NUM_OF_TM_SCHED_AUTO_KEY_IDS 2048
78#define MIN_BASE_TM_SCHED_AUTO_ID 2048
79
80
81rsc_mgr_context_t rsc_mgr_context;
82rsc_mgr_tm_context tm_context;
83
84
85static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id);
86static 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);
87static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data);
88static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data);
89
90
91static 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)
92{
93 return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_ALLOC_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
94}
95
96static 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)
97{
98 return (rsc_mgr_obj_id)(bcmolt_pon_alloc_id)RSC_MGR_ALLOC_ID_LAST_DATA(pon_id, min_data_obj_id);
99}
100
101static 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)
102{
103 return (bcm_topo_pon_is_valid(pon_id) && RSC_MGR_GEM_PORT_ID_IS_VALID_DATA(pon_id, id, min_data_obj_id));
104}
105
106static rsc_mgr_obj_id rsc_mgr_get_last_data_gem_cb(bcmolt_pon_ni pon_id, rsc_mgr_obj_id min_data_obj_id)
107{
108 return (rsc_mgr_obj_id)(bcmolt_pon_gem_port_id)RSC_MGR_GEM_PORT_ID_LAST_DATA(pon_id, min_data_obj_id);
109}
110static bcmos_bool rsc_mgr_is_valid_data_tm_sched_auto_id(rsc_mgr_obj_id id)
111{
112 return (id >= MIN_BASE_TM_SCHED_AUTO_ID && id < MIN_BASE_TM_SCHED_AUTO_ID + NUM_OF_TM_SCHED_AUTO_KEY_IDS);
113}
114
115static 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)
116{
117 return rsc_mgr_is_valid_data_tm_sched_auto_id(id);
118}
119
120static 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)
121{
122 return (rsc_mgr_obj_id)(min_data_obj_id + NUM_OF_TM_SCHED_AUTO_KEY_IDS - 1);
123}
124
125
126static 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)
127{
128 rsc_mgr_obj *obj;
129 bcmos_errno rc;
130
131 if (range_size < RSC_MGR_MIN_RANGE_SIZE || range_size > RSC_MGR_MAX_RANGE_SIZE)
132 {
133 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);
134 return BCM_ERR_PARM;
135 }
136
137 if (*obj_id)
138 {
139 rc = rsc_mgr_obj_get(access_int_id, *obj_id, obj_rsc, &obj, log_id);
140 if (rc != BCM_ERR_OK)
141 return rc;
142
143 if (obj->range_size != range_size)
144 {
145 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",
146 obj_rsc->obj_name, range_size, obj->range_size);
147 return BCM_ERR_PARM;
148 }
149
150 if (obj->type != type)
151 {
152 BCM_LOG(ERROR, log_id, "When reusing %ss, type (%d) must be exactly the same as the type from creation (%u)\n",
153 obj_rsc->obj_name, type, obj->type);
154 return BCM_ERR_PARM;
155 }
156 }
157 else
158 {
159 rsc_mgr_obj *base_obj;
160 rsc_mgr_obj *last_obj;
161 rsc_mgr_obj *obj_iter;
162
163 /* Find the first free range that fits ("first-fit" algorithm). */
164 TAILQ_FOREACH(obj_iter, &obj_rsc->free_objs, list)
165 {
166 if (range_size <= obj_iter->range_size)
167 break;
168 }
169 if (!obj_iter)
170 {
171 BCM_LOG(ERROR, log_id, "No free %ss\n", obj_rsc->obj_name);
172 return BCM_ERR_NORES;
173 }
174 *obj_id = obj_iter->id;
175
176 if (range_size < obj_iter->range_size)
177 {
178 /* Insert a smaller range (decrease by 'range_size') to the list of free objects. It will replace the old free range. */
179 base_obj = &obj_iter[range_size];
180 last_obj = &obj_iter[obj_iter->range_size - 1];
181 TAILQ_INSERT_HEAD(&obj_rsc->free_objs, base_obj, list);
182 base_obj->range_size = obj_iter->range_size - range_size;
183 last_obj->base_obj = base_obj;
184 }
185
186 /* Move 'range_size' objects from the list of free objects to the list of allocated objects. */
187 base_obj = obj_iter;
188 last_obj = &obj_iter[range_size - 1];
189 TAILQ_REMOVE(&obj_rsc->free_objs, base_obj, list);
190 TAILQ_INSERT_HEAD(&obj_rsc->allocated_objs, base_obj, list);
191 base_obj->range_size = range_size;
192 base_obj->type = type;
193 last_obj->base_obj = base_obj;
194
195 obj = obj_iter;
196 /* since new object, initialize the user data list */
197 TAILQ_INIT(&obj->user_data_list);
198
199 }
200 obj->ref_count++;
201
202 /** store user data (flow entry pointer) in a linked list inside the object */
203 rsc_mgr_obj_store_user_data(obj, user_data);
204
205 return BCM_ERR_OK;
206}
207
208static 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)
209{
210 rsc_mgr_obj *obj;
211 rsc_mgr_obj *last_obj;
212 bcmos_errno rc;
213
214 rc = rsc_mgr_obj_get(access_int_id, obj_id, obj_rsc, &obj, log_id);
215 if (rc != BCM_ERR_OK)
216 return rc;
217
218 obj->ref_count--;
219 /** remove user data (flow entry pointer) from the linked list inside the object */
220 rsc_mgr_obj_remove_user_data(obj, user_data);
221
222 if (!obj->ref_count)
223 {
224 rsc_mgr_obj *next_obj = NULL;
225 rsc_mgr_obj *prev_obj = NULL;
226
227 /* Validate that going to the next object won't overflow the array. */
228 if (obj < &obj_rsc->objs[obj_rsc->num_of_objs - 1] && &obj[obj->range_size] <= &obj_rsc->objs[obj_rsc->num_of_objs - 1])
229 {
230 /* Check if the next ID is in the free list (according to its reference count).
231 * If true -> we can merge obj's range with the next range. */
232 if (!obj[obj->range_size].ref_count)
233 next_obj = &obj[obj->range_size];
234 }
235
236 /* Validate that going to the base of the previous range won't underflow the array. */
237 if (obj > obj_rsc->objs)
238 {
239 /* Check if the base ID of the previous range is in the free list (according to the base ID's reference count).
240 * If true -> we can merge obj's range with the previous range. */
241 if (obj[-1].base_obj && !obj[-1].base_obj->ref_count)
242 prev_obj = obj[-1].base_obj;
243 }
244
245 /* First remove the object from the allocated linked list. */
246 TAILQ_REMOVE(&obj_rsc->allocated_objs, obj, list);
247 last_obj = &obj[obj->range_size - 1];
248 obj->type = RSC_MGR_OBJ_TYPE_INVALID; /* Clear type. */
249 if (next_obj && !prev_obj)
250 {
251 /* Merge only with next range. */
252 TAILQ_INSERT_BEFORE(next_obj, obj, list);
253 TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
254 obj->range_size += next_obj->range_size;
255 last_obj->base_obj = NULL;
256 next_obj->range_size = 0;
257 last_obj = &obj[obj->range_size - 1];
258 last_obj->base_obj = obj;
259 }
260 else if (!next_obj && prev_obj)
261 {
262 /* Merge only with previous range. */
263 prev_obj->range_size += obj->range_size;
264 obj->range_size = 0;
265 last_obj->base_obj = prev_obj;
266 }
267 else if (next_obj && prev_obj)
268 {
269 /* Merge with both next and previous ranges. */
270 prev_obj->range_size += obj->range_size + next_obj->range_size;
271 obj->range_size = 0;
272 next_obj->range_size = 0;
273 TAILQ_REMOVE(&obj_rsc->free_objs, next_obj, list);
274 last_obj->base_obj = NULL;
275 last_obj = &prev_obj[prev_obj->range_size - 1];
276 last_obj->base_obj = prev_obj;
277 }
278 else
279 {
280 /* No merge at all. */
281 TAILQ_INSERT_TAIL(&obj_rsc->free_objs, obj, list);
282 }
283 }
284
285 return BCM_ERR_OK;
286}
287
288static 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)
289{
290 bcmos_errno rc;
291
292 rc = rsc_mgr_alloc_validate_common(access_int_id);
293 if (BCM_ERR_OK != rc)
294 return rc;
295
296 if (!obj_rsc->is_valid_data_obj_id_cb(access_int_id, obj_id, obj_rsc->min_data_obj_id))
297 {
298 BCM_LOG(ERROR, log_id, "%s must be in the range %u .. %u\n",
299 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));
300 return BCM_ERR_PARM;
301 }
302
303 *obj = &obj_rsc->objs[obj_id - obj_rsc->min_data_obj_id];
304 /* Only base object must have its reference count > 0. */
305 if (!(*obj)->ref_count)
306 {
307 BCM_LOG(ERROR, log_id, "%s hasn't been allocated before\n", obj_rsc->obj_name);
308 return BCM_ERR_PARM;
309 }
310
311 return BCM_ERR_OK;
312}
313
314/** @brief stores user passed in data in the linked list inside the obj */
315static bcmos_errno rsc_mgr_obj_store_user_data(rsc_mgr_obj *obj, void *user_data)
316{
317 rsc_mgr_user_data_entry *user_data_entry = NULL;
318
319 if (NULL == user_data)
320 return BCM_ERR_OK;
321
322 user_data_entry = bcmos_calloc(sizeof(rsc_mgr_user_data_entry));
323 user_data_entry->user_data = user_data;
324 TAILQ_INSERT_HEAD(&obj->user_data_list, user_data_entry, next);
325
326 return BCM_ERR_OK;
327}
328
329/** @brief removes user data from the linked list inside the obj */
330static bcmos_errno rsc_mgr_obj_remove_user_data(rsc_mgr_obj *obj, void *user_data)
331{
332 rsc_mgr_user_data_entry *user_data_entry = NULL, *user_data_entry_tmp;
333
334 if (NULL == user_data)
335 return BCM_ERR_OK;
336
337 TAILQ_FOREACH_SAFE(user_data_entry, &obj->user_data_list, next, user_data_entry_tmp)
338 {
339 if (user_data == user_data_entry->user_data)
340 break;
341 }
342 TAILQ_REMOVE(&obj->user_data_list, user_data_entry, next);
343
344 user_data_entry->user_data = NULL;
345 bcmos_free(user_data_entry);
346
347 return BCM_ERR_OK;
348}
349
350/** @brief iterator to iterate through the user data list in obj
351 * @note the assumption is if a NULL is returned, then caller code stop the iteration.
352 * */
353static void *rsc_mgr_obj_get_next_user_data(rsc_mgr_obj *obj, void **curr_user_data_entry, void **next_user_data_entry)
354{
355 if (NULL == *curr_user_data_entry)
356 {
357 *curr_user_data_entry = TAILQ_FIRST(&obj->user_data_list);
358 if (*curr_user_data_entry)
359 {
360 *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*curr_user_data_entry), next);
361 return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
362 }
363 }
364 else
365 {
366 *curr_user_data_entry = *next_user_data_entry;
367 if (*next_user_data_entry)
368 {
369 *next_user_data_entry = TAILQ_NEXT(((rsc_mgr_user_data_entry *)*next_user_data_entry), next);
370 return ((rsc_mgr_user_data_entry *)(*curr_user_data_entry))->user_data;
371 }
372 }
373
374 return NULL;
375}
376
377
378/* Alloc ID (aggregation port ID) */
379static 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)
380{
381 bcmolt_pon_alloc_index alloc_index;
382 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
383
384 if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
385 {
386 bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
387 bcmolt_gpon_ni_cfg_id failed_prop;
388
389 BCMOLT_CFG_PROP_SET(&gpon_ni_cfg, gpon_ni, min_data_alloc_id, min_data_agg_port_id);
390 if (!bcmolt_gpon_ni_cfg_data_bounds_check(&gpon_ni_cfg.data, (1ULL << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
391 {
392 BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
393 return BCM_ERR_PARM;
394 }
395 }
396 else
397 {
398 bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
399 bcmolt_xgpon_ni_cfg_id failed_prop;
400
401 BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_alloc_id, min_data_agg_port_id);
402 if (!bcmolt_xgpon_ni_cfg_data_bounds_check(&xgpon_ni_cfg.data, (1ULL << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID), &failed_prop))
403 {
404 BCM_LOG(ERROR, topo_context->log_id, "Minimal data alloc ID is not in the allowed range\n");
405 return BCM_ERR_PARM;
406 }
407 }
408
409 if (!TAILQ_EMPTY(&topo_context->alloc_ids.allocated_objs))
410 {
411 BCM_LOG(ERROR, topo_context->log_id, "Minimal alloc ID cannot be set when there are allocated alloc IDs\n");
412 return BCM_ERR_STATE;
413 }
414
415 topo_context->alloc_ids.min_data_obj_id = (rsc_mgr_obj_id)min_data_agg_port_id;
416 RSC_MGR_FOR_EACH_ALLOC_INDEX(access_int_id, alloc_index)
417 topo_context->alloc_ids.objs[alloc_index].id = topo_context->alloc_ids.min_data_obj_id + alloc_index;
418
419 return BCM_ERR_OK;
420}
421
422bcmos_errno rsc_mgr_access_int_base_alloc_id_set(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id min_data_agg_port_id)
423{
424 bcmos_errno rc;
425
426 rc = rsc_mgr_alloc_validate_common(access_int_id);
427 if (BCM_ERR_OK != rc)
428 return rc;
429
430 return _rsc_mgr_access_int_base_alloc_id_set(access_int_id, min_data_agg_port_id);
431}
432
433
434static bcmos_errno rsc_mgr_alloc_validate_common(bcmbal_intf_id access_int_id)
435{
436 bcmos_errno rc;
437
438 rc = rsc_mgr_init_validate();
439 if (rc != BCM_ERR_OK)
440 {
441 BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
442 return rc;
443 }
444
445 if (!bcm_topo_pon_is_valid(access_int_id))
446 return BCM_ERR_PARM;
447
448 return BCM_ERR_OK;
449}
450
451static bcmos_errno rsc_mgr_alloc_validate_non_unicast(bcmbal_intf_id access_int_id, bcmbal_service_port_id topo_context_gem_port,
452 bcmbal_service_port_id req_gem_port, uint32_t range_size, rsc_mgr_obj_type type,
453 dev_log_id log_id)
454{
455 if (topo_context_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID && req_gem_port && req_gem_port != topo_context_gem_port)
456 {
457 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);
458 return BCM_ERR_ALREADY;
459 }
460
461 if (range_size > 1)
462 {
463 BCM_LOG(ERROR, log_id, "Range bigger than 1 for %s GEM port is not allowed\n", RSC_MGR_OBJ_TYPE_STR(type));
464 return BCM_ERR_PARM;
465 }
466
467 return BCM_ERR_OK;
468}
469
470bcmos_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)
471{
472 bcmos_errno rc;
473 rsc_mgr_obj_id obj_id = *agg_port_id;
474 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
475
476 rc = rsc_mgr_alloc_validate_common(access_int_id);
477 if (BCM_ERR_OK != rc)
478 return rc;
479
480 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);
481 *agg_port_id = obj_id;
482
483 return rc;
484}
485
486bcmos_errno rsc_mgr_alloc_id_free(bcmbal_intf_id access_int_id, bcmbal_aggregation_port_id agg_port_id, void *user_data)
487{
488 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
489
490 if (!bcm_topo_pon_is_valid(access_int_id))
491 return BCM_ERR_PARM;
492
493 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);
494}
495
496bcmos_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)
497{
498 rsc_mgr_obj *obj;
499 bcmos_errno rc;
500 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
501
502 rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
503 if (rc != BCM_ERR_OK)
504 return rc;
505
506 *ref_count = obj->ref_count;
507
508 return BCM_ERR_OK;
509}
510
511/** @brief iterates through user data list of an alloc id object */
512void *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)
513{
514 rsc_mgr_obj *obj;
515 bcmos_errno rc;
516 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
517
518 rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)agg_port_id, &topo_context->alloc_ids, &obj, topo_context->log_id);
519 if (rc != BCM_ERR_OK)
520 return NULL;
521
522 return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry);
523}
524
525/* GEM (service port ID) */
526static bcmos_errno _rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
527{
528 bcmolt_pon_gem_port_index gem_index;
529 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
530
531 if (bcm_topo_pon_get_pon_mode(access_int_id) == BCM_TOPO_PON_MODE_GPON)
532 {
533 bcmolt_gpon_gem_port_cfg gpon_gem_port_cfg = { .key.gem_port_id = min_data_svc_port_id };
534 bcmolt_gpon_gem_port_key_id failed_prop;
535
536 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) ||
537 min_data_svc_port_id < MIN_BASE_GEM_PORT_ID_GPON)
538 {
539 BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
540 return BCM_ERR_PARM;
541 }
542 }
543 else
544 {
545 bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
546 bcmolt_xgpon_ni_cfg_id failed_prop;
547
548 BCMOLT_CFG_PROP_SET(&xgpon_ni_cfg, xgpon_ni, min_data_gem_port_id, min_data_svc_port_id);
549 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))
550 {
551 BCM_LOG(ERROR, topo_context->log_id, "Minimal data GEM port is not in the allowed range\n");
552 return BCM_ERR_PARM;
553 }
554 }
555
556 if (!TAILQ_EMPTY(&topo_context->gems.allocated_objs))
557 {
558 BCM_LOG(ERROR, topo_context->log_id, "Minimal GEM port cannot be set when there are allocated GEM ports\n");
559 return BCM_ERR_STATE;
560 }
561
562 topo_context->gems.min_data_obj_id = (rsc_mgr_obj_id)min_data_svc_port_id;
563 RSC_MGR_FOR_EACH_GEM_INDEX(access_int_id, gem_index)
564 topo_context->gems.objs[gem_index].id = topo_context->gems.min_data_obj_id + gem_index;
565
566 return BCM_ERR_OK;
567}
568
569bcmos_errno rsc_mgr_access_int_base_gem_set(bcmbal_intf_id access_int_id, bcmbal_service_port_id min_data_svc_port_id)
570{
571 bcmos_errno rc;
572
573 rc = rsc_mgr_alloc_validate_common(access_int_id);
574 if (BCM_ERR_OK != rc)
575 return rc;
576
577 return _rsc_mgr_access_int_base_gem_set(access_int_id, min_data_svc_port_id);
578}
579
580static bcmos_errno _rsc_mgr_base_tm_sched_auto_id_set (bcmbal_tm_sched_id min_tm_sched_auto_id)
581{
582 bcmbal_tm_sched_id_index i;
583
584
585 if (!TAILQ_EMPTY(&tm_context.tm_sched_auto_key_ids.allocated_objs))
586 {
587 BCM_LOG(ERROR, tm_context.log_id, "Minimal tm node auto id cannot be set when there are allocated ids \n");
588 return BCM_ERR_STATE;
589 }
590
591 tm_context.tm_sched_auto_key_ids.min_data_obj_id = (rsc_mgr_obj_id)min_tm_sched_auto_id;
592 RSC_MGR_FOR_EACH_TM_SCHED_AUTO_INDEX(i)
593 {
594 tm_context.tm_sched_auto_key_ids.objs[i].id = tm_context.tm_sched_auto_key_ids.min_data_obj_id + i;
595 }
596
597 return BCM_ERR_OK;
598}
599
600bcmos_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)
601{
602 bcmos_errno rc;
603 rsc_mgr_topo_pon_context *topo_context = NULL;
604 rsc_mgr_obj_id obj_id = *svc_port_id;
605
606 rc = rsc_mgr_alloc_validate_common(access_int_id);
607 if (BCM_ERR_OK != rc)
608 return rc;
609
610 topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
611
612 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);
613 *svc_port_id = obj_id;
614
615 return rc;
616}
617
618
619bcmos_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)
620{
621 bcmos_errno rc;
622 rsc_mgr_topo_pon_context *topo_context = NULL;
623 rsc_mgr_obj_id obj_id = *svc_port_id;
624
625 rc = rsc_mgr_alloc_validate_common(access_int_id);
626 if (BCM_ERR_OK != rc)
627 return rc;
628
629 topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
630#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
631 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);
632
633 if (topo_context->multicast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
634 obj_id = topo_context->multicast_gem_port; /* This will cause the reference count of the multicast GEM to increase. */
635#endif
636
637 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);
638 *svc_port_id = obj_id;
639
640#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
641 if (!rc)
642 RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = *svc_port_id;
643#endif
644
645 return rc;
646}
647
648bcmos_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)
649{
650 bcmos_errno rc;
651 rsc_mgr_topo_pon_context *topo_context = NULL;
652 rsc_mgr_obj_id obj_id = *svc_port_id;
653
654 rc = rsc_mgr_alloc_validate_common(access_int_id);
655 if (BCM_ERR_OK != rc)
656 return rc;
657
658 topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
659#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
660 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);
661
662 if (topo_context->broadcast_gem_port != BCMOLT_PON_GEM_PORT_ID_INVALID)
663 obj_id = topo_context->broadcast_gem_port; /* This will cause the reference count of the broadcast GEM to increase. */
664#endif
665
666 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);
667 *svc_port_id = obj_id;
668
669#ifndef MULTIPLE_BROADCAST_GEM_PORTS_PER_PON
670 if (!rc)
671 RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->broadcast_gem_port = *svc_port_id;
672#endif
673
674 return rc;
675}
676
677bcmos_errno rsc_mgr_gem_free(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, void *user_data)
678{
679 bcmos_errno rc;
680#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
681 rsc_mgr_topo_pon_context *topo_context;
682#endif
683
684 if (!bcm_topo_pon_is_valid(access_int_id))
685 return BCM_ERR_PARM;
686
687#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
688 topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
689#endif
690
691 rc = rsc_mgr_obj_free(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, user_data, topo_context->log_id);
692
693#ifndef MULTIPLE_MULTICAST_GEM_PORTS_PER_PON
694 if (!rc && topo_context->multicast_gem_port == svc_port_id)
695 RSC_MGR_PON_TOPO_CONTEXT(access_int_id)->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
696#endif
697
698 return rc;
699}
700
701bcmos_errno rsc_mgr_gem_get_ref_count(bcmbal_intf_id access_int_id, bcmbal_service_port_id svc_port_id, uint32_t *ref_count)
702{
703 rsc_mgr_obj *obj;
704 bcmos_errno rc;
705 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
706
707 rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
708 if (rc != BCM_ERR_OK)
709 return rc;
710
711 *ref_count = obj->ref_count;
712
713 return BCM_ERR_OK;
714}
715
716/** @brief iterates through user data list of a gem object */
717void *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)
718{
719 rsc_mgr_obj *obj;
720 bcmos_errno rc;
721 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(access_int_id);
722
723 rc = rsc_mgr_obj_get(access_int_id, (rsc_mgr_obj_id)svc_port_id, &topo_context->gems, &obj, topo_context->log_id);
724 if (rc != BCM_ERR_OK)
725 return NULL;
726
727 return rsc_mgr_obj_get_next_user_data(obj, curr_user_data_entry, next_user_data_entry);
728}
729
730
731
732bcmos_errno _rsc_mgr_tm_sched_auto_id_alloc(bcmbal_tm_sched_id *tm_sched_id)
733{
734 bcmos_errno rc;
735 rsc_mgr_obj_id obj_id = *tm_sched_id;
736
737 rc = rsc_mgr_init_validate();
738 if (rc != BCM_ERR_OK)
739 {
740 BCM_LOG(ERROR, rsc_mgr_log_id, "Resource manager is uninitialized\n");
741 return rc;
742 }
743
744 /* Allocate a new object. */
745 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);
746 *tm_sched_id = obj_id;
747
748 return rc;
749}
750
751bcmos_errno _rsc_mgr_tm_sched_auto_id_free(bcmbal_tm_sched_id tm_sched_id)
752{
753 bcmos_errno rc;
754
755 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);
756
757 return rc;
758}
759
760bcmos_errno _rsc_mgr_tm_sched_auto_id_get_ref_count(bcmbal_tm_sched_id tm_sched_id, uint32_t *ref_count)
761{
762 rsc_mgr_obj *obj;
763 bcmos_errno rc;
764
765 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);
766 if (rc != BCM_ERR_OK)
767 return rc;
768
769 *ref_count = obj->ref_count;
770
771 return BCM_ERR_OK;
772}
773
774bcmos_bool _rsc_mgr_tm_sched_id_validate(bcmbal_tm_sched_id tm_sched_key_id)
775{
776 return (!rsc_mgr_is_valid_data_tm_sched_auto_id(tm_sched_key_id));
777}
778
779static 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,
780 rsc_mgr_get_last_data_obj_id_cb_t get_last_data_obj_id_cb, uint32_t num_of_objs, const char *obj_name)
781{
782 rsc_mgr_obj *obj;
783
784 obj_rsc->obj_name = obj_name;
785 obj_rsc->is_valid_data_obj_id_cb = is_valid_data_obj_id_cb;
786 obj_rsc->get_last_data_obj_id_cb = get_last_data_obj_id_cb;
787 TAILQ_INIT(&obj_rsc->free_objs);
788 TAILQ_INIT(&obj_rsc->allocated_objs);
789 obj_rsc->objs = bcmos_calloc(num_of_objs * sizeof(*obj_rsc->objs));
790 obj_rsc->num_of_objs = num_of_objs;
791
792 /* Insert a first entry to the list of free objects. */
793 obj = &obj_rsc->objs[0];
794 obj->range_size = num_of_objs;
795 TAILQ_INSERT_HEAD(&obj_rsc->free_objs, obj, list);
796}
797
798static void rsc_mgr_uninit_obj_rsc(rsc_mgr_obj_rsc *obj_rsc)
799{
800 bcmos_free(obj_rsc->objs);
801}
802
803bcmos_errno rsc_mgr_mac_init(void)
804{
805 bcmos_errno rc = BCM_ERR_OK;
806 bcmolt_devid device_id;
807 uint32_t pon_id;
808 rsc_mgr_topo_pon_context *topo_context, *old_topo_context;
809
810 do
811 {
812 rc = rsc_mgr_init_validate();
813 if (rc != BCM_ERR_OK)
814 {
815 BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was not initialized");
816 break;
817 }
818 BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
819 {
820 old_topo_context = bcm_topo_pon_get_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR);
821 if (old_topo_context)
822 {
823 bcmos_free(old_topo_context);
824 }
825 topo_context = bcmos_calloc(sizeof(*topo_context));
826 if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
827 {
828 topo_context->num_of_alloc_ids = GPON_NUM_OF_ALLOC_IDS;
829 topo_context->num_of_gem_ports = GPON_NUM_OF_GEM_PORT_IDS_PER_PON;
830 }
831 else
832 {
833 topo_context->num_of_alloc_ids = XGPON_NUM_OF_ALLOC_IDS;
834 topo_context->num_of_gem_ports = XGPON_NUM_OF_GEM_PORT_IDS_PER_PON;
835 }
836 topo_context->multicast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
837 topo_context->broadcast_gem_port = BCMOLT_PON_GEM_PORT_ID_INVALID;
838 bcm_topo_pon_set_context(pon_id, BCM_TOPO_PON_CONTEXT_ID_RSC_MGR, topo_context);
839#ifdef ENABLE_LOG
840 snprintf(topo_context->log_id_name, sizeof(topo_context->log_id_name), "RSC_MGR%u", pon_id);
841 topo_context->log_id = bcm_dev_log_id_register(topo_context->log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
842 BUG_ON(topo_context->log_id == DEV_LOG_INVALID_ID);
843#endif
844 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,
845 RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_alloc_ids, "alloc ID");
846 rsc_mgr_init_obj_rsc(&topo_context->gems, rsc_mgr_is_valid_data_gem_cb, rsc_mgr_get_last_data_gem_cb,
847 RSC_MGR_PON_TOPO_CONTEXT(pon_id)->num_of_gem_ports, "GEM port");
848
849 if (bcm_topo_pon_get_pon_mode(pon_id) == BCM_TOPO_PON_MODE_GPON)
850 {
851 bcmolt_gpon_ni_cfg gpon_ni_cfg = {};
852
853 bcmolt_gpon_ni_cfg_data_set_default(&gpon_ni_cfg.data, 1 << BCMOLT_GPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
854 _rsc_mgr_access_int_base_alloc_id_set(pon_id, gpon_ni_cfg.data.min_data_alloc_id);
855
856 _rsc_mgr_access_int_base_gem_set(pon_id, MIN_BASE_GEM_PORT_ID_GPON);
857 }
858 else
859 {
860 bcmolt_xgpon_ni_cfg xgpon_ni_cfg = {};
861
862 bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_ALLOC_ID);
863 _rsc_mgr_access_int_base_alloc_id_set(pon_id, xgpon_ni_cfg.data.min_data_alloc_id);
864
865 bcmolt_xgpon_ni_cfg_data_set_default(&xgpon_ni_cfg.data, 1 << BCMOLT_XGPON_NI_CFG_ID_MIN_DATA_GEM_PORT_ID);
866 _rsc_mgr_access_int_base_gem_set(pon_id, xgpon_ni_cfg.data.min_data_gem_port_id);
867 }
868 }
869
870 }while(0);
871 return rc;
872}
873
874bcmos_errno rsc_mgr_init(void)
875{
876 if (rsc_mgr_init_validate() == BCM_ERR_OK)
877 {
878 BCM_LOG(INFO, rsc_mgr_log_id, "Resource Manager was already initialized");
879 return BCM_ERR_OK;
880 }
881
882#ifdef ENABLE_LOG
883 if (rsc_mgr_log_id == DEV_LOG_INVALID_ID)
884 {
885 rsc_mgr_log_id = bcm_dev_log_id_register("RSC_MGR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
886 BUG_ON(rsc_mgr_log_id == DEV_LOG_INVALID_ID);
887 }
888#endif
889
890 /*Init the tm object*/
891 tm_context.num_of_tm_sched_auto_key_ids = NUM_OF_TM_SCHED_AUTO_KEY_IDS;
892 snprintf(tm_context.log_id_name , sizeof(tm_context.log_id_name) , "RSC_MGR_TM");
893 tm_context.log_id = bcm_dev_log_id_register(tm_context.log_id_name, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
894 BUG_ON(tm_context.log_id == DEV_LOG_INVALID_ID);
895
896 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,
897 tm_context.num_of_tm_sched_auto_key_ids, "TM node auto id");
898
899 _rsc_mgr_base_tm_sched_auto_id_set(MIN_BASE_TM_SCHED_AUTO_ID);
900
901 rsc_mgr_context.is_initialized = BCMOS_TRUE;
902 return BCM_ERR_OK;
903}
904
905void rsc_mgr_uninit(void)
906{
907 bcmolt_devid device_id;
908 uint32_t pon_id;
909
910 if (!rsc_mgr_context.is_initialized)
911 return;
912
913 BCM_TOPO_FOR_EACH_PON(device_id, pon_id)
914 {
915 rsc_mgr_topo_pon_context *topo_context = RSC_MGR_PON_TOPO_CONTEXT(pon_id);
916
917 rsc_mgr_uninit_obj_rsc(&topo_context->gems);
918 rsc_mgr_uninit_obj_rsc(&topo_context->alloc_ids);
919 }
920 rsc_mgr_context.is_initialized = BCMOS_FALSE;
921}
922