aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@linux.intel.com>2016-02-24 16:31:36 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-03-08 18:26:43 -0500
commitf14a1396d8f19b6c53593045eba86d10360a0cee (patch)
tree6928de190e4775d90666fb001c3243e72e00aff7
parent16ccbd87c2e5d95f40f3b7a90f40cc2b34b89a22 (diff)
powercap/rapl: reduce ipi calls
Reduce remote CPU calls for MSR access by combining read modify write into one function. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/powercap/intel_rapl.c119
1 files changed, 85 insertions, 34 deletions
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 6c592dc71aee..a50e644ae07a 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -133,6 +133,12 @@ struct rapl_domain_data {
133 unsigned long timestamp; 133 unsigned long timestamp;
134}; 134};
135 135
136struct msrl_action {
137 u32 msr_no;
138 u64 clear_mask;
139 u64 set_mask;
140 int err;
141};
136 142
137#define DOMAIN_STATE_INACTIVE BIT(0) 143#define DOMAIN_STATE_INACTIVE BIT(0)
138#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1) 144#define DOMAIN_STATE_POWER_LIMIT_SET BIT(1)
@@ -800,35 +806,62 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
800 return 0; 806 return 0;
801} 807}
802 808
809
810static int msrl_update_safe(u32 msr_no, u64 clear_mask, u64 set_mask)
811{
812 int err;
813 u64 val;
814
815 err = rdmsrl_safe(msr_no, &val);
816 if (err)
817 goto out;
818
819 val &= ~clear_mask;
820 val |= set_mask;
821
822 err = wrmsrl_safe(msr_no, val);
823
824out:
825 return err;
826}
827
828static void msrl_update_func(void *info)
829{
830 struct msrl_action *ma = info;
831
832 ma->err = msrl_update_safe(ma->msr_no, ma->clear_mask, ma->set_mask);
833}
834
803/* Similar use of primitive info in the read counterpart */ 835/* Similar use of primitive info in the read counterpart */
804static int rapl_write_data_raw(struct rapl_domain *rd, 836static int rapl_write_data_raw(struct rapl_domain *rd,
805 enum rapl_primitives prim, 837 enum rapl_primitives prim,
806 unsigned long long value) 838 unsigned long long value)
807{ 839{
808 u64 msr_val;
809 u32 msr;
810 struct rapl_primitive_info *rp = &rpi[prim]; 840 struct rapl_primitive_info *rp = &rpi[prim];
811 int cpu; 841 int cpu;
842 u64 bits;
843 struct msrl_action ma;
844 int ret;
812 845
813 cpu = find_active_cpu_on_package(rd->package_id); 846 cpu = find_active_cpu_on_package(rd->package_id);
814 if (cpu < 0) 847 if (cpu < 0)
815 return cpu; 848 return cpu;
816 msr = rd->msrs[rp->id];
817 if (rdmsrl_safe_on_cpu(cpu, msr, &msr_val)) {
818 dev_dbg(&rd->power_zone.dev,
819 "failed to read msr 0x%x on cpu %d\n", msr, cpu);
820 return -EIO;
821 }
822 value = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1);
823 msr_val &= ~rp->mask;
824 msr_val |= value << rp->shift;
825 if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
826 dev_dbg(&rd->power_zone.dev,
827 "failed to write msr 0x%x on cpu %d\n", msr, cpu);
828 return -EIO;
829 }
830 849
831 return 0; 850 bits = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1);
851 bits |= bits << rp->shift;
852 memset(&ma, 0, sizeof(ma));
853
854 ma.msr_no = rd->msrs[rp->id];
855 ma.clear_mask = rp->mask;
856 ma.set_mask = bits;
857
858 ret = smp_call_function_single(cpu, msrl_update_func, &ma, 1);
859 if (ret)
860 WARN_ON_ONCE(ret);
861 else
862 ret = ma.err;
863
864 return ret;
832} 865}
833 866
834/* 867/*
@@ -893,6 +926,21 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
893 return 0; 926 return 0;
894} 927}
895 928
929static void power_limit_irq_save_cpu(void *info)
930{
931 u32 l, h = 0;
932 struct rapl_package *rp = (struct rapl_package *)info;
933
934 /* save the state of PLN irq mask bit before disabling it */
935 rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
936 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
937 rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
938 rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
939 }
940 l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
941 wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
942}
943
896 944
897/* REVISIT: 945/* REVISIT:
898 * When package power limit is set artificially low by RAPL, LVT 946 * When package power limit is set artificially low by RAPL, LVT
@@ -906,7 +954,6 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
906 954
907static void package_power_limit_irq_save(int package_id) 955static void package_power_limit_irq_save(int package_id)
908{ 956{
909 u32 l, h = 0;
910 int cpu; 957 int cpu;
911 struct rapl_package *rp; 958 struct rapl_package *rp;
912 959
@@ -920,20 +967,30 @@ static void package_power_limit_irq_save(int package_id)
920 cpu = find_active_cpu_on_package(package_id); 967 cpu = find_active_cpu_on_package(package_id);
921 if (cpu < 0) 968 if (cpu < 0)
922 return; 969 return;
923 /* save the state of PLN irq mask bit before disabling it */ 970 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
924 rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h); 971 return;
925 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) { 972
926 rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE; 973 smp_call_function_single(cpu, power_limit_irq_save_cpu, rp, 1);
927 rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED; 974}
928 } 975
929 l &= ~PACKAGE_THERM_INT_PLN_ENABLE; 976static void power_limit_irq_restore_cpu(void *info)
930 wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); 977{
978 u32 l, h = 0;
979 struct rapl_package *rp = (struct rapl_package *)info;
980
981 rdmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
982
983 if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
984 l |= PACKAGE_THERM_INT_PLN_ENABLE;
985 else
986 l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
987
988 wrmsr_safe(MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
931} 989}
932 990
933/* restore per package power limit interrupt enable state */ 991/* restore per package power limit interrupt enable state */
934static void package_power_limit_irq_restore(int package_id) 992static void package_power_limit_irq_restore(int package_id)
935{ 993{
936 u32 l, h;
937 int cpu; 994 int cpu;
938 struct rapl_package *rp; 995 struct rapl_package *rp;
939 996
@@ -951,14 +1008,8 @@ static void package_power_limit_irq_restore(int package_id)
951 /* irq enable state not saved, nothing to restore */ 1008 /* irq enable state not saved, nothing to restore */
952 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) 1009 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
953 return; 1010 return;
954 rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
955
956 if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
957 l |= PACKAGE_THERM_INT_PLN_ENABLE;
958 else
959 l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
960 1011
961 wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h); 1012 smp_call_function_single(cpu, power_limit_irq_restore_cpu, rp, 1);
962} 1013}
963 1014
964static void set_floor_freq_default(struct rapl_domain *rd, bool mode) 1015static void set_floor_freq_default(struct rapl_domain *rd, bool mode)