| @@ -769,6 +769,171 @@ void coresight_release_path(struct list_head *path) · 768 unmodified lines |
| 769 | path = NULL; | 769 | path = NULL; |
| 770 | } | 770 | } |
| 771 | | 771 | |
| | 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 | |
| 772 | /** coresight_validate_source - make sure a source has the right credentials | 937 | /** coresight_validate_source - make sure a source has the right credentials |
| 773 | * @csdev: the device structure for a source. | 938 | * @csdev: the device structure for a source. |
| 774 | * @function: the function this was called from. | 939 | * @function: the function this was called from. |
| @@ -1358,6 +1523,7 @@ void coresight_unregister(struct coresight_device *csdev) · 583 unmodified lines |
| 1358 | etm_perf_del_symlink_sink(csdev); | 1523 | etm_perf_del_symlink_sink(csdev); |
| 1359 | /* Remove references of that device in the topology */ | 1524 | /* Remove references of that device in the topology */ |
| 1360 | coresight_remove_conns(csdev); | 1525 | coresight_remove_conns(csdev); |
| | 1526 | coresight_clear_default_sink(csdev); |
| 1361 | coresight_release_platform_data(csdev, csdev->pdata); | 1527 | coresight_release_platform_data(csdev, csdev->pdata); |
| 1362 | device_unregister(&csdev->dev); | 1528 | device_unregister(&csdev->dev); |
| 1363 | } | 1529 | } |