File Index
Files and directories
Sign in
FILE

ivpu_sysfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/accel/ivpu/ivpu_sysfs.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2024-2025 Intel Corporation
  4 */
  5
  6#include <linux/device.h>
  7#include <linux/err.h>
  8#include <linux/pm_runtime.h>
  9#include <linux/units.h>
 10
 11#include "ivpu_drv.h"
 12#include "ivpu_gem.h"
 13#include "ivpu_fw.h"
 14#include "ivpu_hw.h"
 15#include "ivpu_sysfs.h"
 16
 17/**
 18 * DOC: npu_busy_time_us
 19 *
 20 * npu_busy_time_us is the time that the device spent executing jobs.
 21 * The time is counted when and only when there are jobs submitted to firmware.
 22 *
 23 * This time can be used to measure the utilization of NPU, either by calculating
 24 * npu_busy_time_us difference between two timepoints (i.e. measuring the time
 25 * that the NPU was active during some workload) or monitoring utilization percentage
 26 * by reading npu_busy_time_us periodically.
 27 *
 28 * When reading the value periodically, it shouldn't be read too often as it may have
 29 * an impact on job submission performance. Recommended period is 1 second.
 30 */
 31static ssize_t
 32npu_busy_time_us_show(struct device *dev, struct device_attribute *attr, char *buf)
 33{
 34	struct drm_device *drm = dev_get_drvdata(dev);
 35	struct ivpu_device *vdev = to_ivpu_device(drm);
 36	ktime_t total, now = 0;
 37
 38	mutex_lock(&vdev->submitted_jobs_lock);
 39
 40	total = vdev->busy_time;
 41	if (!xa_empty(&vdev->submitted_jobs_xa))
 42		now = ktime_sub(ktime_get(), vdev->busy_start_ts);
 43	mutex_unlock(&vdev->submitted_jobs_lock);
 44
 45	return sysfs_emit(buf, "%lld\n", ktime_to_us(ktime_add(total, now)));
 46}
 47
 48static DEVICE_ATTR_RO(npu_busy_time_us);
 49
 50/**
 51 * DOC: npu_memory_utilization
 52 *
 53 * The npu_memory_utilization is used to report in bytes a current NPU memory utilization.
 54 *
 55 */
 56static ssize_t
 57npu_memory_utilization_show(struct device *dev, struct device_attribute *attr, char *buf)
 58{
 59	struct drm_device *drm = dev_get_drvdata(dev);
 60	struct ivpu_device *vdev = to_ivpu_device(drm);
 61	struct ivpu_bo *bo;
 62	u64 total_npu_memory = 0;
 63
 64	mutex_lock(&vdev->bo_list_lock);
 65	list_for_each_entry(bo, &vdev->bo_list, bo_list_node)
 66		if (ivpu_bo_is_resident(bo))
 67			total_npu_memory += ivpu_bo_size(bo);
 68	mutex_unlock(&vdev->bo_list_lock);
 69
 70	return sysfs_emit(buf, "%lld\n", total_npu_memory);
 71}
 72
 73static DEVICE_ATTR_RO(npu_memory_utilization);
 74
 75/**
 76 * DOC: sched_mode
 77 *
 78 * The sched_mode is used to report current NPU scheduling mode.
 79 *
 80 * It returns following strings:
 81 * - "HW"		- Hardware Scheduler mode
 82 * - "OS"		- Operating System Scheduler mode
 83 *
 84 */
 85static ssize_t
 86sched_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 87{
 88	struct drm_device *drm = dev_get_drvdata(dev);
 89	struct ivpu_device *vdev = to_ivpu_device(drm);
 90
 91	return sysfs_emit(buf, "%s\n", vdev->fw->sched_mode ? "HW" : "OS");
 92}
 93
 94static DEVICE_ATTR_RO(sched_mode);
 95
 96/**
 97 * DOC: npu_max_frequency
 98 *
 99 * The npu_max_frequency shows maximum frequency in MHz of the NPU's data
100 * processing unit
101 */
102static ssize_t
103npu_max_frequency_mhz_show(struct device *dev, struct device_attribute *attr, char *buf)
104{
105	struct drm_device *drm = dev_get_drvdata(dev);
106	struct ivpu_device *vdev = to_ivpu_device(drm);
107	u32 freq = ivpu_hw_dpu_max_freq_get(vdev);
108
109	return sysfs_emit(buf, "%lu\n", freq / HZ_PER_MHZ);
110}
111
112static DEVICE_ATTR_RO(npu_max_frequency_mhz);
113
114/**
115 * DOC: npu_current_frequency_mhz
116 *
117 * The npu_current_frequency_mhz shows current frequency in MHz of the NPU's
118 * data processing unit
119 */
120static ssize_t
121npu_current_frequency_mhz_show(struct device *dev, struct device_attribute *attr, char *buf)
122{
123	struct drm_device *drm = dev_get_drvdata(dev);
124	struct ivpu_device *vdev = to_ivpu_device(drm);
125	u32 freq = 0;
126
127	/* Read frequency only if device is active, otherwise frequency is 0 */
128	if (pm_runtime_get_if_active(vdev->drm.dev) > 0) {
129		freq = ivpu_hw_dpu_freq_get(vdev);
130
131		pm_runtime_put_autosuspend(vdev->drm.dev);
132	}
133
134	return sysfs_emit(buf, "%lu\n", freq / HZ_PER_MHZ);
135}
136
137static DEVICE_ATTR_RO(npu_current_frequency_mhz);
138
139static struct attribute *ivpu_dev_attrs[] = {
140	&dev_attr_npu_busy_time_us.attr,
141	&dev_attr_npu_memory_utilization.attr,
142	&dev_attr_sched_mode.attr,
143	&dev_attr_npu_max_frequency_mhz.attr,
144	&dev_attr_npu_current_frequency_mhz.attr,
145	NULL,
146};
147
148static struct attribute_group ivpu_dev_attr_group = {
149	.attrs = ivpu_dev_attrs,
150};
151
152void ivpu_sysfs_init(struct ivpu_device *vdev)
153{
154	int ret;
155
156	ret = devm_device_add_group(vdev->drm.dev, &ivpu_dev_attr_group);
157	if (ret)
158		ivpu_warn(vdev, "Failed to add group to device, ret %d", ret);
159}
~/ Read-only file preview.