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