Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/xe/pmu: Add GT C6 events

Provide a PMU interface for GT C6 residency counters. The interface is
similar to the one available for i915, but gt is passed in the config
when creating the event.

Sample usage and output:

$ perf list | grep gt-c6
xe_0000_00_02.0/gt-c6-residency/ [Kernel PMU event]

$ tail /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency*
==> /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency <==
event=0x01

==> /sys/bus/event_source/devices/xe_0000_00_02.0/events/gt-c6-residency.unit <==
ms

$ perf stat -e xe_0000_00_02.0/gt-c6-residency,gt=0/ -I1000
# time counts unit events
1.001196056 1,001 ms xe_0000_00_02.0/gt-c6-residency,gt=0/
2.005216219 1,003 ms xe_0000_00_02.0/gt-c6-residency,gt=0/

Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Riana Tauro <riana.tauro@intel.com>
Signed-off-by: Vinay Belgaumkar <vinay.belgaumkar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250124050411.2189060-6-lucas.demarchi@intel.com
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>

authored by

Vinay Belgaumkar and committed by
Lucas De Marchi
897286f2 6ea5bf16

+18 -5
+18 -5
drivers/gpu/drm/xe/xe_pmu.c
··· 7 7 #include <linux/device.h> 8 8 9 9 #include "xe_device.h" 10 + #include "xe_gt_idle.h" 10 11 #include "xe_pm.h" 11 12 #include "xe_pmu.h" 12 13 ··· 47 46 { 48 47 return FIELD_GET(XE_PMU_EVENT_GT_MASK, config); 49 48 } 49 + 50 + #define XE_PMU_EVENT_GT_C6_RESIDENCY 0x01 50 51 51 52 static struct xe_gt *event_to_gt(struct perf_event *event) 52 53 { ··· 116 113 static u64 __xe_pmu_event_read(struct perf_event *event) 117 114 { 118 115 struct xe_gt *gt = event_to_gt(event); 119 - u64 val = 0; 120 116 121 117 if (!gt) 122 118 return 0; 123 119 124 - return val; 120 + switch (config_to_event_id(event->attr.config)) { 121 + case XE_PMU_EVENT_GT_C6_RESIDENCY: 122 + return xe_gt_idle_residency_msec(&gt->gtidle); 123 + } 124 + 125 + return 0; 125 126 } 126 127 127 128 static void xe_pmu_event_update(struct perf_event *event) ··· 221 214 .attrs = pmu_format_attrs, 222 215 }; 223 216 224 - __maybe_unused static ssize_t event_attr_show(struct device *dev, 225 - struct device_attribute *attr, char *buf) 217 + static ssize_t event_attr_show(struct device *dev, 218 + struct device_attribute *attr, char *buf) 226 219 { 227 220 struct perf_pmu_events_attr *pmu_attr = 228 221 container_of(attr, struct perf_pmu_events_attr, attr); ··· 269 262 XE_EVENT_ATTR(name_, v_, id_) \ 270 263 XE_EVENT_ATTR_GROUP(v_, id_, &pmu_event_ ##v_.attr.attr) 271 264 265 + XE_EVENT_ATTR_SIMPLE(gt-c6-residency, gt_c6_residency, XE_PMU_EVENT_GT_C6_RESIDENCY, "ms"); 266 + 272 267 static struct attribute *pmu_empty_event_attrs[] = { 273 268 /* Empty - all events are added as groups with .attr_update() */ 274 269 NULL, ··· 282 273 }; 283 274 284 275 static const struct attribute_group *pmu_events_attr_update[] = { 285 - /* No events yet */ 276 + &pmu_group_gt_c6_residency, 286 277 NULL, 287 278 }; 288 279 289 280 static void set_supported_events(struct xe_pmu *pmu) 290 281 { 282 + struct xe_device *xe = container_of(pmu, typeof(*xe), pmu); 283 + 284 + if (!xe->info.skip_guc_pc) 285 + pmu->supported_events |= BIT_ULL(XE_PMU_EVENT_GT_C6_RESIDENCY); 291 286 } 292 287 293 288 /**