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 *
dev_to_pc(struct device * dev)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 *
dev_to_xe(struct device * dev)61 dev_to_xe(struct device *dev)
62 {
63 return gt_to_xe(kobj_to_gt(dev->kobj.parent));
64 }
65
act_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
cur_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
rp0_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
rpe_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
rpa_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
rpn_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
min_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
min_freq_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)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
max_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)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
max_freq_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)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
power_profile_show(struct kobject * kobj,struct kobj_attribute * attr,char * buff)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
power_profile_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)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
freq_fini(void * arg)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 */
xe_gt_freq_init(struct xe_gt * gt)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