blob: 50424cb4b789c134fa1001e9ab7ed3d32d6f6106 [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/**
33 * @file tm_sched_fsm.c
34 * @brief Code to support the BAL tm_sched FSM
35 *
36 *
37 */
38
39/*@{*/
40
41#include <bcmos_system.h>
42#include <tm_sched_fsm.h>
43#include <bal_msg.h>
44#include <bal_osmsg.h>
45#include "bal_worker.h"
46#include "bal_mac_util.h"
47#include "bal_switch_util.h"
48#include <bal_api.h>
49//#include <bal_mac_util_common_itu_pon.h>
50
51
52#include <bal_objs.h>
53#include <fsm_common.h>
54
55#ifdef ENABLE_LOG
56#include <bcm_dev_log.h>
57
58 /*
59 * @brief The logging device id for tm sched
60 */
61static dev_log_id log_id_tm_sched;
62#endif
63
64/* local function declarations */
65
66static bcmos_errno tm_sched_fsm_create(tm_sched_inst *p_tm_sched_inst,
67 void *msg,
68 tm_sched_fsm_event *p_event);
69
70static bcmos_errno tm_sched_free_by_entry(tm_sched_inst *p_entry);
71static void tm_sched_inst_entry_obj_init(tm_sched_inst *p_entry);
72static bcmos_errno queues_list_fill(tm_sched_inst *p_tm_sched_inst,
73 bcmbal_tm_queue_id_list_u8 *queues_list);
74
75
76static bcmos_errno tm_sched_fsm_state_err(tm_sched_inst *p_tm_sched_inst,
77 void *msg,
78 tm_sched_fsm_event *p_event);
79static bcmos_errno tm_sched_fsm_assigned_process_util_msg(tm_sched_inst *p_tm_sched_inst,
80 void *msg,
81 tm_sched_fsm_event *p_event);
82static bcmos_errno tm_sched_fsm_deleting_process_util_msg(tm_sched_inst *p_tm_sched_inst,
83 void *msg,
84 tm_sched_fsm_event *p_event);
85
86static bcmos_errno tm_sched_fsm_inactive_destroy(tm_sched_inst *p_tm_sched_inst,
87 void *msg,
88 tm_sched_fsm_event *p_event);
89
90static bcmos_errno tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst,
91 void *msg,
92 tm_sched_fsm_event *p_event);
93
94static bcmos_errno tm_sched_fsm_assigned_destroy(tm_sched_inst *p_tm_sched_inst,
95 void *msg,
96 tm_sched_fsm_event *p_event);
97
98static bcmos_errno tm_sched_fsm_destroy(tm_sched_inst *p_tm_sched_inst);
99
100static bcmos_errno tm_sched_fsm_exec(tm_sched_inst *p_tm_sched_inst, tm_sched_fsm_event *p_event);
101
102static tm_sched_inst* tm_sched_find_by_owner(bcmbal_tm_sched_owner owner);
103
104static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id);
105static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id);
106
107static bcmos_errno sub_scheds_list_fill(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id_list_u8 *sub_scheds_list);
108/*
109 * @brief The Global tm_sched fsm context data structure
110 */
111static tm_sched_fsm_ctx g_tm_sched_fsm_tm_sched_list_ctx;
112
113/*
114 * Macros for tm_sched ctx access
115 */
116#define TM_SCHED_FSM_TM_SCHED_LIST_CTX (g_tm_sched_fsm_tm_sched_list_ctx)
117#define TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR (&g_tm_sched_fsm_tm_sched_list_ctx)
118
119
120/*
121 * @brief The definition of a tm_sched FSM state processing function
122 */
123typedef bcmos_errno (* tm_sched_fsm_state_processor)(tm_sched_inst *, void *, tm_sched_fsm_event *);
124/*
125 * @brief The tm sched FSM state processing array
126 */
127static tm_sched_fsm_state_processor tm_sched_states[TM_SCHED_FSM_STATE__NUM_OF][TM_SCHED_FSM_EVENT_TYPE__NUM_OF] =
128{
129
130 [TM_SCHED_FSM_STATE_NULL] =
131 {
132 [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_create,
133 [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_state_err,
134 [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
135 [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
136
137 },
138 [TM_SCHED_FSM_STATE_INACTIVE] =
139 {
140 [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
141 [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_inactive_destroy,
142 [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
143 [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
144 },
145 [TM_SCHED_FSM_STATE_ASSIGNED] =
146 {
147 [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
148 [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_assigned_destroy,
149 [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
150 [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_assigned_process_util_msg,
151 },
152 [TM_SCHED_FSM_STATE_ACTIVE] =
153 {
154 [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
155 [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_active_destroy,
156 [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
157 [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
158 },
159
160 [TM_SCHED_FSM_STATE_DELETING] =
161 {
162 [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
163 [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_state_err,
164 [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
165 [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_deleting_process_util_msg,
166
167 },
168
169};
170
171static char *state_name_str[] =
172{
173 "TM_SCHED_FSM_STATE_NULL",
174 "TM_SCHED_FSM_STATE_INACTIVE",
175 "TM_SCHED_FSM_STATE_ASSIGNED",
176 "TM_SCHED_FSM_STATE_ACTIVE",
177 "TM_SCHED_FSM_STATE_DELETING",
178};
179
180/* Ensure that the name array size matches the associated enum */
181BAL_STATIC_ASSERT(TM_SCHED_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), tm_sched_fsm_state);
182
183static char *tm_sched_state_name_get(tm_sched_fsm_state state)
184{
185 if(state < TM_SCHED_FSM_STATE__LAST)
186 {
187 return state_name_str[state];
188 }
189 else
190 {
191 return "TM_SCHED_UNKNOWN";
192 }
193}
194
195static char *event_name_str[] =
196{
197 "TM_SCHED_FSM_CREATE_EVENT",
198 "TM_SCHED_FSM_DESTROY_EVENT",
199 "TM_SCHED_FSM_ASSIGN_EVENT",
200 "FLOW_FSM_UTIL_MSG_EVENT",
201};
202
203/* Ensure that the name array size matches the associated enum */
204BAL_STATIC_ASSERT(TM_SCHED_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), tm_sched_fsm_event_type);
205
206static char *tm_sched_event_name_get(tm_sched_fsm_event_type event)
207{
208 if(event < TM_SCHED_FSM_EVENT_TYPE__LAST)
209 {
210 return event_name_str[event];
211 }
212 else
213 {
214 return "TM_SCHED_EVT_UNKNOWN";
215 }
216}
217
218
219
220
221/*****************************************************************************/
222/**
223 * @brief A function to initialize the tm sched FSM infrastructure.
224 *
225 * NOTE: This is called once on startup and NOT for each FSM instance.
226 *
227 * @returns bcmos_errno
228 *****************************************************************************/
229bcmos_errno tm_sched_fsm_init(void)
230{
231 int ii;
232 tm_sched_inst *new_entry;
233 bcmos_errno ret = BCM_ERR_OK;
234
235#ifdef ENABLE_LOG
236 log_id_tm_sched = bcm_dev_log_id_register("TM_SCHED", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
237 BUG_ON(log_id_tm_sched == DEV_LOG_INVALID_ID);
238#endif
239
240 /* Initialize all of the tm_sched queues */
241 TAILQ_INIT(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list);
242 TAILQ_INIT(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list);
243
244 /* Populate the free list with it's initial set of tm_scheds */
245 for(ii=0; ii<TM_SCHED_ALLOCATION_BLOCK_SIZE; ii++)
246 {
247
248 new_entry = bcmos_calloc(sizeof(tm_sched_inst));
249
250 if(NULL == new_entry)
251 {
252 BCM_LOG(FATAL, log_id_tm_sched, "Failed to initialize the tm_sched free list - FATAL\n");
253 ret = BCM_ERR_NOMEM;
254 break;
255 }
256
257 tm_sched_free_by_entry(new_entry);
258 }
259
260 return ret;
261}
262
263/*****************************************************************************/
264/**
265 * @brief A function to un-initialize the tm sched FSM infrastructure.
266 *
267 * NOTE: This is called once on shutdown and NOT for each FSM instance.
268 *
269 * @returns bcmos_errno
270 *****************************************************************************/
271bcmos_errno tm_sched_fsm_finish(void)
272{
273
274 tm_sched_inst *current_entry, *p_temp_entry;
275
276 /* Free all the entries on the active list */
277 TAILQ_FOREACH_SAFE(current_entry,
278 &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
279 tm_sched_inst_next,
280 p_temp_entry)
281 {
282 /* Remove it from the active list */
283 TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
284
285 bcmos_free(current_entry);
286
287 }
288
289 /* Free all the entries on the free list */
290 TAILQ_FOREACH_SAFE(current_entry,
291 &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list,
292 tm_sched_inst_next,
293 p_temp_entry)
294 {
295 /* Remove it from the active list */
296 TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, current_entry, tm_sched_inst_next);
297
298 bcmos_free(current_entry);
299 }
300
301 return BCM_ERR_OK;
302}
303
304/*****************************************************************************/
305/**
306 * @brief A function to retrieve a tm_sched instance of the specified class.
307 *
308 * @param key A pointer to the key of the tm_sched being referenced
309 * @param search_flag A flag specifying the type of tm_sched
310 * instance to be retrieved
311 *
312 * @returns tm_sched_inst_t* A pointer to the found tm_sched instance,
313 * or NULL if one is not found
314 *****************************************************************************/
315tm_sched_inst *tm_sched_inst_get(bcmbal_tm_sched_key key, tm_sched_flag search_flag)
316{
317 tm_sched_inst *current_entry = NULL;
318
319 /*
320 * First, check the active list if the caller has chosen to do so
321 */
322 if(TM_SCHED_FLAG_ACTIVE & search_flag)
323 {
324 TAILQ_FOREACH(current_entry,
325 &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
326 tm_sched_inst_next)
327 {
328
329 if(current_entry->req_tm_sched_info.key.id == key.id
330 && current_entry->req_tm_sched_info.key.dir == key.dir)
331 {
332 BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched\n");
333 /* The tm_sched instance pointer is in current_entry */
334 break;
335 }
336 }
337 }
338
339 /*
340 * Next, check the free list if the caller has chosen to do so
341 */
342 if((TM_SCHED_FLAG_FREE & search_flag) && (NULL == current_entry))
343 {
344 /* Now check the free list */
345 if(!TAILQ_EMPTY(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list))
346 {
347 /* Just grab the first entry */
348 current_entry = TAILQ_FIRST(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list);
349
350 /* Remove it from the free list */
351 TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, current_entry, tm_sched_inst_next);
352
353 /* And add it to the active list */
354 TAILQ_INSERT_TAIL(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
355
356 /*
357 * Initialize the fsm state
358 */
359 current_entry->fsm_state = TM_SCHED_FSM_STATE_NULL;
360
361 BCM_LOG(DEBUG, log_id_tm_sched, "Using new tm_sched\n");
362
363 }
364 }
365
366 if((TM_SCHED_FLAG_ANY & search_flag) && (NULL == current_entry))
367 {
368 /*A tm_sched was not found on either list */
369
370 BCM_LOG(DEBUG, log_id_tm_sched, "************** ERROR: no tm_sched found\n");
371 }
372
373 return current_entry;
374}
375
376static bcmos_errno bcmbal_tm_sched_validate_sched_parent(const bcmbal_tm_sched_cfg *p_tm_sched_cfg, tm_sched_inst **p_parent_tm_sched_inst)
377{
378 bcmos_errno ret = BCM_ERR_OK;
379 bcmbal_tm_sched_key tm_sched_key;
380 tm_sched_key.dir = p_tm_sched_cfg->key.dir;
381 tm_sched_key.id = p_tm_sched_cfg->data.sched_parent.sched_id;
382
383 do
384 {
385 (*p_parent_tm_sched_inst) = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
386 if(NULL == (*p_parent_tm_sched_inst))
387 {
388 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent dir = %s id = %d does not exist and therefor can not be set at the tm sched parent\n",
389 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
390 ret = BCM_ERR_NOENT;
391 break;
392 }
393
394 /*check weight/priority setting based on parent sched_type*/
395 if(BCMBAL_TM_SCHED_TYPE_SP == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
396 {
397 if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority))
398 {
399 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with a priority, as its sched_parent' sched_type is sp\n");
400 ret = BCM_ERR_PARM;
401 break;
402 }
403 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
404 {
405 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent can not be set with a weight, as its sched_parent' sched_type is sp\n");
406 ret = BCM_ERR_PARM;
407 break;
408 }
409 if(p_tm_sched_cfg->data.sched_parent.priority >= (*p_parent_tm_sched_inst)->req_tm_sched_info.data.num_priorities)
410 {
411 BCM_LOG(ERROR, log_id_tm_sched, "sched priority (%d) is higher than the allowed at parent sched (id = %d dir = %s num of priorities = %d )\n",
412 p_tm_sched_cfg->data.sched_parent.priority , tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir),
413 (*p_parent_tm_sched_inst)->req_tm_sched_info.data.num_priorities);
414
415 ret = BCM_ERR_PARM;
416 break;
417 }
418 }
419 else
420 if(BCMBAL_TM_SCHED_TYPE_WFQ == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
421 {
422 if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
423 {
424 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with a weight, as its sched_parent' sched_type is wrr\n");
425 ret = BCM_ERR_PARM;
426 break;
427 }
428 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority))
429 {
430 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent can not be set with a priority, as its sched_parent' sched_type is wrr \n");
431 ret = BCM_ERR_PARM;
432 break;
433 }
434 }
435 else
436 if(BCMBAL_TM_SCHED_TYPE_SP_WFQ == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
437 {
438 if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority)
439 && BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
440 {
441 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with either weight or priority, not both. as its sched_parent' sched_type is sp_wrr\n");
442 ret = BCM_ERR_PARM;
443 break;
444 }
445 if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority)
446 && !BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
447 {
448 BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with either weight or priority, as its sched_parent' sched_type is sp_wrr\n");
449 ret = BCM_ERR_PARM;
450 break;
451 }
452 }
453 }while(0);
454
455 return ret;
456
457}
458
459/*****************************************************************************/
460/**
461 * @brief tm_sched_fsm_info_validate
462 *
463 * This routine is used to validate all input attributes required for a tm_sched
464 * settings
465 *
466 * @param p_tm_sched_cfg A pointer to a tm sched object
467 *
468 * @return bcmos_errno
469 */
470/*****************************************************************************/
471static bcmos_errno tm_sched_fsm_info_validate(const bcmbal_tm_sched_cfg *p_tm_sched_cfg)
472{
473 bcmos_errno ret = BCM_ERR_OK;
474 bcmbal_tm_sched_owner owner = p_tm_sched_cfg->data.owner;
475 bcmbal_interface_key intf_key;
476 bcmbal_subscriber_terminal_key sub_term_key;
477 sub_term_inst *p_sub_term_inst = NULL;
478 tm_sched_inst *p_tm_sched_inst;
479 bcmos_bool is_sched_type_and_level_mandatory = BCMOS_TRUE;
480
481 do
482 {
483 if(!_rsc_mgr_tm_sched_id_validate(p_tm_sched_cfg->key.id))
484 {
485 BCM_LOG(ERROR, log_id_tm_sched,
486 "Illegal tm sched id (reserved for auto created) \n");
487 ret = BCM_ERR_PARM;
488 break;
489 }
490
491 if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, owner))
492 {
493 switch(owner.type)
494 {
495 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
496 {
497 /*tm sched owned by agg port is the only case sched type might be unset*/
498 is_sched_type_and_level_mandatory = BCMOS_FALSE;
499
500 if(BCMBAL_TM_SCHED_DIR_US != p_tm_sched_cfg->key.dir)
501 {
502 BCM_LOG(ERROR, log_id_tm_sched,
503 "tm sched owned by agg port must be of US direction, while tm sched id = %d is not\n", p_tm_sched_cfg->key.dir);
504 return BCM_ERR_PARM;
505 }
506 /*agg port owned tm sched can not be part of hqos, therefor can not have sched parent set*/
507 if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_parent))
508 {
509 BCM_LOG(ERROR, log_id_tm_sched,
510 "tm sched owned by agg port is a tsand alone and can not have sched_parent set to it");
511 return BCM_ERR_PARM;
512 }
513 /*validate all required parameters are set*/
514 if((owner.u.agg_port.intf_id == BAL_API_MAX_INTF_ID)
515 || (owner.u.agg_port.sub_term_id == BCMBAL_SUB_ID_UNKNOWN))
516 {
517 BCM_LOG(ERROR, log_id_tm_sched,
518 "Illegal owner agg port settings intf_id = %d sub_id = %d \n",
519 owner.u.agg_port.intf_id, owner.u.agg_port.sub_term_id);
520 return BCM_ERR_PARM;
521 }
522
523 /*validate interface is up*/
524 intf_key.intf_id = owner.u.agg_port.intf_id;
525 intf_key.intf_type = BCMBAL_INTF_TYPE_PON;
526
527 if(bcmbal_interface_status_get(intf_key)!= BCMBAL_STATUS_UP)
528 {
529 BCM_LOG(ERROR, log_id_tm_sched,
530 "intf = %d is not UP\n",
531 intf_key.intf_id);
532 return BCM_ERR_NOT_CONNECTED;
533 }
534
535 /*validate sub terminal exist*/
536 sub_term_key.intf_id = owner.u.agg_port.intf_id;
537 sub_term_key.sub_term_id = owner.u.agg_port.sub_term_id;
538
539 p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
540
541 if(!p_sub_term_inst)
542 {
543 BCM_LOG(ERROR, log_id_tm_sched,
544 "Failed to get subscriber terminal with intf = %d id = %u\n",
545 sub_term_key.intf_id, sub_term_key.sub_term_id);
546 return BCM_ERR_NOENT;
547 }
548 }
549 break;
550
551 case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
552 {
553 /*validate sub terminal exist*/
554 sub_term_key.intf_id = owner.u.uni.intf_id;
555 sub_term_key.sub_term_id = owner.u.uni.sub_term_id;
556
557 p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
558
559 if(!p_sub_term_inst)
560 {
561 BCM_LOG(ERROR, log_id_tm_sched,
562 "Failed to get subscriber terminal with intf = %d id = %u\n",
563 sub_term_key.intf_id, sub_term_key.sub_term_id);
564 return BCM_ERR_NOENT;
565 }
566
567 }
568 break;
569
570 default:
571 break;
572 }
573 }
574
575 if(BCMOS_TRUE == is_sched_type_and_level_mandatory)
576 {
577 if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_type))
578 {
579 BCM_LOG(ERROR, log_id_tm_sched, "Sched type is a mandatory parameter for setting tm sched\n");
580 ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
581 break;
582 }
583 /*if sched type is sp or wrr_sp, num_of_priorities is a mandatory parameter*/
584 if(BCMBAL_TM_SCHED_TYPE_SP == p_tm_sched_cfg->data.sched_type
585 || BCMBAL_TM_SCHED_TYPE_SP_WFQ == p_tm_sched_cfg->data.sched_type)
586 {
587 if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, num_priorities))
588 {
589 BCM_LOG(ERROR, log_id_tm_sched, "num_priorities is a mandatory parameter for setting tm sched with sched type %s\n",
590 BCMBAL_TM_SCHED_TYPE_SP == p_tm_sched_cfg->data.sched_type ? "sp" : "sp_wrr");
591 ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
592 break;
593 }
594 }
595 if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_child_type))
596 {
597 BCM_LOG(ERROR, log_id_tm_sched, "Sched child type is a mandatory parameter for setting tm sched\n");
598 ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
599 break;
600 }
601 }
602
603 if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_parent))
604 {
605 if(BCM_ERR_OK == (ret = bcmbal_tm_sched_validate_sched_parent(p_tm_sched_cfg, &p_tm_sched_inst)))
606 {
607 if(BCM_ERR_OK != (ret = bcmbal_tm_sched_sub_scheds_list_entry_add(p_tm_sched_inst, p_tm_sched_cfg->key.id)))
608 {
609 BCM_LOG(ERROR, log_id_tm_sched, "could not set scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
610 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_cfg->data.sched_parent.sched_id,
611 TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->key.id, bcmos_strerror(ret));
612 break;
613 }
614 }
615 else
616 {
617
618 BCM_LOG(ERROR, log_id_tm_sched, "could not validate scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
619 TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->data.sched_parent.sched_id,
620 TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->key.id, bcmos_strerror(ret));
621 break;
622 }
623 }
624
625 }while(0);
626
627 return ret;
628
629}
630/*****************************************************************************/
631/**
632 * @brief A function called by the core worker thread to process an
633 * tm_sched object message (SET, GET, CLEAR, STATS) received
634 * from the BAL Public API.
635 *
636 * @param msg_payload Pointer to a BAL message received from the
637 * BAL Public API.
638 *
639 * @returns bcmos_errno
640 *****************************************************************************/
641bcmos_errno process_tm_sched_object(void *msg_payload)
642{
643 bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
644 bcmbal_tm_sched_cfg *p_tm_sched_cfg = (bcmbal_tm_sched_cfg *)msg_payload;
645 tm_sched_inst *p_tm_sched_inst = NULL;
646 tm_sched_fsm_event fsm_event;
647 bcmbal_tm_sched_key tm_sched_key;
648 bcmbal_obj_msg_type oper_type;
649 bcmbal_tm_sched_owner owner;
650 uint32_t ref_count;
651 queue_entry *current_queue_entry;
652 bcmbal_tm_queue_key current_queue_key;
653 tm_queue_inst *current_queue_inst;
654 bcmbal_interface_key intf_key;
655
656 do
657 {
658 BUG_ON(NULL == msg_payload);
659
660 BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched object\n");
661
662 tm_sched_key = p_tm_sched_cfg->key;
663 oper_type = p_tm_sched_cfg->hdr.hdr.type;
664
665 /*
666 * A message pointer may be passed inside the event structure.
667 */
668 fsm_event.msg = msg_payload;
669
670 /* SET or GET or CLEAR...? */
671 switch(oper_type)
672 {
673 case(BCMBAL_OBJ_MSG_TYPE_SET):
674 {
675 BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched SET REQ mgmt message\n");
676 do
677 {
678 if(BCMBAL_STATUS_UP != acc_term_status_get())
679 {
680 BCM_LOG(ERROR, log_id_tm_sched,
681 "ERROR - Access-terminal is not UP. No further processing\n");
682 ret = BCM_ERR_STATE;
683 break;
684 }
685
686 /*Find the specified tm_sched instance is already created */
687 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
688
689 if(NULL != p_tm_sched_inst)
690 {
691 /* This is a fatal error condition */
692 BCM_LOG(ERROR, log_id_tm_sched,
693 "ERROR - tm sched found. Set after create is currently not supported. No further processing\n");
694 ret = BCM_ERR_NOT_SUPPORTED;
695 break;
696 }
697
698 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_FREE);
699 if(NULL == p_tm_sched_inst)
700 {
701 /* This is a fatal error condition */
702 BCM_LOG(ERROR, log_id_tm_sched,
703 "ERROR - tm sched not found. No further processing\n");
704 ret = BCM_ERR_NOMEM;
705 break;
706 }
707
708 BCM_LOG(DEBUG, log_id_tm_sched,
709 "Creating a new tm sched\n");
710
711 BCMBAL_CFG_PROP_SET(p_tm_sched_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
712
713 /* Fill in given cfg with current tm sched instance API request data structure and validate it*/
714 bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->req_tm_sched_info, p_tm_sched_cfg);
715
716 /* Check if the mandatory tm sched attributes have been set, and range check where applicable */
717 if(BCM_ERR_OK != (ret = tm_sched_fsm_info_validate(p_tm_sched_cfg)))
718 {
719 BCM_LOG(ERROR, log_id_tm_sched, "tm_sched fsm validation Failed (%d)\n", ret);
720 tm_sched_free_by_entry(p_tm_sched_inst);
721 break;
722 }
723
724
725 /* Perform the validation check(s) that the utils require */
726 if(BCM_ERR_OK != (ret = sw_util_tm_sched_validate(p_tm_sched_cfg)))
727 {
728 BCM_LOG(ERROR, log_id_tm_sched, "tm_sched switch validation Failed (%d)\n", ret);
729 tm_sched_free_by_entry(p_tm_sched_inst);
730 break;
731 }
732
733 }while(0);
734 /* We respond to the BAL public API backend with a result. We always
735 * send a complete msg_payload back to the API, but the data portion
736 * of the object is only relevant when a GET or GET-STATS has been requested.
737 */
738 rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
739 if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
740 {
741 break;
742 }
743
744 /*
745 * Initial checks complete. Process the request
746 */
747 fsm_event.event_type = TM_SCHED_FSM_EVENT_TYPE_CREATE;
748 /*
749 * Run the tm sched FSM to process this event
750 */
751 ret = tm_sched_fsm_exec(p_tm_sched_inst, &fsm_event);
752
753 }//SET
754 break;
755
756 case(BCMBAL_OBJ_MSG_TYPE_GET):
757 {
758 bcmbal_tm_queue_id_list_u8 queues_list = {};
759 bcmbal_tm_sched_id_list_u8 sub_scheds_list = {};
760
761 BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched GET REQ mgmt message\n");
762
763 /* Just return the tm sched data info that we have on record for tm sched instance */
764 /*Find the specified tm sched instance */
765 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
766
767 if(NULL == p_tm_sched_inst)
768 {
769 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched not found on GET\n");
770 ret = BCM_ERR_NOENT;
771 }
772 else
773 {
774 /* Return the queues list if requested */
775 BCMBAL_CFG_PROP_CLEAR(&p_tm_sched_inst->req_tm_sched_info,
776 tm_sched,
777 queues);
778
779 /* If the user requested the list of queues for this tm sched then return the list.*/
780 if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg,
781 tm_sched,
782 queues))
783 {
784
785 if(BCM_ERR_OK == queues_list_fill(p_tm_sched_inst, &queues_list))
786 {
787 /* NOTE: The returned list may be empty */
788 BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info,
789 tm_sched,
790 queues,
791 queues_list);
792 }
793 else
794 {
795 BCM_LOG(ERROR, log_id_tm_sched, "Error trying to fill queues list to return\n");
796 ret = BCM_ERR_INTERNAL;
797 break;
798 }
799 }
800
801 /* Return the sub scheds list if requested */
802 BCMBAL_CFG_PROP_CLEAR(&p_tm_sched_inst->req_tm_sched_info,
803 tm_sched,
804 sub_scheds);
805
806 /* If the user requested the list of sub scheds for this tm sched then return the list.*/
807 if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg,
808 tm_sched,
809 sub_scheds))
810 {
811
812 if(BCM_ERR_OK == sub_scheds_list_fill(p_tm_sched_inst, &sub_scheds_list))
813 {
814 /* NOTE: The returned list may be empty */
815 BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info,
816 tm_sched,
817 sub_scheds,
818 sub_scheds_list);
819 }
820 else
821 {
822 BCM_LOG(ERROR, log_id_tm_sched, "Error trying to fill sub_scheds list to return\n");
823 ret = BCM_ERR_INTERNAL;
824 break;
825 }
826 }
827 /* We respond to the BAL public API backend with a result. We always
828 * send a complete msg_payload back to the API, but the data portion
829 * of the object is only relevant when a GET or GET-STATS has been requested.
830 */
831
832 p_tm_sched_inst->req_tm_sched_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
833 *((bcmbal_tm_sched_cfg *)msg_payload) = p_tm_sched_inst->req_tm_sched_info;
834
835 }
836
837 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
838
839 /* Free the temporary lists if they were used */
840 if(queues_list.val)
841 {
842 bcmos_free(queues_list.val);
843 }
844 }//GET
845 break;
846
847 case(BCMBAL_OBJ_MSG_TYPE_CLEAR):
848 {
849 do
850 {
851 BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched CLEAR REQ mgmt message\n");
852 /*Find the specified tm sched instance */
853 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
854
855 if(NULL == p_tm_sched_inst)
856 {
857 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched not found on Clear\n");
858 ret = BCM_ERR_NOENT;
859 break;
860 }
861
862 /*user can not clear auto created sched owned by agg port*/
863 if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
864 {
865 owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
866 if(BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT == owner.type
867 && BCMBAL_TM_CREATION_MODE_AUTO == p_tm_sched_inst->req_tm_sched_info.data.creation_mode)
868 {
869 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is auto created, therefor can not be manually deleted\n");
870 ret = BCM_ERR_PARM;
871 break;
872 }
873
874 /*check that a tm is not active,
875 if that tm owned by interface, it is active if any of its queue is active.
876 if it is owned by agg port, it is active if the agg port id has ref count > 1 */
877 switch(owner.type)
878 {
879 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
880 {
881 rsc_mgr_alloc_id_get_ref_count(owner.u.agg_port.intf_id,owner.u.agg_port.agg_port_id,&ref_count);
882 if(ref_count > 1)
883 {
884 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is active and therefor can not be deleted (if = %d agg id = %d, ref count = %d \n",
885 owner.u.agg_port.intf_id,owner.u.agg_port.agg_port_id, ref_count);
886 ret = BCM_ERR_PARM;
887 }
888 break;
889 }//BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT
890
891 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
892 {
893 TAILQ_FOREACH(current_queue_entry,
894 &p_tm_sched_inst->queues_list,
895 next)
896 {
897 if(NULL != current_queue_entry)
898 {
899 current_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
900 current_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
901 current_queue_key.id = current_queue_entry->queue_id;
902 current_queue_inst = tm_queue_inst_get(current_queue_key, TM_QUEUE_FLAG_ACTIVE);
903 if(NULL == current_queue_inst)
904 {
905 ret = BCM_ERR_INTERNAL;
906 break;
907 }
908 if(TM_QUEUE_FSM_STATE_IN_USE == current_queue_inst->fsm_state)
909 {
910 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is active (has an in use queue) and therefor can not be deleted (queue id = %d \n",
911 current_queue_key.id);
912 ret = BCM_ERR_PARM;
913 break;
914 }
915 }
916 }//TAILQ_FOREACH
917 if(BCM_ERR_OK == ret)
918 {
919 /*TM_SCHEDs (either auto or manually created) with owner interface may only be deleted there are no attached TM_QUEUEs, and only when the associated interface is in the ADMIN-DOWN state*/
920 intf_key.intf_type = owner.u.interface.intf_type;
921 intf_key.intf_id = owner.u.interface.intf_id;
922 if(BCMBAL_STATUS_DOWN != bcmbal_interface_status_get(intf_key))
923 {
924 BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is owned by interface that is not admin down, and can be removed only when the associated interface is in the ADMIN-DOWN state\n");
925 ret = BCM_ERR_PARM;
926 break;
927 }
928 }
929 }//BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE
930 break;
931
932 default:
933 break;
934 }//switch owner.type
935 }//owner is set
936 /*generate destroy event*/
937 if(BCM_ERR_OK == ret)
938 {
939 fsm_event.event_type = TM_SCHED_FSM_EVENT_TYPE_DESTROY;
940 fsm_event.msg = msg_payload;
941 ret = tm_sched_fsm_exec(p_tm_sched_inst,&fsm_event);
942 }
943 }while(0);
944
945 mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
946 }//CLEAR
947 break;
948
949 default:
950 {
951 BCM_LOG(ERROR, log_id_tm_sched, "Unsupported operation on tm sched object (%d)\n",
952 oper_type);
953 ret = BCM_ERR_NOT_SUPPORTED;
954 }
955 }
956 }while(0);
957 BCM_LOG(DEBUG, log_id_tm_sched, "%s returns\n", __FUNCTION__);
958
959 return ret;
960}
961
962
963static void tm_sched_inst_entry_obj_init(tm_sched_inst *p_entry)
964{
965 /* The actual key content is irrelevant for free tm_scheds */
966 bcmbal_tm_sched_key key = { .id = 0, .dir = BCMBAL_TM_SCHED_DIR_DS};
967
968 BCMBAL_CFG_INIT(&p_entry->current_tm_sched_info,
969 tm_sched,
970 key);
971 p_entry->fsm_state = TM_SCHED_FSM_STATE_NULL;
972 /* Initialize the queues and suc scheds lists */
973 p_entry->num_queues_on_node = 0;
974 TAILQ_INIT(&p_entry->queues_list);
975
976 p_entry->num_sub_scheds_on_node = 0;
977 TAILQ_INIT(&p_entry->sub_scheds_list);
978
979 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_tm_sched_info), BCMOS_FALSE);
980}
981/*****************************************************************************/
982/**
983 * @brief A function to free a tm_sched instance specified by a the supplied
984 * entry pointer.
985 *
986 * @param p_entry A pointer to the entry to be freed
987 *
988 *
989 * @returns bcmos_errno
990 *****************************************************************************/
991static bcmos_errno tm_sched_free_by_entry(tm_sched_inst *p_entry)
992{
993 bcmos_errno ret = BCM_ERR_OK;
994 tm_sched_inst *current_entry;
995 tm_sched_inst *p_temp_entry;
996 /*
997 * First, check the active list (an active tm_sched can be in the adding or removing state)
998 */
999 TAILQ_FOREACH_SAFE(current_entry,
1000 &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
1001 tm_sched_inst_next,
1002 p_temp_entry)
1003 {
1004 if(current_entry == p_entry)
1005 {
1006 /* Remove it from the active list */
1007 TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
1008 break;
1009 }
1010 }
1011 tm_sched_inst_entry_obj_init(p_entry);
1012
1013 /* And add it to the free list */
1014 TAILQ_INSERT_TAIL(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, p_entry, tm_sched_inst_next);
1015
1016 return ret;
1017}
1018
1019/*****************************************************************************/
1020/**
1021 * @brief The tm sched FSM state processing executive function
1022 *
1023 * @param p_tm_sched_inst Pointer to a tm_sched instance
1024 * @param p_event Pointer to a tm_sched event structure
1025 *
1026 * @returns bcmos_errno
1027 *****************************************************************************/
1028static bcmos_errno tm_sched_fsm_exec(tm_sched_inst *p_tm_sched_inst, tm_sched_fsm_event *p_event)
1029{
1030 bcmos_errno ret = BCM_ERR_OK;
1031 tm_sched_fsm_state pre_state;
1032 tm_sched_fsm_state_processor tm_sched_state_processor;
1033
1034 /* Parameter checks */
1035 BUG_ON(NULL == p_tm_sched_inst);
1036 BUG_ON(NULL == p_event);
1037
1038 /* Record the present state for debug printing
1039 */
1040 pre_state = p_tm_sched_inst->fsm_state;
1041
1042 /*
1043 * Get the state processing function
1044 */
1045 tm_sched_state_processor = tm_sched_states[p_tm_sched_inst->fsm_state][p_event->event_type];
1046
1047 /*
1048 * If there's a state processing function for this event and state, execute it.
1049 * Otherwise, process a generic error.
1050 */
1051 if(tm_sched_state_processor)
1052 {
1053 ret = tm_sched_state_processor(p_tm_sched_inst, p_event->msg, p_event);
1054 }
1055 else
1056 {
1057 tm_sched_fsm_state_err(p_tm_sched_inst, p_event->msg, p_event);
1058 }
1059
1060 if(BCM_ERR_OK != ret)
1061 {
1062 BCM_LOG(ERROR, log_id_tm_sched, "*** Error detected during state processing\n");
1063 p_tm_sched_inst->fsm_state = pre_state;
1064 }
1065
1066 BCM_LOG(DEBUG, log_id_tm_sched, "*** Event %s, State: %s --> %s\n\n",
1067 tm_sched_event_name_get(p_event->event_type),
1068 tm_sched_state_name_get(pre_state),
1069 tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
1070
1071 return ret;
1072}
1073
1074
1075
1076/*****************************************************************************/
1077/**
1078 * @brief The tm sched FSM function which is executed when an error
1079 * is encountered during FSM processing.
1080 *
1081 * @param p_tm_sched_inst Pointer to a tm_sched instance
1082 * @param msg Pointer to a BAL message received from one of
1083 * the BAL apps.
1084 * @param p_event Pointer to a tm_sched event structure
1085 *
1086 * @returns bcmos_errno
1087 *****************************************************************************/
1088static bcmos_errno tm_sched_fsm_state_err(tm_sched_inst *p_tm_sched_inst,
1089 void *msg,
1090 tm_sched_fsm_event *p_event)
1091{
1092 bcmos_errno ret = BCM_ERR_INVALID_OP;
1093
1094 BCM_LOG(DEBUG, log_id_tm_sched,
1095 "Error encountered processing TM_SCHED FSM"
1096 " - BAD EVENT ()\n");
1097
1098 return ret;
1099}
1100
1101/*****************************************************************************/
1102/**
1103 * @brief A function to process a tm sched object event received
1104 * from one of the BAL apps.
1105 *
1106 * @param msg_payload A pointer to the util message
1107 *
1108 * @returns bcmos_errno
1109 *****************************************************************************/
1110bcmos_errno process_tm_sched_util_msg(void *msg_payload)
1111{
1112
1113
1114 bcmos_errno ret = BCM_ERR_OK;
1115 bcmbal_msg_type type;
1116 bcmbal_tm_sched_key key;
1117 tm_sched_inst *p_tm_sched_inst;
1118 tm_sched_fsm_event tm_sched_event;
1119
1120
1121 BUG_ON(NULL == msg_payload);
1122 do
1123 {
1124 type = bcmbal_type_minor_get(msg_payload);
1125
1126 BCM_LOG(DEBUG, log_id_tm_sched,
1127 "Processing a tm sched %s util message from %s\n",
1128 bcmbal_msg_t_str[type],
1129 subsystem_str[bcmbal_sender_get(msg_payload)]);
1130
1131 if(BAL_MSG_TYPE_IND == type)
1132 {
1133
1134 /* recover the key from the message */
1135 key = ((bal_util_msg_ind *)msg_payload)->obj_key.tm_sched_key;
1136
1137
1138 /*
1139 * Get the sub_term instance that's being referenced
1140 */
1141 p_tm_sched_inst = tm_sched_inst_get(key, TM_SCHED_FLAG_ACTIVE);
1142
1143 if(NULL == p_tm_sched_inst)
1144 {
1145 BCM_LOG(ERROR, log_id_tm_sched,
1146 "invalid tm sched (dir %s id %d) found while processing a util message type %s from %s\n",
1147 TM_SCHED_DIR_TO_STR(key.dir),
1148 key.id,
1149 bcmbal_msg_t_str[type],
1150 subsystem_str[bcmbal_sender_get(msg_payload)]);
1151 ret = BCM_ERR_INTERNAL;
1152 break;
1153 }
1154 tm_sched_event.msg = msg_payload;
1155
1156 tm_sched_event.event_type = TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG;
1157
1158 BCM_LOG(DEBUG, log_id_tm_sched, "p_tm_sched_inst->fsm_state=%d, tm_sched_event.event_type = %d\n",
1159 p_tm_sched_inst->fsm_state, tm_sched_event.event_type);
1160 /*Run the tm sched FSM to process this event */
1161 if(BCM_ERR_OK == ret)
1162 {
1163 ret = tm_sched_fsm_exec(p_tm_sched_inst, &tm_sched_event);
1164 }
1165 }
1166
1167 else
1168 {
1169 ret = BCM_ERR_NOT_SUPPORTED;
1170 BCM_LOG(ERROR, log_id_tm_sched,
1171 "Unknown message type received from the APP (not one of RSP:ACK:IND:AUTO_IND) (type:%d)\n",
1172 type);
1173 }
1174 }while(0);
1175 return ret;
1176}
1177
1178/*****************************************************************************/
1179/**
1180 * @brief The tm sched FSM state processing for a tm sched create command received
1181 * from the BAL Public API.
1182 *
1183 * @param p_tm_sched_inst Pointer to a tm sched instance
1184 * @param msg Pointer to a BAL message received from the BAL Public API
1185 * @param p_event Pointer to a tm sched event structure
1186 *
1187 * @returns bcmos_errno
1188 *****************************************************************************/
1189static bcmos_errno tm_sched_fsm_create(tm_sched_inst *p_tm_sched_inst,
1190 void *msg,
1191 tm_sched_fsm_event *p_event)
1192{
1193
1194 bcmos_errno ret = BCM_ERR_OK;
1195 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_INACTIVE;
1196
1197 if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched,owner))
1198 {
1199 ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst);
1200 }
1201
1202 return ret;
1203}
1204
1205bcmos_errno bcmbal_tm_sched_set_owner(tm_sched_inst *p_tm_sched_inst)
1206{
1207 bcmos_errno ret = BCM_ERR_OK;
1208 bcmbal_tm_sched_owner owner;
1209 bcmbal_tm_queue_key tm_queue_key;
1210 bcmbal_tm_sched_key tm_sched_key = p_tm_sched_inst->req_tm_sched_info.key;
1211 queue_entry *current_queue_entry;
1212
1213
1214 BUG_ON(NULL == p_tm_sched_inst);
1215 do
1216 {
1217 if( BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched,owner))
1218 {
1219 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ASSIGNED;
1220 owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
1221 switch(owner.type)
1222 {
1223 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
1224 case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
1225 case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
1226 {
1227 /*no need to validate owner attributes as these are read only and set by VALID internal objects*/
1228 if(BCM_ERR_OK != (ret = sw_util_tm_sched_set(p_tm_sched_inst)))
1229 {
1230 BCM_LOG(ERROR, log_id_tm_sched, "error %s detected by switch util while adding tm sched\n", bcmos_strerror(ret));
1231 break;
1232 }
1233 /* The hardware has properly accepted the object info, so the request object becomes the current state. */
1234 bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->current_tm_sched_info,
1235 &p_tm_sched_inst->req_tm_sched_info);
1236 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ACTIVE;
1237 /*configure all assigned queues*/
1238
1239 TAILQ_FOREACH(current_queue_entry,
1240 &p_tm_sched_inst->queues_list,
1241 next)
1242 {
1243 tm_queue_key.id = current_queue_entry->queue_id;
1244 tm_queue_key.sched_id = tm_sched_key.id;
1245 tm_queue_key.sched_dir = tm_sched_key.dir;
1246 if(BCM_ERR_OK != (ret = bcmbal_tm_queue_set_owner(tm_queue_key)))
1247 {
1248 BCM_LOG(ERROR, log_id_tm_sched, "Could not set queue sched id = %d sched dir = %s queue id = %d of the tm sched (%s)\n",
1249 tm_queue_key.sched_id, TM_SCHED_DIR_TO_STR(tm_queue_key.sched_dir), tm_queue_key.id, bcmos_strerror(ret));
1250 break;
1251 }
1252 }
1253 BCMBAL_OBJ_IN_PROGRESS_SET(&(p_tm_sched_inst->current_tm_sched_info), BCMOS_FALSE);
1254 p_tm_sched_inst->current_tm_sched_info.hdr.hdr.status = ret;
1255
1256 }
1257 break;
1258
1259 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
1260 {
1261 bcmbal_interface_key intf_key = {.intf_type = BCMBAL_INTF_TYPE_PON, .intf_id = owner.u.agg_port.intf_id};
1262 bcmbal_subscriber_terminal_key sub_key = {.sub_term_id = owner.u.agg_port.sub_term_id, .intf_id = intf_key.intf_id};
1263 /*for agg port, should validate intf and sub term validity*/
1264 if(NULL == sub_term_inst_get(&sub_key, SUB_TERM_FLAG_ACTIVE))
1265 {
1266 BCM_LOG(ERROR, log_id_tm_sched, "Can not set an agg port for onu (if-%d id-%d) which does not exist\n", intf_key.intf_id, sub_key.sub_term_id);
1267 ret = BCM_ERR_PARM;
1268 break;
1269 }
1270
1271 BCM_LOG(DEBUG, log_id_tm_sched, "Getting a new ALLOC ID from resource manager\n");
1272
1273 owner.u.agg_port.agg_port_id = 0; /* 0 is a magic number telling the resource manager that it should provide the initial allocation of the ALLOC ID */
1274 ret = rsc_mgr_alloc_id_alloc(intf_key.intf_id, &owner.u.agg_port.agg_port_id, 1, NULL);
1275
1276 if(BCM_ERR_OK != ret)
1277 {
1278 /* An error has occurred trying to get mandatory data */
1279 BCM_LOG(ERROR, log_id_tm_sched, "Failed to get ALLOC ID from resource manager\n");
1280 ret = BCM_ERR_NORES;
1281 break;
1282 }
1283 /*set the agg port id into the inst*/
1284 BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
1285
1286 ret = mac_util_agg_port_set(p_tm_sched_inst, BAL_UTIL_OPER_AGG_PORT_ADD);
1287 if(BCM_ERR_OK != ret)
1288 {
1289 /* An error has occurred trying to configure mac*/
1290 BCM_LOG(ERROR, log_id_tm_sched, "Failed to configure ALLOC ID at mac (%s)\n",bcmos_strerror(ret));
1291 break;
1292 }
1293 }
1294 break;
1295
1296 case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
1297 default:
1298 BCM_LOG(ERROR, log_id_tm_sched, "nothing to do with owner type %d \n", p_tm_sched_inst->current_tm_sched_info.data.owner.type);
1299 return BCM_ERR_PARM;
1300 break;
1301 }
1302 }
1303 }while(0);
1304
1305 return ret;
1306}
1307
1308
1309bcmos_errno bcmbal_tm_sched_unset_owner(tm_sched_inst *p_tm_sched_inst)
1310{
1311 bcmos_errno ret = BCM_ERR_OK;
1312 bcmbal_tm_sched_owner *owner;
1313 bcmbal_tm_queue_key tm_queue_key;
1314 queue_entry *current_queue_entry;
1315 tm_sched_inst *p_parent_tm_sched_inst;
1316
1317 BUG_ON(NULL == p_tm_sched_inst);
1318
1319 tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
1320 tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
1321
1322 do
1323 {
1324 if( BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
1325 {
1326 owner = &(p_tm_sched_inst->req_tm_sched_info.data.owner);
1327 switch(owner->type)
1328 {
1329 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
1330 {
1331 /*remove all assigned queues*/
1332 TAILQ_FOREACH(current_queue_entry,
1333 &p_tm_sched_inst->queues_list,
1334 next)
1335 {
1336 tm_queue_key.id = current_queue_entry->queue_id;
1337 if(BCM_ERR_OK != (ret = bcmbal_tm_queue_unset_owner(tm_queue_key)))
1338 {
1339 BCM_LOG(ERROR, log_id_tm_sched, "Could not unset queue sched id = %d sched dir = %s queue id = %d of the tm sched (%s) \n",
1340 tm_queue_key.sched_id, TM_SCHED_DIR_TO_STR(tm_queue_key.sched_dir), tm_queue_key.id, bcmos_strerror(ret));
1341 break;
1342 }
1343 }
1344 /*unset from parent scheduler*/
1345 if(BCMBAL_CFG_PROP_IS_SET(&(p_tm_sched_inst->req_tm_sched_info), tm_sched, sched_parent))
1346 {
1347 if(BCM_ERR_OK == (ret = bcmbal_tm_sched_validate_sched_parent(&(p_tm_sched_inst->req_tm_sched_info), &p_parent_tm_sched_inst)))
1348 {
1349 if(BCM_ERR_OK == (ret = bcmbal_tm_sched_sub_scheds_list_entry_remove(p_parent_tm_sched_inst, p_tm_sched_inst->req_tm_sched_info.key.id)))
1350 {
1351 BCM_LOG(ERROR, log_id_tm_sched, "could not remove scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
1352 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.data.sched_parent.sched_id,
1353 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id, bcmos_strerror(ret));
1354 }
1355 }
1356 else
1357 {
1358 BCM_LOG(ERROR, log_id_tm_sched, "could not validate scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
1359 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.data.sched_parent.sched_id,
1360 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id, bcmos_strerror(ret));
1361 }
1362 }
1363
1364 /*no need to validate owner attributes as these are read only and set by VALID internal objects*/
1365 if(BCM_ERR_OK != (ret = sw_util_tm_sched_clear(p_tm_sched_inst)))
1366 {
1367 BCM_LOG(ERROR, log_id_tm_sched, "error %s detected by switch util while clearing tm sched\n", bcmos_strerror(ret));
1368 break;
1369 }
1370 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_INACTIVE;
1371
1372 }
1373 break;
1374
1375 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
1376 case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
1377 case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
1378 case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
1379 default:
1380 {
1381 BCM_LOG(ERROR, log_id_tm_sched, "nothing to do with unsetting owner type %d \n",
1382 p_tm_sched_inst->current_tm_sched_info.data.owner.type);
1383 ret = BCM_ERR_PARM;
1384 }
1385 break;
1386 }
1387 }
1388 }while(0);
1389 return ret;
1390
1391}
1392
1393/*for the auto create, only key dir is set, id will be allocated from rsc mgr*/
1394bcmos_errno bcmbal_tm_sched_auto_create(bcmbal_tm_sched_cfg cfg, tm_sched_inst **p_tm_sched_inst)
1395{
1396 bcmos_errno ret = BCM_ERR_OK;
1397 do
1398 {
1399 cfg.key.id = 0; /* 0 is a magic number telling the resource manager that it should provide the initial allocation of the tm sched id*/
1400 if(BCM_ERR_OK != (ret = _rsc_mgr_tm_sched_auto_id_alloc(&cfg.key.id)))
1401 {
1402 BCM_LOG(ERROR, log_id_tm_sched,"Could not allocate a tm sched auto id \n");
1403 break;
1404 }
1405 *p_tm_sched_inst = tm_sched_inst_get(cfg.key, TM_SCHED_FLAG_FREE);
1406 if(NULL == p_tm_sched_inst)
1407 {
1408 /* This is a fatal error condition */
1409 BCM_LOG(ERROR, log_id_tm_sched,
1410 "ERROR - could not allocate tm sched No further processing\n");
1411 ret = BCM_ERR_NOMEM;
1412 break;
1413 }
1414 BCM_LOG(DEBUG, log_id_tm_sched,
1415 "\n Tm Sched id %d dir %s was created \n", cfg.key.id, TM_SCHED_DIR_TO_STR(cfg.key.dir));
1416
1417 (*p_tm_sched_inst)->req_tm_sched_info = cfg;
1418 ret = tm_sched_fsm_create(*p_tm_sched_inst, NULL,NULL);
1419 }while(0);
1420 return ret;
1421}
1422
1423static bcmos_errno bcmbal_tm_sched_queues_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_queue_key queue_key)
1424{
1425 bcmos_errno ret = BCM_ERR_OK;
1426 queue_entry *current_entry;
1427
1428 do
1429 {
1430 /* Check if the id is already on the list before adding it */
1431 TAILQ_FOREACH(current_entry,
1432 &p_tm_sched_inst->queues_list,
1433 next)
1434 {
1435 if(current_entry->queue_id == queue_key.id)
1436 {
1437 return BCM_ERR_ALREADY;
1438 }
1439 }
1440
1441 /* Get a new entry and configure it */
1442 current_entry = bcmos_calloc(sizeof(queue_entry));
1443
1444 if(NULL == current_entry)
1445 {
1446 BCM_LOG(ERROR, log_id_tm_sched,
1447 "No memory available to add queue\n");
1448 ret = BCM_ERR_NOMEM;
1449 break;
1450 }
1451
1452 current_entry->queue_id = queue_key.id;
1453
1454 BCM_LOG(DEBUG, log_id_tm_sched,
1455 "adding queue id %u to tm sched %u\n", queue_key.id, p_tm_sched_inst->req_tm_sched_info.key.id);
1456
1457 /* Save the entry on the list of queues ids on this sched*/
1458 TAILQ_INSERT_TAIL(&p_tm_sched_inst->queues_list,
1459 current_entry, next);
1460 (p_tm_sched_inst->num_queues_on_node)++;
1461 } while(0);
1462 return ret;
1463}
1464
1465static bcmos_errno bcmbal_tm_sched_queues_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_queue_key queue_key)
1466{
1467 bcmos_errno ret = BCM_ERR_NOENT;
1468 queue_entry *current_entry, *p_temp_entry;
1469
1470 do
1471 {
1472
1473 /* Check if the id is on the list */
1474 TAILQ_FOREACH_SAFE(current_entry,
1475 &p_tm_sched_inst->queues_list,
1476 next,
1477 p_temp_entry)
1478 {
1479 if(current_entry->queue_id == queue_key.id)
1480 {
1481 /* Remove it from the list of queues ids on this sched*/
1482 TAILQ_REMOVE(&p_tm_sched_inst->queues_list,
1483 current_entry, next);
1484
1485 bcmos_free(current_entry);
1486
1487 (p_tm_sched_inst->num_queues_on_node)--;
1488 ret = BCM_ERR_OK;
1489 break;
1490
1491 }
1492 }
1493 } while(0);
1494
1495 return ret;
1496}
1497
1498static bcmos_errno queues_list_fill(tm_sched_inst *p_tm_sched_inst,
1499 bcmbal_tm_queue_id_list_u8 *queues_list)
1500{
1501 bcmos_errno ret = BCM_ERR_OK;
1502 queue_entry *current_entry = NULL;
1503 int ii = 0;
1504
1505 do
1506 {
1507
1508 /* Traverse the list of queues recorded and fill in the list to be returned */
1509 queues_list->len = p_tm_sched_inst->num_queues_on_node;
1510 queues_list->val = bcmos_calloc(sizeof(bcmbal_tm_queue_id) * queues_list->len);
1511
1512 if(NULL == queues_list->val)
1513 {
1514 BCM_LOG(ERROR, log_id_tm_sched,
1515 "No memory available\n");
1516 ret = BCM_ERR_NOMEM;
1517 break;
1518 }
1519
1520 TAILQ_FOREACH(current_entry,
1521 &p_tm_sched_inst->queues_list,
1522 next)
1523 {
1524 BCM_LOG(DEBUG, log_id_tm_sched,
1525 "adding queue %d to response at array location %d\n",
1526 current_entry->queue_id,
1527 ii);
1528 queues_list->val[ii++] = current_entry->queue_id;
1529 }
1530 } while(0);
1531 return ret;
1532}
1533
1534static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id)
1535{
1536 bcmos_errno ret = BCM_ERR_OK;
1537 sub_sched_entry *current_entry;
1538
1539 BUG_ON(NULL == p_tm_sched_inst);
1540
1541 do
1542 {
1543 /* Check if the id is already on the list before adding it */
1544 TAILQ_FOREACH(current_entry,
1545 &p_tm_sched_inst->sub_scheds_list,
1546 next)
1547 {
1548 if(current_entry->sched_id == sched_id)
1549 {
1550 return BCM_ERR_ALREADY;
1551 }
1552 }
1553
1554 /* Get a new entry and configure it */
1555 current_entry = bcmos_calloc(sizeof(sub_sched_entry));
1556
1557 if(NULL == current_entry)
1558 {
1559 BCM_LOG(ERROR, log_id_tm_sched,
1560 "No memory available to add sub sched\n");
1561 ret = BCM_ERR_NOMEM;
1562 break;
1563 }
1564
1565 current_entry->sched_id = sched_id;
1566
1567 BCM_LOG(DEBUG, log_id_tm_sched,
1568 "adding sub sched id %u to tm sched dir = %s id = %u\n",
1569 sched_id, TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id);
1570
1571 /* Save the entry on the list of sub_scheds on that tm sched */
1572 TAILQ_INSERT_TAIL(&p_tm_sched_inst->sub_scheds_list,
1573 current_entry, next);
1574 (p_tm_sched_inst->num_sub_scheds_on_node)++;
1575
1576 } while(0);
1577 return ret;
1578}
1579
1580static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id)
1581{
1582 bcmos_errno ret = BCM_ERR_NOENT;
1583 sub_sched_entry *current_entry, *p_temp_entry;
1584
1585 do
1586 {
1587
1588 /* Check if the id is on the list */
1589 TAILQ_FOREACH_SAFE(current_entry,
1590 &p_tm_sched_inst->sub_scheds_list,
1591 next,
1592 p_temp_entry)
1593 {
1594 if(current_entry->sched_id == sched_id)
1595 {
1596 /* Remove it from the list of sub_scheds ids on this sched*/
1597 TAILQ_REMOVE(&p_tm_sched_inst->sub_scheds_list,
1598 current_entry, next);
1599
1600 bcmos_free(current_entry);
1601
1602 (p_tm_sched_inst->num_sub_scheds_on_node)--;
1603 ret = BCM_ERR_OK;
1604 break;
1605
1606 }
1607 }
1608 } while(0);
1609
1610 return ret;
1611}
1612
1613static bcmos_errno sub_scheds_list_fill(tm_sched_inst *p_tm_sched_inst,
1614 bcmbal_tm_sched_id_list_u8 *sub_scheds_list)
1615{
1616 bcmos_errno ret = BCM_ERR_OK;
1617 sub_sched_entry *current_entry = NULL;
1618 int ii = 0;
1619
1620 do
1621 {
1622
1623 /* Traverse the list of sub_scheds_ids recorded and fill in the list to be returned */
1624 sub_scheds_list->len = p_tm_sched_inst->num_sub_scheds_on_node;
1625 sub_scheds_list->val = bcmos_calloc(sizeof(bcmbal_tm_sched_id) * sub_scheds_list->len);
1626
1627 if(NULL == sub_scheds_list->val)
1628 {
1629 BCM_LOG(ERROR, log_id_tm_sched,
1630 "No memory available\n");
1631 ret = BCM_ERR_NOMEM;
1632 break;
1633 }
1634
1635 TAILQ_FOREACH(current_entry,
1636 &p_tm_sched_inst->sub_scheds_list,
1637 next)
1638 {
1639 BCM_LOG(DEBUG, log_id_tm_sched,
1640 "adding sub sched %d to response at array location %d\n",
1641 current_entry->sched_id,
1642 ii);
1643 sub_scheds_list->val[ii++] = current_entry->sched_id;
1644 }
1645
1646 } while(0);
1647
1648 return ret;
1649}
1650
1651bcmos_errno bcmbal_tm_sched_set_queue(tm_queue_inst *p_tm_queue_inst)
1652{
1653 bcmos_errno ret = BCM_ERR_OK;
1654 tm_sched_inst *p_tm_sched_inst = NULL;
1655 bcmbal_tm_sched_key tm_sched_key;
1656 BUG_ON(NULL == p_tm_queue_inst);
1657 do
1658 {
1659 tm_sched_key.id = p_tm_queue_inst->api_req_tm_queue_info.key.sched_id;
1660 tm_sched_key.dir= p_tm_queue_inst->api_req_tm_queue_info.key.sched_dir;
1661 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
1662
1663 if(NULL == p_tm_sched_inst)
1664 {
1665 BCM_LOG(ERROR, log_id_tm_sched,
1666 "ERROR - could not find an active tm sched (dir = %s id = %d) to attach the queue (id = %d)\n",
1667 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id,p_tm_queue_inst->api_req_tm_queue_info.key.id);
1668 ret = BCM_ERR_NOENT;
1669 break;
1670 }
1671 ret = bcmbal_tm_sched_queues_list_entry_add(p_tm_sched_inst, p_tm_queue_inst->api_req_tm_queue_info.key);
1672 if(BCM_ERR_OK != ret)
1673 {
1674 BCM_LOG(ERROR, log_id_tm_sched,
1675 "ERROR - could not add the queue entry to the sched\n");
1676 break;
1677 }
1678 if(TM_SCHED_FSM_STATE_ACTIVE == p_tm_sched_inst->fsm_state)
1679 {
1680 if(BCM_ERR_OK != (ret = bcmbal_tm_queue_activate(p_tm_queue_inst)))
1681 {
1682 BCM_LOG(ERROR, log_id_tm_sched,
1683 "ERROR - could not activate the newly added queue \n");
1684 break;
1685 }
1686 }
1687 }while(0);
1688 return ret;
1689}
1690
1691bcmos_errno bcmbal_tm_sched_remove_queue(tm_queue_inst *p_tm_queue_inst)
1692{
1693 bcmos_errno ret = BCM_ERR_OK;
1694 tm_sched_inst *p_tm_sched_inst = NULL;
1695 bcmbal_tm_sched_key tm_sched_key;
1696 BUG_ON(NULL == p_tm_queue_inst);
1697 do
1698 {
1699 tm_sched_key.id = p_tm_queue_inst->api_req_tm_queue_info.key.sched_id;
1700 tm_sched_key.dir= p_tm_queue_inst->api_req_tm_queue_info.key.sched_dir;
1701 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
1702
1703 if(NULL == p_tm_sched_inst)
1704 {
1705 BCM_LOG(ERROR, log_id_tm_sched,
1706 "ERROR - could not find an active tm sched (dir = %s id = %d) to attach the queue (id = %d)\n",
1707 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id,p_tm_queue_inst->api_req_tm_queue_info.key.id);
1708 ret = BCM_ERR_NOENT;
1709 break;
1710 }
1711 if(BCM_ERR_OK != (ret = bcmbal_tm_sched_queues_list_entry_remove(p_tm_sched_inst, p_tm_queue_inst->api_req_tm_queue_info.key)))
1712 {
1713 BCM_LOG(ERROR, log_id_tm_sched,
1714 "ERROR - could not remove the queue entry from the sched\n");
1715 break;
1716 }
1717
1718 }while(0);
1719 return ret;
1720}
1721
1722/*tm_sched_find_by_owner - currently might be called for agg port and uni port only*/
1723static tm_sched_inst* tm_sched_find_by_owner(bcmbal_tm_sched_owner owner)
1724{
1725 tm_sched_inst *current_entry = NULL;
1726
1727 TAILQ_FOREACH(current_entry,
1728 &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
1729 tm_sched_inst_next)
1730 {
1731 if(BCMBAL_CFG_PROP_IS_SET(&current_entry->req_tm_sched_info, tm_sched,owner))
1732 {
1733 switch(current_entry->req_tm_sched_info.data.owner.type)
1734 {
1735 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
1736 {
1737 if((owner.u.agg_port.intf_id == current_entry->req_tm_sched_info.data.owner.u.agg_port.intf_id)
1738 && (owner.u.agg_port.agg_port_id == current_entry->req_tm_sched_info.data.owner.u.agg_port.agg_port_id))
1739 {
1740 BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched dir = us id= %d for agg_port_id %d intf_id %d\n",
1741 current_entry->req_tm_sched_info.key.id, owner.u.agg_port.agg_port_id, owner.u.agg_port.intf_id);
1742 return current_entry;
1743 }
1744 }
1745 break;
1746
1747 case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
1748 {
1749 if((owner.u.uni.intf_id == current_entry->req_tm_sched_info.data.owner.u.uni.intf_id)
1750 && (owner.u.uni.sub_term_id == current_entry->req_tm_sched_info.data.owner.u.uni.sub_term_id)
1751 && (owner.u.uni.idx == current_entry->req_tm_sched_info.data.owner.u.uni.idx))
1752 {
1753 BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched id = %d for uni intf_id = %d sub_id = %d uni_id = %d\n",
1754 current_entry->req_tm_sched_info.key.id, owner.u.uni.intf_id, owner.u.uni.sub_term_id, owner.u.uni.idx);
1755 return current_entry;
1756 }
1757 }
1758
1759 default:
1760 break;
1761 }
1762 }
1763 }
1764 return current_entry;
1765}
1766
1767tm_sched_inst* tm_sched_find_agg_port_node(uint8_t intf_id, bcmbal_aggregation_port_id agg_port_id)
1768{
1769 bcmbal_tm_sched_owner owner;
1770 owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
1771 owner.u.agg_port.intf_id = intf_id;
1772 owner.u.agg_port.agg_port_id = agg_port_id;
1773
1774 return tm_sched_find_by_owner(owner);
1775}
1776
1777
1778
1779static bcmos_errno tm_sched_fsm_assigned_process_util_msg(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
1780{
1781
1782 bcmos_errno ret;
1783 bal_util_msg_ind *ind_msg;
1784
1785 /* Parameter checks */
1786 BUG_ON(NULL == p_tm_sched_inst);
1787 BUG_ON(NULL == msg);
1788 BUG_ON(NULL == p_event);
1789
1790 ind_msg = (bal_util_msg_ind *)msg;
1791
1792 BCM_LOG(DEBUG, log_id_tm_sched,
1793 " Received a IND message from BAL UTIL (%s) during %s state\n",
1794 subsystem_str[bcmbal_sender_get(msg)],
1795 tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
1796
1797 /* Handle response */
1798 ret = ind_msg->status;
1799
1800 if(BCM_ERR_OK == ret)
1801 {
1802 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ACTIVE;
1803 bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->current_tm_sched_info,
1804 &p_tm_sched_inst->req_tm_sched_info);
1805 }
1806 else
1807 {
1808 /* Error */
1809 BCM_LOG(ERROR, log_id_tm_sched,
1810 "Failed in state %s;%s\n",
1811 tm_sched_state_name_get(p_tm_sched_inst->fsm_state),
1812 bcmos_strerror(ret));
1813 }
1814
1815 mgmt_msg_send_balapi_ind(ret,
1816 (void *)&p_tm_sched_inst->current_tm_sched_info.hdr,
1817 log_id_tm_sched);
1818
1819 return ret;
1820}
1821
1822/*currently handling util msg of alloc id setting complete only for agg port tm sched only*/
1823static bcmos_errno tm_sched_fsm_deleting_process_util_msg(tm_sched_inst *p_tm_sched_inst,
1824 void *msg,
1825 tm_sched_fsm_event *p_event)
1826{
1827 bcmos_errno ret;
1828 bal_util_msg_ind *ind_msg;
1829
1830 /* Parameter checks */
1831 BUG_ON(NULL == p_tm_sched_inst);
1832 BUG_ON(NULL == msg);
1833 BUG_ON(NULL == p_event);
1834
1835 do
1836 {
1837 ind_msg = (bal_util_msg_ind *)msg;
1838
1839 BCM_LOG(DEBUG, log_id_tm_sched,
1840 " Received a IND message from BAL UTIL (%s) during %s state\n",
1841 subsystem_str[bcmbal_sender_get(msg)],
1842 tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
1843
1844 /* Handle response */
1845 ret = ind_msg->status;
1846
1847 if(BCM_ERR_OK == ret)
1848 {
1849 ret = tm_sched_fsm_destroy(p_tm_sched_inst);
1850 }
1851 else
1852 {
1853 /* Error */
1854 BCM_LOG(ERROR, log_id_tm_sched,
1855 "Failed in state %s;%s\n",
1856 tm_sched_state_name_get(p_tm_sched_inst->fsm_state),
1857 bcmos_strerror(ret));
1858 }
1859 }while(0);
1860 return ret;
1861}
1862
1863static bcmos_errno tm_sched_fsm_destroy(tm_sched_inst *p_tm_sched_inst)
1864{
1865 queue_entry *current_entry = NULL;
1866 bcmos_errno ret = BCM_ERR_OK;
1867 bcmbal_tm_queue_key tm_queue_key;
1868 tm_queue_inst *p_tm_queue_inst;
1869 int i=0;
1870 bcmbal_tm_sched_owner owner;
1871
1872 do
1873 {
1874 switch(p_tm_sched_inst->req_tm_sched_info.data.owner.type)
1875 {
1876 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
1877 {
1878 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_NULL;
1879 owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
1880
1881 ret = rsc_mgr_alloc_id_free(owner.u.agg_port.intf_id, owner.u.agg_port.agg_port_id, NULL);
1882 if(BCM_ERR_OK != ret)
1883 {
1884 BCM_LOG(ERROR, log_id_tm_sched,
1885 "Failed to free alloc id if=%d id=%d at resource manager",
1886 owner.u.agg_port.intf_id, owner.u.agg_port.agg_port_id);
1887 break;
1888 }
1889 ret = tm_sched_fsm_destroy(p_tm_sched_inst);
1890 if(BCM_ERR_OK != ret)
1891 {
1892 BCM_LOG(ERROR, log_id_tm_sched,
1893 "Failed to free auto created tm sched id, id=%d at resource manager",
1894 p_tm_sched_inst->req_tm_sched_info.key.id);
1895 break;
1896 }
1897 break;
1898 }
1899 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
1900 {
1901 tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
1902 tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
1903
1904 /*delete all attached queues*/
1905 TAILQ_FOREACH(current_entry,
1906 &p_tm_sched_inst->queues_list,
1907 next)
1908 {
1909
1910 BCM_LOG(DEBUG, log_id_tm_sched,
1911 "deleting queue %u (location %u)\n",
1912 current_entry->queue_id,
1913 i);
1914 tm_queue_key.id = current_entry->queue_id;
1915
1916 p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_ACTIVE);
1917 if(NULL == p_tm_queue_inst)
1918 {
1919 BCM_LOG(ERROR, log_id_tm_sched,"ERROR - tm queue not found. No further processing\n");
1920 ret = BCM_ERR_NOENT;
1921 break;
1922 }
1923
1924 ret = bcmbal_tm_queue_destroy(p_tm_queue_inst, BCMOS_FALSE);
1925 if(BCM_ERR_OK != ret)
1926 {
1927 BCM_LOG(ERROR, log_id_tm_sched,"ERROR - could not destroy tm queue %d .No further processing\n",
1928 tm_queue_key.id);
1929 ret = BCM_ERR_NOENT;
1930 break;
1931 }
1932
1933 bcmos_free(current_entry);
1934 i++;
1935 }
1936 }
1937 break;
1938
1939 default:
1940 break;
1941 }
1942 if(p_tm_sched_inst->req_tm_sched_info.data.creation_mode == BCMBAL_TM_CREATION_MODE_AUTO)
1943 {
1944 ret = _rsc_mgr_tm_sched_auto_id_free(p_tm_sched_inst->req_tm_sched_info.key.id);
1945 if(BCM_ERR_OK != ret)
1946 {
1947 BCM_LOG(ERROR, log_id_tm_sched,
1948 "Failed to free auto created tm sched id, id=%d at resource manager ",
1949 p_tm_sched_inst->req_tm_sched_info.key.id);
1950 break;
1951 }
1952 }
1953
1954 mgmt_msg_send_balapi_ind(ret,
1955 (void *)&p_tm_sched_inst->req_tm_sched_info.hdr,
1956 log_id_tm_sched);
1957
1958 ret = tm_sched_free_by_entry(p_tm_sched_inst);
1959 if(BCM_ERR_OK != ret)
1960 {
1961 BCM_LOG(ERROR, log_id_tm_sched,
1962 "Failed to free tm sched id=%d dir = %s",p_tm_sched_inst->req_tm_sched_info.key.id,
1963 TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir));
1964 break;
1965 }
1966 }while(0);
1967 return ret;
1968
1969}
1970
1971static bcmos_errno tm_sched_fsm_inactive_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
1972{
1973 return tm_sched_fsm_destroy(p_tm_sched_inst);
1974}
1975
1976static bcmos_errno tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
1977{
1978 return bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
1979}
1980
1981static bcmos_errno tm_sched_fsm_assigned_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
1982{
1983 bcmos_errno ret = bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
1984 if (BCM_ERR_OK == ret)
1985 ret = tm_sched_fsm_destroy(p_tm_sched_inst);
1986
1987 return ret;
1988
1989}
1990bcmos_errno bcmbal_tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst)
1991{
1992 bcmos_errno ret = BCM_ERR_OK;
1993 bcmbal_tm_sched_owner owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
1994 bcmbal_interface_key intf_key;
1995
1996
1997 switch(owner.type)
1998 {
1999 case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
2000 {
2001 uint32_t ref_count;
2002 ret = rsc_mgr_alloc_id_get_ref_count(p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.intf_id,
2003 p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.agg_port_id, &ref_count);
2004 if(1!= ref_count)
2005 {
2006 BCM_LOG(ERROR, log_id_tm_sched, "Cant destroy tm sched owned by agg port (if %d id %d) "
2007 "with reference count %d (greated than 1)\n",
2008 p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.intf_id,
2009 p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.agg_port_id, ref_count);
2010 ret = BCM_ERR_INTERNAL;
2011 break;
2012
2013 }
2014 ret = mac_util_agg_port_set(p_tm_sched_inst, BAL_UTIL_OPER_AGG_PORT_REMOVE);
2015 if(BCM_ERR_OK != ret)
2016 {
2017 /* An error has occurred trying to configure mac*/
2018 BCM_LOG(ERROR, log_id_tm_sched, "Failed to remove ALLOC ID at mac (%s)\n",bcmos_strerror(ret));
2019 break;
2020 }
2021 else
2022 {
2023 p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_DELETING;
2024 }
2025 break;
2026 }
2027 case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
2028 {
2029 /*remove the setting of the sched from the owner configuration*/
2030 intf_key.intf_type = owner.u.interface.intf_type;
2031 intf_key.intf_id = owner.u.interface.intf_id;
2032 ret = interface_tm_sched_unset(intf_key, p_tm_sched_inst->req_tm_sched_info.key);
2033 tm_sched_fsm_destroy(p_tm_sched_inst);
2034 break;
2035 }
2036
2037 default:
2038 break;
2039 }
2040 return ret;
2041
2042}
2043
2044/*****************************************************************************/
2045/**
2046 * @brief A function to set an interface as a tm sched owner
2047 *
2048 * @param interface_key the interface to become the owner
2049 * @param p_tm_sched_inst the tm sched instance to be set
2050 *
2051 * @returns bcmos_errno
2052 *****************************************************************************/
2053bcmos_errno bcmbal_tm_sched_set_interface_owner(bcmbal_interface_key interface_key, tm_sched_inst *p_tm_sched_inst)
2054{
2055 BUG_ON(NULL == p_tm_sched_inst);
2056
2057 bcmos_errno ret = BCM_ERR_OK;
2058 bcmbal_tm_sched_owner owner;
2059 do
2060 {
2061 if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
2062 {
2063 owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
2064 if (BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE!= owner.type )
2065 {
2066 BCM_LOG(ERROR, log_id_tm_sched, "tm sched %s%d is already assigned with an owner of type %d",
2067 p_tm_sched_inst->current_tm_sched_info.key.dir == BCMBAL_TM_SCHED_DIR_US ? "us" : "ds",
2068 p_tm_sched_inst->current_tm_sched_info.key.id, owner.type );
2069 break;
2070 }
2071 if(owner.u.interface.intf_type != interface_key.intf_type
2072 || owner.u.interface.intf_id != interface_key.intf_id)
2073 {
2074 BCM_LOG(ERROR, log_id_tm_sched, "tm sched %s%d is already assigned with an interface owner",
2075 p_tm_sched_inst->current_tm_sched_info.key.dir == BCMBAL_TM_SCHED_DIR_US ? "us" : "ds",
2076 p_tm_sched_inst->current_tm_sched_info.key.id);
2077
2078 ret = BCM_ERR_ALREADY;
2079 break;
2080 }
2081 }
2082 else
2083 {
2084 owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE;
2085 owner.u.interface.intf_type = interface_key.intf_type;
2086 owner.u.interface.intf_id = interface_key.intf_id;
2087 BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
2088 ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst);
2089 }
2090 }while(0);
2091 return ret;
2092}
2093
2094#define BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES 4
2095#define BCMBAL_INTERFACE_DEFAULT_SCHED_TYPE BCMBAL_TM_SCHED_TYPE_SP_WFQ
2096#define BCMBAL_INTERFACE_DEFAULT_SCHED_CHILD_TYPE BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE
2097
2098#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_SIZE 128
2099#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_SBR 128
2100#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_PBR 128
2101#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_BURST_SIZE 128
2102
2103bcmos_errno bcmbal_tm_sched_interface_tm_auto_create(bcmbal_interface_cfg *p_interface_info)
2104{
2105
2106 bcmos_errno ret = BCM_ERR_OK;
2107 tm_sched_inst *p_tm_sched_inst = NULL;
2108 bcmbal_tm_sched_cfg tm_sched_default_cfg;
2109 bcmbal_tm_queue_cfg tm_queue_default_cfg;
2110 bcmbal_tm_shaping default_shaping;
2111 bcmbal_tm_sched_key tm_sched_key;
2112 bcmbal_tm_queue_key tm_queue_key;
2113 int i;
2114
2115 do
2116 {
2117 /*create the auto tm sched*/
2118 tm_sched_key.dir = p_interface_info->key.intf_type == BCMBAL_INTF_TYPE_PON ? BCMBAL_TM_SCHED_DIR_DS : BCMBAL_TM_SCHED_DIR_US;
2119 BCMBAL_CFG_INIT(&tm_sched_default_cfg, tm_sched, tm_sched_key);
2120 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, sched_type, BCMBAL_INTERFACE_DEFAULT_SCHED_TYPE);
2121 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, sched_child_type, BCMBAL_INTERFACE_DEFAULT_SCHED_CHILD_TYPE);
2122 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, num_priorities, BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES);
2123 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
2124
2125 if (BCM_ERR_OK != (ret = bcmbal_tm_sched_auto_create(tm_sched_default_cfg, &p_tm_sched_inst)))
2126 {
2127 BCM_LOG(ERROR, log_id_tm_sched,"Could not create the auto tm sched \n");
2128 break;
2129 }
2130 if (tm_sched_key.dir == BCMBAL_TM_SCHED_DIR_US)
2131 {
2132 BCMBAL_CFG_PROP_SET(p_interface_info, interface, us_tm, p_tm_sched_inst->req_tm_sched_info.key.id);
2133 }
2134 else
2135 {
2136 BCMBAL_CFG_PROP_SET(p_interface_info, interface, ds_tm, p_tm_sched_inst->req_tm_sched_info.key.id);
2137 }
2138
2139 /*SET THE DEFAULT ATTRIBUTES FOR AUTO CREATED QUEUE*/
2140 tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
2141 tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
2142 default_shaping.sbr = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_SBR;
2143 default_shaping.pbr = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_PBR;
2144 default_shaping.burst = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_BURST_SIZE;
2145 BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, rate, default_shaping);
2146 BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_queue, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
2147
2148 /*create its queues*/
2149 for(i=0; i<BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES; i++)
2150 {
2151 tm_queue_key.id = i;
2152 BCMBAL_CFG_INIT(&tm_queue_default_cfg, tm_queue, tm_queue_key);
2153
2154 BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, priority, i);
2155 BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, rate, default_shaping);
2156 if (BCM_ERR_OK != (ret = bcmbal_tm_queue_auto_create(tm_queue_default_cfg)))
2157 {
2158 BCM_LOG(ERROR, log_id_tm_sched,"Could not create the %d tm queue\n", i);
2159 break;
2160 }
2161 }
2162
2163 ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
2164
2165 }while(0);
2166
2167 return ret;
2168}
2169
2170bcmos_errno bcmbal_tm_sched_set_sub_term_owner( bcmbal_tm_sched_key tm_sched_key, const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg)
2171{
2172 bcmos_errno ret = BCM_ERR_OK;
2173 tm_sched_inst *p_tm_sched_inst;
2174 bcmbal_tm_sched_owner owner;
2175
2176 do
2177 {
2178 p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
2179 if (NULL == p_tm_sched_inst)
2180 {
2181 BCM_LOG(ERROR, log_id_tm_sched,
2182 "tm sched dir = %s id = %d which is set as the subscriber tm does not exist \n",
2183 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
2184 ret = BCM_ERR_NOENT;
2185 break;
2186 }
2187 if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
2188 {
2189 /*check if it is already owned by that sub term*/
2190 owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
2191 if (owner.type != BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM)
2192 {
2193 BCM_LOG(ERROR, log_id_tm_sched,
2194 "tm sched dir = %s id = %d which is set as the subscriber tm already owned with owner type %d\n",
2195 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id, owner.type);
2196 ret = BCM_ERR_PARM;
2197 break;
2198
2199 }
2200 if (owner.u.sub_term.intf_id != p_sub_term_cfg->key.intf_id
2201 || owner.u.sub_term.sub_term_id != p_sub_term_cfg->key.sub_term_id)
2202 {
2203 BCM_LOG(ERROR, log_id_tm_sched,
2204 "tm sched dir = %s id = %d which is set as the subscriber tm already owned by sub_term intf_id = %d sub_term_id = %d\n",
2205 TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id, owner.u.sub_term.intf_id, owner.u.sub_term.sub_term_id);
2206 ret = BCM_ERR_PARM;
2207 break;
2208 }
2209 }
2210 else
2211 {
2212 owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM;
2213 owner.u.sub_term.intf_id = p_sub_term_cfg->key.intf_id;
2214 owner.u.sub_term.sub_term_id = p_sub_term_cfg->key.sub_term_id;
2215 BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
2216
2217 if (BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst)))
2218 {
2219 BCM_LOG(ERROR, log_id_tm_sched,
2220 "could not set sub term intf_id = %d sub_term_id = %d as the owner of tm sched dir = %s id = %d which is set as the subscriber tm \n",
2221 owner.u.sub_term.intf_id, owner.u.sub_term.sub_term_id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
2222 break;
2223 }
2224 }
2225 }while (0);
2226 return ret;
2227}
2228
2229/*@}*/