1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright(C) 2015-2018 Linaro Limited.
5 * Author: Tor Jeremiassen <tor@ti.com>
6 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
10 #include <linux/list.h>
11 #include <linux/zalloc.h>
13 #include <opencsd/c_api/opencsd_c_api.h>
14 #include <opencsd/etmv4/trc_pkt_types_etmv4.h>
15 #include <opencsd/ocsd_if_types.h>
18 #include "cs-etm-decoder.h"
23 #define CS_LOG_RAW_FRAMES
25 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT | \
26 OCSD_DFRMTR_PACKED_RAW_OUT)
28 #define CS_RAW_DEBUG_FLAGS (OCSD_DFRMTR_UNPACKED_RAW_OUT)
32 struct cs_etm_decoder
{
34 void (*packet_printer
)(const char *msg
);
35 dcd_tree_handle_t dcd_tree
;
36 cs_etm_mem_cb_type mem_access
;
37 ocsd_datapath_resp_t prev_return
;
41 cs_etm_decoder__mem_access(const void *context
,
42 const ocsd_vaddr_t address
,
43 const ocsd_mem_space_acc_t mem_space __maybe_unused
,
44 const u8 trace_chan_id
,
48 struct cs_etm_decoder
*decoder
= (struct cs_etm_decoder
*) context
;
50 return decoder
->mem_access(decoder
->data
, trace_chan_id
,
51 address
, req_size
, buffer
);
54 int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder
*decoder
,
56 cs_etm_mem_cb_type cb_func
)
58 decoder
->mem_access
= cb_func
;
60 if (ocsd_dt_add_callback_trcid_mem_acc(decoder
->dcd_tree
, start
, end
,
62 cs_etm_decoder__mem_access
,
69 int cs_etm_decoder__reset(struct cs_etm_decoder
*decoder
)
71 ocsd_datapath_resp_t dp_ret
;
73 decoder
->prev_return
= OCSD_RESP_CONT
;
75 dp_ret
= ocsd_dt_process_data(decoder
->dcd_tree
, OCSD_OP_RESET
,
77 if (OCSD_DATA_RESP_IS_FATAL(dp_ret
))
83 int cs_etm_decoder__get_packet(struct cs_etm_packet_queue
*packet_queue
,
84 struct cs_etm_packet
*packet
)
86 if (!packet_queue
|| !packet
)
89 /* Nothing to do, might as well just return */
90 if (packet_queue
->packet_count
== 0)
93 * The queueing process in function cs_etm_decoder__buffer_packet()
94 * increments the tail *before* using it. This is somewhat counter
95 * intuitive but it has the advantage of centralizing tail management
96 * at a single location. Because of that we need to follow the same
97 * heuristic with the head, i.e we increment it before using its
98 * value. Otherwise the first element of the packet queue is not
101 packet_queue
->head
= (packet_queue
->head
+ 1) &
102 (CS_ETM_PACKET_MAX_BUFFER
- 1);
104 *packet
= packet_queue
->packet_buffer
[packet_queue
->head
];
106 packet_queue
->packet_count
--;
111 static int cs_etm_decoder__gen_etmv3_config(struct cs_etm_trace_params
*params
,
112 ocsd_etmv3_cfg
*config
)
114 config
->reg_idr
= params
->etmv3
.reg_idr
;
115 config
->reg_ctrl
= params
->etmv3
.reg_ctrl
;
116 config
->reg_ccer
= params
->etmv3
.reg_ccer
;
117 config
->reg_trc_id
= params
->etmv3
.reg_trc_id
;
118 config
->arch_ver
= ARCH_V7
;
119 config
->core_prof
= profile_CortexA
;
124 static void cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params
*params
,
125 ocsd_etmv4_cfg
*config
)
127 config
->reg_configr
= params
->etmv4
.reg_configr
;
128 config
->reg_traceidr
= params
->etmv4
.reg_traceidr
;
129 config
->reg_idr0
= params
->etmv4
.reg_idr0
;
130 config
->reg_idr1
= params
->etmv4
.reg_idr1
;
131 config
->reg_idr2
= params
->etmv4
.reg_idr2
;
132 config
->reg_idr8
= params
->etmv4
.reg_idr8
;
133 config
->reg_idr9
= 0;
134 config
->reg_idr10
= 0;
135 config
->reg_idr11
= 0;
136 config
->reg_idr12
= 0;
137 config
->reg_idr13
= 0;
138 config
->arch_ver
= ARCH_V8
;
139 config
->core_prof
= profile_CortexA
;
142 static void cs_etm_decoder__print_str_cb(const void *p_context
,
146 if (p_context
&& str_len
)
147 ((struct cs_etm_decoder
*)p_context
)->packet_printer(msg
);
151 cs_etm_decoder__init_def_logger_printing(struct cs_etm_decoder_params
*d_params
,
152 struct cs_etm_decoder
*decoder
)
156 if (d_params
->packet_printer
== NULL
)
159 decoder
->packet_printer
= d_params
->packet_printer
;
162 * Set up a library default logger to process any printers
163 * (packet/raw frame) we add later.
165 ret
= ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR
, 1);
169 /* no stdout / err / file output */
170 ret
= ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE
, NULL
);
175 * Set the string CB for the default logger, passes strings to
178 ret
= ocsd_def_errlog_set_strprint_cb(decoder
->dcd_tree
,
180 cs_etm_decoder__print_str_cb
);
187 #ifdef CS_LOG_RAW_FRAMES
189 cs_etm_decoder__init_raw_frame_logging(struct cs_etm_decoder_params
*d_params
,
190 struct cs_etm_decoder
*decoder
)
192 /* Only log these during a --dump operation */
193 if (d_params
->operation
== CS_ETM_OPERATION_PRINT
) {
194 /* set up a library default logger to process the
195 * raw frame printer we add later
197 ocsd_def_errlog_init(OCSD_ERR_SEV_ERROR
, 1);
199 /* no stdout / err / file output */
200 ocsd_def_errlog_config_output(C_API_MSGLOGOUT_FLG_NONE
, NULL
);
202 /* set the string CB for the default logger,
203 * passes strings to perf print logger.
205 ocsd_def_errlog_set_strprint_cb(decoder
->dcd_tree
,
207 cs_etm_decoder__print_str_cb
);
209 /* use the built in library printer for the raw frames */
210 ocsd_dt_set_raw_frame_printer(decoder
->dcd_tree
,
216 cs_etm_decoder__init_raw_frame_logging(
217 struct cs_etm_decoder_params
*d_params __maybe_unused
,
218 struct cs_etm_decoder
*decoder __maybe_unused
)
223 static int cs_etm_decoder__create_packet_printer(struct cs_etm_decoder
*decoder
,
224 const char *decoder_name
,
229 if (ocsd_dt_create_decoder(decoder
->dcd_tree
, decoder_name
,
230 OCSD_CREATE_FLG_PACKET_PROC
,
231 trace_config
, &csid
))
234 if (ocsd_dt_set_pkt_protocol_printer(decoder
->dcd_tree
, csid
, 0))
241 cs_etm_decoder__create_etm_packet_printer(struct cs_etm_trace_params
*t_params
,
242 struct cs_etm_decoder
*decoder
)
244 const char *decoder_name
;
245 ocsd_etmv3_cfg config_etmv3
;
246 ocsd_etmv4_cfg trace_config_etmv4
;
249 switch (t_params
->protocol
) {
250 case CS_ETM_PROTO_ETMV3
:
251 case CS_ETM_PROTO_PTM
:
252 cs_etm_decoder__gen_etmv3_config(t_params
, &config_etmv3
);
253 decoder_name
= (t_params
->protocol
== CS_ETM_PROTO_ETMV3
) ?
254 OCSD_BUILTIN_DCD_ETMV3
:
255 OCSD_BUILTIN_DCD_PTM
;
256 trace_config
= &config_etmv3
;
258 case CS_ETM_PROTO_ETMV4i
:
259 cs_etm_decoder__gen_etmv4_config(t_params
, &trace_config_etmv4
);
260 decoder_name
= OCSD_BUILTIN_DCD_ETMV4I
;
261 trace_config
= &trace_config_etmv4
;
267 return cs_etm_decoder__create_packet_printer(decoder
,
272 static ocsd_datapath_resp_t
273 cs_etm_decoder__do_soft_timestamp(struct cs_etm_queue
*etmq
,
274 struct cs_etm_packet_queue
*packet_queue
,
275 const uint8_t trace_chan_id
)
277 /* No timestamp packet has been received, nothing to do */
278 if (!packet_queue
->timestamp
)
279 return OCSD_RESP_CONT
;
281 packet_queue
->timestamp
= packet_queue
->next_timestamp
;
283 /* Estimate the timestamp for the next range packet */
284 packet_queue
->next_timestamp
+= packet_queue
->instr_count
;
285 packet_queue
->instr_count
= 0;
287 /* Tell the front end which traceid_queue needs attention */
288 cs_etm__etmq_set_traceid_queue_timestamp(etmq
, trace_chan_id
);
290 return OCSD_RESP_WAIT
;
293 static ocsd_datapath_resp_t
294 cs_etm_decoder__do_hard_timestamp(struct cs_etm_queue
*etmq
,
295 const ocsd_generic_trace_elem
*elem
,
296 const uint8_t trace_chan_id
)
298 struct cs_etm_packet_queue
*packet_queue
;
300 /* First get the packet queue for this traceID */
301 packet_queue
= cs_etm__etmq_get_packet_queue(etmq
, trace_chan_id
);
303 return OCSD_RESP_FATAL_SYS_ERR
;
306 * We've seen a timestamp packet before - simply record the new value.
307 * Function do_soft_timestamp() will report the value to the front end,
308 * hence asking the decoder to keep decoding rather than stopping.
310 if (packet_queue
->timestamp
) {
311 packet_queue
->next_timestamp
= elem
->timestamp
;
312 return OCSD_RESP_CONT
;
316 * This is the first timestamp we've seen since the beginning of traces
317 * or a discontinuity. Since timestamps packets are generated *after*
318 * range packets have been generated, we need to estimate the time at
319 * which instructions started by substracting the number of instructions
320 * executed to the timestamp.
322 packet_queue
->timestamp
= elem
->timestamp
- packet_queue
->instr_count
;
323 packet_queue
->next_timestamp
= elem
->timestamp
;
324 packet_queue
->instr_count
= 0;
326 /* Tell the front end which traceid_queue needs attention */
327 cs_etm__etmq_set_traceid_queue_timestamp(etmq
, trace_chan_id
);
329 /* Halt processing until we are being told to proceed */
330 return OCSD_RESP_WAIT
;
334 cs_etm_decoder__reset_timestamp(struct cs_etm_packet_queue
*packet_queue
)
336 packet_queue
->timestamp
= 0;
337 packet_queue
->next_timestamp
= 0;
338 packet_queue
->instr_count
= 0;
341 static ocsd_datapath_resp_t
342 cs_etm_decoder__buffer_packet(struct cs_etm_packet_queue
*packet_queue
,
343 const u8 trace_chan_id
,
344 enum cs_etm_sample_type sample_type
)
349 if (packet_queue
->packet_count
>= CS_ETM_PACKET_MAX_BUFFER
- 1)
350 return OCSD_RESP_FATAL_SYS_ERR
;
352 if (cs_etm__get_cpu(trace_chan_id
, &cpu
) < 0)
353 return OCSD_RESP_FATAL_SYS_ERR
;
355 et
= packet_queue
->tail
;
356 et
= (et
+ 1) & (CS_ETM_PACKET_MAX_BUFFER
- 1);
357 packet_queue
->tail
= et
;
358 packet_queue
->packet_count
++;
360 packet_queue
->packet_buffer
[et
].sample_type
= sample_type
;
361 packet_queue
->packet_buffer
[et
].isa
= CS_ETM_ISA_UNKNOWN
;
362 packet_queue
->packet_buffer
[et
].cpu
= cpu
;
363 packet_queue
->packet_buffer
[et
].start_addr
= CS_ETM_INVAL_ADDR
;
364 packet_queue
->packet_buffer
[et
].end_addr
= CS_ETM_INVAL_ADDR
;
365 packet_queue
->packet_buffer
[et
].instr_count
= 0;
366 packet_queue
->packet_buffer
[et
].last_instr_taken_branch
= false;
367 packet_queue
->packet_buffer
[et
].last_instr_size
= 0;
368 packet_queue
->packet_buffer
[et
].last_instr_type
= 0;
369 packet_queue
->packet_buffer
[et
].last_instr_subtype
= 0;
370 packet_queue
->packet_buffer
[et
].last_instr_cond
= 0;
371 packet_queue
->packet_buffer
[et
].flags
= 0;
372 packet_queue
->packet_buffer
[et
].exception_number
= UINT32_MAX
;
373 packet_queue
->packet_buffer
[et
].trace_chan_id
= trace_chan_id
;
375 if (packet_queue
->packet_count
== CS_ETM_PACKET_MAX_BUFFER
- 1)
376 return OCSD_RESP_WAIT
;
378 return OCSD_RESP_CONT
;
381 static ocsd_datapath_resp_t
382 cs_etm_decoder__buffer_range(struct cs_etm_queue
*etmq
,
383 struct cs_etm_packet_queue
*packet_queue
,
384 const ocsd_generic_trace_elem
*elem
,
385 const uint8_t trace_chan_id
)
388 struct cs_etm_packet
*packet
;
390 ret
= cs_etm_decoder__buffer_packet(packet_queue
, trace_chan_id
,
392 if (ret
!= OCSD_RESP_CONT
&& ret
!= OCSD_RESP_WAIT
)
395 packet
= &packet_queue
->packet_buffer
[packet_queue
->tail
];
398 case ocsd_isa_aarch64
:
399 packet
->isa
= CS_ETM_ISA_A64
;
402 packet
->isa
= CS_ETM_ISA_A32
;
404 case ocsd_isa_thumb2
:
405 packet
->isa
= CS_ETM_ISA_T32
;
408 case ocsd_isa_jazelle
:
409 case ocsd_isa_custom
:
410 case ocsd_isa_unknown
:
412 packet
->isa
= CS_ETM_ISA_UNKNOWN
;
415 packet
->start_addr
= elem
->st_addr
;
416 packet
->end_addr
= elem
->en_addr
;
417 packet
->instr_count
= elem
->num_instr_range
;
418 packet
->last_instr_type
= elem
->last_i_type
;
419 packet
->last_instr_subtype
= elem
->last_i_subtype
;
420 packet
->last_instr_cond
= elem
->last_instr_cond
;
422 switch (elem
->last_i_type
) {
424 case OCSD_INSTR_BR_INDIRECT
:
425 packet
->last_instr_taken_branch
= elem
->last_instr_exec
;
428 case OCSD_INSTR_DSB_DMB
:
429 case OCSD_INSTR_WFI_WFE
:
430 case OCSD_INSTR_OTHER
:
432 packet
->last_instr_taken_branch
= false;
436 packet
->last_instr_size
= elem
->last_instr_sz
;
438 /* per-thread scenario, no need to generate a timestamp */
439 if (cs_etm__etmq_is_timeless(etmq
))
443 * The packet queue is full and we haven't seen a timestamp (had we
444 * seen one the packet queue wouldn't be full). Let the front end
447 if (ret
== OCSD_RESP_WAIT
)
450 packet_queue
->instr_count
+= elem
->num_instr_range
;
451 /* Tell the front end we have a new timestamp to process */
452 ret
= cs_etm_decoder__do_soft_timestamp(etmq
, packet_queue
,
458 static ocsd_datapath_resp_t
459 cs_etm_decoder__buffer_discontinuity(struct cs_etm_packet_queue
*queue
,
460 const uint8_t trace_chan_id
)
463 * Something happened and who knows when we'll get new traces so
464 * reset time statistics.
466 cs_etm_decoder__reset_timestamp(queue
);
467 return cs_etm_decoder__buffer_packet(queue
, trace_chan_id
,
468 CS_ETM_DISCONTINUITY
);
471 static ocsd_datapath_resp_t
472 cs_etm_decoder__buffer_exception(struct cs_etm_packet_queue
*queue
,
473 const ocsd_generic_trace_elem
*elem
,
474 const uint8_t trace_chan_id
)
476 struct cs_etm_packet
*packet
;
478 ret
= cs_etm_decoder__buffer_packet(queue
, trace_chan_id
,
480 if (ret
!= OCSD_RESP_CONT
&& ret
!= OCSD_RESP_WAIT
)
483 packet
= &queue
->packet_buffer
[queue
->tail
];
484 packet
->exception_number
= elem
->exception_number
;
489 static ocsd_datapath_resp_t
490 cs_etm_decoder__buffer_exception_ret(struct cs_etm_packet_queue
*queue
,
491 const uint8_t trace_chan_id
)
493 return cs_etm_decoder__buffer_packet(queue
, trace_chan_id
,
494 CS_ETM_EXCEPTION_RET
);
497 static ocsd_datapath_resp_t
498 cs_etm_decoder__set_tid(struct cs_etm_queue
*etmq
,
499 struct cs_etm_packet_queue
*packet_queue
,
500 const ocsd_generic_trace_elem
*elem
,
501 const uint8_t trace_chan_id
)
505 /* Ignore PE_CONTEXT packets that don't have a valid contextID */
506 if (!elem
->context
.ctxt_id_valid
)
507 return OCSD_RESP_CONT
;
509 tid
= elem
->context
.context_id
;
510 if (cs_etm__etmq_set_tid(etmq
, tid
, trace_chan_id
))
511 return OCSD_RESP_FATAL_SYS_ERR
;
514 * A timestamp is generated after a PE_CONTEXT element so make sure
515 * to rely on that coming one.
517 cs_etm_decoder__reset_timestamp(packet_queue
);
519 return OCSD_RESP_CONT
;
522 static ocsd_datapath_resp_t
cs_etm_decoder__gen_trace_elem_printer(
524 const ocsd_trc_index_t indx __maybe_unused
,
525 const u8 trace_chan_id __maybe_unused
,
526 const ocsd_generic_trace_elem
*elem
)
528 ocsd_datapath_resp_t resp
= OCSD_RESP_CONT
;
529 struct cs_etm_decoder
*decoder
= (struct cs_etm_decoder
*) context
;
530 struct cs_etm_queue
*etmq
= decoder
->data
;
531 struct cs_etm_packet_queue
*packet_queue
;
533 /* First get the packet queue for this traceID */
534 packet_queue
= cs_etm__etmq_get_packet_queue(etmq
, trace_chan_id
);
536 return OCSD_RESP_FATAL_SYS_ERR
;
538 switch (elem
->elem_type
) {
539 case OCSD_GEN_TRC_ELEM_UNKNOWN
:
541 case OCSD_GEN_TRC_ELEM_EO_TRACE
:
542 case OCSD_GEN_TRC_ELEM_NO_SYNC
:
543 case OCSD_GEN_TRC_ELEM_TRACE_ON
:
544 resp
= cs_etm_decoder__buffer_discontinuity(packet_queue
,
547 case OCSD_GEN_TRC_ELEM_INSTR_RANGE
:
548 resp
= cs_etm_decoder__buffer_range(etmq
, packet_queue
, elem
,
551 case OCSD_GEN_TRC_ELEM_EXCEPTION
:
552 resp
= cs_etm_decoder__buffer_exception(packet_queue
, elem
,
555 case OCSD_GEN_TRC_ELEM_EXCEPTION_RET
:
556 resp
= cs_etm_decoder__buffer_exception_ret(packet_queue
,
559 case OCSD_GEN_TRC_ELEM_TIMESTAMP
:
560 resp
= cs_etm_decoder__do_hard_timestamp(etmq
, elem
,
563 case OCSD_GEN_TRC_ELEM_PE_CONTEXT
:
564 resp
= cs_etm_decoder__set_tid(etmq
, packet_queue
,
565 elem
, trace_chan_id
);
567 /* Unused packet types */
568 case OCSD_GEN_TRC_ELEM_I_RANGE_NOPATH
:
569 case OCSD_GEN_TRC_ELEM_ADDR_NACC
:
570 case OCSD_GEN_TRC_ELEM_CYCLE_COUNT
:
571 case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN
:
572 case OCSD_GEN_TRC_ELEM_EVENT
:
573 case OCSD_GEN_TRC_ELEM_SWTRACE
:
574 case OCSD_GEN_TRC_ELEM_CUSTOM
:
582 static int cs_etm_decoder__create_etm_packet_decoder(
583 struct cs_etm_trace_params
*t_params
,
584 struct cs_etm_decoder
*decoder
)
586 const char *decoder_name
;
587 ocsd_etmv3_cfg config_etmv3
;
588 ocsd_etmv4_cfg trace_config_etmv4
;
592 switch (t_params
->protocol
) {
593 case CS_ETM_PROTO_ETMV3
:
594 case CS_ETM_PROTO_PTM
:
595 cs_etm_decoder__gen_etmv3_config(t_params
, &config_etmv3
);
596 decoder_name
= (t_params
->protocol
== CS_ETM_PROTO_ETMV3
) ?
597 OCSD_BUILTIN_DCD_ETMV3
:
598 OCSD_BUILTIN_DCD_PTM
;
599 trace_config
= &config_etmv3
;
601 case CS_ETM_PROTO_ETMV4i
:
602 cs_etm_decoder__gen_etmv4_config(t_params
, &trace_config_etmv4
);
603 decoder_name
= OCSD_BUILTIN_DCD_ETMV4I
;
604 trace_config
= &trace_config_etmv4
;
610 if (ocsd_dt_create_decoder(decoder
->dcd_tree
,
612 OCSD_CREATE_FLG_FULL_DECODER
,
613 trace_config
, &csid
))
616 if (ocsd_dt_set_gen_elem_outfn(decoder
->dcd_tree
,
617 cs_etm_decoder__gen_trace_elem_printer
,
625 cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params
*d_params
,
626 struct cs_etm_trace_params
*t_params
,
627 struct cs_etm_decoder
*decoder
)
629 if (d_params
->operation
== CS_ETM_OPERATION_PRINT
)
630 return cs_etm_decoder__create_etm_packet_printer(t_params
,
632 else if (d_params
->operation
== CS_ETM_OPERATION_DECODE
)
633 return cs_etm_decoder__create_etm_packet_decoder(t_params
,
639 struct cs_etm_decoder
*
640 cs_etm_decoder__new(int num_cpu
, struct cs_etm_decoder_params
*d_params
,
641 struct cs_etm_trace_params t_params
[])
643 struct cs_etm_decoder
*decoder
;
644 ocsd_dcd_tree_src_t format
;
648 if ((!t_params
) || (!d_params
))
651 decoder
= zalloc(sizeof(*decoder
));
656 decoder
->data
= d_params
->data
;
657 decoder
->prev_return
= OCSD_RESP_CONT
;
658 format
= (d_params
->formatted
? OCSD_TRC_SRC_FRAME_FORMATTED
:
659 OCSD_TRC_SRC_SINGLE
);
661 flags
|= (d_params
->fsyncs
? OCSD_DFRMTR_HAS_FSYNCS
: 0);
662 flags
|= (d_params
->hsyncs
? OCSD_DFRMTR_HAS_HSYNCS
: 0);
663 flags
|= (d_params
->frame_aligned
? OCSD_DFRMTR_FRAME_MEM_ALIGN
: 0);
666 * Drivers may add barrier frames when used with perf, set up to
667 * handle this. Barriers const of FSYNC packet repeated 4 times.
669 flags
|= OCSD_DFRMTR_RESET_ON_4X_FSYNC
;
671 /* Create decode tree for the data source */
672 decoder
->dcd_tree
= ocsd_create_dcd_tree(format
, flags
);
674 if (decoder
->dcd_tree
== 0)
675 goto err_free_decoder
;
677 /* init library print logging support */
678 ret
= cs_etm_decoder__init_def_logger_printing(d_params
, decoder
);
680 goto err_free_decoder
;
682 /* init raw frame logging if required */
683 cs_etm_decoder__init_raw_frame_logging(d_params
, decoder
);
685 for (i
= 0; i
< num_cpu
; i
++) {
686 ret
= cs_etm_decoder__create_etm_decoder(d_params
,
690 goto err_free_decoder
;
696 cs_etm_decoder__free(decoder
);
700 int cs_etm_decoder__process_data_block(struct cs_etm_decoder
*decoder
,
701 u64 indx
, const u8
*buf
,
702 size_t len
, size_t *consumed
)
705 ocsd_datapath_resp_t cur
= OCSD_RESP_CONT
;
706 ocsd_datapath_resp_t prev_return
= decoder
->prev_return
;
707 size_t processed
= 0;
710 while (processed
< len
) {
711 if (OCSD_DATA_RESP_IS_WAIT(prev_return
)) {
712 cur
= ocsd_dt_process_data(decoder
->dcd_tree
,
718 } else if (OCSD_DATA_RESP_IS_CONT(prev_return
)) {
719 cur
= ocsd_dt_process_data(decoder
->dcd_tree
,
732 * Return to the input code if the packet buffer is full.
733 * Flushing will get done once the packet buffer has been
736 if (OCSD_DATA_RESP_IS_WAIT(cur
))
742 decoder
->prev_return
= cur
;
743 *consumed
= processed
;
748 void cs_etm_decoder__free(struct cs_etm_decoder
*decoder
)
753 ocsd_destroy_dcd_tree(decoder
->dcd_tree
);
754 decoder
->dcd_tree
= NULL
;