History

coresight: Add default sink selection to CoreSight base

Adds a method to select a suitable sink connected to a given source. In cases where no sink is defined, the coresight_find_default_sink routine can search from a given source, through the child connections until a suitable sink is found. The suitability is defined in by the sink coresight_dev_subtype on the CoreSight device, and the distance from the source by counting connections. Higher value subtype is preferred - where these are equal, shorter distance from source is used as a tie-break. This allows for default sink to be discovered were none is specified (e.g. perf command line)

Mike Leach committed 6 years ago

Commit 0336bdf1 parent d021f5c3 files · +171 −0Browse files

Unified · Split

3 files
  1. drivers/hwtracing/coresight/coresight-priv.h +2 −0
  2. drivers/hwtracing/coresight/coresight.c +166 −0
  3. include/linux/coresight.h +3 −0
drivers/hwtracing/coresight/coresight-priv.h+2−0
@@ -150,6 +150,8 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data); · 149 unmodified lines
150150 struct coresight_device *coresight_get_sink(struct list_head *path);
151151 struct coresight_device *coresight_get_enabled_sink(bool reset);
152152 struct coresight_device *coresight_get_sink_by_id(u32 id);
153+struct coresight_device *
154+coresight_find_default_sink(struct coresight_device *csdev);
153155 struct list_head *coresight_build_path(struct coresight_device *csdev,
154156 struct coresight_device *sink);
155157 void coresight_release_path(struct list_head *path);
drivers/hwtracing/coresight/coresight.c+166−0
@@ -769,6 +769,171 @@ void coresight_release_path(struct list_head *path) · 768 unmodified lines
769769 path = NULL;
770770 }
771771
772+/* return true if the device is a suitable type for a default sink */
773+static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
774+{
775+ /* sink & correct subtype */
776+ if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
777+ (csdev->type == CORESIGHT_DEV_TYPE_LINKSINK)) &&
778+ (csdev->subtype.sink_subtype >= CORESIGHT_DEV_SUBTYPE_SINK_BUFFER))
779+ return true;
780+ return false;
781+}
782+
783+/**
784+ * coresight_select_best_sink - return the best sink for use as default from
785+ * the two provided.
786+ *
787+ * @sink: current best sink.
788+ * @depth: search depth where current sink was found.
789+ * @new_sink: new sink for comparison with current sink.
790+ * @new_depth: search depth where new sink was found.
791+ *
792+ * Sinks prioritised according to coresight_dev_subtype_sink, with only
793+ * subtypes CORESIGHT_DEV_SUBTYPE_SINK_BUFFER or higher being used.
794+ *
795+ * Where two sinks of equal priority are found, the sink closest to the
796+ * source is used (smallest search depth).
797+ *
798+ * return @new_sink & update @depth if better than @sink, else return @sink.
799+ */
800+static struct coresight_device *
801+coresight_select_best_sink(struct coresight_device *sink, int *depth,
802+ struct coresight_device *new_sink, int new_depth)
803+{
804+ bool update = false;
805+
806+ if (!sink) {
807+ /* first found at this level */
808+ update = true;
809+ } else if (new_sink->subtype.sink_subtype >
810+ sink->subtype.sink_subtype) {
811+ /* found better sink */
812+ update = true;
813+ } else if ((new_sink->subtype.sink_subtype ==
814+ sink->subtype.sink_subtype) &&
815+ (*depth > new_depth)) {
816+ /* found same but closer sink */
817+ update = true;
818+ }
819+
820+ if (update)
821+ *depth = new_depth;
822+ return update ? new_sink : sink;
823+}
824+
825+/**
826+ * coresight_find_sink - recursive function to walk trace connections from
827+ * source to find a suitable default sink.
828+ *
829+ * @csdev: source / current device to check.
830+ * @depth: [in] search depth of calling dev, [out] depth of found sink.
831+ *
832+ * This will walk the connection path from a source (ETM) till a suitable
833+ * sink is encountered and return that sink to the original caller.
834+ *
835+ * If current device is a plain sink return that & depth, otherwise recursively
836+ * call child connections looking for a sink. Select best possible using
837+ * coresight_select_best_sink.
838+ *
839+ * return best sink found, or NULL if not found at this node or child nodes.
840+ */
841+static struct coresight_device *
842+coresight_find_sink(struct coresight_device *csdev, int *depth)
843+{
844+ int i, curr_depth = *depth + 1, found_depth = 0;
845+ struct coresight_device *found_sink = NULL;
846+
847+ if (coresight_is_def_sink_type(csdev)) {
848+ found_depth = curr_depth;
849+ found_sink = csdev;
850+ if (csdev->type == CORESIGHT_DEV_TYPE_SINK)
851+ goto return_def_sink;
852+ /* look past LINKSINK for something better */
853+ }
854+
855+ /*
856+ * Not a sink we want - or possible child sink may be better.
857+ * recursively explore each port found on this element.
858+ */
859+ for (i = 0; i < csdev->pdata->nr_outport; i++) {
860+ struct coresight_device *child_dev, *sink = NULL;
861+ int child_depth = curr_depth;
862+
863+ child_dev = csdev->pdata->conns[i].child_dev;
864+ if (child_dev)
865+ sink = coresight_find_sink(child_dev, &child_depth);
866+
867+ if (sink)
868+ found_sink = coresight_select_best_sink(found_sink,
869+ &found_depth,
870+ sink,
871+ child_depth);
872+ }
873+
874+return_def_sink:
875+ /* return found sink and depth */
876+ if (found_sink)
877+ *depth = found_depth;
878+ return found_sink;
879+}
880+
881+/**
882+ * coresight_find_default_sink: Find a sink suitable for use as a
883+ * default sink.
884+ *
885+ * @csdev: starting source to find a connected sink.
886+ *
887+ * Walks connections graph looking for a suitable sink to enable for the
888+ * supplied source. Uses CoreSight device subtypes and distance from source
889+ * to select the best sink.
890+ *
891+ * If a sink is found, then the default sink for this device is set and
892+ * will be automatically used in future.
893+ *
894+ * Used in cases where the CoreSight user (perf / sysfs) has not selected a
895+ * sink.
896+ */
897+struct coresight_device *
898+coresight_find_default_sink(struct coresight_device *csdev)
899+{
900+ int depth = 0;
901+
902+ /* look for a default sink if we have not found for this device */
903+ if (!csdev->def_sink)
904+ csdev->def_sink = coresight_find_sink(csdev, &depth);
905+ return csdev->def_sink;
906+}
907+
908+static int coresight_remove_sink_ref(struct device *dev, void *data)
909+{
910+ struct coresight_device *sink = data;
911+ struct coresight_device *source = to_coresight_device(dev);
912+
913+ if (source->def_sink == sink)
914+ source->def_sink = NULL;
915+ return 0;
916+}
917+
918+/**
919+ * coresight_clear_default_sink: Remove all default sink references to the
920+ * supplied sink.
921+ *
922+ * If supplied device is a sink, then check all the bus devices and clear
923+ * out all the references to this sink from the coresight_device def_sink
924+ * parameter.
925+ *
926+ * @csdev: coresight sink - remove references to this from all sources.
927+ */
928+static void coresight_clear_default_sink(struct coresight_device *csdev)
929+{
930+ if ((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
931+ (csdev->type == CORESIGHT_DEV_TYPE_LINKSINK)) {
932+ bus_for_each_dev(&coresight_bustype, NULL, csdev,
933+ coresight_remove_sink_ref);
934+ }
935+}
936+
772937 /** coresight_validate_source - make sure a source has the right credentials
773938 * @csdev: the device structure for a source.
774939 * @function: the function this was called from.
@@ -1358,6 +1523,7 @@ void coresight_unregister(struct coresight_device *csdev) · 583 unmodified lines
13581523 etm_perf_del_symlink_sink(csdev);
13591524 /* Remove references of that device in the topology */
13601525 coresight_remove_conns(csdev);
1526+ coresight_clear_default_sink(csdev);
13611527 coresight_release_platform_data(csdev, csdev->pdata);
13621528 device_unregister(&csdev->dev);
13631529 }
include/linux/coresight.h+3−0
@@ -48,6 +48,7 @@ enum coresight_dev_subtype_sink { · 47 unmodified lines
4848 CORESIGHT_DEV_SUBTYPE_SINK_NONE,
4949 CORESIGHT_DEV_SUBTYPE_SINK_PORT,
5050 CORESIGHT_DEV_SUBTYPE_SINK_BUFFER,
51+ CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM,
5152 };
5253
5354 enum coresight_dev_subtype_link {
@@ -182,6 +183,7 @@ struct coresight_sysfs_link { · 128 unmodified lines
182183 * happens when a source has been selected and a path is enabled
183184 * from source to that sink.
184185 * @ea: Device attribute for sink representation under PMU directory.
186+ * @def_sink: cached reference to default sink found for this device.
185187 * @ect_dev: Associated cross trigger device. Not part of the trace data
186188 * path or connections.
187189 * @nr_links: number of sysfs links created to other components from this
@@ -200,6 +202,7 @@ struct coresight_device { · 12 unmodified lines
200202 /* sink specific fields */
201203 bool activated; /* true only if a sink is part of a path */
202204 struct dev_ext_attribute *ea;
205+ struct coresight_device *def_sink;
203206 /* cross trigger handling */
204207 struct coresight_device *ect_dev;
205208 /* sysfs links between components */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t