From 9370bb92b2d16684ee45cf24e879c93c509162da Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 19 Dec 2024 01:47:39 +0000
Subject: [PATCH] add wifi6 8852be driver

---
 kernel/tools/perf/util/record.c |  221 ++++++++++++++++++++++--------------------------------
 1 files changed, 91 insertions(+), 130 deletions(-)

diff --git a/kernel/tools/perf/util/record.c b/kernel/tools/perf/util/record.c
index 9cfc7bf..07e4b96 100644
--- a/kernel/tools/perf/util/record.c
+++ b/kernel/tools/perf/util/record.c
@@ -1,141 +1,98 @@
 // SPDX-License-Identifier: GPL-2.0
+#include "debug.h"
 #include "evlist.h"
 #include "evsel.h"
-#include "cpumap.h"
+#include "evsel_config.h"
 #include "parse-events.h"
 #include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
 #include <api/fs/fs.h>
 #include <subcmd/parse-options.h>
-#include "util.h"
+#include <perf/cpumap.h>
 #include "cloexec.h"
+#include "util/perf_api_probe.h"
+#include "record.h"
+#include "../perf-sys.h"
+#include "topdown.h"
 
-typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
-
-static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
+/*
+ * evsel__config_leader_sampling() uses special rules for leader sampling.
+ * However, if the leader is an AUX area event, then assume the event to sample
+ * is the next event.
+ */
+static struct evsel *evsel__read_sampler(struct evsel *evsel, struct evlist *evlist)
 {
-	struct perf_evlist *evlist;
-	struct perf_evsel *evsel;
-	unsigned long flags = perf_event_open_cloexec_flag();
-	int err = -EAGAIN, fd;
-	static pid_t pid = -1;
+	struct evsel *leader = evsel->leader;
 
-	evlist = perf_evlist__new();
-	if (!evlist)
-		return -ENOMEM;
-
-	if (parse_events(evlist, str, NULL))
-		goto out_delete;
-
-	evsel = perf_evlist__first(evlist);
-
-	while (1) {
-		fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
-		if (fd < 0) {
-			if (pid == -1 && errno == EACCES) {
-				pid = 0;
-				continue;
-			}
-			goto out_delete;
+	if (evsel__is_aux_event(leader) || arch_topdown_sample_read(leader)) {
+		evlist__for_each_entry(evlist, evsel) {
+			if (evsel->leader == leader && evsel != evsel->leader)
+				return evsel;
 		}
-		break;
 	}
-	close(fd);
 
-	fn(evsel);
+	return leader;
+}
 
-	fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
-	if (fd < 0) {
-		if (errno == EINVAL)
-			err = -EINVAL;
-		goto out_delete;
+static u64 evsel__config_term_mask(struct evsel *evsel)
+{
+	struct evsel_config_term *term;
+	struct list_head *config_terms = &evsel->config_terms;
+	u64 term_types = 0;
+
+	list_for_each_entry(term, config_terms, list) {
+		term_types |= 1 << term->type;
 	}
-	close(fd);
-	err = 0;
-
-out_delete:
-	perf_evlist__delete(evlist);
-	return err;
+	return term_types;
 }
 
-static bool perf_probe_api(setup_probe_fn_t fn)
+static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist)
 {
-	const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
-	struct cpu_map *cpus;
-	int cpu, ret, i = 0;
+	struct perf_event_attr *attr = &evsel->core.attr;
+	struct evsel *leader = evsel->leader;
+	struct evsel *read_sampler;
+	u64 term_types, freq_mask;
 
-	cpus = cpu_map__new(NULL);
-	if (!cpus)
-		return false;
-	cpu = cpus->map[0];
-	cpu_map__put(cpus);
+	if (!leader->sample_read)
+		return;
 
-	do {
-		ret = perf_do_probe_api(fn, cpu, try[i++]);
-		if (!ret)
-			return true;
-	} while (ret == -EAGAIN && try[i]);
+	read_sampler = evsel__read_sampler(evsel, evlist);
 
-	return false;
+	if (evsel == read_sampler)
+		return;
+
+	term_types = evsel__config_term_mask(evsel);
+	/*
+	 * Disable sampling for all group members except those with explicit
+	 * config terms or the leader. In the case of an AUX area event, the 2nd
+	 * event in the group is the one that 'leads' the sampling.
+	 */
+	freq_mask = (1 << EVSEL__CONFIG_TERM_FREQ) | (1 << EVSEL__CONFIG_TERM_PERIOD);
+	if ((term_types & freq_mask) == 0) {
+		attr->freq           = 0;
+		attr->sample_freq    = 0;
+		attr->sample_period  = 0;
+	}
+	if ((term_types & (1 << EVSEL__CONFIG_TERM_OVERWRITE)) == 0)
+		attr->write_backward = 0;
+
+	/*
+	 * We don't get a sample for slave events, we make them when delivering
+	 * the group leader sample. Set the slave event to follow the master
+	 * sample_type to ease up reporting.
+	 * An AUX area event also has sample_type requirements, so also include
+	 * the sample type bits from the leader's sample_type to cover that
+	 * case.
+	 */
+	attr->sample_type = read_sampler->core.attr.sample_type |
+			    leader->core.attr.sample_type;
 }
 
-static void perf_probe_sample_identifier(struct perf_evsel *evsel)
-{
-	evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER;
-}
-
-static void perf_probe_comm_exec(struct perf_evsel *evsel)
-{
-	evsel->attr.comm_exec = 1;
-}
-
-static void perf_probe_context_switch(struct perf_evsel *evsel)
-{
-	evsel->attr.context_switch = 1;
-}
-
-bool perf_can_sample_identifier(void)
-{
-	return perf_probe_api(perf_probe_sample_identifier);
-}
-
-static bool perf_can_comm_exec(void)
-{
-	return perf_probe_api(perf_probe_comm_exec);
-}
-
-bool perf_can_record_switch_events(void)
-{
-	return perf_probe_api(perf_probe_context_switch);
-}
-
-bool perf_can_record_cpu_wide(void)
-{
-	struct perf_event_attr attr = {
-		.type = PERF_TYPE_SOFTWARE,
-		.config = PERF_COUNT_SW_CPU_CLOCK,
-		.exclude_kernel = 1,
-	};
-	struct cpu_map *cpus;
-	int cpu, fd;
-
-	cpus = cpu_map__new(NULL);
-	if (!cpus)
-		return false;
-	cpu = cpus->map[0];
-	cpu_map__put(cpus);
-
-	fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
-	if (fd < 0)
-		return false;
-	close(fd);
-
-	return true;
-}
-
-void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
+void perf_evlist__config(struct evlist *evlist, struct record_opts *opts,
 			 struct callchain_param *callchain)
 {
-	struct perf_evsel *evsel;
+	struct evsel *evsel;
 	bool use_sample_identifier = false;
 	bool use_comm_exec;
 	bool sample_id = opts->sample_id;
@@ -147,16 +104,20 @@
 	if (opts->group)
 		perf_evlist__set_leader(evlist);
 
-	if (evlist->cpus->map[0] < 0)
+	if (evlist->core.cpus->map[0] < 0)
 		opts->no_inherit = true;
 
 	use_comm_exec = perf_can_comm_exec();
 
 	evlist__for_each_entry(evlist, evsel) {
-		perf_evsel__config(evsel, opts, callchain);
+		evsel__config(evsel, opts, callchain);
 		if (evsel->tracking && use_comm_exec)
-			evsel->attr.comm_exec = 1;
+			evsel->core.attr.comm_exec = 1;
 	}
+
+	/* Configure leader sampling here now that the sample type is known */
+	evlist__for_each_entry(evlist, evsel)
+		evsel__config_leader_sampling(evsel, evlist);
 
 	if (opts->full_auxtrace) {
 		/*
@@ -166,11 +127,11 @@
 		 */
 		use_sample_identifier = perf_can_sample_identifier();
 		sample_id = true;
-	} else if (evlist->nr_entries > 1) {
-		struct perf_evsel *first = perf_evlist__first(evlist);
+	} else if (evlist->core.nr_entries > 1) {
+		struct evsel *first = evlist__first(evlist);
 
 		evlist__for_each_entry(evlist, evsel) {
-			if (evsel->attr.sample_type == first->attr.sample_type)
+			if (evsel->core.attr.sample_type == first->core.attr.sample_type)
 				continue;
 			use_sample_identifier = perf_can_sample_identifier();
 			break;
@@ -180,7 +141,7 @@
 
 	if (sample_id) {
 		evlist__for_each_entry(evlist, evsel)
-			perf_evsel__set_sample_id(evsel, use_sample_identifier);
+			evsel__set_sample_id(evsel, use_sample_identifier);
 	}
 
 	perf_evlist__set_id_pos(evlist);
@@ -256,15 +217,15 @@
 	return record_opts__config_freq(opts);
 }
 
-bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
+bool perf_evlist__can_select_event(struct evlist *evlist, const char *str)
 {
-	struct perf_evlist *temp_evlist;
-	struct perf_evsel *evsel;
+	struct evlist *temp_evlist;
+	struct evsel *evsel;
 	int err, fd, cpu;
 	bool ret = false;
 	pid_t pid = -1;
 
-	temp_evlist = perf_evlist__new();
+	temp_evlist = evlist__new();
 	if (!temp_evlist)
 		return false;
 
@@ -272,19 +233,19 @@
 	if (err)
 		goto out_delete;
 
-	evsel = perf_evlist__last(temp_evlist);
+	evsel = evlist__last(temp_evlist);
 
-	if (!evlist || cpu_map__empty(evlist->cpus)) {
-		struct cpu_map *cpus = cpu_map__new(NULL);
+	if (!evlist || perf_cpu_map__empty(evlist->core.cpus)) {
+		struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
 
 		cpu =  cpus ? cpus->map[0] : 0;
-		cpu_map__put(cpus);
+		perf_cpu_map__put(cpus);
 	} else {
-		cpu = evlist->cpus->map[0];
+		cpu = evlist->core.cpus->map[0];
 	}
 
 	while (1) {
-		fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
+		fd = sys_perf_event_open(&evsel->core.attr, pid, cpu, -1,
 					 perf_event_open_cloexec_flag());
 		if (fd < 0) {
 			if (pid == -1 && errno == EACCES) {
@@ -299,7 +260,7 @@
 	ret = true;
 
 out_delete:
-	perf_evlist__delete(temp_evlist);
+	evlist__delete(temp_evlist);
 	return ret;
 }
 

--
Gitblit v1.6.2