@@ -75,22 +75,54 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
75
75
}
76
76
EXPORT_SYMBOL_GPL (coresight_get_percpu_sink );
77
77
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
+
78
107
static 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 )
81
111
{
82
112
int i ;
83
113
struct coresight_connection * conn ;
84
114
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 )
88
120
return conn ;
89
121
}
90
122
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 ));
94
126
95
127
return ERR_PTR (- ENODEV );
96
128
}
@@ -251,16 +283,17 @@ static void coresight_disable_sink(struct coresight_device *csdev)
251
283
252
284
static int coresight_enable_link (struct coresight_device * csdev ,
253
285
struct coresight_device * parent ,
254
- struct coresight_device * child )
286
+ struct coresight_device * child ,
287
+ struct coresight_device * source )
255
288
{
256
289
int link_subtype ;
257
290
struct coresight_connection * inconn , * outconn ;
258
291
259
292
if (!parent || !child )
260
293
return - EINVAL ;
261
294
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 );
264
297
link_subtype = csdev -> subtype .link_subtype ;
265
298
266
299
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR (inconn ))
@@ -273,15 +306,16 @@ static int coresight_enable_link(struct coresight_device *csdev,
273
306
274
307
static void coresight_disable_link (struct coresight_device * csdev ,
275
308
struct coresight_device * parent ,
276
- struct coresight_device * child )
309
+ struct coresight_device * child ,
310
+ struct coresight_device * source )
277
311
{
278
312
struct coresight_connection * inconn , * outconn ;
279
313
280
314
if (!parent || !child )
281
315
return ;
282
316
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 );
285
319
286
320
link_ops (csdev )-> disable (csdev , inconn , outconn );
287
321
}
@@ -375,7 +409,8 @@ static void coresight_disable_path_from(struct list_head *path,
375
409
case CORESIGHT_DEV_TYPE_LINK :
376
410
parent = list_prev_entry (nd , link )-> csdev ;
377
411
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 ));
379
414
break ;
380
415
default :
381
416
break ;
@@ -418,7 +453,9 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
418
453
u32 type ;
419
454
struct coresight_node * nd ;
420
455
struct coresight_device * csdev , * parent , * child ;
456
+ struct coresight_device * source ;
421
457
458
+ source = coresight_get_source (path );
422
459
list_for_each_entry_reverse (nd , path , link ) {
423
460
csdev = nd -> csdev ;
424
461
type = csdev -> type ;
@@ -456,7 +493,7 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode,
456
493
case CORESIGHT_DEV_TYPE_LINK :
457
494
parent = list_prev_entry (nd , link )-> csdev ;
458
495
child = list_next_entry (nd , link )-> csdev ;
459
- ret = coresight_enable_link (csdev , parent , child );
496
+ ret = coresight_enable_link (csdev , parent , child , source );
460
497
if (ret )
461
498
goto err ;
462
499
break ;
@@ -619,6 +656,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
619
656
/**
620
657
* _coresight_build_path - recursively build a path from a @csdev to a sink.
621
658
* @csdev: The device to start from.
659
+ * @source: The trace source device of the path.
622
660
* @sink: The final sink we want in this path.
623
661
* @path: The list to add devices to.
624
662
*
@@ -628,6 +666,7 @@ static void coresight_drop_device(struct coresight_device *csdev)
628
666
* the source is the first device and the sink the last one.
629
667
*/
630
668
static int _coresight_build_path (struct coresight_device * csdev ,
669
+ struct coresight_device * source ,
631
670
struct coresight_device * sink ,
632
671
struct list_head * path )
633
672
{
@@ -641,7 +680,7 @@ static int _coresight_build_path(struct coresight_device *csdev,
641
680
642
681
if (coresight_is_percpu_source (csdev ) && coresight_is_percpu_sink (sink ) &&
643
682
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 ) {
645
684
found = true;
646
685
goto out ;
647
686
}
@@ -652,8 +691,12 @@ static int _coresight_build_path(struct coresight_device *csdev,
652
691
struct coresight_device * child_dev ;
653
692
654
693
child_dev = csdev -> pdata -> out_conns [i ]-> dest_dev ;
694
+
695
+ if (coresight_blocks_source (source , csdev -> pdata -> out_conns [i ]))
696
+ continue ;
697
+
655
698
if (child_dev &&
656
- _coresight_build_path (child_dev , sink , path ) == 0 ) {
699
+ _coresight_build_path (child_dev , source , sink , path ) == 0 ) {
657
700
found = true;
658
701
break ;
659
702
}
@@ -698,7 +741,7 @@ struct list_head *coresight_build_path(struct coresight_device *source,
698
741
699
742
INIT_LIST_HEAD (path );
700
743
701
- rc = _coresight_build_path (source , sink , path );
744
+ rc = _coresight_build_path (source , source , sink , path );
702
745
if (rc ) {
703
746
kfree (path );
704
747
return ERR_PTR (rc );
@@ -927,6 +970,16 @@ static int coresight_orphan_match(struct device *dev, void *data)
927
970
for (i = 0 ; i < src_csdev -> pdata -> nr_outconns ; i ++ ) {
928
971
conn = src_csdev -> pdata -> out_conns [i ];
929
972
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
+
930
983
/* Skip the port if it's already connected. */
931
984
if (conn -> dest_dev )
932
985
continue ;
@@ -977,18 +1030,40 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
977
1030
csdev , coresight_orphan_match );
978
1031
}
979
1032
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
+
980
1046
/* coresight_remove_conns - Remove other device's references to this device */
981
1047
static void coresight_remove_conns (struct coresight_device * csdev )
982
1048
{
983
1049
int i , j ;
984
1050
struct coresight_connection * conn ;
985
1051
1052
+ if (coresight_is_device_source (csdev ))
1053
+ bus_for_each_dev (& coresight_bustype , NULL , csdev ,
1054
+ coresight_clear_filter_source );
1055
+
986
1056
/*
987
1057
* Remove the input connection references from the destination device
988
1058
* for each output connection.
989
1059
*/
990
1060
for (i = 0 ; i < csdev -> pdata -> nr_outconns ; i ++ ) {
991
1061
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
+
992
1067
if (!conn -> dest_dev )
993
1068
continue ;
994
1069
0 commit comments