brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · ab76973 Raw
250 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */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 Management22 *23 * This component is responsible for the raw GT frequency management, including24 * the sysfs API.25 *26 * Underneath, Xe enables GuC SLPC automated frequency management. GuC is then27 * allowed to request PCODE any frequency between the Minimum and the Maximum28 * selected by this component. Furthermore, it is important to highlight that29 * PCODE is the ultimate decision maker of the actual running frequency, based30 * 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 47static struct xe_guc_pc *48dev_to_pc(struct device *dev)49{50	return &kobj_to_gt(dev->kobj.parent)->uc.guc.pc;51}52 53static struct xe_device *54dev_to_xe(struct device *dev)55{56	return gt_to_xe(kobj_to_gt(dev->kobj.parent));57}58 59static 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}71static DEVICE_ATTR_RO(act_freq);72 73static 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}88static DEVICE_ATTR_RO(cur_freq);89 90static 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}102static DEVICE_ATTR_RO(rp0_freq);103 104static 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}116static DEVICE_ATTR_RO(rpe_freq);117 118static ssize_t rpn_freq_show(struct device *dev,119			     struct device_attribute *attr, char *buf)120{121	struct xe_guc_pc *pc = dev_to_pc(dev);122 123	return sysfs_emit(buf, "%d\n", xe_guc_pc_get_rpn_freq(pc));124}125static DEVICE_ATTR_RO(rpn_freq);126 127static ssize_t min_freq_show(struct device *dev,128			     struct device_attribute *attr, char *buf)129{130	struct xe_guc_pc *pc = dev_to_pc(dev);131	u32 freq;132	ssize_t ret;133 134	xe_pm_runtime_get(dev_to_xe(dev));135	ret = xe_guc_pc_get_min_freq(pc, &freq);136	xe_pm_runtime_put(dev_to_xe(dev));137	if (ret)138		return ret;139 140	return sysfs_emit(buf, "%d\n", freq);141}142 143static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,144			      const char *buff, size_t count)145{146	struct xe_guc_pc *pc = dev_to_pc(dev);147	u32 freq;148	ssize_t ret;149 150	ret = kstrtou32(buff, 0, &freq);151	if (ret)152		return ret;153 154	xe_pm_runtime_get(dev_to_xe(dev));155	ret = xe_guc_pc_set_min_freq(pc, freq);156	xe_pm_runtime_put(dev_to_xe(dev));157	if (ret)158		return ret;159 160	return count;161}162static DEVICE_ATTR_RW(min_freq);163 164static ssize_t max_freq_show(struct device *dev,165			     struct device_attribute *attr, char *buf)166{167	struct xe_guc_pc *pc = dev_to_pc(dev);168	u32 freq;169	ssize_t ret;170 171	xe_pm_runtime_get(dev_to_xe(dev));172	ret = xe_guc_pc_get_max_freq(pc, &freq);173	xe_pm_runtime_put(dev_to_xe(dev));174	if (ret)175		return ret;176 177	return sysfs_emit(buf, "%d\n", freq);178}179 180static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,181			      const char *buff, size_t count)182{183	struct xe_guc_pc *pc = dev_to_pc(dev);184	u32 freq;185	ssize_t ret;186 187	ret = kstrtou32(buff, 0, &freq);188	if (ret)189		return ret;190 191	xe_pm_runtime_get(dev_to_xe(dev));192	ret = xe_guc_pc_set_max_freq(pc, freq);193	xe_pm_runtime_put(dev_to_xe(dev));194	if (ret)195		return ret;196 197	return count;198}199static DEVICE_ATTR_RW(max_freq);200 201static const struct attribute *freq_attrs[] = {202	&dev_attr_act_freq.attr,203	&dev_attr_cur_freq.attr,204	&dev_attr_rp0_freq.attr,205	&dev_attr_rpe_freq.attr,206	&dev_attr_rpn_freq.attr,207	&dev_attr_min_freq.attr,208	&dev_attr_max_freq.attr,209	NULL210};211 212static void freq_fini(void *arg)213{214	struct kobject *kobj = arg;215 216	sysfs_remove_files(kobj, freq_attrs);217	kobject_put(kobj);218}219 220/**221 * xe_gt_freq_init - Initialize Xe Freq component222 * @gt: Xe GT object223 *224 * It needs to be initialized after GT Sysfs and GuC PC components are ready.225 *226 * Returns: Returns error value for failure and 0 for success.227 */228int xe_gt_freq_init(struct xe_gt *gt)229{230	struct xe_device *xe = gt_to_xe(gt);231	int err;232 233	if (xe->info.skip_guc_pc)234		return 0;235 236	gt->freq = kobject_create_and_add("freq0", gt->sysfs);237	if (!gt->freq)238		return -ENOMEM;239 240	err = sysfs_create_files(gt->freq, freq_attrs);241	if (err)242		return err;243 244	err = devm_add_action_or_reset(xe->drm.dev, freq_fini, gt->freq);245	if (err)246		return err;247 248	return xe_gt_throttle_init(gt);249}250