1515#define TRACE_FILTER_ELEMENTS_PER_ENTRY 4
1616#define TRACE_FILTER_MAX_CONFIG_STRING_LENGTH 1024
1717
18+ enum sof_dtrace_state {
19+ SOF_DTRACE_DISABLED ,
20+ SOF_DTRACE_STOPPED ,
21+ SOF_DTRACE_ENABLED ,
22+ };
23+
24+ struct sof_dtrace_priv {
25+ struct snd_dma_buffer dmatb ;
26+ struct snd_dma_buffer dmatp ;
27+ int dma_trace_pages ;
28+ wait_queue_head_t trace_sleep ;
29+ u32 host_offset ;
30+ bool dtrace_error ;
31+ bool dtrace_draining ;
32+ enum sof_dtrace_state dtrace_state ;
33+ };
34+
1835static int trace_filter_append_elem (struct snd_sof_dev * sdev , u32 key , u32 value ,
1936 struct sof_ipc_trace_filter_elem * elem_list ,
2037 int capacity , int * counter )
@@ -227,7 +244,8 @@ static int debugfs_create_trace_filter(struct snd_sof_dev *sdev)
227244static size_t sof_dtrace_avail (struct snd_sof_dev * sdev ,
228245 loff_t pos , size_t buffer_size )
229246{
230- loff_t host_offset = READ_ONCE (sdev -> host_offset );
247+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
248+ loff_t host_offset = READ_ONCE (priv -> host_offset );
231249
232250 /*
233251 * If host offset is less than local pos, it means write pointer of
@@ -247,32 +265,33 @@ static size_t sof_dtrace_avail(struct snd_sof_dev *sdev,
247265static size_t sof_wait_dtrace_avail (struct snd_sof_dev * sdev , loff_t pos ,
248266 size_t buffer_size )
249267{
250- wait_queue_entry_t wait ;
251268 size_t ret = sof_dtrace_avail (sdev , pos , buffer_size );
269+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
270+ wait_queue_entry_t wait ;
252271
253272 /* data immediately available */
254273 if (ret )
255274 return ret ;
256275
257- if (sdev -> dtrace_state != SOF_DTRACE_ENABLED && sdev -> dtrace_draining ) {
276+ if (priv -> dtrace_state != SOF_DTRACE_ENABLED && priv -> dtrace_draining ) {
258277 /*
259278 * tracing has ended and all traces have been
260279 * read by client, return EOF
261280 */
262- sdev -> dtrace_draining = false;
281+ priv -> dtrace_draining = false;
263282 return 0 ;
264283 }
265284
266285 /* wait for available trace data from FW */
267286 init_waitqueue_entry (& wait , current );
268287 set_current_state (TASK_INTERRUPTIBLE );
269- add_wait_queue (& sdev -> trace_sleep , & wait );
288+ add_wait_queue (& priv -> trace_sleep , & wait );
270289
271290 if (!signal_pending (current )) {
272291 /* set timeout to max value, no error code */
273292 schedule_timeout (MAX_SCHEDULE_TIMEOUT );
274293 }
275- remove_wait_queue (& sdev -> trace_sleep , & wait );
294+ remove_wait_queue (& priv -> trace_sleep , & wait );
276295
277296 return sof_dtrace_avail (sdev , pos , buffer_size );
278297}
@@ -282,13 +301,14 @@ static ssize_t dfsentry_dtrace_read(struct file *file, char __user *buffer,
282301{
283302 struct snd_sof_dfsentry * dfse = file -> private_data ;
284303 struct snd_sof_dev * sdev = dfse -> sdev ;
304+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
285305 unsigned long rem ;
286306 loff_t lpos = * ppos ;
287307 size_t avail , buffer_size = dfse -> size ;
288308 u64 lpos_64 ;
289309
290310 /* make sure we know about any failures on the DSP side */
291- sdev -> dtrace_error = false;
311+ priv -> dtrace_error = false;
292312
293313 /* check pos and count */
294314 if (lpos < 0 )
@@ -302,7 +322,7 @@ static ssize_t dfsentry_dtrace_read(struct file *file, char __user *buffer,
302322
303323 /* get available count based on current host offset */
304324 avail = sof_wait_dtrace_avail (sdev , lpos , buffer_size );
305- if (sdev -> dtrace_error ) {
325+ if (priv -> dtrace_error ) {
306326 dev_err (sdev -> dev , "trace IO error\n" );
307327 return - EIO ;
308328 }
@@ -317,7 +337,7 @@ static ssize_t dfsentry_dtrace_read(struct file *file, char __user *buffer,
317337 * Note: snd_dma_buffer_sync() is called for normal audio playback and
318338 * capture streams also.
319339 */
320- snd_dma_buffer_sync (& sdev -> dmatb , SNDRV_DMA_SYNC_CPU );
340+ snd_dma_buffer_sync (& priv -> dmatb , SNDRV_DMA_SYNC_CPU );
321341 /* copy available trace data to debugfs */
322342 rem = copy_to_user (buffer , ((u8 * )(dfse -> buf ) + lpos ), count );
323343 if (rem )
@@ -333,10 +353,11 @@ static int dfsentry_dtrace_release(struct inode *inode, struct file *file)
333353{
334354 struct snd_sof_dfsentry * dfse = inode -> i_private ;
335355 struct snd_sof_dev * sdev = dfse -> sdev ;
356+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
336357
337358 /* avoid duplicate traces at next open */
338- if (sdev -> dtrace_state != SOF_DTRACE_ENABLED )
339- sdev -> host_offset = 0 ;
359+ if (priv -> dtrace_state != SOF_DTRACE_ENABLED )
360+ priv -> host_offset = 0 ;
340361
341362 return 0 ;
342363}
@@ -350,12 +371,15 @@ static const struct file_operations sof_dfs_dtrace_fops = {
350371
351372static int debugfs_create_dtrace (struct snd_sof_dev * sdev )
352373{
374+ struct sof_dtrace_priv * priv ;
353375 struct snd_sof_dfsentry * dfse ;
354376 int ret ;
355377
356378 if (!sdev )
357379 return - EINVAL ;
358380
381+ priv = sdev -> fw_trace_data ;
382+
359383 ret = debugfs_create_trace_filter (sdev );
360384 if (ret < 0 )
361385 dev_warn (sdev -> dev , "failed to create filter debugfs file: %d" , ret );
@@ -365,8 +389,8 @@ static int debugfs_create_dtrace(struct snd_sof_dev *sdev)
365389 return - ENOMEM ;
366390
367391 dfse -> type = SOF_DFSENTRY_TYPE_BUF ;
368- dfse -> buf = sdev -> dmatb .area ;
369- dfse -> size = sdev -> dmatb .bytes ;
392+ dfse -> buf = priv -> dmatb .area ;
393+ dfse -> size = priv -> dmatb .bytes ;
370394 dfse -> sdev = sdev ;
371395
372396 debugfs_create_file ("trace" , 0444 , sdev -> debugfs_root , dfse ,
@@ -377,6 +401,7 @@ static int debugfs_create_dtrace(struct snd_sof_dev *sdev)
377401
378402static int ipc3_dtrace_enable (struct snd_sof_dev * sdev )
379403{
404+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
380405 struct sof_ipc_fw_ready * ready = & sdev -> fw_ready ;
381406 struct sof_ipc_fw_version * v = & ready -> version ;
382407 struct sof_ipc_dma_trace_params_ext params ;
@@ -386,10 +411,10 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev)
386411 if (!sdev -> fw_trace_is_supported )
387412 return 0 ;
388413
389- if (sdev -> dtrace_state == SOF_DTRACE_ENABLED || !sdev -> dma_trace_pages )
414+ if (priv -> dtrace_state == SOF_DTRACE_ENABLED || !priv -> dma_trace_pages )
390415 return - EINVAL ;
391416
392- if (sdev -> dtrace_state == SOF_DTRACE_STOPPED )
417+ if (priv -> dtrace_state == SOF_DTRACE_STOPPED )
393418 goto start ;
394419
395420 /* set IPC parameters */
@@ -403,15 +428,15 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev)
403428 params .hdr .size = sizeof (struct sof_ipc_dma_trace_params );
404429 params .hdr .cmd |= SOF_IPC_TRACE_DMA_PARAMS ;
405430 }
406- params .buffer .phy_addr = sdev -> dmatp .addr ;
407- params .buffer .size = sdev -> dmatb .bytes ;
408- params .buffer .pages = sdev -> dma_trace_pages ;
431+ params .buffer .phy_addr = priv -> dmatp .addr ;
432+ params .buffer .size = priv -> dmatb .bytes ;
433+ params .buffer .pages = priv -> dma_trace_pages ;
409434 params .stream_tag = 0 ;
410435
411- sdev -> host_offset = 0 ;
412- sdev -> dtrace_draining = false;
436+ priv -> host_offset = 0 ;
437+ priv -> dtrace_draining = false;
413438
414- ret = sof_dtrace_host_init (sdev , & sdev -> dmatb , & params );
439+ ret = sof_dtrace_host_init (sdev , & priv -> dmatb , & params );
415440 if (ret < 0 ) {
416441 dev_err (sdev -> dev , "Host dtrace init failed: %d\n" , ret );
417442 return ret ;
@@ -432,7 +457,7 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev)
432457 goto trace_release ;
433458 }
434459
435- sdev -> dtrace_state = SOF_DTRACE_ENABLED ;
460+ priv -> dtrace_state = SOF_DTRACE_ENABLED ;
436461
437462 return 0 ;
438463
@@ -443,18 +468,30 @@ static int ipc3_dtrace_enable(struct snd_sof_dev *sdev)
443468
444469static int ipc3_dtrace_init (struct snd_sof_dev * sdev )
445470{
471+ struct sof_dtrace_priv * priv ;
446472 int ret ;
447473
448474 /* dtrace is only supported with SOF_IPC */
449475 if (sdev -> pdata -> ipc_type != SOF_IPC )
450476 return - EOPNOTSUPP ;
451477
478+ if (sdev -> fw_trace_data ) {
479+ dev_err (sdev -> dev , "fw_trace_data has been already allocated\n" );
480+ return - EBUSY ;
481+ }
482+
483+ priv = devm_kzalloc (sdev -> dev , sizeof (* priv ), GFP_KERNEL );
484+ if (!priv )
485+ return - ENOMEM ;
486+
487+ sdev -> fw_trace_data = priv ;
488+
452489 /* set false before start initialization */
453- sdev -> dtrace_state = SOF_DTRACE_DISABLED ;
490+ priv -> dtrace_state = SOF_DTRACE_DISABLED ;
454491
455492 /* allocate trace page table buffer */
456493 ret = snd_dma_alloc_pages (SNDRV_DMA_TYPE_DEV , sdev -> dev ,
457- PAGE_SIZE , & sdev -> dmatp );
494+ PAGE_SIZE , & priv -> dmatp );
458495 if (ret < 0 ) {
459496 dev_err (sdev -> dev , "can't alloc page table for trace %d\n" , ret );
460497 return ret ;
@@ -463,53 +500,55 @@ static int ipc3_dtrace_init(struct snd_sof_dev *sdev)
463500 /* allocate trace data buffer */
464501 ret = snd_dma_alloc_dir_pages (SNDRV_DMA_TYPE_DEV_SG , sdev -> dev ,
465502 DMA_FROM_DEVICE , DMA_BUF_SIZE_FOR_TRACE ,
466- & sdev -> dmatb );
503+ & priv -> dmatb );
467504 if (ret < 0 ) {
468505 dev_err (sdev -> dev , "can't alloc buffer for trace %d\n" , ret );
469506 goto page_err ;
470507 }
471508
472509 /* create compressed page table for audio firmware */
473- ret = snd_sof_create_page_table (sdev -> dev , & sdev -> dmatb ,
474- sdev -> dmatp .area , sdev -> dmatb .bytes );
510+ ret = snd_sof_create_page_table (sdev -> dev , & priv -> dmatb ,
511+ priv -> dmatp .area , priv -> dmatb .bytes );
475512 if (ret < 0 )
476513 goto table_err ;
477514
478- sdev -> dma_trace_pages = ret ;
515+ priv -> dma_trace_pages = ret ;
479516 dev_dbg (sdev -> dev , "%s: dma_trace_pages: %d\n" , __func__ ,
480- sdev -> dma_trace_pages );
517+ priv -> dma_trace_pages );
481518
482519 if (sdev -> first_boot ) {
483520 ret = debugfs_create_dtrace (sdev );
484521 if (ret < 0 )
485522 goto table_err ;
486523 }
487524
488- init_waitqueue_head (& sdev -> trace_sleep );
525+ init_waitqueue_head (& priv -> trace_sleep );
489526
490527 ret = ipc3_dtrace_enable (sdev );
491528 if (ret < 0 )
492529 goto table_err ;
493530
494531 return 0 ;
495532table_err :
496- sdev -> dma_trace_pages = 0 ;
497- snd_dma_free_pages (& sdev -> dmatb );
533+ priv -> dma_trace_pages = 0 ;
534+ snd_dma_free_pages (& priv -> dmatb );
498535page_err :
499- snd_dma_free_pages (& sdev -> dmatp );
536+ snd_dma_free_pages (& priv -> dmatp );
500537 return ret ;
501538}
502539
503540int ipc3_dtrace_posn_update (struct snd_sof_dev * sdev ,
504541 struct sof_ipc_dma_trace_posn * posn )
505542{
543+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
544+
506545 if (!sdev -> fw_trace_is_supported )
507546 return 0 ;
508547
509- if (sdev -> dtrace_state == SOF_DTRACE_ENABLED &&
510- sdev -> host_offset != posn -> host_offset ) {
511- sdev -> host_offset = posn -> host_offset ;
512- wake_up (& sdev -> trace_sleep );
548+ if (priv -> dtrace_state == SOF_DTRACE_ENABLED &&
549+ priv -> host_offset != posn -> host_offset ) {
550+ priv -> host_offset = posn -> host_offset ;
551+ wake_up (& priv -> trace_sleep );
513552 }
514553
515554 if (posn -> overflow != 0 )
@@ -523,27 +562,30 @@ int ipc3_dtrace_posn_update(struct snd_sof_dev *sdev,
523562/* an error has occurred within the DSP that prevents further trace */
524563static void ipc3_dtrace_fw_crashed (struct snd_sof_dev * sdev )
525564{
526- if (sdev -> dtrace_state == SOF_DTRACE_ENABLED ) {
527- sdev -> dtrace_error = true;
528- wake_up (& sdev -> trace_sleep );
565+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
566+
567+ if (priv -> dtrace_state == SOF_DTRACE_ENABLED ) {
568+ priv -> dtrace_error = true;
569+ wake_up (& priv -> trace_sleep );
529570 }
530571}
531572
532573static void ipc3_dtrace_release (struct snd_sof_dev * sdev , bool only_stop )
533574{
575+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
534576 struct sof_ipc_fw_ready * ready = & sdev -> fw_ready ;
535577 struct sof_ipc_fw_version * v = & ready -> version ;
536578 struct sof_ipc_cmd_hdr hdr ;
537579 struct sof_ipc_reply ipc_reply ;
538580 int ret ;
539581
540- if (!sdev -> fw_trace_is_supported || sdev -> dtrace_state == SOF_DTRACE_DISABLED )
582+ if (!sdev -> fw_trace_is_supported || priv -> dtrace_state == SOF_DTRACE_DISABLED )
541583 return ;
542584
543585 ret = sof_dtrace_host_trigger (sdev , SNDRV_PCM_TRIGGER_STOP );
544586 if (ret < 0 )
545587 dev_err (sdev -> dev , "Host dtrace trigger stop failed: %d\n" , ret );
546- sdev -> dtrace_state = SOF_DTRACE_STOPPED ;
588+ priv -> dtrace_state = SOF_DTRACE_STOPPED ;
547589
548590 /*
549591 * stop and free trace DMA in the DSP. TRACE_DMA_FREE is only supported from
@@ -566,11 +608,11 @@ static void ipc3_dtrace_release(struct snd_sof_dev *sdev, bool only_stop)
566608 if (ret < 0 )
567609 dev_err (sdev -> dev , "Host dtrace release failed %d\n" , ret );
568610
569- sdev -> dtrace_state = SOF_DTRACE_DISABLED ;
611+ priv -> dtrace_state = SOF_DTRACE_DISABLED ;
570612
571613out :
572- sdev -> dtrace_draining = true;
573- wake_up (& sdev -> trace_sleep );
614+ priv -> dtrace_draining = true;
615+ wake_up (& priv -> trace_sleep );
574616}
575617
576618static void ipc3_dtrace_suspend (struct snd_sof_dev * sdev , pm_message_t pm_state )
@@ -585,13 +627,15 @@ static int ipc3_dtrace_resume(struct snd_sof_dev *sdev)
585627
586628static void ipc3_dtrace_free (struct snd_sof_dev * sdev )
587629{
630+ struct sof_dtrace_priv * priv = sdev -> fw_trace_data ;
631+
588632 /* release trace */
589633 ipc3_dtrace_release (sdev , false);
590634
591- if (sdev -> dma_trace_pages ) {
592- snd_dma_free_pages (& sdev -> dmatb );
593- snd_dma_free_pages (& sdev -> dmatp );
594- sdev -> dma_trace_pages = 0 ;
635+ if (priv -> dma_trace_pages ) {
636+ snd_dma_free_pages (& priv -> dmatb );
637+ snd_dma_free_pages (& priv -> dmatp );
638+ priv -> dma_trace_pages = 0 ;
595639 }
596640}
597641
0 commit comments