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 xe_pm_runtime_get(dev_to_xe(dev));
74 freq = xe_guc_pc_get_act_freq(pc);
75 xe_pm_runtime_put(dev_to_xe(dev));
76
77 return sysfs_emit(buf, "%d\n", freq);
78 }
79 static struct kobj_attribute attr_act_freq = __ATTR_RO(act_freq);
80
cur_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)81 static ssize_t cur_freq_show(struct kobject *kobj,
82 struct kobj_attribute *attr, char *buf)
83 {
84 struct device *dev = kobj_to_dev(kobj);
85 struct xe_guc_pc *pc = dev_to_pc(dev);
86 u32 freq;
87 ssize_t ret;
88
89 xe_pm_runtime_get(dev_to_xe(dev));
90 ret = xe_guc_pc_get_cur_freq(pc, &freq);
91 xe_pm_runtime_put(dev_to_xe(dev));
92 if (ret)
93 return ret;
94
95 return sysfs_emit(buf, "%d\n", freq);
96 }
97 static struct kobj_attribute attr_cur_freq = __ATTR_RO(cur_freq);
98
rp0_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)99 static ssize_t rp0_freq_show(struct kobject *kobj,
100 struct kobj_attribute *attr, char *buf)
101 {
102 struct device *dev = kobj_to_dev(kobj);
103 struct xe_guc_pc *pc = dev_to_pc(dev);
104
105 return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rp0_freq(pc));
106 }
107 static struct kobj_attribute attr_rp0_freq = __ATTR_RO(rp0_freq);
108
rpe_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)109 static ssize_t rpe_freq_show(struct kobject *kobj,
110 struct kobj_attribute *attr, char *buf)
111 {
112 struct device *dev = kobj_to_dev(kobj);
113 struct xe_guc_pc *pc = dev_to_pc(dev);
114 u32 freq;
115
116 xe_pm_runtime_get(dev_to_xe(dev));
117 freq = xe_guc_pc_get_rpe_freq(pc);
118 xe_pm_runtime_put(dev_to_xe(dev));
119
120 return sysfs_emit(buf, "%d\n", freq);
121 }
122 static struct kobj_attribute attr_rpe_freq = __ATTR_RO(rpe_freq);
123
rpa_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)124 static ssize_t rpa_freq_show(struct kobject *kobj,
125 struct kobj_attribute *attr, char *buf)
126 {
127 struct device *dev = kobj_to_dev(kobj);
128 struct xe_guc_pc *pc = dev_to_pc(dev);
129 u32 freq;
130
131 xe_pm_runtime_get(dev_to_xe(dev));
132 freq = xe_guc_pc_get_rpa_freq(pc);
133 xe_pm_runtime_put(dev_to_xe(dev));
134
135 return sysfs_emit(buf, "%d\n", freq);
136 }
137 static struct kobj_attribute attr_rpa_freq = __ATTR_RO(rpa_freq);
138
rpn_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)139 static ssize_t rpn_freq_show(struct kobject *kobj,
140 struct kobj_attribute *attr, char *buf)
141 {
142 struct device *dev = kobj_to_dev(kobj);
143 struct xe_guc_pc *pc = dev_to_pc(dev);
144
145 return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rpn_freq(pc));
146 }
147 static struct kobj_attribute attr_rpn_freq = __ATTR_RO(rpn_freq);
148
min_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)149 static ssize_t min_freq_show(struct kobject *kobj,
150 struct kobj_attribute *attr, char *buf)
151 {
152 struct device *dev = kobj_to_dev(kobj);
153 struct xe_guc_pc *pc = dev_to_pc(dev);
154 u32 freq;
155 ssize_t ret;
156
157 xe_pm_runtime_get(dev_to_xe(dev));
158 ret = xe_guc_pc_get_min_freq(pc, &freq);
159 xe_pm_runtime_put(dev_to_xe(dev));
160 if (ret)
161 return ret;
162
163 return sysfs_emit(buf, "%d\n", freq);
164 }
165
min_freq_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)166 static ssize_t min_freq_store(struct kobject *kobj,
167 struct kobj_attribute *attr, const char *buff, size_t count)
168 {
169 struct device *dev = kobj_to_dev(kobj);
170 struct xe_guc_pc *pc = dev_to_pc(dev);
171 u32 freq;
172 ssize_t ret;
173
174 ret = kstrtou32(buff, 0, &freq);
175 if (ret)
176 return ret;
177
178 xe_pm_runtime_get(dev_to_xe(dev));
179 ret = xe_guc_pc_set_min_freq(pc, freq);
180 xe_pm_runtime_put(dev_to_xe(dev));
181 if (ret)
182 return ret;
183
184 return count;
185 }
186 static struct kobj_attribute attr_min_freq = __ATTR_RW(min_freq);
187
max_freq_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)188 static ssize_t max_freq_show(struct kobject *kobj,
189 struct kobj_attribute *attr, char *buf)
190 {
191 struct device *dev = kobj_to_dev(kobj);
192 struct xe_guc_pc *pc = dev_to_pc(dev);
193 u32 freq;
194 ssize_t ret;
195
196 xe_pm_runtime_get(dev_to_xe(dev));
197 ret = xe_guc_pc_get_max_freq(pc, &freq);
198 xe_pm_runtime_put(dev_to_xe(dev));
199 if (ret)
200 return ret;
201
202 return sysfs_emit(buf, "%d\n", freq);
203 }
204
max_freq_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)205 static ssize_t max_freq_store(struct kobject *kobj,
206 struct kobj_attribute *attr, const char *buff, size_t count)
207 {
208 struct device *dev = kobj_to_dev(kobj);
209 struct xe_guc_pc *pc = dev_to_pc(dev);
210 u32 freq;
211 ssize_t ret;
212
213 ret = kstrtou32(buff, 0, &freq);
214 if (ret)
215 return ret;
216
217 xe_pm_runtime_get(dev_to_xe(dev));
218 ret = xe_guc_pc_set_max_freq(pc, freq);
219 xe_pm_runtime_put(dev_to_xe(dev));
220 if (ret)
221 return ret;
222
223 return count;
224 }
225 static struct kobj_attribute attr_max_freq = __ATTR_RW(max_freq);
226
power_profile_show(struct kobject * kobj,struct kobj_attribute * attr,char * buff)227 static ssize_t power_profile_show(struct kobject *kobj,
228 struct kobj_attribute *attr,
229 char *buff)
230 {
231 struct device *dev = kobj_to_dev(kobj);
232
233 xe_guc_pc_get_power_profile(dev_to_pc(dev), buff);
234
235 return strlen(buff);
236 }
237
power_profile_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buff,size_t count)238 static ssize_t power_profile_store(struct kobject *kobj,
239 struct kobj_attribute *attr,
240 const char *buff, size_t count)
241 {
242 struct device *dev = kobj_to_dev(kobj);
243 struct xe_guc_pc *pc = dev_to_pc(dev);
244 int err;
245
246 xe_pm_runtime_get(dev_to_xe(dev));
247 err = xe_guc_pc_set_power_profile(pc, buff);
248 xe_pm_runtime_put(dev_to_xe(dev));
249
250 return err ?: count;
251 }
252 static struct kobj_attribute attr_power_profile = __ATTR_RW(power_profile);
253
254 static const struct attribute *freq_attrs[] = {
255 &attr_act_freq.attr,
256 &attr_cur_freq.attr,
257 &attr_rp0_freq.attr,
258 &attr_rpa_freq.attr,
259 &attr_rpe_freq.attr,
260 &attr_rpn_freq.attr,
261 &attr_min_freq.attr,
262 &attr_max_freq.attr,
263 &attr_power_profile.attr,
264 NULL
265 };
266
freq_fini(void * arg)267 static void freq_fini(void *arg)
268 {
269 struct kobject *kobj = arg;
270
271 sysfs_remove_files(kobj, freq_attrs);
272 kobject_put(kobj);
273 }
274
275 /**
276 * xe_gt_freq_init - Initialize Xe Freq component
277 * @gt: Xe GT object
278 *
279 * It needs to be initialized after GT Sysfs and GuC PC components are ready.
280 *
281 * Returns: Returns error value for failure and 0 for success.
282 */
xe_gt_freq_init(struct xe_gt * gt)283 int xe_gt_freq_init(struct xe_gt *gt)
284 {
285 struct xe_device *xe = gt_to_xe(gt);
286 int err;
287
288 if (xe->info.skip_guc_pc)
289 return 0;
290
291 gt->freq = kobject_create_and_add("freq0", gt->sysfs);
292 if (!gt->freq)
293 return -ENOMEM;
294
295 err = sysfs_create_files(gt->freq, freq_attrs);
296 if (err) {
297 kobject_put(gt->freq);
298 return err;
299 }
300
301 err = devm_add_action_or_reset(xe->drm.dev, freq_fini, gt->freq);
302 if (err)
303 return err;
304
305 return xe_gt_throttle_init(gt);
306 }
307