1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log_frontend_stmesp_demux.h>
8 #include <zephyr/logging/log_frontend_stmesp.h>
9 #include <zephyr/logging/log_ctrl.h>
10 #include <zephyr/sys/mpsc_pbuf.h>
11 #include <zephyr/sys/__assert.h>
12 #include <zephyr/logging/log_msg.h>
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(stmesp_demux);
15
16 BUILD_ASSERT(sizeof(struct log_frontend_stmesp_demux_log_header) == sizeof(uint32_t),
17 "Must fit in a word");
18
19 #ifndef CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID
20 #define CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID 0
21 #endif
22
23 #ifndef CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE
24 #define CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE 0x8000
25 #endif
26
27 #define NUM_OF_ACTIVE CONFIG_LOG_FRONTEND_STMESP_DEMUX_ACTIVE_PACKETS
28 #define M_ID_OFF 16
29 #define M_ID_MASK (BIT_MASK(16) << M_ID_OFF)
30 #define C_ID_MASK BIT_MASK(16)
31
32 #define M_CH_HW_EVENT 0x00800000
33 #define M_CH_INVALID 0xFFFFFFFF
34
35 #define APP_M_ID 0x22
36 #define FLPR_M_ID 0x2D
37 #define PPR_M_ID 0x2E
38
39 struct log_frontend_stmesp_demux_active_entry {
40 sys_snode_t node;
41 uint32_t m_ch;
42 uint32_t ts;
43 struct log_frontend_stmesp_demux_log *packet;
44 int off;
45 };
46
47 /* Coprocessors (FLPR, PPR) sends location where APP can find strings and logging
48 * source names utilizing the fact that APP has access to FLPR/PPR memory if it is
49 * an owner of that coprocessor. During the initialization FLPR/PPR sends 2 DMTS32
50 * to the specific channel. First word is an address where logging source constant
51 * data section is located and second is where a section with addresses to constant
52 * strings used for logging is located.
53 */
54 struct log_frontend_stmesp_coproc_sources {
55 uint32_t m_id;
56 uint32_t data_cnt;
57 union {
58 struct {
59 const struct log_source_const_data *log_const;
60 uintptr_t *log_str_section;
61 } data;
62 struct {
63 uintptr_t data[2];
64 } raw_data;
65 };
66 };
67
68 struct log_frontend_stmesp_demux {
69 /* Pool for active entries. */
70 struct k_mem_slab mslab;
71
72 /* List of currently active entries. */
73 sys_slist_t active_entries;
74
75 /* The most recently used entry. */
76 struct log_frontend_stmesp_demux_active_entry *curr;
77
78 struct mpsc_pbuf_buffer pbuf;
79
80 uint32_t curr_m_ch;
81
82 const uint16_t *m_ids;
83
84 uint32_t *source_ids;
85
86 uint16_t m_ids_cnt;
87
88 uint16_t source_id_len;
89
90 uint32_t dropped;
91
92 struct log_frontend_stmesp_coproc_sources coproc_sources[2];
93 };
94
95 struct log_frontend_stmesp_entry_source_pair {
96 uint16_t entry_id;
97 uint16_t source_id;
98 };
99
100 static uint32_t buffer[CONFIG_LOG_FRONTEND_STMESP_DEMUX_BUFFER_SIZE]
101 __aligned(Z_LOG_MSG_ALIGNMENT);
102
103 static struct log_frontend_stmesp_demux demux;
104 static uint32_t slab_buf[NUM_OF_ACTIVE * sizeof(struct log_frontend_stmesp_demux_active_entry)];
105 static bool skip;
106
notify_drop(const struct mpsc_pbuf_buffer * buffer,const union mpsc_pbuf_generic * packet)107 static void notify_drop(const struct mpsc_pbuf_buffer *buffer,
108 const union mpsc_pbuf_generic *packet)
109 {
110 demux.dropped++;
111 }
112
store_source_id(uint16_t m_id,uint16_t entry_id,uint16_t source_id)113 static void store_source_id(uint16_t m_id, uint16_t entry_id, uint16_t source_id)
114 {
115 uint32_t *source_ids_data = &demux.source_ids[m_id * (demux.source_id_len + 1)];
116 uint32_t *wr_idx = source_ids_data;
117 struct log_frontend_stmesp_entry_source_pair *source_ids =
118 (struct log_frontend_stmesp_entry_source_pair *)&source_ids_data[1];
119
120 source_ids[*wr_idx].entry_id = entry_id;
121 source_ids[*wr_idx].source_id = source_id;
122 *wr_idx = *wr_idx + 1;
123 if (*wr_idx == (demux.source_id_len)) {
124 *wr_idx = 0;
125 }
126 }
127
get_source_id(uint16_t m_id,uint16_t entry_id)128 static uint16_t get_source_id(uint16_t m_id, uint16_t entry_id)
129 {
130 uint32_t *source_ids_data = &demux.source_ids[m_id * (demux.source_id_len + 1)];
131 int32_t rd_idx = source_ids_data[0];
132 uint32_t cnt = demux.source_id_len;
133 struct log_frontend_stmesp_entry_source_pair *source_ids =
134 (struct log_frontend_stmesp_entry_source_pair *)&source_ids_data[1];
135
136 do {
137 rd_idx = (rd_idx == 0) ? (demux.source_id_len - 1) : (rd_idx - 1);
138 if (source_ids[rd_idx].entry_id == entry_id) {
139 return source_ids[rd_idx].source_id;
140 }
141 cnt--;
142 } while (cnt);
143
144 return 0;
145 }
146
calc_wlen(uint32_t total_len)147 static uint32_t calc_wlen(uint32_t total_len)
148 {
149 return DIV_ROUND_UP(ROUND_UP(total_len, Z_LOG_MSG_ALIGNMENT), sizeof(uint32_t));
150 }
151
get_wlen(const union mpsc_pbuf_generic * packet)152 static uint32_t get_wlen(const union mpsc_pbuf_generic *packet)
153 {
154 union log_frontend_stmesp_demux_packet p = {.rgeneric = packet};
155 uint32_t len;
156
157 switch (p.generic_packet->type) {
158 case LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT:
159 len = sizeof(struct log_frontend_stmesp_demux_trace_point) / sizeof(uint32_t);
160 break;
161 case LOG_FRONTEND_STMESP_DEMUX_TYPE_HW_EVENT:
162 len = sizeof(struct log_frontend_stmesp_demux_hw_event) / sizeof(uint32_t);
163 break;
164 default:
165 len = calc_wlen(p.log->hdr.total_len +
166 offsetof(struct log_frontend_stmesp_demux_log, data));
167 break;
168 }
169
170 return len;
171 }
172
log_frontend_stmesp_demux_init(const struct log_frontend_stmesp_demux_config * config)173 int log_frontend_stmesp_demux_init(const struct log_frontend_stmesp_demux_config *config)
174 {
175 int err;
176 static const struct mpsc_pbuf_buffer_config pbuf_config = {
177 .buf = buffer,
178 .size = ARRAY_SIZE(buffer),
179 .notify_drop = notify_drop,
180 .get_wlen = get_wlen,
181 .flags = MPSC_PBUF_MODE_OVERWRITE |
182 (IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_DEMUX_MAX_UTILIZATION) ?
183 MPSC_PBUF_MAX_UTILIZATION : 0)};
184
185 memset(buffer, 0, sizeof(buffer));
186 mpsc_pbuf_init(&demux.pbuf, &pbuf_config);
187
188 sys_slist_init(&demux.active_entries);
189
190 if (config->m_ids_cnt > BIT(3)) {
191 return -EINVAL;
192 }
193
194 demux.m_ids = config->m_ids;
195 demux.m_ids_cnt = config->m_ids_cnt;
196 demux.dropped = 0;
197 demux.curr_m_ch = M_CH_INVALID;
198 demux.curr = NULL;
199 demux.source_ids = config->source_id_buf;
200 demux.source_id_len = config->source_id_buf_len / config->m_ids_cnt - 1;
201
202 err = k_mem_slab_init(&demux.mslab, slab_buf,
203 sizeof(struct log_frontend_stmesp_demux_active_entry),
204 NUM_OF_ACTIVE);
205
206 return err;
207 }
208
log_frontend_stmesp_demux_major(uint16_t id)209 void log_frontend_stmesp_demux_major(uint16_t id)
210 {
211 for (int i = 0; i < demux.m_ids_cnt; i++) {
212 if (id == demux.m_ids[i]) {
213 sys_snode_t *node;
214
215 demux.curr_m_ch = id << M_ID_OFF;
216 demux.curr = NULL;
217
218 SYS_SLIST_FOR_EACH_NODE(&demux.active_entries, node) {
219 struct log_frontend_stmesp_demux_active_entry *entry =
220 CONTAINER_OF(node,
221 struct log_frontend_stmesp_demux_active_entry,
222 node);
223
224 if (entry->m_ch == demux.curr_m_ch) {
225 demux.curr = entry;
226 break;
227 }
228 }
229 skip = false;
230 return;
231 }
232 }
233
234 skip = true;
235 }
236
log_frontend_stmesp_demux_channel(uint16_t id)237 void log_frontend_stmesp_demux_channel(uint16_t id)
238 {
239 if (skip) {
240 return;
241 }
242
243 if (id == CONFIG_LOG_FRONTEND_STMESP_FLUSH_PORT_ID) {
244 /* Flushing data that shall be discarded. */
245 goto bail;
246 }
247
248 demux.curr_m_ch &= ~C_ID_MASK;
249 demux.curr_m_ch |= id;
250
251 sys_snode_t *node;
252
253 SYS_SLIST_FOR_EACH_NODE(&demux.active_entries, node) {
254 struct log_frontend_stmesp_demux_active_entry *entry =
255 CONTAINER_OF(node, struct log_frontend_stmesp_demux_active_entry, node);
256
257 if (entry->m_ch == demux.curr_m_ch) {
258 demux.curr = entry;
259 return;
260 }
261 }
262
263 bail:
264 demux.curr = NULL;
265 }
266
get_major_id(uint16_t m_id)267 static uint8_t get_major_id(uint16_t m_id)
268 {
269 for (int i = 0; i < demux.m_ids_cnt; i++) {
270 if (m_id == demux.m_ids[i]) {
271 return i;
272 }
273 }
274
275 __ASSERT_NO_MSG(0);
276 return 0;
277 }
278
store_turbo_log0(uint16_t m_id,uint16_t id,uint64_t * ts,uint16_t source_id)279 static void store_turbo_log0(uint16_t m_id, uint16_t id, uint64_t *ts, uint16_t source_id)
280 {
281 struct log_frontend_stmesp_demux_trace_point packet = {
282 .valid = 1,
283 .type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
284 .content_invalid = 0,
285 .has_data = 0,
286 .timestamp = ts ? *ts : 0,
287 .major = m_id,
288 .source_id = source_id,
289 .id = id,
290 .data = 0};
291 static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
292
293 mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
294 }
295
store_turbo_log1(uint16_t m_id,uint16_t id,uint64_t * ts,uint32_t data)296 static void store_turbo_log1(uint16_t m_id, uint16_t id, uint64_t *ts, uint32_t data)
297 {
298 struct log_frontend_stmesp_demux_trace_point packet = {
299 .valid = 1,
300 .type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
301 .content_invalid = 0,
302 .has_data = 0,
303 .timestamp = ts ? *ts : 0,
304 .major = m_id,
305 .source_id = get_source_id(m_id, id),
306 .id = id,
307 .data = data};
308 static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
309
310 mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
311 }
312
store_tracepoint(uint16_t m_id,uint16_t id,uint64_t * ts,uint32_t * data)313 static void store_tracepoint(uint16_t m_id, uint16_t id, uint64_t *ts, uint32_t *data)
314 {
315 struct log_frontend_stmesp_demux_trace_point packet = {.valid = 1,
316 .type = LOG_FRONTEND_STMESP_DEMUX_TYPE_TRACE_POINT,
317 .content_invalid = 0,
318 .has_data = data ? 1 : 0,
319 .timestamp = ts ? *ts : 0,
320 .major = m_id,
321 .id = id,
322 .data = data ? *data : 0};
323 static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
324
325 mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
326 }
327
log_frontend_stmesp_demux_hw_event(uint64_t * ts,uint8_t data)328 static void log_frontend_stmesp_demux_hw_event(uint64_t *ts, uint8_t data)
329 {
330 struct log_frontend_stmesp_demux_hw_event packet = {.valid = 1,
331 .type = LOG_FRONTEND_STMESP_DEMUX_TYPE_HW_EVENT,
332 .content_invalid = 0,
333 .timestamp = ts ? *ts : 0,
334 .evt = data};
335 static const size_t wlen = sizeof(packet) / sizeof(uint32_t);
336
337 mpsc_pbuf_put_data(&demux.pbuf, (const uint32_t *)&packet, wlen);
338 }
339
340 /* Check if there are any active messages which are not completed for a significant
341 * amount of time. It may indicate that part of message was lost (due to reset,
342 * fault in the core or fault on the bus). In that case message shall be closed as
343 * incomplete to not block processing of other messages.
344 */
garbage_collector(uint32_t now)345 static void garbage_collector(uint32_t now)
346 {
347 sys_snode_t *node;
348
349 SYS_SLIST_FOR_EACH_NODE(&demux.active_entries, node) {
350 struct log_frontend_stmesp_demux_active_entry *entry =
351 CONTAINER_OF(node, struct log_frontend_stmesp_demux_active_entry, node);
352
353 if ((now - entry->ts) > CONFIG_LOG_FRONTEND_STMESP_DEMUX_GC_TIMEOUT) {
354 union log_frontend_stmesp_demux_packet p = {.log = entry->packet};
355
356 sys_slist_find_and_remove(&demux.active_entries, node);
357 entry->packet->content_invalid = 1;
358 mpsc_pbuf_commit(&demux.pbuf, p.generic);
359 demux.dropped++;
360 k_mem_slab_free(&demux.mslab, entry);
361 /* After removing one we need to stop as removing disrupts
362 * iterating over the list as current node is no longer in
363 * the list.
364 */
365 break;
366 }
367 }
368 }
369
log_frontend_stmesp_demux_log0(uint16_t source_id,uint64_t * ts)370 int log_frontend_stmesp_demux_log0(uint16_t source_id, uint64_t *ts)
371 {
372 if (skip) {
373 return 0;
374 }
375
376 if (demux.curr_m_ch == M_CH_INVALID) {
377 return -EINVAL;
378 }
379
380 if (demux.curr != NULL) {
381 /* Previous package was incompleted. Finish it and potentially
382 * mark as incompleted if not all data is received.
383 */
384 log_frontend_stmesp_demux_packet_end();
385 return -EINVAL;
386 }
387
388 uint16_t ch = demux.curr_m_ch & C_ID_MASK;
389 uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
390
391 if (ch < CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE) {
392 return -EINVAL;
393 }
394
395 store_turbo_log0(m, ch, ts, source_id);
396
397 return 1;
398 }
399
log_frontend_stmesp_demux_source_id(uint16_t data)400 void log_frontend_stmesp_demux_source_id(uint16_t data)
401 {
402 if (skip) {
403 return;
404 }
405
406 if (demux.curr_m_ch == M_CH_INVALID) {
407 return;
408 }
409
410 uint16_t ch = demux.curr_m_ch & C_ID_MASK;
411 uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
412
413 store_source_id(m, ch, data);
414 }
415
log_frontend_stmesp_demux_sname_get(uint32_t m_id,uint16_t s_id)416 const char *log_frontend_stmesp_demux_sname_get(uint32_t m_id, uint16_t s_id)
417 {
418 if (!IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG)) {
419 return "";
420 }
421
422 if (demux.m_ids[m_id] == APP_M_ID) {
423 return log_source_name_get(0, s_id);
424 } else if (m_id == demux.coproc_sources[0].m_id) {
425 return demux.coproc_sources[0].data.log_const[s_id].name;
426 } else if (m_id == demux.coproc_sources[1].m_id) {
427 return demux.coproc_sources[1].data.log_const[s_id].name;
428 }
429
430 return "unknown";
431 }
432
log_frontend_stmesp_demux_str_get(uint32_t m_id,uint16_t s_id)433 const char *log_frontend_stmesp_demux_str_get(uint32_t m_id, uint16_t s_id)
434 {
435 if (!IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG)) {
436 return "";
437 }
438
439 uintptr_t *log_str_start = NULL;
440
441 if (demux.m_ids[m_id] == APP_M_ID) {
442 log_str_start = (uintptr_t *)TYPE_SECTION_START(log_stmesp_ptr);
443 } else if (m_id == demux.coproc_sources[0].m_id) {
444 log_str_start = demux.coproc_sources[0].data.log_str_section;
445 } else if (m_id == demux.coproc_sources[1].m_id) {
446 log_str_start = demux.coproc_sources[1].data.log_str_section;
447 }
448
449 if (log_str_start) {
450 return (const char *)log_str_start[s_id];
451 }
452
453 return "unknown";
454 }
455
log_frontend_stmesp_demux_packet_start(uint32_t * data,uint64_t * ts)456 int log_frontend_stmesp_demux_packet_start(uint32_t *data, uint64_t *ts)
457 {
458 if (skip) {
459 return 0;
460 }
461
462 struct log_frontend_stmesp_demux_active_entry *entry;
463 union log_frontend_stmesp_demux_packet p;
464 int err;
465
466 if (demux.curr_m_ch == M_CH_INVALID) {
467 return -EINVAL;
468 }
469
470 if (demux.curr_m_ch == M_CH_HW_EVENT) {
471 /* HW event */
472 log_frontend_stmesp_demux_hw_event(ts, (uint8_t)*data);
473
474 return 1;
475 }
476
477 uint16_t ch = demux.curr_m_ch & C_ID_MASK;
478 uint16_t m = get_major_id(demux.curr_m_ch >> M_ID_OFF);
479
480 if (IS_ENABLED(CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG) &&
481 (ch == CONFIG_LOG_FRONTEND_STPESP_TURBO_SOURCE_PORT_ID)) {
482 struct log_frontend_stmesp_coproc_sources *src =
483 &demux.coproc_sources[demux.m_ids[m] == FLPR_M_ID ? 0 : 1];
484
485 if (src->data_cnt >= 2) {
486 /* Unexpected packet. */
487 return -EINVAL;
488 }
489
490 src->m_id = m;
491 src->raw_data.data[src->data_cnt++] = (uintptr_t)*data;
492 return 0;
493 }
494
495 if (demux.curr != NULL) {
496 /* Previous package was incompleted. Finish it and potentially
497 * mark as incompleted if not all data is received.
498 */
499 log_frontend_stmesp_demux_packet_end();
500 return -EINVAL;
501 }
502
503 if (ch >= CONFIG_LOG_FRONTEND_STMESP_TP_CHAN_BASE) {
504 /* Trace point */
505 if (ch >= CONFIG_LOG_FRONTEND_STMESP_TURBO_LOG_BASE) {
506 store_turbo_log1(m, ch, ts, *data);
507 } else {
508 store_tracepoint(m, ch, ts, data);
509 }
510
511 return 1;
512 }
513
514 union log_frontend_stmesp_demux_header hdr = {.raw = *data};
515 uint32_t pkt_len = hdr.log.total_len + offsetof(struct log_frontend_stmesp_demux_log, data);
516 uint32_t wlen = calc_wlen(pkt_len);
517 uint32_t now = k_uptime_get_32();
518
519 garbage_collector(now);
520 err = k_mem_slab_alloc(&demux.mslab, (void **)&entry, K_NO_WAIT);
521 if (err < 0) {
522 goto on_nomem;
523 }
524
525 entry->m_ch = demux.curr_m_ch;
526 entry->off = 0;
527 p.generic = mpsc_pbuf_alloc(&demux.pbuf, wlen, K_NO_WAIT);
528 if (p.generic == NULL) {
529 k_mem_slab_free(&demux.mslab, entry);
530 goto on_nomem;
531 }
532
533 entry->packet = p.log;
534 entry->packet->type = LOG_FRONTEND_STMESP_DEMUX_TYPE_LOG;
535 entry->packet->content_invalid = 0;
536 if (ts) {
537 entry->packet->timestamp = *ts;
538 }
539 entry->packet->hdr = hdr.log;
540 entry->packet->hdr.major = m;
541 entry->ts = now;
542 demux.curr = entry;
543 sys_slist_append(&demux.active_entries, &entry->node);
544
545 return 0;
546
547 on_nomem:
548 demux.curr = NULL;
549 demux.dropped++;
550 return -ENOMEM;
551 }
552
log_frontend_stmesp_demux_timestamp(uint64_t ts)553 void log_frontend_stmesp_demux_timestamp(uint64_t ts)
554 {
555 if (demux.curr == NULL) {
556 return;
557 }
558
559 demux.curr->packet->timestamp = ts;
560 }
561
log_frontend_stmesp_demux_data(uint8_t * data,size_t len)562 void log_frontend_stmesp_demux_data(uint8_t *data, size_t len)
563 {
564 if (demux.curr == NULL) {
565 return;
566 }
567
568 if (demux.curr->off + len <= demux.curr->packet->hdr.total_len) {
569 memcpy(&demux.curr->packet->data[demux.curr->off], data, len);
570 demux.curr->off += len;
571 }
572 }
573
log_frontend_stmesp_demux_packet_end(void)574 void log_frontend_stmesp_demux_packet_end(void)
575 {
576 if (demux.curr == NULL) {
577 return;
578 }
579
580 union log_frontend_stmesp_demux_packet p = {.log = demux.curr->packet};
581
582 if (demux.curr->off != demux.curr->packet->hdr.total_len) {
583 demux.curr->packet->content_invalid = 1;
584 demux.dropped++;
585 }
586
587 mpsc_pbuf_commit(&demux.pbuf, p.generic);
588
589 sys_slist_find_and_remove(&demux.active_entries, &demux.curr->node);
590 k_mem_slab_free(&demux.mslab, demux.curr);
591 demux.curr = NULL;
592 }
593
log_frontend_stmesp_demux_get_dropped(void)594 uint32_t log_frontend_stmesp_demux_get_dropped(void)
595 {
596 uint32_t rv = demux.dropped;
597
598 demux.dropped = 0;
599
600 return rv;
601 }
602
log_frontend_stmesp_demux_claim(void)603 union log_frontend_stmesp_demux_packet log_frontend_stmesp_demux_claim(void)
604 {
605 union log_frontend_stmesp_demux_packet p;
606
607 /* Discard any invalid packets. */
608 while ((p.rgeneric = mpsc_pbuf_claim(&demux.pbuf)) != NULL) {
609 if (p.generic_packet->content_invalid) {
610 mpsc_pbuf_free(&demux.pbuf, p.rgeneric);
611 } else {
612 break;
613 }
614 }
615
616 return p;
617 }
618
log_frontend_stmesp_demux_free(union log_frontend_stmesp_demux_packet packet)619 void log_frontend_stmesp_demux_free(union log_frontend_stmesp_demux_packet packet)
620 {
621 mpsc_pbuf_free(&demux.pbuf, packet.rgeneric);
622 }
623
log_frontend_stmesp_demux_reset(void)624 void log_frontend_stmesp_demux_reset(void)
625 {
626 sys_snode_t *node;
627
628 while ((node = sys_slist_get(&demux.active_entries)) != NULL) {
629 struct log_frontend_stmesp_demux_active_entry *entry =
630 CONTAINER_OF(node, struct log_frontend_stmesp_demux_active_entry, node);
631 union log_frontend_stmesp_demux_packet p = {.log = entry->packet};
632
633 entry->packet->content_invalid = 1;
634 mpsc_pbuf_commit(&demux.pbuf, p.generic);
635 demux.dropped++;
636 demux.curr_m_ch = M_CH_INVALID;
637
638 k_mem_slab_free(&demux.mslab, entry);
639 }
640 }
641
log_frontend_stmesp_demux_is_idle(void)642 bool log_frontend_stmesp_demux_is_idle(void)
643 {
644 return sys_slist_is_empty(&demux.active_entries);
645 }
646
log_frontend_stmesp_demux_max_utilization(void)647 int log_frontend_stmesp_demux_max_utilization(void)
648 {
649 uint32_t max;
650 int rv = mpsc_pbuf_get_max_utilization(&demux.pbuf, &max);
651
652 return rv == 0 ? max : rv;
653 }
654