was previously read, userspace is expected to stay with that larger previous
value until a monotonic update is seen.
+- drm-total-cycles-<keystr>: <uint>
+
+Engine identifier string must be the same as the one specified in the
+drm-cycles-<keystr> tag and shall contain the total number cycles for the given
+engine.
+
+This is a timestamp in GPU unspecified unit that matches the update rate
+of drm-cycles-<keystr>. For drivers that implement this interface, the engine
+utilization can be calculated entirely on the GPU clock domain, without
+considering the CPU sleep time between 2 samples.
+
+A driver may implement either this key or drm-maxfreq-<keystr>, but not both.
+
- drm-maxfreq-<keystr>: <uint> [Hz|MHz|KHz]
Engine identifier string must be the same as the one specified in the
time active without considering what frequency the engine is operating as a
percentage of its maximum frequency.
+A driver may implement either this key or drm-total-cycles-<keystr>, but not
+both.
+
Memory
^^^^^^
Driver specific implementations
-------------------------------
-:ref:`i915-usage-stats`
-:ref:`panfrost-usage-stats`
+* :ref:`i915-usage-stats`
+* :ref:`panfrost-usage-stats`
+* :ref:`xe-usage-stats`
/*
* Copyright © 2023 Intel Corporation
*/
+#include "xe_drm_client.h"
#include <drm/drm_print.h>
#include <drm/xe_drm.h>
#include "xe_bo.h"
#include "xe_bo_types.h"
#include "xe_device_types.h"
-#include "xe_drm_client.h"
+#include "xe_exec_queue.h"
+#include "xe_force_wake.h"
+#include "xe_gt.h"
+#include "xe_hw_engine.h"
+#include "xe_pm.h"
#include "xe_trace.h"
+/**
+ * DOC: DRM Client usage stats
+ *
+ * The drm/xe driver implements the DRM client usage stats specification as
+ * documented in :ref:`drm-client-usage-stats`.
+ *
+ * Example of the output showing the implemented key value pairs and entirety of
+ * the currently possible format options:
+ *
+ * ::
+ *
+ * pos: 0
+ * flags: 0100002
+ * mnt_id: 26
+ * ino: 685
+ * drm-driver: xe
+ * drm-client-id: 3
+ * drm-pdev: 0000:03:00.0
+ * drm-total-system: 0
+ * drm-shared-system: 0
+ * drm-active-system: 0
+ * drm-resident-system: 0
+ * drm-purgeable-system: 0
+ * drm-total-gtt: 192 KiB
+ * drm-shared-gtt: 0
+ * drm-active-gtt: 0
+ * drm-resident-gtt: 192 KiB
+ * drm-total-vram0: 23992 KiB
+ * drm-shared-vram0: 16 MiB
+ * drm-active-vram0: 0
+ * drm-resident-vram0: 23992 KiB
+ * drm-total-stolen: 0
+ * drm-shared-stolen: 0
+ * drm-active-stolen: 0
+ * drm-resident-stolen: 0
+ * drm-cycles-rcs: 28257900
+ * drm-total-cycles-rcs: 7655183225
+ * drm-cycles-bcs: 0
+ * drm-total-cycles-bcs: 7655183225
+ * drm-cycles-vcs: 0
+ * drm-total-cycles-vcs: 7655183225
+ * drm-engine-capacity-vcs: 2
+ * drm-cycles-vecs: 0
+ * drm-total-cycles-vecs: 7655183225
+ * drm-engine-capacity-vecs: 2
+ * drm-cycles-ccs: 0
+ * drm-total-cycles-ccs: 7655183225
+ * drm-engine-capacity-ccs: 4
+ *
+ * Possible `drm-cycles-` key names are: `rcs`, `ccs`, `bcs`, `vcs`, `vecs` and
+ * "other".
+ */
+
/**
* xe_drm_client_alloc() - Allocate drm client
* @void: No arg
}
}
+static void show_runtime(struct drm_printer *p, struct drm_file *file)
+{
+ unsigned long class, i, gt_id, capacity[XE_ENGINE_CLASS_MAX] = { };
+ struct xe_file *xef = file->driver_priv;
+ struct xe_device *xe = xef->xe;
+ struct xe_gt *gt;
+ struct xe_hw_engine *hwe;
+ struct xe_exec_queue *q;
+ u64 gpu_timestamp;
+
+ xe_pm_runtime_get(xe);
+
+ /* Accumulate all the exec queues from this client */
+ mutex_lock(&xef->exec_queue.lock);
+ xa_for_each(&xef->exec_queue.xa, i, q)
+ xe_exec_queue_update_runtime(q);
+ mutex_unlock(&xef->exec_queue.lock);
+
+ /* Get the total GPU cycles */
+ for_each_gt(gt, xe, gt_id) {
+ hwe = xe_gt_any_hw_engine(gt);
+ if (!hwe)
+ continue;
+
+ xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
+ gpu_timestamp = xe_hw_engine_read_timestamp(hwe);
+ xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
+ break;
+ }
+
+ xe_pm_runtime_put(xe);
+
+ if (unlikely(!hwe))
+ return;
+
+ for (class = 0; class < XE_ENGINE_CLASS_MAX; class++) {
+ const char *class_name;
+
+ for_each_gt(gt, xe, gt_id)
+ capacity[class] += gt->user_engines.instances_per_class[class];
+
+ /*
+ * Engines may be fused off or not exposed to userspace. Don't
+ * return anything if this entire class is not available
+ */
+ if (!capacity[class])
+ continue;
+
+ class_name = xe_hw_engine_class_to_str(class);
+ drm_printf(p, "drm-cycles-%s:\t%llu\n",
+ class_name, xef->runtime[class]);
+ drm_printf(p, "drm-total-cycles-%s:\t%llu\n",
+ class_name, gpu_timestamp);
+
+ if (capacity[class] > 1)
+ drm_printf(p, "drm-engine-capacity-%s:\t%lu\n",
+ class_name, capacity[class]);
+ }
+}
+
/**
* xe_drm_client_fdinfo() - Callback for fdinfo interface
* @p: The drm_printer ptr
void xe_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file)
{
show_meminfo(p, file);
+ show_runtime(p, file);
}
#endif