@@ -203,9 +203,99 @@ struct sof_ipc_trace_filter_elem *trace_filter_fill(struct sof_ipc_trace_filter_
203203 return NULL ;
204204}
205205
206+ /* update global components, which tr_ctx is stored inside special section */
207+ static int trace_filter_update_global (int32_t log_level , uint32_t uuid_id )
208+ {
209+ extern void * _trace_ctx_start ;
210+ extern void * _trace_ctx_end ;
211+ struct tr_ctx * ptr = (struct tr_ctx * )& _trace_ctx_start ;
212+ struct tr_ctx * end = (struct tr_ctx * )& _trace_ctx_end ;
213+ int cnt = 0 ;
214+
215+ /* iterate over global `tr_ctx` entries located in their own section */
216+ while (ptr < end ) {
217+ /*
218+ * when looking for specific uuid element,
219+ * then find, update and stop searching
220+ */
221+ if ((uint32_t )ptr -> uuid_p == uuid_id ) {
222+ ptr -> level = log_level ;
223+ return 1 ;
224+ }
225+ /* otherwise each element should be updated */
226+ if (!ptr -> uuid_p ) {
227+ ptr -> level = log_level ;
228+ ++ cnt ;
229+ }
230+ ++ ptr ;
231+ }
232+
233+ return cnt ;
234+ }
235+
236+ /* return trace context from any ipc component type */
237+ static struct tr_ctx * trace_filter_ipc_comp_context (struct ipc_comp_dev * icd )
238+ {
239+ switch (icd -> type ) {
240+ case COMP_TYPE_COMPONENT :
241+ return & icd -> cd -> tctx ;
242+ case COMP_TYPE_BUFFER :
243+ return & icd -> cb -> tctx ;
244+ case COMP_TYPE_PIPELINE :
245+ return & icd -> pipeline -> tctx ;
246+ /* each COMP_TYPE must be specified */
247+ default :
248+ tr_err (& ipc_tr , "Unknown trace context for ipc component type 0x%X" ,
249+ icd -> type );
250+ return NULL ;
251+ }
252+ }
253+
254+ /* update ipc components, wchich tr_ctx may be read from ipc_comp_dev structure */
255+ static int trace_filter_update_instances (int32_t log_level , uint32_t uuid_id ,
256+ int32_t pipe_id , int32_t comp_id )
257+ {
258+ struct ipc * ipc = ipc_get ();
259+ struct ipc_comp_dev * icd ;
260+ struct list_item * clist ;
261+ struct tr_ctx * ctx ;
262+ bool correct_comp ;
263+ int cnt = 0 ;
264+
265+ /* compare each ipc component with filter settings and update log level after pass */
266+ list_for_item (clist , & ipc -> comp_list ) {
267+ icd = container_of (clist , struct ipc_comp_dev , list );
268+ ctx = trace_filter_ipc_comp_context (icd );
269+ correct_comp = comp_id == -1 || icd -> id == comp_id ; /* todo: icd->topo_id */
270+ correct_comp &= uuid_id == 0 || (uint32_t )ctx -> uuid_p == uuid_id ;
271+ correct_comp &= pipe_id == -1 || ipc_comp_pipe_id (icd ) == pipe_id ;
272+ if (correct_comp ) {
273+ ctx -> level = log_level ;
274+ ++ cnt ;
275+ }
276+
277+ platform_shared_commit (icd , sizeof (* icd ));
278+ }
279+ return cnt ;
280+ }
281+
206282int trace_filter_update (const struct trace_filter * filter )
207283{
208- return - EINVAL ;
284+ int ret = 0 ;
285+
286+ /* validate log level, LOG_LEVEL_CRITICAL has low value, LOG_LEVEL_VERBOSE high */
287+ if (filter -> log_level < LOG_LEVEL_CRITICAL ||
288+ filter -> log_level > LOG_LEVEL_VERBOSE )
289+ return - EINVAL ;
290+
291+ /* update `*`, `name*` or global `name` */
292+ if (filter -> pipe_id == -1 && filter -> comp_id == -1 )
293+ ret = trace_filter_update_global (filter -> log_level , filter -> uuid_id );
294+
295+ /* update `*`, `name*`, `nameX.*` or `nameX.Y`, `name` may be '*' */
296+ ret += trace_filter_update_instances (filter -> log_level , filter -> uuid_id ,
297+ filter -> pipe_id , filter -> comp_id );
298+ return ret > 0 ? ret : - EINVAL ;
209299}
210300
211301void trace_flush (void )
0 commit comments