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