intel_gt_sysfs_pm.c (15586B)
1// SPDX-License-Identifier: MIT 2/* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6#include <drm/drm_device.h> 7#include <linux/sysfs.h> 8#include <linux/printk.h> 9 10#include "i915_drv.h" 11#include "i915_reg.h" 12#include "i915_sysfs.h" 13#include "intel_gt.h" 14#include "intel_gt_regs.h" 15#include "intel_gt_sysfs.h" 16#include "intel_gt_sysfs_pm.h" 17#include "intel_rc6.h" 18#include "intel_rps.h" 19 20enum intel_gt_sysfs_op { 21 INTEL_GT_SYSFS_MIN = 0, 22 INTEL_GT_SYSFS_MAX, 23}; 24 25static int 26sysfs_gt_attribute_w_func(struct device *dev, struct device_attribute *attr, 27 int (func)(struct intel_gt *gt, u32 val), u32 val) 28{ 29 struct intel_gt *gt; 30 int ret; 31 32 if (!is_object_gt(&dev->kobj)) { 33 int i; 34 struct drm_i915_private *i915 = kdev_minor_to_i915(dev); 35 36 for_each_gt(gt, i915, i) { 37 ret = func(gt, val); 38 if (ret) 39 break; 40 } 41 } else { 42 gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 43 ret = func(gt, val); 44 } 45 46 return ret; 47} 48 49static u32 50sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr, 51 u32 (func)(struct intel_gt *gt), 52 enum intel_gt_sysfs_op op) 53{ 54 struct intel_gt *gt; 55 u32 ret; 56 57 ret = (op == INTEL_GT_SYSFS_MAX) ? 0 : (u32) -1; 58 59 if (!is_object_gt(&dev->kobj)) { 60 int i; 61 struct drm_i915_private *i915 = kdev_minor_to_i915(dev); 62 63 for_each_gt(gt, i915, i) { 64 u32 val = func(gt); 65 66 switch (op) { 67 case INTEL_GT_SYSFS_MIN: 68 if (val < ret) 69 ret = val; 70 break; 71 72 case INTEL_GT_SYSFS_MAX: 73 if (val > ret) 74 ret = val; 75 break; 76 } 77 } 78 } else { 79 gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 80 ret = func(gt); 81 } 82 83 return ret; 84} 85 86/* RC6 interfaces will show the minimum RC6 residency value */ 87#define sysfs_gt_attribute_r_min_func(d, a, f) \ 88 sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MIN) 89 90/* Frequency interfaces will show the maximum frequency value */ 91#define sysfs_gt_attribute_r_max_func(d, a, f) \ 92 sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX) 93 94#ifdef CONFIG_PM 95static u32 get_residency(struct intel_gt *gt, i915_reg_t reg) 96{ 97 intel_wakeref_t wakeref; 98 u64 res = 0; 99 100 with_intel_runtime_pm(gt->uncore->rpm, wakeref) 101 res = intel_rc6_residency_us(>->rc6, reg); 102 103 return DIV_ROUND_CLOSEST_ULL(res, 1000); 104} 105 106static ssize_t rc6_enable_show(struct device *dev, 107 struct device_attribute *attr, 108 char *buff) 109{ 110 struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 111 u8 mask = 0; 112 113 if (HAS_RC6(gt->i915)) 114 mask |= BIT(0); 115 if (HAS_RC6p(gt->i915)) 116 mask |= BIT(1); 117 if (HAS_RC6pp(gt->i915)) 118 mask |= BIT(2); 119 120 return sysfs_emit(buff, "%x\n", mask); 121} 122 123static u32 __rc6_residency_ms_show(struct intel_gt *gt) 124{ 125 return get_residency(gt, GEN6_GT_GFX_RC6); 126} 127 128static ssize_t rc6_residency_ms_show(struct device *dev, 129 struct device_attribute *attr, 130 char *buff) 131{ 132 u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr, 133 __rc6_residency_ms_show); 134 135 return sysfs_emit(buff, "%u\n", rc6_residency); 136} 137 138static u32 __rc6p_residency_ms_show(struct intel_gt *gt) 139{ 140 return get_residency(gt, GEN6_GT_GFX_RC6p); 141} 142 143static ssize_t rc6p_residency_ms_show(struct device *dev, 144 struct device_attribute *attr, 145 char *buff) 146{ 147 u32 rc6p_residency = sysfs_gt_attribute_r_min_func(dev, attr, 148 __rc6p_residency_ms_show); 149 150 return sysfs_emit(buff, "%u\n", rc6p_residency); 151} 152 153static u32 __rc6pp_residency_ms_show(struct intel_gt *gt) 154{ 155 return get_residency(gt, GEN6_GT_GFX_RC6pp); 156} 157 158static ssize_t rc6pp_residency_ms_show(struct device *dev, 159 struct device_attribute *attr, 160 char *buff) 161{ 162 u32 rc6pp_residency = sysfs_gt_attribute_r_min_func(dev, attr, 163 __rc6pp_residency_ms_show); 164 165 return sysfs_emit(buff, "%u\n", rc6pp_residency); 166} 167 168static u32 __media_rc6_residency_ms_show(struct intel_gt *gt) 169{ 170 return get_residency(gt, VLV_GT_MEDIA_RC6); 171} 172 173static ssize_t media_rc6_residency_ms_show(struct device *dev, 174 struct device_attribute *attr, 175 char *buff) 176{ 177 u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr, 178 __media_rc6_residency_ms_show); 179 180 return sysfs_emit(buff, "%u\n", rc6_residency); 181} 182 183static DEVICE_ATTR_RO(rc6_enable); 184static DEVICE_ATTR_RO(rc6_residency_ms); 185static DEVICE_ATTR_RO(rc6p_residency_ms); 186static DEVICE_ATTR_RO(rc6pp_residency_ms); 187static DEVICE_ATTR_RO(media_rc6_residency_ms); 188 189static struct attribute *rc6_attrs[] = { 190 &dev_attr_rc6_enable.attr, 191 &dev_attr_rc6_residency_ms.attr, 192 NULL 193}; 194 195static struct attribute *rc6p_attrs[] = { 196 &dev_attr_rc6p_residency_ms.attr, 197 &dev_attr_rc6pp_residency_ms.attr, 198 NULL 199}; 200 201static struct attribute *media_rc6_attrs[] = { 202 &dev_attr_media_rc6_residency_ms.attr, 203 NULL 204}; 205 206static const struct attribute_group rc6_attr_group[] = { 207 { .attrs = rc6_attrs, }, 208 { .name = power_group_name, .attrs = rc6_attrs, }, 209}; 210 211static const struct attribute_group rc6p_attr_group[] = { 212 { .attrs = rc6p_attrs, }, 213 { .name = power_group_name, .attrs = rc6p_attrs, }, 214}; 215 216static const struct attribute_group media_rc6_attr_group[] = { 217 { .attrs = media_rc6_attrs, }, 218 { .name = power_group_name, .attrs = media_rc6_attrs, }, 219}; 220 221static int __intel_gt_sysfs_create_group(struct kobject *kobj, 222 const struct attribute_group *grp) 223{ 224 return is_object_gt(kobj) ? 225 sysfs_create_group(kobj, &grp[0]) : 226 sysfs_merge_group(kobj, &grp[1]); 227} 228 229static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj) 230{ 231 int ret; 232 233 if (!HAS_RC6(gt->i915)) 234 return; 235 236 ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group); 237 if (ret) 238 drm_warn(>->i915->drm, 239 "failed to create gt%u RC6 sysfs files (%pe)\n", 240 gt->info.id, ERR_PTR(ret)); 241 242 /* 243 * cannot use the is_visible() attribute because 244 * the upper object inherits from the parent group. 245 */ 246 if (HAS_RC6p(gt->i915)) { 247 ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group); 248 if (ret) 249 drm_warn(>->i915->drm, 250 "failed to create gt%u RC6p sysfs files (%pe)\n", 251 gt->info.id, ERR_PTR(ret)); 252 } 253 254 if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) { 255 ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group); 256 if (ret) 257 drm_warn(>->i915->drm, 258 "failed to create media %u RC6 sysfs files (%pe)\n", 259 gt->info.id, ERR_PTR(ret)); 260 } 261} 262#else 263static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj) 264{ 265} 266#endif /* CONFIG_PM */ 267 268static u32 __act_freq_mhz_show(struct intel_gt *gt) 269{ 270 return intel_rps_read_actual_frequency(>->rps); 271} 272 273static ssize_t act_freq_mhz_show(struct device *dev, 274 struct device_attribute *attr, char *buff) 275{ 276 u32 actual_freq = sysfs_gt_attribute_r_max_func(dev, attr, 277 __act_freq_mhz_show); 278 279 return sysfs_emit(buff, "%u\n", actual_freq); 280} 281 282static u32 __cur_freq_mhz_show(struct intel_gt *gt) 283{ 284 return intel_rps_get_requested_frequency(>->rps); 285} 286 287static ssize_t cur_freq_mhz_show(struct device *dev, 288 struct device_attribute *attr, char *buff) 289{ 290 u32 cur_freq = sysfs_gt_attribute_r_max_func(dev, attr, 291 __cur_freq_mhz_show); 292 293 return sysfs_emit(buff, "%u\n", cur_freq); 294} 295 296static u32 __boost_freq_mhz_show(struct intel_gt *gt) 297{ 298 return intel_rps_get_boost_frequency(>->rps); 299} 300 301static ssize_t boost_freq_mhz_show(struct device *dev, 302 struct device_attribute *attr, 303 char *buff) 304{ 305 u32 boost_freq = sysfs_gt_attribute_r_max_func(dev, attr, 306 __boost_freq_mhz_show); 307 308 return sysfs_emit(buff, "%u\n", boost_freq); 309} 310 311static int __boost_freq_mhz_store(struct intel_gt *gt, u32 val) 312{ 313 return intel_rps_set_boost_frequency(>->rps, val); 314} 315 316static ssize_t boost_freq_mhz_store(struct device *dev, 317 struct device_attribute *attr, 318 const char *buff, size_t count) 319{ 320 ssize_t ret; 321 u32 val; 322 323 ret = kstrtou32(buff, 0, &val); 324 if (ret) 325 return ret; 326 327 return sysfs_gt_attribute_w_func(dev, attr, 328 __boost_freq_mhz_store, val) ?: count; 329} 330 331static u32 __rp0_freq_mhz_show(struct intel_gt *gt) 332{ 333 return intel_rps_get_rp0_frequency(>->rps); 334} 335 336static ssize_t RP0_freq_mhz_show(struct device *dev, 337 struct device_attribute *attr, char *buff) 338{ 339 u32 rp0_freq = sysfs_gt_attribute_r_max_func(dev, attr, 340 __rp0_freq_mhz_show); 341 342 return sysfs_emit(buff, "%u\n", rp0_freq); 343} 344 345static u32 __rp1_freq_mhz_show(struct intel_gt *gt) 346{ 347 return intel_rps_get_rp1_frequency(>->rps); 348} 349 350static ssize_t RP1_freq_mhz_show(struct device *dev, 351 struct device_attribute *attr, char *buff) 352{ 353 u32 rp1_freq = sysfs_gt_attribute_r_max_func(dev, attr, 354 __rp1_freq_mhz_show); 355 356 return sysfs_emit(buff, "%u\n", rp1_freq); 357} 358 359static u32 __rpn_freq_mhz_show(struct intel_gt *gt) 360{ 361 return intel_rps_get_rpn_frequency(>->rps); 362} 363 364static ssize_t RPn_freq_mhz_show(struct device *dev, 365 struct device_attribute *attr, char *buff) 366{ 367 u32 rpn_freq = sysfs_gt_attribute_r_max_func(dev, attr, 368 __rpn_freq_mhz_show); 369 370 return sysfs_emit(buff, "%u\n", rpn_freq); 371} 372 373static u32 __max_freq_mhz_show(struct intel_gt *gt) 374{ 375 return intel_rps_get_max_frequency(>->rps); 376} 377 378static ssize_t max_freq_mhz_show(struct device *dev, 379 struct device_attribute *attr, char *buff) 380{ 381 u32 max_freq = sysfs_gt_attribute_r_max_func(dev, attr, 382 __max_freq_mhz_show); 383 384 return sysfs_emit(buff, "%u\n", max_freq); 385} 386 387static int __set_max_freq(struct intel_gt *gt, u32 val) 388{ 389 return intel_rps_set_max_frequency(>->rps, val); 390} 391 392static ssize_t max_freq_mhz_store(struct device *dev, 393 struct device_attribute *attr, 394 const char *buff, size_t count) 395{ 396 int ret; 397 u32 val; 398 399 ret = kstrtou32(buff, 0, &val); 400 if (ret) 401 return ret; 402 403 ret = sysfs_gt_attribute_w_func(dev, attr, __set_max_freq, val); 404 405 return ret ?: count; 406} 407 408static u32 __min_freq_mhz_show(struct intel_gt *gt) 409{ 410 return intel_rps_get_min_frequency(>->rps); 411} 412 413static ssize_t min_freq_mhz_show(struct device *dev, 414 struct device_attribute *attr, char *buff) 415{ 416 u32 min_freq = sysfs_gt_attribute_r_min_func(dev, attr, 417 __min_freq_mhz_show); 418 419 return sysfs_emit(buff, "%u\n", min_freq); 420} 421 422static int __set_min_freq(struct intel_gt *gt, u32 val) 423{ 424 return intel_rps_set_min_frequency(>->rps, val); 425} 426 427static ssize_t min_freq_mhz_store(struct device *dev, 428 struct device_attribute *attr, 429 const char *buff, size_t count) 430{ 431 int ret; 432 u32 val; 433 434 ret = kstrtou32(buff, 0, &val); 435 if (ret) 436 return ret; 437 438 ret = sysfs_gt_attribute_w_func(dev, attr, __set_min_freq, val); 439 440 return ret ?: count; 441} 442 443static u32 __vlv_rpe_freq_mhz_show(struct intel_gt *gt) 444{ 445 struct intel_rps *rps = >->rps; 446 447 return intel_gpu_freq(rps, rps->efficient_freq); 448} 449 450static ssize_t vlv_rpe_freq_mhz_show(struct device *dev, 451 struct device_attribute *attr, char *buff) 452{ 453 u32 rpe_freq = sysfs_gt_attribute_r_max_func(dev, attr, 454 __vlv_rpe_freq_mhz_show); 455 456 return sysfs_emit(buff, "%u\n", rpe_freq); 457} 458 459#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \ 460 static struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \ 461 static struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store) 462 463#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name) \ 464 INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL) 465#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name) \ 466 INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store) 467 468/* The below macros generate static structures */ 469INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz); 470INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz); 471INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz); 472INTEL_GT_RPS_SYSFS_ATTR_RO(RP0_freq_mhz); 473INTEL_GT_RPS_SYSFS_ATTR_RO(RP1_freq_mhz); 474INTEL_GT_RPS_SYSFS_ATTR_RO(RPn_freq_mhz); 475INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz); 476INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz); 477 478static DEVICE_ATTR_RO(vlv_rpe_freq_mhz); 479 480#define GEN6_ATTR(s) { \ 481 &dev_attr_##s##_act_freq_mhz.attr, \ 482 &dev_attr_##s##_cur_freq_mhz.attr, \ 483 &dev_attr_##s##_boost_freq_mhz.attr, \ 484 &dev_attr_##s##_max_freq_mhz.attr, \ 485 &dev_attr_##s##_min_freq_mhz.attr, \ 486 &dev_attr_##s##_RP0_freq_mhz.attr, \ 487 &dev_attr_##s##_RP1_freq_mhz.attr, \ 488 &dev_attr_##s##_RPn_freq_mhz.attr, \ 489 NULL, \ 490 } 491 492#define GEN6_RPS_ATTR GEN6_ATTR(rps) 493#define GEN6_GT_ATTR GEN6_ATTR(gt) 494 495static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR; 496static const struct attribute * const gen6_gt_attrs[] = GEN6_GT_ATTR; 497 498static ssize_t punit_req_freq_mhz_show(struct device *dev, 499 struct device_attribute *attr, 500 char *buff) 501{ 502 struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 503 u32 preq = intel_rps_read_punit_req_frequency(>->rps); 504 505 return sysfs_emit(buff, "%u\n", preq); 506} 507 508struct intel_gt_bool_throttle_attr { 509 struct attribute attr; 510 ssize_t (*show)(struct device *dev, struct device_attribute *attr, 511 char *buf); 512 i915_reg_t reg32; 513 u32 mask; 514}; 515 516static ssize_t throttle_reason_bool_show(struct device *dev, 517 struct device_attribute *attr, 518 char *buff) 519{ 520 struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); 521 struct intel_gt_bool_throttle_attr *t_attr = 522 (struct intel_gt_bool_throttle_attr *) attr; 523 bool val = rps_read_mask_mmio(>->rps, t_attr->reg32, t_attr->mask); 524 525 return sysfs_emit(buff, "%u\n", val); 526} 527 528#define INTEL_GT_RPS_BOOL_ATTR_RO(sysfs_func__, mask__) \ 529struct intel_gt_bool_throttle_attr attr_##sysfs_func__ = { \ 530 .attr = { .name = __stringify(sysfs_func__), .mode = 0444 }, \ 531 .show = throttle_reason_bool_show, \ 532 .reg32 = GT0_PERF_LIMIT_REASONS, \ 533 .mask = mask__, \ 534} 535 536static DEVICE_ATTR_RO(punit_req_freq_mhz); 537static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_status, GT0_PERF_LIMIT_REASONS_MASK); 538static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl1, POWER_LIMIT_1_MASK); 539static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl2, POWER_LIMIT_2_MASK); 540static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl4, POWER_LIMIT_4_MASK); 541static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_thermal, THERMAL_LIMIT_MASK); 542static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_prochot, PROCHOT_MASK); 543static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_ratl, RATL_MASK); 544static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_thermalert, VR_THERMALERT_MASK); 545static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_tdc, VR_TDC_MASK); 546 547static const struct attribute *freq_attrs[] = { 548 &dev_attr_punit_req_freq_mhz.attr, 549 &attr_throttle_reason_status.attr, 550 &attr_throttle_reason_pl1.attr, 551 &attr_throttle_reason_pl2.attr, 552 &attr_throttle_reason_pl4.attr, 553 &attr_throttle_reason_thermal.attr, 554 &attr_throttle_reason_prochot.attr, 555 &attr_throttle_reason_ratl.attr, 556 &attr_throttle_reason_vr_thermalert.attr, 557 &attr_throttle_reason_vr_tdc.attr, 558 NULL 559}; 560 561static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj, 562 const struct attribute * const *attrs) 563{ 564 int ret; 565 566 if (GRAPHICS_VER(gt->i915) < 6) 567 return 0; 568 569 ret = sysfs_create_files(kobj, attrs); 570 if (ret) 571 return ret; 572 573 if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) 574 ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr); 575 576 return ret; 577} 578 579void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) 580{ 581 int ret; 582 583 intel_sysfs_rc6_init(gt, kobj); 584 585 ret = is_object_gt(kobj) ? 586 intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) : 587 intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs); 588 if (ret) 589 drm_warn(>->i915->drm, 590 "failed to create gt%u RPS sysfs files (%pe)", 591 gt->info.id, ERR_PTR(ret)); 592 593 /* end of the legacy interfaces */ 594 if (!is_object_gt(kobj)) 595 return; 596 597 ret = sysfs_create_files(kobj, freq_attrs); 598 if (ret) 599 drm_warn(>->i915->drm, 600 "failed to create gt%u throttle sysfs files (%pe)", 601 gt->info.id, ERR_PTR(ret)); 602}