xref: /linux/drivers/gpu/drm/xe/xe_gt_freq.c (revision 2c1ed907520c50326b8f604907a8478b27881a2e)
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:
33  *
34  * device/tile#/gt#/freq0/<item>_freq *read-only* files:
35  * - act_freq: The actual resolved frequency decided by PCODE.
36  * - cur_freq: The current one requested by GuC PC to the PCODE.
37  * - rpn_freq: The Render Performance (RP) N level, which is the minimal one.
38  * - rpe_freq: The Render Performance (RP) E level, which is the efficient one.
39  * - rp0_freq: The Render Performance (RP) 0 level, which is the maximum one.
40  *
41  * device/tile#/gt#/freq0/<item>_freq *read-write* files:
42  * - min_freq: Min frequency request.
43  * - max_freq: Max frequency request.
44  *             If max <= min, then freq_min becomes a fixed frequency request.
45  */
46 
47 static struct xe_guc_pc *
dev_to_pc(struct device * dev)48 dev_to_pc(struct device *dev)
49 {
50 	return &kobj_to_gt(dev->kobj.parent)->uc.guc.pc;
51 }
52 
53 static struct xe_device *
dev_to_xe(struct device * dev)54 dev_to_xe(struct device *dev)
55 {
56 	return gt_to_xe(kobj_to_gt(dev->kobj.parent));
57 }
58 
act_freq_show(struct device * dev,struct device_attribute * attr,char * buf)59 static ssize_t act_freq_show(struct device *dev,
60 			     struct device_attribute *attr, char *buf)
61 {
62 	struct xe_guc_pc *pc = dev_to_pc(dev);
63 	u32 freq;
64 
65 	xe_pm_runtime_get(dev_to_xe(dev));
66 	freq = xe_guc_pc_get_act_freq(pc);
67 	xe_pm_runtime_put(dev_to_xe(dev));
68 
69 	return sysfs_emit(buf, "%d\n", freq);
70 }
71 static DEVICE_ATTR_RO(act_freq);
72 
cur_freq_show(struct device * dev,struct device_attribute * attr,char * buf)73 static ssize_t cur_freq_show(struct device *dev,
74 			     struct device_attribute *attr, char *buf)
75 {
76 	struct xe_guc_pc *pc = dev_to_pc(dev);
77 	u32 freq;
78 	ssize_t ret;
79 
80 	xe_pm_runtime_get(dev_to_xe(dev));
81 	ret = xe_guc_pc_get_cur_freq(pc, &freq);
82 	xe_pm_runtime_put(dev_to_xe(dev));
83 	if (ret)
84 		return ret;
85 
86 	return sysfs_emit(buf, "%d\n", freq);
87 }
88 static DEVICE_ATTR_RO(cur_freq);
89 
rp0_freq_show(struct device * dev,struct device_attribute * attr,char * buf)90 static ssize_t rp0_freq_show(struct device *dev,
91 			     struct device_attribute *attr, char *buf)
92 {
93 	struct xe_guc_pc *pc = dev_to_pc(dev);
94 	u32 freq;
95 
96 	xe_pm_runtime_get(dev_to_xe(dev));
97 	freq = xe_guc_pc_get_rp0_freq(pc);
98 	xe_pm_runtime_put(dev_to_xe(dev));
99 
100 	return sysfs_emit(buf, "%d\n", freq);
101 }
102 static DEVICE_ATTR_RO(rp0_freq);
103 
rpe_freq_show(struct device * dev,struct device_attribute * attr,char * buf)104 static ssize_t rpe_freq_show(struct device *dev,
105 			     struct device_attribute *attr, char *buf)
106 {
107 	struct xe_guc_pc *pc = dev_to_pc(dev);
108 	u32 freq;
109 
110 	xe_pm_runtime_get(dev_to_xe(dev));
111 	freq = xe_guc_pc_get_rpe_freq(pc);
112 	xe_pm_runtime_put(dev_to_xe(dev));
113 
114 	return sysfs_emit(buf, "%d\n", freq);
115 }
116 static DEVICE_ATTR_RO(rpe_freq);
117 
rpa_freq_show(struct device * dev,struct device_attribute * attr,char * buf)118 static ssize_t rpa_freq_show(struct device *dev,
119 			     struct device_attribute *attr, char *buf)
120 {
121 	struct xe_guc_pc *pc = dev_to_pc(dev);
122 	u32 freq;
123 
124 	xe_pm_runtime_get(dev_to_xe(dev));
125 	freq = xe_guc_pc_get_rpa_freq(pc);
126 	xe_pm_runtime_put(dev_to_xe(dev));
127 
128 	return sysfs_emit(buf, "%d\n", freq);
129 }
130 static DEVICE_ATTR_RO(rpa_freq);
131 
rpn_freq_show(struct device * dev,struct device_attribute * attr,char * buf)132 static ssize_t rpn_freq_show(struct device *dev,
133 			     struct device_attribute *attr, char *buf)
134 {
135 	struct xe_guc_pc *pc = dev_to_pc(dev);
136 
137 	return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rpn_freq(pc));
138 }
139 static DEVICE_ATTR_RO(rpn_freq);
140 
min_freq_show(struct device * dev,struct device_attribute * attr,char * buf)141 static ssize_t min_freq_show(struct device *dev,
142 			     struct device_attribute *attr, char *buf)
143 {
144 	struct xe_guc_pc *pc = dev_to_pc(dev);
145 	u32 freq;
146 	ssize_t ret;
147 
148 	xe_pm_runtime_get(dev_to_xe(dev));
149 	ret = xe_guc_pc_get_min_freq(pc, &freq);
150 	xe_pm_runtime_put(dev_to_xe(dev));
151 	if (ret)
152 		return ret;
153 
154 	return sysfs_emit(buf, "%d\n", freq);
155 }
156 
min_freq_store(struct device * dev,struct device_attribute * attr,const char * buff,size_t count)157 static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
158 			      const char *buff, size_t count)
159 {
160 	struct xe_guc_pc *pc = dev_to_pc(dev);
161 	u32 freq;
162 	ssize_t ret;
163 
164 	ret = kstrtou32(buff, 0, &freq);
165 	if (ret)
166 		return ret;
167 
168 	xe_pm_runtime_get(dev_to_xe(dev));
169 	ret = xe_guc_pc_set_min_freq(pc, freq);
170 	xe_pm_runtime_put(dev_to_xe(dev));
171 	if (ret)
172 		return ret;
173 
174 	return count;
175 }
176 static DEVICE_ATTR_RW(min_freq);
177 
max_freq_show(struct device * dev,struct device_attribute * attr,char * buf)178 static ssize_t max_freq_show(struct device *dev,
179 			     struct device_attribute *attr, char *buf)
180 {
181 	struct xe_guc_pc *pc = dev_to_pc(dev);
182 	u32 freq;
183 	ssize_t ret;
184 
185 	xe_pm_runtime_get(dev_to_xe(dev));
186 	ret = xe_guc_pc_get_max_freq(pc, &freq);
187 	xe_pm_runtime_put(dev_to_xe(dev));
188 	if (ret)
189 		return ret;
190 
191 	return sysfs_emit(buf, "%d\n", freq);
192 }
193 
max_freq_store(struct device * dev,struct device_attribute * attr,const char * buff,size_t count)194 static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
195 			      const char *buff, size_t count)
196 {
197 	struct xe_guc_pc *pc = dev_to_pc(dev);
198 	u32 freq;
199 	ssize_t ret;
200 
201 	ret = kstrtou32(buff, 0, &freq);
202 	if (ret)
203 		return ret;
204 
205 	xe_pm_runtime_get(dev_to_xe(dev));
206 	ret = xe_guc_pc_set_max_freq(pc, freq);
207 	xe_pm_runtime_put(dev_to_xe(dev));
208 	if (ret)
209 		return ret;
210 
211 	return count;
212 }
213 static DEVICE_ATTR_RW(max_freq);
214 
215 static const struct attribute *freq_attrs[] = {
216 	&dev_attr_act_freq.attr,
217 	&dev_attr_cur_freq.attr,
218 	&dev_attr_rp0_freq.attr,
219 	&dev_attr_rpa_freq.attr,
220 	&dev_attr_rpe_freq.attr,
221 	&dev_attr_rpn_freq.attr,
222 	&dev_attr_min_freq.attr,
223 	&dev_attr_max_freq.attr,
224 	NULL
225 };
226 
freq_fini(void * arg)227 static void freq_fini(void *arg)
228 {
229 	struct kobject *kobj = arg;
230 
231 	sysfs_remove_files(kobj, freq_attrs);
232 	kobject_put(kobj);
233 }
234 
235 /**
236  * xe_gt_freq_init - Initialize Xe Freq component
237  * @gt: Xe GT object
238  *
239  * It needs to be initialized after GT Sysfs and GuC PC components are ready.
240  *
241  * Returns: Returns error value for failure and 0 for success.
242  */
xe_gt_freq_init(struct xe_gt * gt)243 int xe_gt_freq_init(struct xe_gt *gt)
244 {
245 	struct xe_device *xe = gt_to_xe(gt);
246 	int err;
247 
248 	if (xe->info.skip_guc_pc)
249 		return 0;
250 
251 	gt->freq = kobject_create_and_add("freq0", gt->sysfs);
252 	if (!gt->freq)
253 		return -ENOMEM;
254 
255 	err = sysfs_create_files(gt->freq, freq_attrs);
256 	if (err)
257 		return err;
258 
259 	err = devm_add_action_or_reset(xe->drm.dev, freq_fini, gt->freq);
260 	if (err)
261 		return err;
262 
263 	return xe_gt_throttle_init(gt);
264 }
265