@@ -403,8 +403,8 @@ static void coresight_disable_link(struct coresight_device *csdev,
403403 csdev -> enable = false;
404404}
405405
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 )
408408{
409409 int ret ;
410410
@@ -413,7 +413,7 @@ static int coresight_enable_source(struct coresight_device *csdev,
413413 ret = coresight_control_assoc_ectdev (csdev , true);
414414 if (ret )
415415 return ret ;
416- ret = source_ops (csdev )-> enable (csdev , NULL , mode );
416+ ret = source_ops (csdev )-> enable (csdev , data , mode );
417417 if (ret ) {
418418 coresight_control_assoc_ectdev (csdev , false);
419419 return ret ;
@@ -426,25 +426,75 @@ static int coresight_enable_source(struct coresight_device *csdev,
426426
427427 return 0 ;
428428}
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+ }
429475
430476/**
431477 * coresight_disable_source - Drop the reference count by 1 and disable
432478 * the device if there are no users left.
433479 *
434480 * @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.
435483 *
436484 * Returns true if the device has been disabled.
437485 */
438- static bool coresight_disable_source (struct coresight_device * csdev )
486+ bool coresight_disable_source (struct coresight_device * csdev , void * data )
439487{
440488 if (atomic_dec_return (& csdev -> refcnt ) == 0 ) {
441489 if (source_ops (csdev )-> disable )
442- source_ops (csdev )-> disable (csdev , NULL );
490+ source_ops (csdev )-> disable (csdev , data );
443491 coresight_control_assoc_ectdev (csdev , false);
492+ coresight_disable_helpers (csdev );
444493 csdev -> enable = false;
445494 }
446495 return !csdev -> enable ;
447496}
497+ EXPORT_SYMBOL_GPL (coresight_disable_source );
448498
449499/*
450500 * 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,
495545 default :
496546 break ;
497547 }
548+
549+ /* Disable all helpers adjacent along the path last */
550+ coresight_disable_helpers (csdev );
498551 }
499552}
500553
@@ -504,9 +557,28 @@ void coresight_disable_path(struct list_head *path)
504557}
505558EXPORT_SYMBOL_GPL (coresight_disable_path );
506559
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 )
508562{
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+ }
509575
576+ return 0 ;
577+ }
578+
579+ int coresight_enable_path (struct list_head * path , enum cs_mode mode ,
580+ void * sink_data )
581+ {
510582 int ret = 0 ;
511583 u32 type ;
512584 struct coresight_node * nd ;
@@ -516,6 +588,10 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode, void *sink_
516588 csdev = nd -> csdev ;
517589 type = csdev -> type ;
518590
591+ /* Enable all helpers adjacent to the path first */
592+ ret = coresight_enable_helpers (csdev , mode , sink_data );
593+ if (ret )
594+ goto err ;
519595 /*
520596 * ETF devices are tricky... They can be a link or a sink,
521597 * depending on how they are configured. If an ETF has been
@@ -710,7 +786,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
710786 struct coresight_device * child ;
711787
712788 child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
713- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
789+ if (child && coresight_is_helper ( child ) )
714790 if (!coresight_get_ref (child ))
715791 goto err ;
716792 }
@@ -721,7 +797,7 @@ static int coresight_grab_device(struct coresight_device *csdev)
721797 struct coresight_device * child ;
722798
723799 child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
724- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
800+ if (child && coresight_is_helper ( child ) )
725801 coresight_put_ref (child );
726802 }
727803 return - ENODEV ;
@@ -740,7 +816,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
740816 struct coresight_device * child ;
741817
742818 child = csdev -> pdata -> out_conns [i ]-> dest_dev ;
743- if (child && child -> type == CORESIGHT_DEV_TYPE_HELPER )
819+ if (child && coresight_is_helper ( child ) )
744820 coresight_put_ref (child );
745821 }
746822}
@@ -1102,7 +1178,7 @@ int coresight_enable(struct coresight_device *csdev)
11021178 if (ret )
11031179 goto err_path ;
11041180
1105- ret = coresight_enable_source (csdev , CS_MODE_SYSFS );
1181+ ret = coresight_enable_source (csdev , CS_MODE_SYSFS , NULL );
11061182 if (ret )
11071183 goto err_source ;
11081184
@@ -1159,7 +1235,7 @@ void coresight_disable(struct coresight_device *csdev)
11591235 if (ret )
11601236 goto out ;
11611237
1162- if (!csdev -> enable || !coresight_disable_source (csdev ))
1238+ if (!csdev -> enable || !coresight_disable_source (csdev , NULL ))
11631239 goto out ;
11641240
11651241 switch (csdev -> subtype .source_subtype ) {
@@ -1644,6 +1720,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
16441720 return - ENOENT ;
16451721}
16461722
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+
16471786bool coresight_loses_context_with_cpu (struct device * dev )
16481787{
16491788 return fwnode_property_present (dev_fwnode (dev ),
0 commit comments