1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include <drm/drm_device.h> 7 #include <linux/device.h> 8 #include <linux/kobject.h> 9 #include <linux/printk.h> 10 #include <linux/sysfs.h> 11 12 #include "i915_drv.h" 13 #include "i915_sysfs.h" 14 #include "intel_gt.h" 15 #include "intel_gt_sysfs.h" 16 #include "intel_gt_sysfs_pm.h" 17 #include "intel_gt_types.h" 18 #include "intel_rc6.h" 19 20 bool is_object_gt(struct kobject *kobj) 21 { 22 return !strncmp(kobj->name, "gt", 2); 23 } 24 25 static struct intel_gt *kobj_to_gt(struct kobject *kobj) 26 { 27 return container_of(kobj, struct kobj_gt, base)->gt; 28 } 29 30 struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, 31 const char *name) 32 { 33 struct kobject *kobj = &dev->kobj; 34 35 /* 36 * We are interested at knowing from where the interface 37 * has been called, whether it's called from gt/ or from 38 * the parent directory. 39 * From the interface position it depends also the value of 40 * the private data. 41 * If the interface is called from gt/ then private data is 42 * of the "struct intel_gt *" type, otherwise it's * a 43 * "struct drm_i915_private *" type. 44 */ 45 if (!is_object_gt(kobj)) { 46 struct drm_i915_private *i915 = kdev_minor_to_i915(dev); 47 48 return to_gt(i915); 49 } 50 51 return kobj_to_gt(kobj); 52 } 53 54 static struct kobject *gt_get_parent_obj(struct intel_gt *gt) 55 { 56 return >->i915->drm.primary->kdev->kobj; 57 } 58 59 static ssize_t id_show(struct device *dev, 60 struct device_attribute *attr, 61 char *buf) 62 { 63 struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 64 65 return sysfs_emit(buf, "%u\n", gt->info.id); 66 } 67 static DEVICE_ATTR_RO(id); 68 69 static struct attribute *id_attrs[] = { 70 &dev_attr_id.attr, 71 NULL, 72 }; 73 ATTRIBUTE_GROUPS(id); 74 75 static void kobj_gt_release(struct kobject *kobj) 76 { 77 kfree(kobj); 78 } 79 80 static struct kobj_type kobj_gt_type = { 81 .release = kobj_gt_release, 82 .sysfs_ops = &kobj_sysfs_ops, 83 .default_groups = id_groups, 84 }; 85 86 void intel_gt_sysfs_register(struct intel_gt *gt) 87 { 88 struct kobj_gt *kg; 89 90 /* 91 * We need to make things right with the 92 * ABI compatibility. The files were originally 93 * generated under the parent directory. 94 * 95 * We generate the files only for gt 0 96 * to avoid duplicates. 97 */ 98 if (gt_is_root(gt)) 99 intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt)); 100 101 kg = kzalloc(sizeof(*kg), GFP_KERNEL); 102 if (!kg) 103 goto exit_fail; 104 105 kobject_init(&kg->base, &kobj_gt_type); 106 kg->gt = gt; 107 108 /* xfer ownership to sysfs tree */ 109 if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id)) 110 goto exit_kobj_put; 111 112 intel_gt_sysfs_pm_init(gt, &kg->base); 113 114 return; 115 116 exit_kobj_put: 117 kobject_put(&kg->base); 118 119 exit_fail: 120 drm_warn(>->i915->drm, 121 "failed to initialize gt%d sysfs root\n", gt->info.id); 122 } 123