1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Resource Director Technology(RDT) 4 * - Intel Application Energy Telemetry 5 * 6 * Copyright (C) 2025 Intel Corporation 7 * 8 * Author: 9 * Tony Luck <tony.luck@intel.com> 10 */ 11 12 #define pr_fmt(fmt) "resctrl: " fmt 13 14 #include <linux/err.h> 15 #include <linux/init.h> 16 #include <linux/intel_pmt_features.h> 17 #include <linux/intel_vsec.h> 18 #include <linux/resctrl.h> 19 #include <linux/stddef.h> 20 21 #include "internal.h" 22 23 /** 24 * struct event_group - Events with the same feature type ("energy" or "perf") and GUID. 25 * @pfname: PMT feature name ("energy" or "perf") of this event group. 26 * @pfg: Points to the aggregated telemetry space information 27 * returned by the intel_pmt_get_regions_by_feature() 28 * call to the INTEL_PMT_TELEMETRY driver that contains 29 * data for all telemetry regions of type @pfname. 30 * Valid if the system supports the event group, 31 * NULL otherwise. 32 */ 33 struct event_group { 34 /* Data fields for additional structures to manage this group. */ 35 const char *pfname; 36 struct pmt_feature_group *pfg; 37 }; 38 39 static struct event_group *known_event_groups[] = { 40 }; 41 42 #define for_each_event_group(_peg) \ 43 for (_peg = known_event_groups; \ 44 _peg < &known_event_groups[ARRAY_SIZE(known_event_groups)]; \ 45 _peg++) 46 47 /* Stub for now */ 48 static bool enable_events(struct event_group *e, struct pmt_feature_group *p) 49 { 50 return false; 51 } 52 53 static enum pmt_feature_id lookup_pfid(const char *pfname) 54 { 55 if (!strcmp(pfname, "energy")) 56 return FEATURE_PER_RMID_ENERGY_TELEM; 57 else if (!strcmp(pfname, "perf")) 58 return FEATURE_PER_RMID_PERF_TELEM; 59 60 pr_warn("Unknown PMT feature name '%s'\n", pfname); 61 62 return FEATURE_INVALID; 63 } 64 65 /* 66 * Request a copy of struct pmt_feature_group for each event group. If there is 67 * one, the returned structure has an array of telemetry_region structures, 68 * each element of the array describes one telemetry aggregator. The 69 * telemetry aggregators may have different GUIDs so obtain duplicate struct 70 * pmt_feature_group for event groups with same feature type but different 71 * GUID. Post-processing ensures an event group can only use the telemetry 72 * aggregators that match its GUID. An event group keeps a pointer to its 73 * struct pmt_feature_group to indicate that its events are successfully 74 * enabled. 75 */ 76 bool intel_aet_get_events(void) 77 { 78 struct pmt_feature_group *p; 79 enum pmt_feature_id pfid; 80 struct event_group **peg; 81 bool ret = false; 82 83 for_each_event_group(peg) { 84 pfid = lookup_pfid((*peg)->pfname); 85 p = intel_pmt_get_regions_by_feature(pfid); 86 if (IS_ERR_OR_NULL(p)) 87 continue; 88 if (enable_events(*peg, p)) { 89 (*peg)->pfg = p; 90 ret = true; 91 } else { 92 intel_pmt_put_feature_group(p); 93 } 94 } 95 96 return ret; 97 } 98 99 void __exit intel_aet_exit(void) 100 { 101 struct event_group **peg; 102 103 for_each_event_group(peg) { 104 if ((*peg)->pfg) { 105 intel_pmt_put_feature_group((*peg)->pfg); 106 (*peg)->pfg = NULL; 107 } 108 } 109 } 110