1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include "xe_gt_freq.h" 7 8 #include <linux/kobject.h> 9 #include <linux/sysfs.h> 10 11 #include <drm/drm_managed.h> 12 #include <drm/drm_print.h> 13 14 #include "xe_gt_sysfs.h" 15 #include "xe_gt_throttle.h" 16 #include "xe_gt_types.h" 17 #include "xe_guc_pc.h" 18 #include "xe_pm.h" 19 20 /** 21 * DOC: Xe GT Frequency Management 22 * 23 * This component is responsible for the raw GT frequency management, including 24 * the sysfs API. 25 * 26 * Underneath, Xe enables GuC SLPC automated frequency management. GuC is then 27 * allowed to request PCODE any frequency between the Minimum and the Maximum 28 * selected by this component. Furthermore, it is important to highlight that 29 * PCODE is the ultimate decision maker of the actual running frequency, based 30 * on thermal and other running conditions. 31 * 32 * Xe's Freq provides a sysfs API for frequency management under 33 * ``<device>/tile#/gt#/freq0/`` directory. 34 * 35 * **Read-only** attributes: 36 * 37 * - ``act_freq``: The actual resolved frequency decided by PCODE. 38 * - ``cur_freq``: The current one requested by GuC PC to the PCODE. 39 * - ``rpn_freq``: The Render Performance (RP) N level, which is the minimal one. 40 * - ``rpa_freq``: The Render Performance (RP) A level, which is the achievable one. 41 * Calculated by PCODE at runtime based on multiple running conditions 42 * - ``rpe_freq``: The Render Performance (RP) E level, which is the efficient one. 43 * Calculated by PCODE at runtime based on multiple running conditions 44 * - ``rp0_freq``: The Render Performance (RP) 0 level, which is the maximum one. 45 * 46 * **Read-write** attributes: 47 * 48 * - ``min_freq``: Min frequency request. 49 * - ``max_freq``: Max frequency request. 50 * If max <= min, then freq_min becomes a fixed frequency 51 * request. 52 */ 53 54 static struct xe_guc_pc * 55 dev_to_pc(struct device *dev) 56 { 57 return &kobj_to_gt(dev->kobj.parent)->uc.guc.pc; 58 } 59 60 static struct xe_device * 61 dev_to_xe(struct device *dev) 62 { 63 return gt_to_xe(kobj_to_gt(dev->kobj.parent)); 64 } 65 66 static ssize_t act_freq_show(struct kobject *kobj, 67 struct kobj_attribute *attr, char *buf) 68 { 69 struct device *dev = kobj_to_dev(kobj); 70 struct xe_guc_pc *pc = dev_to_pc(dev); 71 u32 freq; 72 73 guard(xe_pm_runtime)(dev_to_xe(dev)); 74 freq = xe_guc_pc_get_act_freq(pc); 75 76 return sysfs_emit(buf, "%d\n", freq); 77 } 78 static struct kobj_attribute attr_act_freq = __ATTR_RO(act_freq); 79 80 static ssize_t cur_freq_show(struct kobject *kobj, 81 struct kobj_attribute *attr, char *buf) 82 { 83 struct device *dev = kobj_to_dev(kobj); 84 struct xe_guc_pc *pc = dev_to_pc(dev); 85 u32 freq; 86 ssize_t ret; 87 88 guard(xe_pm_runtime)(dev_to_xe(dev)); 89 ret = xe_guc_pc_get_cur_freq(pc, &freq); 90 if (ret) 91 return ret; 92 93 return sysfs_emit(buf, "%d\n", freq); 94 } 95 static struct kobj_attribute attr_cur_freq = __ATTR_RO(cur_freq); 96 97 static ssize_t rp0_freq_show(struct kobject *kobj, 98 struct kobj_attribute *attr, char *buf) 99 { 100 struct device *dev = kobj_to_dev(kobj); 101 struct xe_guc_pc *pc = dev_to_pc(dev); 102 103 return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rp0_freq(pc)); 104 } 105 static struct kobj_attribute attr_rp0_freq = __ATTR_RO(rp0_freq); 106 107 static ssize_t rpe_freq_show(struct kobject *kobj, 108 struct kobj_attribute *attr, char *buf) 109 { 110 struct device *dev = kobj_to_dev(kobj); 111 struct xe_guc_pc *pc = dev_to_pc(dev); 112 u32 freq; 113 114 guard(xe_pm_runtime)(dev_to_xe(dev)); 115 freq = xe_guc_pc_get_rpe_freq(pc); 116 117 return sysfs_emit(buf, "%d\n", freq); 118 } 119 static struct kobj_attribute attr_rpe_freq = __ATTR_RO(rpe_freq); 120 121 static ssize_t rpa_freq_show(struct kobject *kobj, 122 struct kobj_attribute *attr, char *buf) 123 { 124 struct device *dev = kobj_to_dev(kobj); 125 struct xe_guc_pc *pc = dev_to_pc(dev); 126 u32 freq; 127 128 guard(xe_pm_runtime)(dev_to_xe(dev)); 129 freq = xe_guc_pc_get_rpa_freq(pc); 130 131 return sysfs_emit(buf, "%d\n", freq); 132 } 133 static struct kobj_attribute attr_rpa_freq = __ATTR_RO(rpa_freq); 134 135 static ssize_t rpn_freq_show(struct kobject *kobj, 136 struct kobj_attribute *attr, char *buf) 137 { 138 struct device *dev = kobj_to_dev(kobj); 139 struct xe_guc_pc *pc = dev_to_pc(dev); 140 141 return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rpn_freq(pc)); 142 } 143 static struct kobj_attribute attr_rpn_freq = __ATTR_RO(rpn_freq); 144 145 static ssize_t min_freq_show(struct kobject *kobj, 146 struct kobj_attribute *attr, char *buf) 147 { 148 struct device *dev = kobj_to_dev(kobj); 149 struct xe_guc_pc *pc = dev_to_pc(dev); 150 u32 freq; 151 ssize_t ret; 152 153 guard(xe_pm_runtime)(dev_to_xe(dev)); 154 ret = xe_guc_pc_get_min_freq(pc, &freq); 155 if (ret) 156 return ret; 157 158 return sysfs_emit(buf, "%d\n", freq); 159 } 160 161 static ssize_t min_freq_store(struct kobject *kobj, 162 struct kobj_attribute *attr, const char *buff, size_t count) 163 { 164 struct device *dev = kobj_to_dev(kobj); 165 struct xe_guc_pc *pc = dev_to_pc(dev); 166 u32 freq; 167 ssize_t ret; 168 169 ret = kstrtou32(buff, 0, &freq); 170 if (ret) 171 return ret; 172 173 guard(xe_pm_runtime)(dev_to_xe(dev)); 174 ret = xe_guc_pc_set_min_freq(pc, freq); 175 if (ret) 176 return ret; 177 178 return count; 179 } 180 static struct kobj_attribute attr_min_freq = __ATTR_RW(min_freq); 181 182 static ssize_t max_freq_show(struct kobject *kobj, 183 struct kobj_attribute *attr, char *buf) 184 { 185 struct device *dev = kobj_to_dev(kobj); 186 struct xe_guc_pc *pc = dev_to_pc(dev); 187 u32 freq; 188 ssize_t ret; 189 190 guard(xe_pm_runtime)(dev_to_xe(dev)); 191 ret = xe_guc_pc_get_max_freq(pc, &freq); 192 if (ret) 193 return ret; 194 195 return sysfs_emit(buf, "%d\n", freq); 196 } 197 198 static ssize_t max_freq_store(struct kobject *kobj, 199 struct kobj_attribute *attr, const char *buff, size_t count) 200 { 201 struct device *dev = kobj_to_dev(kobj); 202 struct xe_guc_pc *pc = dev_to_pc(dev); 203 u32 freq; 204 ssize_t ret; 205 206 ret = kstrtou32(buff, 0, &freq); 207 if (ret) 208 return ret; 209 210 guard(xe_pm_runtime)(dev_to_xe(dev)); 211 ret = xe_guc_pc_set_max_freq(pc, freq); 212 if (ret) 213 return ret; 214 215 return count; 216 } 217 static struct kobj_attribute attr_max_freq = __ATTR_RW(max_freq); 218 219 static ssize_t power_profile_show(struct kobject *kobj, 220 struct kobj_attribute *attr, 221 char *buff) 222 { 223 struct device *dev = kobj_to_dev(kobj); 224 225 xe_guc_pc_get_power_profile(dev_to_pc(dev), buff); 226 227 return strlen(buff); 228 } 229 230 static ssize_t power_profile_store(struct kobject *kobj, 231 struct kobj_attribute *attr, 232 const char *buff, size_t count) 233 { 234 struct device *dev = kobj_to_dev(kobj); 235 struct xe_guc_pc *pc = dev_to_pc(dev); 236 int err; 237 238 guard(xe_pm_runtime)(dev_to_xe(dev)); 239 err = xe_guc_pc_set_power_profile(pc, buff); 240 241 return err ?: count; 242 } 243 static struct kobj_attribute attr_power_profile = __ATTR_RW(power_profile); 244 245 static const struct attribute *freq_attrs[] = { 246 &attr_act_freq.attr, 247 &attr_cur_freq.attr, 248 &attr_rp0_freq.attr, 249 &attr_rpa_freq.attr, 250 &attr_rpe_freq.attr, 251 &attr_rpn_freq.attr, 252 &attr_min_freq.attr, 253 &attr_max_freq.attr, 254 &attr_power_profile.attr, 255 NULL 256 }; 257 258 static void freq_fini(void *arg) 259 { 260 struct kobject *kobj = arg; 261 262 sysfs_remove_files(kobj, freq_attrs); 263 kobject_put(kobj); 264 } 265 266 /** 267 * xe_gt_freq_init - Initialize Xe Freq component 268 * @gt: Xe GT object 269 * 270 * It needs to be initialized after GT Sysfs and GuC PC components are ready. 271 * 272 * Returns: Returns error value for failure and 0 for success. 273 */ 274 int xe_gt_freq_init(struct xe_gt *gt) 275 { 276 struct xe_device *xe = gt_to_xe(gt); 277 int err; 278 279 if (xe->info.skip_guc_pc) 280 return 0; 281 282 gt->freq = kobject_create_and_add("freq0", gt->sysfs); 283 if (!gt->freq) 284 return -ENOMEM; 285 286 err = sysfs_create_files(gt->freq, freq_attrs); 287 if (err) { 288 kobject_put(gt->freq); 289 return err; 290 } 291 292 err = devm_add_action_or_reset(xe->drm.dev, freq_fini, gt->freq); 293 if (err) 294 return err; 295 296 return xe_gt_throttle_init(gt); 297 } 298