@@ -403,8 +403,8 @@ static void coresight_disable_link(struct coresight_device *csdev,
403
403
csdev -> enable = false;
404
404
}
405
405
406
- static int coresight_enable_source (struct coresight_device * csdev ,
407
- enum cs_mode mode )
406
+ int coresight_enable_source (struct coresight_device * csdev , enum cs_mode mode ,
407
+ void * data )
408
408
{
409
409
int ret ;
410
410
@@ -413,7 +413,7 @@ static int coresight_enable_source(struct coresight_device *csdev,
413
413
ret = coresight_control_assoc_ectdev (csdev , true);
414
414
if (ret )
415
415
return ret ;
416
- ret = source_ops (csdev )-> enable (csdev , NULL , mode );
416
+ ret = source_ops (csdev )-> enable (csdev , data , mode );
417
417
if (ret ) {
418
418
coresight_control_assoc_ectdev (csdev , false);
419
419
return ret ;
@@ -426,25 +426,75 @@ static int coresight_enable_source(struct coresight_device *csdev,
426
426
427
427
return 0 ;
428
428
}
429
+ EXPORT_SYMBOL_GPL (coresight_enable_source );
430
+
431
+ static bool coresight_is_helper (struct coresight_device * csdev )
432
+ {
433
+ return csdev -> type == CORESIGHT_DEV_TYPE_HELPER ;
434
+ }
435
+
436
+ static int coresight_enable_helper (struct coresight_device * csdev ,
437
+ enum cs_mode mode , void * data )
438
+ {
439
+ int ret ;
440
+
441
+ if (!helper_ops (csdev )-> enable )
442
+ return 0 ;
443
+ ret = helper_ops (csdev )-> enable (csdev , mode , data );
444
+ if (ret )
445
+ return ret ;
446
+
447
+ csdev -> enable = true;
448
+ return 0 ;
449
+ }
450
+
451
+ static void coresight_disable_helper (struct coresight_device * csdev )
452
+ {
453
+ int ret ;
454
+
455
+ if (!helper_ops (csdev )-> disable )
456
+ return ;
457
+
458
+ ret = helper_ops (csdev )-> disable (csdev , NULL );
459
+ if (ret )
460
+ return ;
461
+ csdev -> enable = false;
462
+ }
463
+
464
+ static void coresight_disable_helpers (struct coresight_device * csdev )
465
+ {
466
+ int i ;
467
+ struct coresight_device * helper ;
468
+
469
+ for (i = 0 ; i < csdev -> pdata -> nr_outconns ; ++ i ) {
470
+ helper = csdev -> pdata -> out_conns [i ]-> dest_dev ;
471
+ if (helper && coresight_is_helper (helper ))
472
+ coresight_disable_helper (helper );
473
+ }
474
+ }
429
475
430
476
/**
431
477
* coresight_disable_source - Drop the reference count by 1 and disable
432
478
* the device if there are no users left.
433
479
*
434
480
* @csdev: The coresight device to disable
481
+ * @data: Opaque data to pass on to the disable function of the source device.
482
+ * For example in perf mode this is a pointer to the struct perf_event.
435
483
*
436
484
* Returns true if the device has been disabled.
437
485
*/
438
- static bool coresight_disable_source (struct coresight_device * csdev )
486
+ bool coresight_disable_source (struct coresight_device * csdev , void * data )
439
487
{
440
488
if (atomic_dec_return (& csdev -> refcnt ) == 0 ) {
441
489
if (source_ops (csdev )-> disable )
442
- source_ops (csdev )-> disable (csdev , NULL );
490
+ source_ops (csdev )-> disable (csdev , data );
443
491
coresight_control_assoc_ectdev (csdev , false);
492
+ coresight_disable_helpers (csdev );
444
493
csdev -> enable = false;
445
494
}
446
495
return !csdev -> enable ;
447
496
}
497
+ EXPORT_SYMBOL_GPL (coresight_disable_source );
448
498
449
499
/*
450
500
* coresight_disable_path_from : Disable components in the given path beyond
@@ -495,6 +545,9 @@ static void coresight_disable_path_from(struct list_head *path,
495
545
default :
496
546
break ;
497
547
}
548
+
549
+ /* Disable all helpers adjacent along the path last */
550
+ coresight_disable_helpers (csdev );
498
551
}
499
552
}
500
553
@@ -504,9 +557,28 @@ void coresight_disable_path(struct list_head *path)
504
557
}
505
558
EXPORT_SYMBOL_GPL (coresight_disable_path );
506
559
507
- int coresight_enable_path (struct list_head * path , enum cs_mode mode , void * sink_data )
560
+ static int coresight_enable_helpers (struct coresight_device * csdev ,
561
+ enum cs_mode mode , void * data )
508
562
{
563
+ int i , ret = 0 ;
564
+ struct coresight_device * helper ;
565
+
566
+ for (i = 0 ; i < csdev -> pdata -> nr_outconns ; ++ i ) {
567
+ helper = csdev -> pdata -> out_conns [i ]-> dest_dev ;
568
+ if (!helper || !coresight_is_helper (helper ))
569
+ continue ;
570
+
571
+ ret = coresight_enable_helper (helper , mode , data );
572
+ if (ret )
573
+ return ret ;
574
+ }
509
575
576
+ return 0 ;
577
+ }
578
+
579
+ int coresight_enable_path (struct list_head * path , enum cs_mode mode ,
580
+ void * sink_data )
581
+ {
510
582
int ret = 0 ;
511
583
u32 type ;
512
584
struct coresight_node * nd ;
@@ -516,6 +588,10 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode, void *sink_
516
588
csdev = nd -> csdev ;
517
589
type = csdev -> type ;
518
590
591
+ /* Enable all helpers adjacent to the path first */
592
+ ret = coresight_enable_helpers (csdev , mode , sink_data );
593
+ if (ret )
594
+ goto err ;
519
595
/*
520
596
* ETF devices are tricky... They can be a link or a sink,
521
597
* depending on how they are configured. If an ETF has been
@@ -710,7 +786,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
710
786
struct coresight_device * child ;
711
787
712
788
child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
713
- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
789
+ if (child && coresight_is_helper ( child ) )
714
790
if (!coresight_get_ref (child ))
715
791
goto err ;
716
792
}
@@ -721,7 +797,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
721
797
struct coresight_device * child ;
722
798
723
799
child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
724
- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
800
+ if (child && coresight_is_helper ( child ) )
725
801
coresight_put_ref (child );
726
802
}
727
803
return - ENODEV ;
@@ -740,7 +816,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
740
816
struct coresight_device * child ;
741
817
742
818
child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
743
- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
819
+ if (child && coresight_is_helper ( child ) )
744
820
coresight_put_ref (child );
745
821
}
746
822
}
@@ -1102,7 +1178,7 @@ int coresight_enable(struct coresight_device *csdev)
1102
1178
if (ret )
1103
1179
goto err_path ;
1104
1180
1105
- ret = coresight_enable_source (csdev , CS_MODE_SYSFS );
1181
+ ret = coresight_enable_source (csdev , CS_MODE_SYSFS , NULL );
1106
1182
if (ret )
1107
1183
goto err_source ;
1108
1184
@@ -1159,7 +1235,7 @@ void coresight_disable(struct coresight_device *csdev)
1159
1235
if (ret )
1160
1236
goto out ;
1161
1237
1162
- if (!csdev -> enable || !coresight_disable_source (csdev ))
1238
+ if (!csdev -> enable || !coresight_disable_source (csdev , NULL ))
1163
1239
goto out ;
1164
1240
1165
1241
switch (csdev -> subtype .source_subtype ) {
@@ -1644,6 +1720,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
1644
1720
return - ENOENT ;
1645
1721
}
1646
1722
1723
+ static bool coresight_compare_type (enum coresight_dev_type type_a ,
1724
+ union coresight_dev_subtype subtype_a ,
1725
+ enum coresight_dev_type type_b ,
1726
+ union coresight_dev_subtype subtype_b )
1727
+ {
1728
+ if (type_a != type_b )
1729
+ return false;
1730
+
1731
+ switch (type_a ) {
1732
+ case CORESIGHT_DEV_TYPE_SINK :
1733
+ return subtype_a .sink_subtype == subtype_b .sink_subtype ;
1734
+ case CORESIGHT_DEV_TYPE_LINK :
1735
+ return subtype_a .link_subtype == subtype_b .link_subtype ;
1736
+ case CORESIGHT_DEV_TYPE_LINKSINK :
1737
+ return subtype_a .link_subtype == subtype_b .link_subtype &&
1738
+ subtype_a .sink_subtype == subtype_b .sink_subtype ;
1739
+ case CORESIGHT_DEV_TYPE_SOURCE :
1740
+ return subtype_a .source_subtype == subtype_b .source_subtype ;
1741
+ case CORESIGHT_DEV_TYPE_HELPER :
1742
+ return subtype_a .helper_subtype == subtype_b .helper_subtype ;
1743
+ default :
1744
+ return false;
1745
+ }
1746
+ }
1747
+
1748
+ struct coresight_device *
1749
+ coresight_find_input_type (struct coresight_platform_data * pdata ,
1750
+ enum coresight_dev_type type ,
1751
+ union coresight_dev_subtype subtype )
1752
+ {
1753
+ int i ;
1754
+ struct coresight_connection * conn ;
1755
+
1756
+ for (i = 0 ; i < pdata -> nr_inconns ; ++ i ) {
1757
+ conn = pdata -> in_conns [i ];
1758
+ if (conn &&
1759
+ coresight_compare_type (type , subtype , conn -> src_dev -> type ,
1760
+ conn -> src_dev -> subtype ))
1761
+ return conn -> src_dev ;
1762
+ }
1763
+ return NULL ;
1764
+ }
1765
+ EXPORT_SYMBOL_GPL (coresight_find_input_type );
1766
+
1767
+ struct coresight_device *
1768
+ coresight_find_output_type (struct coresight_platform_data * pdata ,
1769
+ enum coresight_dev_type type ,
1770
+ union coresight_dev_subtype subtype )
1771
+ {
1772
+ int i ;
1773
+ struct coresight_connection * conn ;
1774
+
1775
+ for (i = 0 ; i < pdata -> nr_outconns ; ++ i ) {
1776
+ conn = pdata -> out_conns [i ];
1777
+ if (conn -> dest_dev &&
1778
+ coresight_compare_type (type , subtype , conn -> dest_dev -> type ,
1779
+ conn -> dest_dev -> subtype ))
1780
+ return conn -> dest_dev ;
1781
+ }
1782
+ return NULL ;
1783
+ }
1784
+ EXPORT_SYMBOL_GPL (coresight_find_output_type );
1785
+
1647
1786
bool coresight_loses_context_with_cpu (struct device * dev )
1648
1787
{
1649
1788
return fwnode_property_present (dev_fwnode (dev ),
0 commit comments