250 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */5 6#include <drm/drm_managed.h>7 8#include <regs/xe_gt_regs.h>9#include "xe_device.h"10#include "xe_gt.h"11#include "xe_gt_sysfs.h"12#include "xe_gt_throttle.h"13#include "xe_mmio.h"14#include "xe_pm.h"15 16/**17 * DOC: Xe GT Throttle18 *19 * Provides sysfs entries and other helpers for frequency throttle reasons in GT20 *21 * device/gt#/freq0/throttle/status - Overall status22 * device/gt#/freq0/throttle/reason_pl1 - Frequency throttle due to PL123 * device/gt#/freq0/throttle/reason_pl2 - Frequency throttle due to PL224 * device/gt#/freq0/throttle/reason_pl4 - Frequency throttle due to PL4, Iccmax etc.25 * device/gt#/freq0/throttle/reason_thermal - Frequency throttle due to thermal26 * device/gt#/freq0/throttle/reason_prochot - Frequency throttle due to prochot27 * device/gt#/freq0/throttle/reason_ratl - Frequency throttle due to RATL28 * device/gt#/freq0/throttle/reason_vr_thermalert - Frequency throttle due to VR THERMALERT29 * device/gt#/freq0/throttle/reason_vr_tdc - Frequency throttle due to VR TDC30 */31 32static struct xe_gt *33dev_to_gt(struct device *dev)34{35 return kobj_to_gt(dev->kobj.parent);36}37 38u32 xe_gt_throttle_get_limit_reasons(struct xe_gt *gt)39{40 u32 reg;41 42 xe_pm_runtime_get(gt_to_xe(gt));43 if (xe_gt_is_media_type(gt))44 reg = xe_mmio_read32(gt, MTL_MEDIA_PERF_LIMIT_REASONS);45 else46 reg = xe_mmio_read32(gt, GT0_PERF_LIMIT_REASONS);47 xe_pm_runtime_put(gt_to_xe(gt));48 49 return reg;50}51 52static u32 read_status(struct xe_gt *gt)53{54 u32 status = xe_gt_throttle_get_limit_reasons(gt) & GT0_PERF_LIMIT_REASONS_MASK;55 56 return status;57}58 59static u32 read_reason_pl1(struct xe_gt *gt)60{61 u32 pl1 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_1_MASK;62 63 return pl1;64}65 66static u32 read_reason_pl2(struct xe_gt *gt)67{68 u32 pl2 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_2_MASK;69 70 return pl2;71}72 73static u32 read_reason_pl4(struct xe_gt *gt)74{75 u32 pl4 = xe_gt_throttle_get_limit_reasons(gt) & POWER_LIMIT_4_MASK;76 77 return pl4;78}79 80static u32 read_reason_thermal(struct xe_gt *gt)81{82 u32 thermal = xe_gt_throttle_get_limit_reasons(gt) & THERMAL_LIMIT_MASK;83 84 return thermal;85}86 87static u32 read_reason_prochot(struct xe_gt *gt)88{89 u32 prochot = xe_gt_throttle_get_limit_reasons(gt) & PROCHOT_MASK;90 91 return prochot;92}93 94static u32 read_reason_ratl(struct xe_gt *gt)95{96 u32 ratl = xe_gt_throttle_get_limit_reasons(gt) & RATL_MASK;97 98 return ratl;99}100 101static u32 read_reason_vr_thermalert(struct xe_gt *gt)102{103 u32 thermalert = xe_gt_throttle_get_limit_reasons(gt) & VR_THERMALERT_MASK;104 105 return thermalert;106}107 108static u32 read_reason_vr_tdc(struct xe_gt *gt)109{110 u32 tdc = xe_gt_throttle_get_limit_reasons(gt) & VR_TDC_MASK;111 112 return tdc;113}114 115static ssize_t status_show(struct device *dev,116 struct device_attribute *attr,117 char *buff)118{119 struct xe_gt *gt = dev_to_gt(dev);120 bool status = !!read_status(gt);121 122 return sysfs_emit(buff, "%u\n", status);123}124static DEVICE_ATTR_RO(status);125 126static ssize_t reason_pl1_show(struct device *dev,127 struct device_attribute *attr,128 char *buff)129{130 struct xe_gt *gt = dev_to_gt(dev);131 bool pl1 = !!read_reason_pl1(gt);132 133 return sysfs_emit(buff, "%u\n", pl1);134}135static DEVICE_ATTR_RO(reason_pl1);136 137static ssize_t reason_pl2_show(struct device *dev,138 struct device_attribute *attr,139 char *buff)140{141 struct xe_gt *gt = dev_to_gt(dev);142 bool pl2 = !!read_reason_pl2(gt);143 144 return sysfs_emit(buff, "%u\n", pl2);145}146static DEVICE_ATTR_RO(reason_pl2);147 148static ssize_t reason_pl4_show(struct device *dev,149 struct device_attribute *attr,150 char *buff)151{152 struct xe_gt *gt = dev_to_gt(dev);153 bool pl4 = !!read_reason_pl4(gt);154 155 return sysfs_emit(buff, "%u\n", pl4);156}157static DEVICE_ATTR_RO(reason_pl4);158 159static ssize_t reason_thermal_show(struct device *dev,160 struct device_attribute *attr,161 char *buff)162{163 struct xe_gt *gt = dev_to_gt(dev);164 bool thermal = !!read_reason_thermal(gt);165 166 return sysfs_emit(buff, "%u\n", thermal);167}168static DEVICE_ATTR_RO(reason_thermal);169 170static ssize_t reason_prochot_show(struct device *dev,171 struct device_attribute *attr,172 char *buff)173{174 struct xe_gt *gt = dev_to_gt(dev);175 bool prochot = !!read_reason_prochot(gt);176 177 return sysfs_emit(buff, "%u\n", prochot);178}179static DEVICE_ATTR_RO(reason_prochot);180 181static ssize_t reason_ratl_show(struct device *dev,182 struct device_attribute *attr,183 char *buff)184{185 struct xe_gt *gt = dev_to_gt(dev);186 bool ratl = !!read_reason_ratl(gt);187 188 return sysfs_emit(buff, "%u\n", ratl);189}190static DEVICE_ATTR_RO(reason_ratl);191 192static ssize_t reason_vr_thermalert_show(struct device *dev,193 struct device_attribute *attr,194 char *buff)195{196 struct xe_gt *gt = dev_to_gt(dev);197 bool thermalert = !!read_reason_vr_thermalert(gt);198 199 return sysfs_emit(buff, "%u\n", thermalert);200}201static DEVICE_ATTR_RO(reason_vr_thermalert);202 203static ssize_t reason_vr_tdc_show(struct device *dev,204 struct device_attribute *attr,205 char *buff)206{207 struct xe_gt *gt = dev_to_gt(dev);208 bool tdc = !!read_reason_vr_tdc(gt);209 210 return sysfs_emit(buff, "%u\n", tdc);211}212static DEVICE_ATTR_RO(reason_vr_tdc);213 214static struct attribute *throttle_attrs[] = {215 &dev_attr_status.attr,216 &dev_attr_reason_pl1.attr,217 &dev_attr_reason_pl2.attr,218 &dev_attr_reason_pl4.attr,219 &dev_attr_reason_thermal.attr,220 &dev_attr_reason_prochot.attr,221 &dev_attr_reason_ratl.attr,222 &dev_attr_reason_vr_thermalert.attr,223 &dev_attr_reason_vr_tdc.attr,224 NULL225};226 227static const struct attribute_group throttle_group_attrs = {228 .name = "throttle",229 .attrs = throttle_attrs,230};231 232static void gt_throttle_sysfs_fini(void *arg)233{234 struct xe_gt *gt = arg;235 236 sysfs_remove_group(gt->freq, &throttle_group_attrs);237}238 239int xe_gt_throttle_init(struct xe_gt *gt)240{241 struct xe_device *xe = gt_to_xe(gt);242 int err;243 244 err = sysfs_create_group(gt->freq, &throttle_group_attrs);245 if (err)246 return err;247 248 return devm_add_action_or_reset(xe->drm.dev, gt_throttle_sysfs_fini, gt);249}250