diff options
Diffstat (limited to 'drivers/powercap/intel_rapl.c')
-rw-r--r-- | drivers/powercap/intel_rapl.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 97b5e4ee1ca4..63d4033eb683 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c | |||
@@ -73,7 +73,7 @@ | |||
73 | 73 | ||
74 | #define TIME_WINDOW_MAX_MSEC 40000 | 74 | #define TIME_WINDOW_MAX_MSEC 40000 |
75 | #define TIME_WINDOW_MIN_MSEC 250 | 75 | #define TIME_WINDOW_MIN_MSEC 250 |
76 | 76 | #define ENERGY_UNIT_SCALE 1000 /* scale from driver unit to powercap unit */ | |
77 | enum unit_type { | 77 | enum unit_type { |
78 | ARBITRARY_UNIT, /* no translation */ | 78 | ARBITRARY_UNIT, /* no translation */ |
79 | POWER_UNIT, | 79 | POWER_UNIT, |
@@ -158,6 +158,7 @@ struct rapl_domain { | |||
158 | struct rapl_power_limit rpl[NR_POWER_LIMITS]; | 158 | struct rapl_power_limit rpl[NR_POWER_LIMITS]; |
159 | u64 attr_map; /* track capabilities */ | 159 | u64 attr_map; /* track capabilities */ |
160 | unsigned int state; | 160 | unsigned int state; |
161 | unsigned int domain_energy_unit; | ||
161 | int package_id; | 162 | int package_id; |
162 | }; | 163 | }; |
163 | #define power_zone_to_rapl_domain(_zone) \ | 164 | #define power_zone_to_rapl_domain(_zone) \ |
@@ -190,6 +191,7 @@ struct rapl_defaults { | |||
190 | void (*set_floor_freq)(struct rapl_domain *rd, bool mode); | 191 | void (*set_floor_freq)(struct rapl_domain *rd, bool mode); |
191 | u64 (*compute_time_window)(struct rapl_package *rp, u64 val, | 192 | u64 (*compute_time_window)(struct rapl_package *rp, u64 val, |
192 | bool to_raw); | 193 | bool to_raw); |
194 | unsigned int dram_domain_energy_unit; | ||
193 | }; | 195 | }; |
194 | static struct rapl_defaults *rapl_defaults; | 196 | static struct rapl_defaults *rapl_defaults; |
195 | 197 | ||
@@ -227,7 +229,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd, | |||
227 | static int rapl_write_data_raw(struct rapl_domain *rd, | 229 | static int rapl_write_data_raw(struct rapl_domain *rd, |
228 | enum rapl_primitives prim, | 230 | enum rapl_primitives prim, |
229 | unsigned long long value); | 231 | unsigned long long value); |
230 | static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, | 232 | static u64 rapl_unit_xlate(struct rapl_domain *rd, int package, |
233 | enum unit_type type, u64 value, | ||
231 | int to_raw); | 234 | int to_raw); |
232 | static void package_power_limit_irq_save(int package_id); | 235 | static void package_power_limit_irq_save(int package_id); |
233 | 236 | ||
@@ -305,7 +308,9 @@ static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw) | |||
305 | 308 | ||
306 | static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) | 309 | static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy) |
307 | { | 310 | { |
308 | *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); | 311 | struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev); |
312 | |||
313 | *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0); | ||
309 | return 0; | 314 | return 0; |
310 | } | 315 | } |
311 | 316 | ||
@@ -639,6 +644,11 @@ static void rapl_init_domains(struct rapl_package *rp) | |||
639 | rd->msrs[4] = MSR_DRAM_POWER_INFO; | 644 | rd->msrs[4] = MSR_DRAM_POWER_INFO; |
640 | rd->rpl[0].prim_id = PL1_ENABLE; | 645 | rd->rpl[0].prim_id = PL1_ENABLE; |
641 | rd->rpl[0].name = pl1_name; | 646 | rd->rpl[0].name = pl1_name; |
647 | rd->domain_energy_unit = | ||
648 | rapl_defaults->dram_domain_energy_unit; | ||
649 | if (rd->domain_energy_unit) | ||
650 | pr_info("DRAM domain energy unit %dpj\n", | ||
651 | rd->domain_energy_unit); | ||
642 | break; | 652 | break; |
643 | } | 653 | } |
644 | if (mask) { | 654 | if (mask) { |
@@ -648,11 +658,13 @@ static void rapl_init_domains(struct rapl_package *rp) | |||
648 | } | 658 | } |
649 | } | 659 | } |
650 | 660 | ||
651 | static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, | 661 | static u64 rapl_unit_xlate(struct rapl_domain *rd, int package, |
662 | enum unit_type type, u64 value, | ||
652 | int to_raw) | 663 | int to_raw) |
653 | { | 664 | { |
654 | u64 units = 1; | 665 | u64 units = 1; |
655 | struct rapl_package *rp; | 666 | struct rapl_package *rp; |
667 | u64 scale = 1; | ||
656 | 668 | ||
657 | rp = find_package_by_id(package); | 669 | rp = find_package_by_id(package); |
658 | if (!rp) | 670 | if (!rp) |
@@ -663,7 +675,12 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, | |||
663 | units = rp->power_unit; | 675 | units = rp->power_unit; |
664 | break; | 676 | break; |
665 | case ENERGY_UNIT: | 677 | case ENERGY_UNIT: |
666 | units = rp->energy_unit; | 678 | scale = ENERGY_UNIT_SCALE; |
679 | /* per domain unit takes precedence */ | ||
680 | if (rd && rd->domain_energy_unit) | ||
681 | units = rd->domain_energy_unit; | ||
682 | else | ||
683 | units = rp->energy_unit; | ||
667 | break; | 684 | break; |
668 | case TIME_UNIT: | 685 | case TIME_UNIT: |
669 | return rapl_defaults->compute_time_window(rp, value, to_raw); | 686 | return rapl_defaults->compute_time_window(rp, value, to_raw); |
@@ -673,11 +690,11 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value, | |||
673 | }; | 690 | }; |
674 | 691 | ||
675 | if (to_raw) | 692 | if (to_raw) |
676 | return div64_u64(value, units); | 693 | return div64_u64(value, units) * scale; |
677 | 694 | ||
678 | value *= units; | 695 | value *= units; |
679 | 696 | ||
680 | return value; | 697 | return div64_u64(value, scale); |
681 | } | 698 | } |
682 | 699 | ||
683 | /* in the order of enum rapl_primitives */ | 700 | /* in the order of enum rapl_primitives */ |
@@ -773,7 +790,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd, | |||
773 | final = value & rp->mask; | 790 | final = value & rp->mask; |
774 | final = final >> rp->shift; | 791 | final = final >> rp->shift; |
775 | if (xlate) | 792 | if (xlate) |
776 | *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0); | 793 | *data = rapl_unit_xlate(rd, rd->package_id, rp->unit, final, 0); |
777 | else | 794 | else |
778 | *data = final; | 795 | *data = final; |
779 | 796 | ||
@@ -799,7 +816,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd, | |||
799 | "failed to read msr 0x%x on cpu %d\n", msr, cpu); | 816 | "failed to read msr 0x%x on cpu %d\n", msr, cpu); |
800 | return -EIO; | 817 | return -EIO; |
801 | } | 818 | } |
802 | value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1); | 819 | value = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1); |
803 | msr_val &= ~rp->mask; | 820 | msr_val &= ~rp->mask; |
804 | msr_val |= value << rp->shift; | 821 | msr_val |= value << rp->shift; |
805 | if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) { | 822 | if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) { |
@@ -818,7 +835,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd, | |||
818 | * calculate units differ on different CPUs. | 835 | * calculate units differ on different CPUs. |
819 | * We convert the units to below format based on CPUs. | 836 | * We convert the units to below format based on CPUs. |
820 | * i.e. | 837 | * i.e. |
821 | * energy unit: microJoules : Represented in microJoules by default | 838 | * energy unit: picoJoules : Represented in picoJoules by default |
822 | * power unit : microWatts : Represented in milliWatts by default | 839 | * power unit : microWatts : Represented in milliWatts by default |
823 | * time unit : microseconds: Represented in seconds by default | 840 | * time unit : microseconds: Represented in seconds by default |
824 | */ | 841 | */ |
@@ -834,7 +851,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu) | |||
834 | } | 851 | } |
835 | 852 | ||
836 | value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; | 853 | value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; |
837 | rp->energy_unit = 1000000 / (1 << value); | 854 | rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value); |
838 | 855 | ||
839 | value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; | 856 | value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; |
840 | rp->power_unit = 1000000 / (1 << value); | 857 | rp->power_unit = 1000000 / (1 << value); |
@@ -842,7 +859,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu) | |||
842 | value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; | 859 | value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; |
843 | rp->time_unit = 1000000 / (1 << value); | 860 | rp->time_unit = 1000000 / (1 << value); |
844 | 861 | ||
845 | pr_debug("Core CPU package %d energy=%duJ, time=%dus, power=%duW\n", | 862 | pr_debug("Core CPU package %d energy=%dpJ, time=%dus, power=%duW\n", |
846 | rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); | 863 | rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); |
847 | 864 | ||
848 | return 0; | 865 | return 0; |
@@ -859,7 +876,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu) | |||
859 | return -ENODEV; | 876 | return -ENODEV; |
860 | } | 877 | } |
861 | value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; | 878 | value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET; |
862 | rp->energy_unit = 1 << value; | 879 | rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value; |
863 | 880 | ||
864 | value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; | 881 | value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET; |
865 | rp->power_unit = (1 << value) * 1000; | 882 | rp->power_unit = (1 << value) * 1000; |
@@ -867,7 +884,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu) | |||
867 | value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; | 884 | value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; |
868 | rp->time_unit = 1000000 / (1 << value); | 885 | rp->time_unit = 1000000 / (1 << value); |
869 | 886 | ||
870 | pr_debug("Atom package %d energy=%duJ, time=%dus, power=%duW\n", | 887 | pr_debug("Atom package %d energy=%dpJ, time=%dus, power=%duW\n", |
871 | rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); | 888 | rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); |
872 | 889 | ||
873 | return 0; | 890 | return 0; |
@@ -1017,6 +1034,13 @@ static const struct rapl_defaults rapl_defaults_core = { | |||
1017 | .compute_time_window = rapl_compute_time_window_core, | 1034 | .compute_time_window = rapl_compute_time_window_core, |
1018 | }; | 1035 | }; |
1019 | 1036 | ||
1037 | static const struct rapl_defaults rapl_defaults_hsw_server = { | ||
1038 | .check_unit = rapl_check_unit_core, | ||
1039 | .set_floor_freq = set_floor_freq_default, | ||
1040 | .compute_time_window = rapl_compute_time_window_core, | ||
1041 | .dram_domain_energy_unit = 15300, | ||
1042 | }; | ||
1043 | |||
1020 | static const struct rapl_defaults rapl_defaults_atom = { | 1044 | static const struct rapl_defaults rapl_defaults_atom = { |
1021 | .check_unit = rapl_check_unit_atom, | 1045 | .check_unit = rapl_check_unit_atom, |
1022 | .set_floor_freq = set_floor_freq_atom, | 1046 | .set_floor_freq = set_floor_freq_atom, |
@@ -1037,7 +1061,7 @@ static const struct x86_cpu_id rapl_ids[] = { | |||
1037 | RAPL_CPU(0x3a, rapl_defaults_core),/* Ivy Bridge */ | 1061 | RAPL_CPU(0x3a, rapl_defaults_core),/* Ivy Bridge */ |
1038 | RAPL_CPU(0x3c, rapl_defaults_core),/* Haswell */ | 1062 | RAPL_CPU(0x3c, rapl_defaults_core),/* Haswell */ |
1039 | RAPL_CPU(0x3d, rapl_defaults_core),/* Broadwell */ | 1063 | RAPL_CPU(0x3d, rapl_defaults_core),/* Broadwell */ |
1040 | RAPL_CPU(0x3f, rapl_defaults_core),/* Haswell */ | 1064 | RAPL_CPU(0x3f, rapl_defaults_hsw_server),/* Haswell servers */ |
1041 | RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */ | 1065 | RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */ |
1042 | RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */ | 1066 | RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */ |
1043 | RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */ | 1067 | RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */ |