blob: a1b8638f398dc7227f508d3689ff5a9848579a63 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include <bcmos_system.h>
31#include <bcmolt_msg.h>
32#include <bcm_dev_log.h>
33#include <bcm_api_cli_helpers.h>
34#include "bcm_api_dev_log.h"
35
36/* maximum number of tasks that can use the API/logger integration simultaneously */
37#define API_LOG_NUM_BLKS 16
38
39/* string that denotes that this entry is not complete - there is more data to come */
40#define API_LOG_CONT_STR "..."
41
42/* number of characters reserved at the end of each log entry (continuation string + newline) */
43#define API_LOG_ENTRY_OVERHEAD sizeof(API_LOG_CONT_STR)
44
45typedef struct
46{
47 dev_log_id log_id;
48 const bcmolt_msg *msg;
49 char *buf;
50 uint32_t used;
51} api_log_rec;
52
53static bcmos_blk_pool api_log_blk_pool;
54
55static bcmos_errno api_log_dump_data_type(
56 api_log_rec *rec,
57 const bcmcli_type_descr *td,
58 const void *data,
59 const char *name,
60 uint32_t num_entries,
61 uint32_t entry_size);
62
63static bcmos_bool api_log_is_singleton(bcmolt_mgt_group group)
64{
65 switch (group)
66 {
67 case BCMOLT_MGT_GROUP_CFG:
68 case BCMOLT_MGT_GROUP_STAT:
69 case BCMOLT_MGT_GROUP_STAT_CFG:
70 case BCMOLT_MGT_GROUP_AUTO_CFG:
71 return BCMOS_TRUE;
72 default:
73 return BCMOS_FALSE;
74 }
75}
76
77static inline uint32_t api_log_buf_remaining(const api_log_rec *rec)
78{
79 return (MAX_DEV_LOG_STRING_NET_SIZE - API_LOG_ENTRY_OVERHEAD) - rec->used;
80}
81
82static void api_log_flush(api_log_rec *rec, const char *end_of_line)
83{
84 if (rec->used != 0)
85 {
86 strncat(rec->buf, end_of_line, MAX_DEV_LOG_STRING_NET_SIZE - rec->used);
87 bcm_dev_log_log(rec->log_id, DEV_LOG_LEVEL_INFO, BCM_LOG_FLAG_CALLER_FMT, "%s", rec->buf);
88 rec->used = 0;
89 }
90}
91
92static void api_log_print(api_log_rec *rec, const char *format, ...)
93{
94 va_list args;
95 int ret;
96
97 va_start(args, format);
98 ret = vsnprintf(rec->buf + rec->used, api_log_buf_remaining(rec), format, args);
99 va_end(args);
100
101 if (ret < 0 || ret > api_log_buf_remaining(rec))
102 {
103 /* this print doesn't fit in the buffer - send the current buffer and create a new continuation log entry */
104 rec->buf[rec->used] = '\0';
105 api_log_flush(rec, API_LOG_CONT_STR "\n");
106
107 /* the continuation entry can skip the header */
108 api_log_print(rec, API_LOG_CONT_STR);
109
110 /* try again, this time against the continuation entry */
111 va_start(args, format);
112 ret = vsnprintf(rec->buf + rec->used, api_log_buf_remaining(rec), format, args);
113 va_end(args);
114
115 if (ret < 0 || ret > api_log_buf_remaining(rec))
116 {
117 BCM_LOG(ERROR, rec->log_id, "API message log overflow on msg #%u\n", rec->msg->corr_tag);
118 }
119 else
120 {
121 rec->used += ret;
122 }
123 }
124 else
125 {
126 rec->used += ret;
127 }
128}
129
130static bcmos_errno api_log_read_snum(const bcmcli_type_descr *td, const void *data, int64_t *n)
131{
132 switch (td->size)
133 {
134 case 1:
135 {
136 int8_t n1 = *(const int8_t *)data;
137 *n = n1;
138 break;
139 }
140 case 2:
141 {
142 int16_t n2 = *(const int16_t *)data;
143 *n = n2;
144 break;
145 }
146 case 4:
147 {
148 int32_t n4 = *(const int32_t *)data;
149 *n = n4;
150 break;
151 }
152 case 8:
153 {
154 memcpy(n, data, sizeof(*n));
155 break;
156 }
157 default:
158 return BCM_ERR_NOT_SUPPORTED;
159 }
160 return BCM_ERR_OK;
161}
162
163static bcmos_errno api_log_read_unum(const bcmcli_type_descr *td, const void *data, uint64_t *n)
164{
165 switch (td->size)
166 {
167 case 1:
168 {
169 uint8_t n1 = *(const uint8_t *)data;
170 *n = n1;
171 break;
172 }
173 case 2:
174 {
175 uint16_t n2 = *(const uint16_t *)data;
176 *n = n2;
177 break;
178 }
179 case 4:
180 {
181 uint32_t n4 = *(const uint32_t *)data;
182 *n = n4;
183 break;
184 }
185 case 8:
186 {
187 memcpy(n, data, sizeof(*n));
188 break;
189 }
190 default:
191 return BCM_ERR_NOT_SUPPORTED;
192 }
193 return BCM_ERR_OK;
194}
195
196/* break a string up into smaller chunks (preferably at \n boundaries) so we don't overflow the size of a log entry */
197static void api_log_print_long_line(api_log_rec *rec, const char *line, uint32_t len)
198{
199 uint32_t i;
200 uint32_t handled = 0;
201 for (i = 0; i < len; i++)
202 {
203 if (line[i] == '\n')
204 {
205 if (i > handled)
206 {
207 api_log_print(rec, "%.*s", i - handled, &line[handled]);
208 api_log_flush(rec, API_LOG_CONT_STR "\n");
209 api_log_print(rec, API_LOG_CONT_STR);
210 }
211 handled = i + 1;
212 }
213 if (i > handled && i - handled == 32)
214 {
215 api_log_print(rec, "%.*s", 32, &line[handled]);
216 handled = i;
217 }
218 }
219 if (handled < len)
220 {
221 api_log_print(rec, "%.*s", len - handled, &line[handled]);
222 }
223}
224
225static bcmos_errno api_log_dump_simple_data_type(
226 api_log_rec *rec,
227 const bcmcli_type_descr *td,
228 const void *data,
229 const char *name)
230{
231 bcmos_errno err = BCM_ERR_OK;
232
233 switch (td->base_type)
234 {
235 case BCMOLT_BASE_TYPE_ID_SNUM: /* signed number */
236 {
237 int64_t n = 0;
238 err = api_log_read_snum(td, data, &n);
239 api_log_print(rec, "%lld", (long long)n);
240 break;
241 }
242
243 case BCMOLT_BASE_TYPE_ID_UNUM: /* unsigned number */
244 {
245 uint64_t n = 0;
246 err = api_log_read_unum(td, data, &n);
247 api_log_print(rec, "%llu", (unsigned long long)n);
248 break;
249 }
250
251 case BCMOLT_BASE_TYPE_ID_UNUM_HEX: /* unsigned number printed in hex */
252 {
253 uint64_t n = 0;
254 err = api_log_read_unum(td, data, &n);
255 api_log_print(rec, "0x%llx", (unsigned long long)n);
256 break;
257 }
258
259 case BCMOLT_BASE_TYPE_ID_FLOAT: /* floating-point number */
260 {
261 if (td->size == sizeof(float))
262 {
263 api_log_print(rec, "%f", *(const float *)data);
264 }
265 else if (td->size == sizeof(double))
266 {
267 api_log_print(rec, "%f", *(const double *)data);
268 }
269 else
270 {
271 err = BCM_ERR_NOT_SUPPORTED;
272 }
273 break;
274 }
275
276 case BCMOLT_BASE_TYPE_ID_BOOL:
277 {
278 uint64_t n = 0;
279 err = api_log_read_unum(td, data, &n);
280 api_log_print(rec, "%s", n == 0 ? "no" : "yes");
281 break;
282 }
283
284 case BCMOLT_BASE_TYPE_ID_STRING: /* string */
285 {
286 uint32_t size = td->size;
287 if (size == 0)
288 {
289 size = strlen((const char *)data);
290 }
291 api_log_print_long_line(rec, (const char *)data, size);
292 break;
293 }
294
295 case BCMOLT_BASE_TYPE_ID_IPV4: /* IPv4 address */
296 {
297 uint32_t ip;
298 memcpy(&ip, data, sizeof(ip));
299 api_log_print(rec, "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip & 0xff);
300 break;
301 }
302
303 case BCMOLT_BASE_TYPE_ID_MAC: /* MAC address */
304 {
305 bcmos_mac_address mac;
306 memcpy(mac.u8, data, sizeof(mac.u8));
307 api_log_print(rec, "%02x:%02x:%02x:%02x:%02x:%02x",
308 mac.u8[0], mac.u8[1], mac.u8[2], mac.u8[3], mac.u8[4], mac.u8[5]);
309 break;
310 }
311
312 case BCMOLT_BASE_TYPE_ID_ENUM: /* enum */
313 {
314 uint64_t n = 0;
315 err = api_log_read_unum(td, data, &n);
316 BUG_ON(td->x.e == NULL);
317 api_log_print(rec, "%s", bcmcli_enum_stringval(td->x.e, n));
318 break;
319 }
320
321 case BCMOLT_BASE_TYPE_ID_ENUM_MASK:
322 {
323 uint64_t n = 0;
324 bcmcli_enum_val *value = td->x.e;
325 bcmos_bool first = BCMOS_TRUE;
326 BUG_ON(value == NULL);
327 err = api_log_read_unum(td, data, &n);
328 while (value->name != NULL && n != 0)
329 {
330 if ((value->val & n) != 0)
331 {
332 api_log_print(rec, "%s%s", first ? "" : "+", value->name);
333 first = BCMOS_FALSE;
334 }
335 n -= value->val;
336 ++value;
337 }
338 if (first)
339 {
340 api_log_print(rec, "-");
341 }
342 break;
343 }
344
345 default:
346 err = BCM_ERR_NOT_SUPPORTED;
347 break;
348 }
349 return err;
350}
351
352static uint16_t api_log_get_num_enum_vals(const bcmcli_enum_val *vals)
353{
354 const bcmcli_enum_val *v = vals;
355 while (v != NULL && v->name != NULL)
356 {
357 ++v;
358 }
359 return (uint16_t)(v - vals);
360}
361
362static bcmos_errno api_log_dump_array(
363 api_log_rec *rec,
364 const bcmcli_type_descr *td,
365 const void *data,
366 uint32_t size,
367 const char *name)
368{
369 bcmos_errno err = BCM_ERR_OK;
370
371 /* Print as buffer or element by element ? */
372 if ((td->base_type == BCMOLT_BASE_TYPE_ID_UNUM || td->base_type == BCMOLT_BASE_TYPE_ID_UNUM_HEX) && td->size == 1)
373 {
374 uint32_t i;
375 api_log_print(rec, "%s=", name);
376 if (size == 0)
377 {
378 api_log_print(rec, "-");
379 }
380 else
381 {
382 for (i = 0; i < size; i++)
383 {
384 api_log_print(rec, "%02X", ((const uint8_t *)data)[i]);
385 }
386 }
387 api_log_print(rec, " ");
388 }
389 else
390 {
391 err = api_log_dump_data_type(rec, td, data, name, size, td->size);
392 }
393 return err;
394}
395
396static bcmos_errno api_log_dump_data_type(
397 api_log_rec *rec,
398 const bcmcli_type_descr *td,
399 const void *data,
400 const char *name,
401 uint32_t num_entries,
402 uint32_t entry_size)
403{
404 bcmos_errno err = BCM_ERR_OK;
405
406 switch (td->base_type)
407 {
408 case BCMOLT_BASE_TYPE_ID_STRUCT:
409 {
410 uint16_t f;
411 char full_name[APICLI_MAX_PARM_NAME_LENGTH];
412 if (td->x.s.num_fields == 0)
413 {
414 return 0;
415 }
416 BUG_ON(td->x.s.fields == NULL);
417 for (f = 0; f < td->x.s.num_fields; f++)
418 {
419 const bcmcli_field_descr *fld = &td->x.s.fields[f];
420 void *fdata = (void *)((long)data + fld->offset);
421 bcmcli_strncpy(full_name, name, sizeof(full_name));
422 bcmcli_strncat(full_name, ".", sizeof(full_name));
423 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
424 err = api_log_dump_data_type(rec, fld->type, fdata, full_name, num_entries, entry_size);
425 }
426 break;
427 }
428
429 case BCMOLT_BASE_TYPE_ID_UNION:
430 {
431 /* Print fields up to selector, then selector, then selected sub-structure */
432 uint16_t f;
433 char full_name[APICLI_MAX_PARM_NAME_LENGTH];
434 const bcmcli_field_descr *fld;
435 void *fdata;
436 int64_t selector_val = 0;
437 uint16_t num_union_vals;
438
439 if (td->x.u.num_common_fields == 0)
440 {
441 return 0;
442 }
443 BUG_ON(td->x.u.common_fields == NULL);
444 /* Common fields, including selector */
445 for (f = 0; f <= td->x.u.classifier_idx && err == BCM_ERR_OK; f++)
446 {
447 fld = &td->x.u.common_fields[f];
448 fdata = (void *)((long)data + fld->offset);
449
450 bcmcli_strncpy(full_name, name, sizeof(full_name));
451 if (fld->name != NULL && strlen(fld->name) != 0)
452 {
453 bcmcli_strncat(full_name, ".", sizeof(full_name));
454 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
455 }
456 err = api_log_dump_data_type(rec, fld->type, fdata, full_name, num_entries, entry_size);
457 if (err == BCM_ERR_OK && f == td->x.u.classifier_idx)
458 {
459 err = api_log_read_snum(fld->type, fdata, &selector_val);
460 }
461 }
462 if (err != BCM_ERR_OK)
463 {
464 return err;
465 }
466
467 num_union_vals = api_log_get_num_enum_vals(td->x.u.common_fields[td->x.u.classifier_idx].type->x.e);
468 if ((unsigned)selector_val >= num_union_vals)
469 {
470 return BCM_ERR_INTERNAL;
471 }
472
473 /* Selected field */
474 fld = &td->x.u.union_fields[selector_val];
475 if (fld->type == NULL)
476 {
477 return BCM_ERR_OK;
478 }
479 fdata = (void *)((long)data + fld->offset);
480
481 bcmcli_strncpy(full_name, name, sizeof(full_name));
482 if (fld->name != NULL && strlen(fld->name) != 0)
483 {
484 bcmcli_strncat(full_name, ".", sizeof(full_name));
485 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
486 }
487 err = api_log_dump_data_type(rec, fld->type, fdata, full_name, num_entries, entry_size);
488 if (err != BCM_ERR_OK)
489 {
490 return err;
491 }
492
493 /* Common fields following selector */
494 for (; f < td->x.u.num_common_fields; f++)
495 {
496 fld = &td->x.u.common_fields[f];
497 fdata = (void *)((long)data + fld->offset);
498
499 bcmcli_strncpy(full_name, name, sizeof(full_name));
500 if (fld->name != NULL && strlen(fld->name) != 0)
501 {
502 bcmcli_strncat(full_name, ".", sizeof(full_name));
503 bcmcli_strncat(full_name, fld->name, sizeof(full_name));
504 }
505 err = api_log_dump_data_type(rec, fld->type, fdata, full_name, num_entries, entry_size);
506 }
507 break;
508 }
509
510 case BCMOLT_BASE_TYPE_ID_ARR_FIXED:
511 {
512 err = api_log_dump_array(rec, td->x.arr_fixed.elem_type, data, td->x.arr_fixed.size, name);
513 break;
514 }
515
516 case BCMOLT_BASE_TYPE_ID_ARR_DYN:
517 {
518 /* Read length */
519 uint32_t array_size;
520 long base_ptr;
521
522 switch (td->x.arr_dyn.len_size)
523 {
524 case 1: array_size = *(const uint8_t *)data; break;
525 case 2: array_size = *(const uint16_t *)data; break;
526 case 4: array_size = *(const uint32_t *)data; break;
527 default:
528 return BCM_ERR_NOT_SUPPORTED;
529 }
530 base_ptr = BCMOS_ROUND_UP((long)data + td->x.arr_dyn.len_size, sizeof(void *));
531 BUG_ON(base_ptr == 0);
532 data = *(void **)base_ptr;
533 err = api_log_dump_array(rec, td->x.arr_dyn.elem_type, data, array_size, name);
534 break;
535 }
536
537 default:
538 {
539 int n;
540 /* Finally! Simple type that maps to a single name=value pair */
541 if (name != NULL)
542 {
543 api_log_print(rec, "%s=", name);
544 }
545 /* Dump simple value or array of simple values */
546 if (num_entries == 0)
547 {
548 api_log_print(rec, "-");
549 }
550 for (n = 0; n < num_entries; n++)
551 {
552 if (n != 0)
553 {
554 api_log_print(rec, ",");
555 }
556 err = api_log_dump_simple_data_type(rec, td, data, name);
557 if (err != BCM_ERR_OK)
558 {
559 return err;
560 }
561 data = (const void *)((long)data + entry_size);
562 }
563 api_log_print(rec, " ");
564 break;
565 }
566 }
567 return err;
568}
569
570static bcmos_errno api_log_dump_prop(api_log_rec *rec, const bcmcli_prop_descr *pd, const void *prop_data)
571{
572 return api_log_dump_data_type(rec, pd->type, prop_data, pd->name, 1, 0);
573}
574
575/* Calculate property pointer given the group data pointer and property description */
576static inline const void *api_log_prop_data_ptr(const void *group_ptr, const bcmcli_prop_descr *pd)
577{
578 return (const void *)((long)group_ptr + pd->offset);
579}
580
581static bcmos_errno api_log_append_key(api_log_rec *rec, const void *key, uint32_t key_size)
582{
583 uint16_t prop;
584 bcmos_errno err = BCM_ERR_OK;
585 const bcmcli_prop_descr *pd;
586
587 for (prop = 0;
588 api_cli_object_property(rec->msg->obj_type, BCMOLT_MGT_GROUP_KEY, 0, prop, &pd) == BCM_ERR_OK;
589 ++prop)
590 {
591 const void *prop_data = api_log_prop_data_ptr(key, pd);
592 if (prop_data == NULL)
593 {
594 continue;
595 }
596 BUG_ON(pd->offset > key_size);
597 err = api_log_dump_prop(rec, pd, prop_data);
598 if (err != BCM_ERR_OK)
599 {
600 break;
601 }
602 }
603 return err;
604}
605
606static bcmos_errno api_log_append_data(api_log_rec *rec, const void *data, uint32_t data_size)
607{
608 uint16_t prop;
609 bcmos_errno err = BCM_ERR_OK;
610 const bcmcli_prop_descr *pd;
611
612 for (prop = 0;
613 api_cli_object_property(rec->msg->obj_type, rec->msg->group, rec->msg->subgroup, prop, &pd) == BCM_ERR_OK;
614 ++prop)
615 {
616 const void *prop_data = api_log_prop_data_ptr(data, pd);
617 if (((rec->msg->presence_mask & (1LL << prop)) == 0) || (prop_data == NULL))
618 {
619 continue;
620 }
621 BUG_ON(pd->offset > data_size);
622 err = api_log_dump_prop(rec, pd, prop_data);
623 if (err != BCM_ERR_OK)
624 {
625 break;
626 }
627 }
628 return err;
629}
630
631static bcmos_errno api_log_append_hdr(api_log_rec *rec)
632{
633 bcmos_errno err;
634 const char *name;
635 const char *descr;
636
637 err = api_cli_object_name(rec->msg->obj_type, &name, &descr);
638 if (err != BCM_ERR_OK)
639 {
640 return err;
641 }
642
643 api_log_print(rec, apicli_mgt_group_to_str(rec->msg->group));
644 if (api_log_is_singleton(rec->msg->group))
645 {
646 api_log_print(rec, (rec->msg->type & BCMOLT_MSG_TYPE_SET) != 0 ? "_set" : "_get");
647 if ((rec->msg->type & BCMOLT_MSG_TYPE_MULTI) != 0)
648 {
649 api_log_print(rec, "_multi");
650 }
651 }
652
653 if (rec->msg->group != BCMOLT_MGT_GROUP_AUTO && rec->msg->group != BCMOLT_MGT_GROUP_PROXY_RX)
654 {
655 if (rec->msg->dir == BCMOLT_MSG_DIR_REQUEST)
656 {
657 api_log_print(rec, " request");
658 }
659 else
660 {
661 api_log_print(rec, " response[%d]", rec->msg->err);
662 }
663 }
664
665 api_log_print(rec, "> %s", name);
666 if (!api_log_is_singleton(rec->msg->group))
667 {
668 const char *sub_name;
669 const char *sub_d;
670 err = api_cli_object_subgroup_name(rec->msg->obj_type, rec->msg->group, rec->msg->subgroup, &sub_name, &sub_d);
671 if (err != BCM_ERR_OK)
672 {
673 return err;
674 }
675 api_log_print(rec, ".%s", sub_name);
676 }
677
678 api_log_print(rec, ": ");
679
680 return BCM_ERR_OK;
681}
682
683static bcmos_errno api_log_append_body(api_log_rec *rec)
684{
685 bcmos_errno err;
686 uint32_t key_size;
687 uint32_t key_offset;
688 uint32_t data_size;
689 uint32_t data_offset;
690
691 err = api_cli_object_struct_size(
692 rec->msg->obj_type,
693 rec->msg->group,
694 rec->msg->subgroup,
695 &key_size,
696 &key_offset,
697 &data_size,
698 &data_offset);
699 if (err != BCM_ERR_OK)
700 {
701 return err;
702 }
703
704 if ((rec->msg->type & BCMOLT_MSG_TYPE_MULTI) != 0)
705 {
706 /* message set printing for multi-object cfg not implemented */
707 api_log_print(rec, "(data omitted)");
708 }
709 else
710 {
711 if ((rec->msg->group != BCMOLT_MGT_GROUP_AUTO_CFG) && (key_size != 0))
712 {
713 const void *key = (const void *)((long)rec->msg + key_offset);
714 err = api_log_append_key(rec, key, key_size);
715 if (err != BCM_ERR_OK)
716 {
717 return err;
718 }
719 }
720
721 if ((data_size != 0) &&
722 (((rec->msg->dir == BCMOLT_MSG_DIR_REQUEST) && (rec->msg->type & BCMOLT_MSG_TYPE_SET)) ||
723 ((rec->msg->dir == BCMOLT_MSG_DIR_RESPONSE) && (rec->msg->type & BCMOLT_MSG_TYPE_GET)) ||
724 (rec->msg->group == BCMOLT_MGT_GROUP_AUTO) ||
725 (rec->msg->group == BCMOLT_MGT_GROUP_PROXY_RX)))
726 {
727 const void *data = (const void *)((long)rec->msg + data_offset);
728 err = api_log_append_data(rec, data, data_size);
729 if (err != BCM_ERR_OK)
730 {
731 return err;
732 }
733 }
734 }
735
736 return BCM_ERR_OK;
737}
738
739bcmos_errno bcmolt_msg_log(dev_log_id log_id, const bcmolt_msg *msg)
740{
741 bcmos_errno err = BCM_ERR_OK;
742 api_log_rec rec = { .log_id = log_id, .msg = msg, .used = 0 };
743
744 rec.buf = bcmos_blk_pool_alloc(&api_log_blk_pool);
745 if (rec.buf == NULL)
746 {
747 err = BCM_ERR_NOMEM;
748 }
749
750 err = (err != BCM_ERR_OK) ? err : api_log_append_hdr(&rec);
751 err = (err != BCM_ERR_OK) ? err : api_log_append_body(&rec);
752 api_log_flush(&rec, "\n");
753
754 if (rec.buf != NULL)
755 {
756 bcmos_blk_pool_free(rec.buf);
757 }
758 if (err != BCM_ERR_OK)
759 {
760 BCM_LOG(ERROR, log_id, "API message log error: %s (%d)\n", bcmos_strerror(err), err);
761 }
762 return err;
763}
764
765void bcmolt_msg_log_init(void)
766{
767 bcmos_errno err;
768 bcmos_blk_pool_parm blk_pool_parm =
769 {
770 .name = "api_dev_log",
771 .blk_size = MAX_DEV_LOG_STRING_NET_SIZE,
772 .num_blks = API_LOG_NUM_BLKS,
773 };
774
775 err = bcmos_blk_pool_create(&api_log_blk_pool, &blk_pool_parm);
776 BUG_ON(err != BCM_ERR_OK);
777}
778