@@ -75,22 +75,54 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
7575}
7676EXPORT_SYMBOL_GPL (coresight_get_percpu_sink );
7777
78+ static struct coresight_device * coresight_get_source (struct list_head * path )
79+ {
80+ struct coresight_device * csdev ;
81+
82+ if (!path )
83+ return NULL ;
84+
85+ csdev = list_first_entry (path , struct coresight_node , link )-> csdev ;
86+ if (!coresight_is_device_source (csdev ))
87+ return NULL ;
88+
89+ return csdev ;
90+ }
91+
92+ /**
93+ * coresight_blocks_source - checks whether the connection matches the source
94+ * of path if connection is bound to specific source.
95+ * @src: The source device of the trace path
96+ * @conn: The connection of one outport
97+ *
98+ * Return false if the connection doesn't have a source binded or source of the
99+ * path matches the source binds to connection.
100+ */
101+ static bool coresight_blocks_source (struct coresight_device * src ,
102+ struct coresight_connection * conn )
103+ {
104+ return conn -> filter_src_fwnode && (conn -> filter_src_dev != src );
105+ }
106+
78107static struct coresight_connection *
79- coresight_find_out_connection (struct coresight_device * src_dev ,
80- struct coresight_device * dest_dev )
108+ coresight_find_out_connection (struct coresight_device * csdev ,
109+ struct coresight_device * out_dev ,
110+ struct coresight_device * trace_src )
81111{
82112 int i ;
83113 struct coresight_connection * conn ;
84114
85- for (i = 0 ; i < src_dev -> pdata -> nr_outconns ; i ++ ) {
86- conn = src_dev -> pdata -> out_conns [i ];
87- if (conn -> dest_dev == dest_dev )
115+ for (i = 0 ; i < csdev -> pdata -> nr_outconns ; i ++ ) {
116+ conn = csdev -> pdata -> out_conns [i ];
117+ if (coresight_blocks_source (trace_src , conn ))
118+ continue ;
119+ if (conn -> dest_dev == out_dev )
88120 return conn ;
89121 }
90122
91- dev_err (& src_dev -> dev ,
92- "couldn't find output connection, src_dev : %s, dest_dev : %s\n" ,
93- dev_name (& src_dev -> dev ), dev_name (& dest_dev -> dev ));
123+ dev_err (& csdev -> dev ,
124+ "couldn't find output connection, csdev : %s, out_dev : %s\n" ,
125+ dev_name (& csdev -> dev ), dev_name (& out_dev -> dev ));
94126
95127 return ERR_PTR (- ENODEV );
96128}
@@ -251,16 +283,17 @@ static void coresight_disable_sink(struct coresight_device *csdev)
251283
252284static int coresight_enable_link (struct coresight_device * csdev ,
253285 struct coresight_device * parent ,
254- struct coresight_device * child )
286+ struct coresight_device * child ,
287+ struct coresight_device * source )
255288{
256289 int link_subtype ;
257290 struct coresight_connection * inconn , * outconn ;
258291
259292 if (!parent || !child )
260293 return - EINVAL ;
261294
262- inconn = coresight_find_out_connection (parent , csdev );
263- outconn = coresight_find_out_connection (csdev , child );
295+ inconn = coresight_find_out_connection (parent , csdev , source );
296+ outconn = coresight_find_out_connection (csdev , child , source );
264297 link_subtype = csdev -> subtype .link_subtype ;
265298
266299 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR (inconn ))
@@ -273,15 +306,16 @@ static int coresight_enable_link(struct coresight_device *csdev,
273306
274307static void coresight_disable_link (struct coresight_device * csdev ,
275308 struct coresight_device * parent ,
276- struct coresight_device * child )
309+ struct coresight_device * child ,
310+ struct coresight_device * source )
277311{
278312 struct coresight_connection * inconn , * outconn ;
279313
280314 if (!parent || !child )
281315 return ;
282316
283- inconn = coresight_find_out_connection (parent , csdev );
284- outconn = coresight_find_out_connection (csdev , child );
317+ inconn = coresight_find_out_connection (parent , csdev , source );
318+ outconn = coresight_find_out_connection (csdev , child , source );
285319
286320 link_ops (csdev )-> disable (csdev , inconn , outconn );
287321}
@@ -375,7 +409,8 @@ static void coresight_disable_path_from(struct list_head *path,
375409 case CORESIGHT_DEV_TYPE_LINK :
376410 parent = list_prev_entry (nd , link )-> csdev ;
377411 child = list_next_entry (nd , link )-> csdev ;
378- coresight_disable_link (csdev , parent , child );
412+ coresight_disable_link (csdev , parent , child ,
413+ coresight_get_source (path ));
379414 break ;
380415 default :
381416 break ;
@@ -418,7 +453,9 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
418453 u32 type ;
419454 struct coresight_node * nd ;
420455 struct coresight_device * csdev , * parent , * child ;
456+ struct coresight_device * source ;
421457
458+ source = coresight_get_source (path );
422459 list_for_each_entry_reverse (nd , path , link ) {
423460 csdev = nd -> csdev ;
424461 type = csdev -> type ;
@@ -456,7 +493,7 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
456493 case CORESIGHT_DEV_TYPE_LINK :
457494 parent = list_prev_entry (nd , link )-> csdev ;
458495 child = list_next_entry (nd , link )-> csdev ;
459- ret = coresight_enable_link (csdev , parent , child );
496+ ret = coresight_enable_link (csdev , parent , child , source );
460497 if (ret )
461498 goto err ;
462499 break ;
@@ -619,6 +656,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
619656/**
620657 * _coresight_build_path - recursively build a path from a @csdev to a sink.
621658 * @csdev: The device to start from.
659+ * @source: The trace source device of the path.
622660 * @sink: The final sink we want in this path.
623661 * @path: The list to add devices to.
624662 *
@@ -628,6 +666,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
628666 * the source is the first device and the sink the last one.
629667 */
630668static int _coresight_build_path (struct coresight_device * csdev ,
669+ struct coresight_device * source ,
631670 struct coresight_device * sink ,
632671 struct list_head * path )
633672{
@@ -641,7 +680,7 @@ static int _coresight_build_path(struct coresight_device *csdev,
641680
642681 if (coresight_is_percpu_source (csdev ) && coresight_is_percpu_sink (sink ) &&
643682 sink == per_cpu (csdev_sink , source_ops (csdev )-> cpu_id (csdev ))) {
644- if (_coresight_build_path (sink , sink , path ) == 0 ) {
683+ if (_coresight_build_path (sink , source , sink , path ) == 0 ) {
645684 found = true;
646685 goto out ;
647686 }
@@ -652,8 +691,12 @@ static int _coresight_build_path(struct coresight_device *csdev,
652691 struct coresight_device * child_dev ;
653692
654693 child_dev = csdev -> pdata -> out_conns [i ]-> dest_dev ;
694+
695+ if (coresight_blocks_source (source , csdev -> pdata -> out_conns [i ]))
696+ continue ;
697+
655698 if (child_dev &&
656- _coresight_build_path (child_dev , sink , path ) == 0 ) {
699+ _coresight_build_path (child_dev , source , sink , path ) == 0 ) {
657700 found = true;
658701 break ;
659702 }
@@ -698,7 +741,7 @@ struct list_head *coresight_build_path(struct coresight_device *source,
698741
699742 INIT_LIST_HEAD (path );
700743
701- rc = _coresight_build_path (source , sink , path );
744+ rc = _coresight_build_path (source , source , sink , path );
702745 if (rc ) {
703746 kfree (path );
704747 return ERR_PTR (rc );
@@ -927,6 +970,16 @@ static int coresight_orphan_match(struct device *dev, void *data)
927970 for (i = 0 ; i < src_csdev -> pdata -> nr_outconns ; i ++ ) {
928971 conn = src_csdev -> pdata -> out_conns [i ];
929972
973+ /* Fix filter source device before skip the port */
974+ if (conn -> filter_src_fwnode && !conn -> filter_src_dev ) {
975+ if (dst_csdev &&
976+ (conn -> filter_src_fwnode == dst_csdev -> dev .fwnode ) &&
977+ !WARN_ON_ONCE (!coresight_is_device_source (dst_csdev )))
978+ conn -> filter_src_dev = dst_csdev ;
979+ else
980+ still_orphan = true;
981+ }
982+
930983 /* Skip the port if it's already connected. */
931984 if (conn -> dest_dev )
932985 continue ;
@@ -977,18 +1030,40 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
9771030 csdev , coresight_orphan_match );
9781031}
9791032
1033+ static int coresight_clear_filter_source (struct device * dev , void * data )
1034+ {
1035+ int i ;
1036+ struct coresight_device * source = data ;
1037+ struct coresight_device * csdev = to_coresight_device (dev );
1038+
1039+ for (i = 0 ; i < csdev -> pdata -> nr_outconns ; ++ i ) {
1040+ if (csdev -> pdata -> out_conns [i ]-> filter_src_dev == source )
1041+ csdev -> pdata -> out_conns [i ]-> filter_src_dev = NULL ;
1042+ }
1043+ return 0 ;
1044+ }
1045+
9801046/* coresight_remove_conns - Remove other device's references to this device */
9811047static void coresight_remove_conns (struct coresight_device * csdev )
9821048{
9831049 int i , j ;
9841050 struct coresight_connection * conn ;
9851051
1052+ if (coresight_is_device_source (csdev ))
1053+ bus_for_each_dev (& coresight_bustype , NULL , csdev ,
1054+ coresight_clear_filter_source );
1055+
9861056 /*
9871057 * Remove the input connection references from the destination device
9881058 * for each output connection.
9891059 */
9901060 for (i = 0 ; i < csdev -> pdata -> nr_outconns ; i ++ ) {
9911061 conn = csdev -> pdata -> out_conns [i ];
1062+ if (conn -> filter_src_fwnode ) {
1063+ conn -> filter_src_dev = NULL ;
1064+ fwnode_handle_put (conn -> filter_src_fwnode );
1065+ }
1066+
9921067 if (!conn -> dest_dev )
9931068 continue ;
9941069
0 commit comments