Lines Matching +full:non +full:- +full:coresight

1 // SPDX-License-Identifier: GPL-2.0
8 #include <linux/coresight.h>
9 #include <linux/coresight-pmu.h>
16 #include <linux/percpu-defs.h>
22 #include "coresight-config.h"
23 #include "coresight-etm-perf.h"
24 #include "coresight-priv.h"
25 #include "coresight-syscfg.h"
26 #include "coresight-trace-id.h"
65 /* preset - if sink ID is used as a configuration selector */
66 PMU_FORMAT_ATTR(preset, "config:0-3");
67 /* Sink ID - same for all ETMs */
68 PMU_FORMAT_ATTR(sinkid, "config2:0-31");
69 /* config ID - set if a system configuration is selected */
70 PMU_FORMAT_ATTR(configid, "config2:32-63");
71 PMU_FORMAT_ATTR(cc_threshold, "config3:0-11");
142 return per_cpu_ptr(data->path, cpu); in etm_event_cpu_path_ptr()
156 int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu); in etm_addr_filters_alloc()
160 return -ENOMEM; in etm_addr_filters_alloc()
162 if (event->parent) in etm_addr_filters_alloc()
163 memcpy(filters, event->parent->hw.addr_filters, in etm_addr_filters_alloc()
166 event->hw.addr_filters = filters; in etm_addr_filters_alloc()
173 kfree(event->hw.addr_filters); in etm_event_destroy()
174 event->hw.addr_filters = NULL; in etm_event_destroy()
181 if (event->attr.type != etm_pmu.type) { in etm_event_init()
182 ret = -ENOENT; in etm_event_init()
190 event->destroy = etm_event_destroy; in etm_event_init()
198 cpumask_t *mask = &event_data->mask; in free_sink_buffer()
201 if (!event_data->snk_config) in free_sink_buffer()
209 sink_ops(sink)->free_buffer(event_data->snk_config); in free_sink_buffer()
219 mask = &event_data->mask; in free_event_data()
225 if (event_data->cfg_hash) in free_event_data()
226 cscfg_deactivate_config(event_data->cfg_hash); in free_event_data()
243 coresight_trace_id_perf_stop(&sink->perf_sink_id_map); in free_event_data()
250 free_percpu(event_data->path); in free_event_data()
265 mask = &event_data->mask; in alloc_event_data()
266 if (cpu != -1) in alloc_event_data()
279 event_data->path = alloc_percpu(struct list_head *); in alloc_event_data()
281 if (!event_data->path) { in alloc_event_data()
293 schedule_work(&event_data->work); in etm_free_aux()
311 return (a->subtype.sink_subtype == b->subtype.sink_subtype) && in sinks_compatible()
319 int cpu = event->cpu; in etm_setup_aux()
329 INIT_WORK(&event_data->work, free_event_data); in etm_setup_aux()
332 if (event->attr.config2 & GENMASK_ULL(31, 0)) { in etm_setup_aux()
333 id = (u32)event->attr.config2; in etm_setup_aux()
337 /* check if user wants a coresight configuration selected */ in etm_setup_aux()
338 cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32); in etm_setup_aux()
342 event_data->cfg_hash = cfg_hash; in etm_setup_aux()
345 mask = &event_data->mask; in etm_setup_aux()
370 * No sink provided - look for a default sink for all the ETMs, in etm_setup_aux()
410 trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map); in etm_setup_aux()
417 coresight_trace_id_perf_start(&sink->perf_sink_id_map); in etm_setup_aux()
421 /* no sink found for any CPU - cannot trace */ in etm_setup_aux()
430 if (!sink_ops(sink)->alloc_buffer || !sink_ops(sink)->free_buffer) in etm_setup_aux()
439 event_data->snk_config = in etm_setup_aux()
440 sink_ops(sink)->alloc_buffer(sink, event, pages, in etm_setup_aux()
442 if (!event_data->snk_config) in etm_setup_aux()
459 struct perf_output_handle *handle = &ctxt->handle; in etm_event_start()
469 if (WARN_ON(ctxt->event_data)) in etm_event_start()
492 if (!cpumask_test_cpu(cpu, &event_data->mask)) in etm_event_start()
506 if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF, in etm_event_start()
507 &sink->perf_sink_id_map)) in etm_event_start()
514 if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) { in etm_event_start()
515 cpumask_set_cpu(cpu, &event_data->aux_hwid_done); in etm_event_start()
517 trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map); in etm_event_start()
531 event->hw.state = 0; in etm_event_start()
533 ctxt->event_data = event_data; in etm_event_start()
544 if (READ_ONCE(handle->event)) { in etm_event_start()
549 event->hw.state = PERF_HES_STOPPED; in etm_event_start()
559 struct perf_output_handle *handle = &ctxt->handle; in etm_event_stop()
567 if (handle->event && in etm_event_stop()
568 WARN_ON(perf_get_aux(handle) != ctxt->event_data)) in etm_event_stop()
571 event_data = ctxt->event_data; in etm_event_stop()
573 ctxt->event_data = NULL; in etm_event_stop()
575 if (event->hw.state == PERF_HES_STOPPED) in etm_event_stop()
588 if (handle->event && (mode & PERF_EF_UPDATE) && in etm_event_stop()
589 !cpumask_test_cpu(cpu, &event_data->mask)) { in etm_event_stop()
590 event->hw.state = PERF_HES_STOPPED; in etm_event_stop()
610 event->hw.state = PERF_HES_STOPPED; in etm_event_stop()
618 if (handle->event && (mode & PERF_EF_UPDATE)) { in etm_event_stop()
619 if (WARN_ON_ONCE(handle->event != event)) in etm_event_stop()
623 if (!sink_ops(sink)->update_buffer) in etm_event_stop()
626 size = sink_ops(sink)->update_buffer(sink, handle, in etm_event_stop()
627 event_data->snk_config); in etm_event_stop()
636 * But we should never get a non-zero size with in etm_event_stop()
639 if (READ_ONCE(handle->event)) in etm_event_stop()
652 struct hw_perf_event *hwc = &event->hw; in etm_event_add()
656 if (hwc->state & PERF_HES_STOPPED) in etm_event_add()
657 ret = -EINVAL; in etm_event_add()
659 hwc->state = PERF_HES_STOPPED; in etm_event_add()
682 return -EOPNOTSUPP; in etm_addr_filters_validate()
685 if (filter->size) { in etm_addr_filters_validate()
690 if (filter->action == PERF_ADDR_FILTER_ACTION_START || in etm_addr_filters_validate()
691 filter->action == PERF_ADDR_FILTER_ACTION_STOP) in etm_addr_filters_validate()
692 return -EOPNOTSUPP; in etm_addr_filters_validate()
703 return -EOPNOTSUPP; in etm_addr_filters_validate()
713 struct perf_addr_filter_range *fr = event->addr_filter_ranges; in etm_addr_filters_sync()
714 struct etm_filters *filters = event->hw.addr_filters; in etm_addr_filters_sync()
719 list_for_each_entry(filter, &head->list, entry) { in etm_addr_filters_sync()
722 etm_filter = &filters->etm_filter[i]; in etm_addr_filters_sync()
724 switch (filter->action) { in etm_addr_filters_sync()
726 etm_filter->start_addr = start; in etm_addr_filters_sync()
727 etm_filter->stop_addr = stop; in etm_addr_filters_sync()
728 etm_filter->type = ETM_ADDR_TYPE_RANGE; in etm_addr_filters_sync()
731 etm_filter->start_addr = start; in etm_addr_filters_sync()
732 etm_filter->type = ETM_ADDR_TYPE_START; in etm_addr_filters_sync()
735 etm_filter->stop_addr = stop; in etm_addr_filters_sync()
736 etm_filter->type = ETM_ADDR_TYPE_STOP; in etm_addr_filters_sync()
742 filters->nr_filters = i; in etm_addr_filters_sync()
748 int ret = 0, cpu = source_ops(csdev)->cpu_id(csdev); in etm_perf_symlink()
750 struct device *cs_dev = &csdev->dev; in etm_perf_symlink()
755 return -EPROBE_DEFER; in etm_perf_symlink()
758 ret = sysfs_create_link(&pmu_dev->kobj, &cs_dev->kobj, entry); in etm_perf_symlink()
763 sysfs_remove_link(&pmu_dev->kobj, entry); in etm_perf_symlink()
778 return scnprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)(ea->var)); in etm_perf_sink_name_show()
790 return ERR_PTR(-EPROBE_DEFER); in etm_perf_add_symlink_group()
794 return ERR_PTR(-ENOMEM); in etm_perf_add_symlink_group()
798 * sink selection - see function coresight_get_sink_by_id(). in etm_perf_add_symlink_group()
804 sysfs_attr_init(&ea->attr.attr); in etm_perf_add_symlink_group()
805 ea->attr.attr.name = devm_kstrdup(dev, name, GFP_KERNEL); in etm_perf_add_symlink_group()
806 if (!ea->attr.attr.name) in etm_perf_add_symlink_group()
807 return ERR_PTR(-ENOMEM); in etm_perf_add_symlink_group()
809 ea->attr.attr.mode = 0444; in etm_perf_add_symlink_group()
810 ea->var = (unsigned long *)hash; in etm_perf_add_symlink_group()
812 ret = sysfs_add_file_to_group(&pmu_dev->kobj, in etm_perf_add_symlink_group()
813 &ea->attr.attr, group_name); in etm_perf_add_symlink_group()
821 struct device *dev = &csdev->dev; in etm_perf_add_symlink_sink()
824 if (csdev->type != CORESIGHT_DEV_TYPE_SINK && in etm_perf_add_symlink_sink()
825 csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) in etm_perf_add_symlink_sink()
826 return -EINVAL; in etm_perf_add_symlink_sink()
828 if (csdev->ea != NULL) in etm_perf_add_symlink_sink()
829 return -EINVAL; in etm_perf_add_symlink_sink()
832 csdev->ea = etm_perf_add_symlink_group(dev, name, "sinks"); in etm_perf_add_symlink_sink()
833 if (IS_ERR(csdev->ea)) { in etm_perf_add_symlink_sink()
834 err = PTR_ERR(csdev->ea); in etm_perf_add_symlink_sink()
835 csdev->ea = NULL; in etm_perf_add_symlink_sink()
837 csdev->ea->attr.show = etm_perf_sink_name_show; in etm_perf_add_symlink_sink()
846 sysfs_remove_file_from_group(&pmu_dev->kobj, in etm_perf_del_symlink_group()
847 &ea->attr.attr, group_name); in etm_perf_del_symlink_group()
852 if (csdev->type != CORESIGHT_DEV_TYPE_SINK && in etm_perf_del_symlink_sink()
853 csdev->type != CORESIGHT_DEV_TYPE_LINKSINK) in etm_perf_del_symlink_sink()
856 if (!csdev->ea) in etm_perf_del_symlink_sink()
859 etm_perf_del_symlink_group(csdev->ea, "sinks"); in etm_perf_del_symlink_sink()
860 csdev->ea = NULL; in etm_perf_del_symlink_sink()
870 return scnprintf(buf, PAGE_SIZE, "configid=0x%lx\n", (unsigned long)(ea->var)); in etm_perf_cscfg_event_show()
877 if (config_desc->event_ea != NULL) in etm_perf_add_symlink_cscfg()
880 config_desc->event_ea = etm_perf_add_symlink_group(dev, config_desc->name, "events"); in etm_perf_add_symlink_cscfg()
883 if (!IS_ERR(config_desc->event_ea)) in etm_perf_add_symlink_cscfg()
884 config_desc->event_ea->attr.show = etm_perf_cscfg_event_show; in etm_perf_add_symlink_cscfg()
886 err = PTR_ERR(config_desc->event_ea); in etm_perf_add_symlink_cscfg()
887 config_desc->event_ea = NULL; in etm_perf_add_symlink_cscfg()
895 if (!config_desc->event_ea) in etm_perf_del_symlink_cscfg()
898 etm_perf_del_symlink_group(config_desc->event_ea, "events"); in etm_perf_del_symlink_cscfg()
899 config_desc->event_ea = NULL; in etm_perf_del_symlink_cscfg()
924 ret = perf_pmu_register(&etm_pmu, CORESIGHT_ETM_PMU_NAME, -1); in etm_perf_init()