summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/gt/sysfs_gt.c
diff options
context:
space:
mode:
authorAndi Shyti <andi.shyti@linux.intel.com>2020-03-23 07:55:44 +0530
committerAndi Shyti <andi.shyti@linux.intel.com>2022-01-06 13:50:58 +0200
commitce5d314cdd2215ac206cf615dfa2a0e214528ef2 (patch)
tree9978f18ee5636b3ee1c68faab621bc1a3c62e16c /drivers/gpu/drm/i915/gt/sysfs_gt.c
parentcbf88fc029bdb41141c59d36448eb5e230699795 (diff)
drm/i915/gt: make a gt sysfs group and move power management filesmultitile
The GT has its own properties and in sysfs they should be grouped in the 'gt/' directory. Create a 'gt/' directory in sysfs which will contain gt0...gtN directories related to each tile configured in the GPU. Move the power management files inside those directories. The previous power management files are kept in their original root directory to avoid breaking the ABI. They point to the tile '0' and a warning message is printed whenever accessed to. The deprecated interface needs for the CONFIG_SYSFS_DEPRECATED_V2 flag in order to be generated. The new sysfs structure will have a similar layout for the 4 tile case: /sys/.../card0 ├── gt │   ├── gt0 │   │   ├── id │   │   ├── rc6_enable │   │   ├── rc6_residency_ms │   │   ├── rps_act_freq_mhz │   │   ├── rps_boost_freq_mhz │   │   ├── rps_cur_freq_mhz │   │   ├── rps_max_freq_mhz │   │   ├── rps_min_freq_mhz │   │   ├── rps_RP0_freq_mhz │   │   ├── rps_RP1_freq_mhz │   │  └── rps_RPn_freq_mhz . . . . . . │   └── gt3 │   ├── id │   ├── rc6_enable │   ├── rc6_residency_ms │   ├── rps_act_freq_mhz │   ├── rps_boost_freq_mhz │   ├── rps_cur_freq_mhz │   ├── rps_max_freq_mhz │   ├── rps_min_freq_mhz │   ├── rps_RP0_freq_mhz │   ├── rps_RP1_freq_mhz │   └── rps_RPn_freq_mhz ├── gt_act_freq_mhz -+ ├── gt_boost_freq_mhz | ├── gt_cur_freq_mhz | Original interface ├── gt_max_freq_mhz +─-> kept as existing ABI; ├── gt_min_freq_mhz | it points to gt0/ ├── gt_RP0_freq_mhz | └── gt_RP1_freq_mhz | └── gt_RPn_freq_mhz -+ Signed-off-by: Andi Shyti <andi.shyti@linux.intel.com> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com> Cc: Matt Roper <matthew.d.roper@intel.com> Cc: Sujaritha Sundaresan <sujaritha.sundaresan@intel.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/gt/sysfs_gt.c')
-rw-r--r--drivers/gpu/drm/i915/gt/sysfs_gt.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/gt/sysfs_gt.c b/drivers/gpu/drm/i915/gt/sysfs_gt.c
new file mode 100644
index 000000000000..46cf033a53ec
--- /dev/null
+++ b/drivers/gpu/drm/i915/gt/sysfs_gt.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include <drm/drm_device.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/printk.h>
+#include <linux/sysfs.h>
+
+#include "i915_drv.h"
+#include "i915_sysfs.h"
+#include "intel_gt.h"
+#include "intel_gt_types.h"
+#include "intel_rc6.h"
+
+#include "sysfs_gt.h"
+#include "sysfs_gt_pm.h"
+
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+ const char *name)
+{
+ struct kobject *kobj = &dev->kobj;
+
+ /*
+ * We are interested at knowing from where the interface
+ * has been called, whether it's called from gt/ or from
+ * the parent directory.
+ * From the interface position it depends also the value of
+ * the private data.
+ * If the interface is called from gt/ then private data is
+ * of the "struct intel_gt *" type, otherwise it's * a
+ * "struct drm_i915_private *" type.
+ */
+ if (!is_object_gt(kobj)) {
+ struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
+
+ pr_devel_ratelimited(DEPRECATED
+ "%s (pid %d) is trying to access deprecated %s "
+ "sysfs control, please use gt/gt<n>/%s instead\n",
+ current->comm, task_pid_nr(current), name, name);
+ return to_gt(i915);
+ }
+
+ return kobj_to_gt(kobj);
+}
+
+static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
+{
+ return &gt->i915->drm.primary->kdev->kobj;
+}
+
+static ssize_t id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+
+ return sysfs_emit(buf, "%u\n", gt->info.id);
+}
+
+static DEVICE_ATTR_RO(id);
+
+static void kobj_gt_release(struct kobject *kobj)
+{
+ kfree(kobj);
+}
+
+static struct kobj_type kobj_gt_type = {
+ .release = kobj_gt_release,
+ .sysfs_ops = &kobj_sysfs_ops
+};
+
+struct kobject *
+intel_gt_create_kobj(struct intel_gt *gt, struct kobject *dir, const char *name)
+{
+ struct kobj_gt *kg;
+
+ kg = kzalloc(sizeof(*kg), GFP_KERNEL);
+ if (!kg)
+ return NULL;
+
+ kobject_init(&kg->base, &kobj_gt_type);
+ kg->gt = gt;
+
+ /* xfer ownership to sysfs tree */
+ if (kobject_add(&kg->base, dir, "%s", name)) {
+ kobject_put(&kg->base);
+ return NULL;
+ }
+
+ return &kg->base; /* borrowed ref */
+}
+
+void intel_gt_sysfs_register(struct intel_gt *gt)
+{
+ struct kobject *dir;
+ char name[80];
+
+ /*
+ * We need to make things right with the
+ * ABI compatibility. The files were originally
+ * generated under the parent directory.
+ *
+ * We generate the files only for gt 0
+ * to avoid duplicates.
+ */
+ if (!gt->info.id)
+ intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt));
+
+ snprintf(name, sizeof(name), "gt%d", gt->info.id);
+
+ dir = intel_gt_create_kobj(gt, gt->i915->sysfs_gt, name);
+ if (!dir) {
+ drm_err(&gt->i915->drm,
+ "failed to initialize %s sysfs root\n", name);
+ return;
+ }
+
+ if (sysfs_create_file(dir, &dev_attr_id.attr))
+ drm_err(&gt->i915->drm,
+ "failed to create sysfs %s info files\n", name);
+
+ intel_gt_sysfs_pm_init(gt, dir);
+}