Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/i915: Expose RPS thresholds in sysfs

User feedback indicates significant performance gains are possible in
specific games with non default RPS up/down thresholds.

Expose these tunables via sysfs which will allow users to achieve best
performance when running games and best power efficiency elsewhere.

Note this patch supports non GuC based platforms only.

v2:
* Make checkpatch happy.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
References: https://gitlab.freedesktop.org/drm/intel/-/issues/8389
Cc: Rodrigo Vivi <rodrigo.vivi@kernel.org>
Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230717164013.826614-4-tvrtko.ursulin@linux.intel.com

+108
+108
drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
··· 701 701 }; 702 702 703 703 static ssize_t 704 + rps_up_threshold_pct_show(struct kobject *kobj, struct kobj_attribute *attr, 705 + char *buf) 706 + { 707 + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); 708 + struct intel_rps *rps = &gt->rps; 709 + 710 + return sysfs_emit(buf, "%u\n", intel_rps_get_up_threshold(rps)); 711 + } 712 + 713 + static ssize_t 714 + rps_up_threshold_pct_store(struct kobject *kobj, struct kobj_attribute *attr, 715 + const char *buf, size_t count) 716 + { 717 + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); 718 + struct intel_rps *rps = &gt->rps; 719 + int ret; 720 + u8 val; 721 + 722 + ret = kstrtou8(buf, 10, &val); 723 + if (ret) 724 + return ret; 725 + 726 + ret = intel_rps_set_up_threshold(rps, val); 727 + 728 + return ret == 0 ? count : ret; 729 + } 730 + 731 + static struct kobj_attribute rps_up_threshold_pct = 732 + __ATTR(rps_up_threshold_pct, 733 + 0664, 734 + rps_up_threshold_pct_show, 735 + rps_up_threshold_pct_store); 736 + 737 + static ssize_t 738 + rps_down_threshold_pct_show(struct kobject *kobj, struct kobj_attribute *attr, 739 + char *buf) 740 + { 741 + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); 742 + struct intel_rps *rps = &gt->rps; 743 + 744 + return sysfs_emit(buf, "%u\n", intel_rps_get_down_threshold(rps)); 745 + } 746 + 747 + static ssize_t 748 + rps_down_threshold_pct_store(struct kobject *kobj, struct kobj_attribute *attr, 749 + const char *buf, size_t count) 750 + { 751 + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); 752 + struct intel_rps *rps = &gt->rps; 753 + int ret; 754 + u8 val; 755 + 756 + ret = kstrtou8(buf, 10, &val); 757 + if (ret) 758 + return ret; 759 + 760 + ret = intel_rps_set_down_threshold(rps, val); 761 + 762 + return ret == 0 ? count : ret; 763 + } 764 + 765 + static struct kobj_attribute rps_down_threshold_pct = 766 + __ATTR(rps_down_threshold_pct, 767 + 0664, 768 + rps_down_threshold_pct_show, 769 + rps_down_threshold_pct_store); 770 + 771 + static const struct attribute * const gen6_gt_rps_attrs[] = { 772 + &rps_up_threshold_pct.attr, 773 + &rps_down_threshold_pct.attr, 774 + NULL 775 + }; 776 + 777 + static ssize_t 704 778 default_min_freq_mhz_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 705 779 { 706 780 struct intel_gt *gt = kobj_to_gt(kobj->parent); ··· 796 722 static struct kobj_attribute default_max_freq_mhz = 797 723 __ATTR(rps_max_freq_mhz, 0444, default_max_freq_mhz_show, NULL); 798 724 725 + static ssize_t 726 + default_rps_up_threshold_pct_show(struct kobject *kobj, 727 + struct kobj_attribute *attr, 728 + char *buf) 729 + { 730 + struct intel_gt *gt = kobj_to_gt(kobj->parent); 731 + 732 + return sysfs_emit(buf, "%u\n", gt->defaults.rps_up_threshold); 733 + } 734 + 735 + static struct kobj_attribute default_rps_up_threshold_pct = 736 + __ATTR(rps_up_threshold_pct, 0444, default_rps_up_threshold_pct_show, NULL); 737 + 738 + static ssize_t 739 + default_rps_down_threshold_pct_show(struct kobject *kobj, 740 + struct kobj_attribute *attr, 741 + char *buf) 742 + { 743 + struct intel_gt *gt = kobj_to_gt(kobj->parent); 744 + 745 + return sysfs_emit(buf, "%u\n", gt->defaults.rps_down_threshold); 746 + } 747 + 748 + static struct kobj_attribute default_rps_down_threshold_pct = 749 + __ATTR(rps_down_threshold_pct, 0444, default_rps_down_threshold_pct_show, NULL); 750 + 799 751 static const struct attribute * const rps_defaults_attrs[] = { 800 752 &default_min_freq_mhz.attr, 801 753 &default_max_freq_mhz.attr, 754 + &default_rps_up_threshold_pct.attr, 755 + &default_rps_down_threshold_pct.attr, 802 756 NULL 803 757 }; 804 758 ··· 853 751 854 752 if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) 855 753 ret = sysfs_create_file(kobj, vlv_attr); 754 + 755 + if (is_object_gt(kobj) && !intel_uc_uses_guc_slpc(&gt->uc)) { 756 + ret = sysfs_create_files(kobj, gen6_gt_rps_attrs); 757 + if (ret) 758 + return ret; 759 + } 856 760 857 761 return ret; 858 762 }