aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/powercap/intel_rapl.c
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@linux.intel.com>2016-02-24 16:31:38 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-03-08 18:26:44 -0500
commit323ee64aa175a67fbbe744e809777d17e6fb42d7 (patch)
treea56a447915be723943f9570681d6ca52a07149e7 /drivers/powercap/intel_rapl.c
parent309557f558a6f276e364b08d916c0f644b5bd2e1 (diff)
powercap/rapl: track lead cpu per package
RAPL driver operates on MSRs that are under package/socket scope instead of core scope. However, the current code does not keep track of which CPUs are available on each package for MSR access. Therefore it has to search for an active CPU on a given package each time. This patch optimizes the package level operations by tracking a per package lead CPU during initialization and CPU hotplug. The runtime search for active CPU is avoided. Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/powercap/intel_rapl.c')
-rw-r--r--drivers/powercap/intel_rapl.c59
1 files changed, 20 insertions, 39 deletions
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 3413692c4dde..cdfd01f0adb8 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -191,6 +191,7 @@ struct rapl_package {
191 * notify interrupt enable status. 191 * notify interrupt enable status.
192 */ 192 */
193 struct list_head plist; 193 struct list_head plist;
194 int lead_cpu; /* one active cpu per package for access */
194}; 195};
195 196
196struct rapl_defaults { 197struct rapl_defaults {
@@ -267,20 +268,6 @@ static struct rapl_package *find_package_by_id(int id)
267 return NULL; 268 return NULL;
268} 269}
269 270
270/* caller to ensure CPU hotplug lock is held */
271static int find_active_cpu_on_package(int package_id)
272{
273 int i;
274
275 for_each_online_cpu(i) {
276 if (topology_physical_package_id(i) == package_id)
277 return i;
278 }
279 /* all CPUs on this package are offline */
280
281 return -ENODEV;
282}
283
284/* caller must hold cpu hotplug lock */ 271/* caller must hold cpu hotplug lock */
285static void rapl_cleanup_data(void) 272static void rapl_cleanup_data(void)
286{ 273{
@@ -761,10 +748,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
761 msr = rd->msrs[rp->id]; 748 msr = rd->msrs[rp->id];
762 if (!msr) 749 if (!msr)
763 return -EINVAL; 750 return -EINVAL;
764 /* use physical package id to look up active cpus */ 751
765 cpu = find_active_cpu_on_package(rd->rp->id); 752 cpu = rd->rp->lead_cpu;
766 if (cpu < 0)
767 return cpu;
768 753
769 /* special-case package domain, which uses a different bit*/ 754 /* special-case package domain, which uses a different bit*/
770 if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) { 755 if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) {
@@ -829,10 +814,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
829 struct msrl_action ma; 814 struct msrl_action ma;
830 int ret; 815 int ret;
831 816
832 cpu = find_active_cpu_on_package(rd->rp->id); 817 cpu = rd->rp->lead_cpu;
833 if (cpu < 0)
834 return cpu;
835
836 bits = rapl_unit_xlate(rd, rp->unit, value, 1); 818 bits = rapl_unit_xlate(rd, rp->unit, value, 1);
837 bits |= bits << rp->shift; 819 bits |= bits << rp->shift;
838 memset(&ma, 0, sizeof(ma)); 820 memset(&ma, 0, sizeof(ma));
@@ -940,18 +922,10 @@ static void power_limit_irq_save_cpu(void *info)
940 922
941static void package_power_limit_irq_save(struct rapl_package *rp) 923static void package_power_limit_irq_save(struct rapl_package *rp)
942{ 924{
943 int cpu;
944
945 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
946 return;
947
948 cpu = find_active_cpu_on_package(rp->id);
949 if (cpu < 0)
950 return;
951 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) 925 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
952 return; 926 return;
953 927
954 smp_call_function_single(cpu, power_limit_irq_save_cpu, rp, 1); 928 smp_call_function_single(rp->lead_cpu, power_limit_irq_save_cpu, rp, 1);
955} 929}
956 930
957static void power_limit_irq_restore_cpu(void *info) 931static void power_limit_irq_restore_cpu(void *info)
@@ -972,20 +946,14 @@ static void power_limit_irq_restore_cpu(void *info)
972/* restore per package power limit interrupt enable state */ 946/* restore per package power limit interrupt enable state */
973static void package_power_limit_irq_restore(struct rapl_package *rp) 947static void package_power_limit_irq_restore(struct rapl_package *rp)
974{ 948{
975 int cpu;
976
977 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN)) 949 if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
978 return; 950 return;
979 951
980 cpu = find_active_cpu_on_package(rp->id);
981 if (cpu < 0)
982 return;
983
984 /* irq enable state not saved, nothing to restore */ 952 /* irq enable state not saved, nothing to restore */
985 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) 953 if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
986 return; 954 return;
987 955
988 smp_call_function_single(cpu, power_limit_irq_restore_cpu, rp, 1); 956 smp_call_function_single(rp->lead_cpu, power_limit_irq_restore_cpu, rp, 1);
989} 957}
990 958
991static void set_floor_freq_default(struct rapl_domain *rd, bool mode) 959static void set_floor_freq_default(struct rapl_domain *rd, bool mode)
@@ -1419,7 +1387,8 @@ static int rapl_detect_topology(void)
1419 /* add the new package to the list */ 1387 /* add the new package to the list */
1420 new_package->id = phy_package_id; 1388 new_package->id = phy_package_id;
1421 new_package->nr_cpus = 1; 1389 new_package->nr_cpus = 1;
1422 1390 /* use the first active cpu of the package to access */
1391 new_package->lead_cpu = i;
1423 /* check if the package contains valid domains */ 1392 /* check if the package contains valid domains */
1424 if (rapl_detect_domains(new_package, i) || 1393 if (rapl_detect_domains(new_package, i) ||
1425 rapl_defaults->check_unit(new_package, i)) { 1394 rapl_defaults->check_unit(new_package, i)) {
@@ -1475,6 +1444,8 @@ static int rapl_add_package(int cpu)
1475 /* add the new package to the list */ 1444 /* add the new package to the list */
1476 rp->id = phy_package_id; 1445 rp->id = phy_package_id;
1477 rp->nr_cpus = 1; 1446 rp->nr_cpus = 1;
1447 rp->lead_cpu = cpu;
1448
1478 /* check if the package contains valid domains */ 1449 /* check if the package contains valid domains */
1479 if (rapl_detect_domains(rp, cpu) || 1450 if (rapl_detect_domains(rp, cpu) ||
1480 rapl_defaults->check_unit(rp, cpu)) { 1451 rapl_defaults->check_unit(rp, cpu)) {
@@ -1507,6 +1478,7 @@ static int rapl_cpu_callback(struct notifier_block *nfb,
1507 unsigned long cpu = (unsigned long)hcpu; 1478 unsigned long cpu = (unsigned long)hcpu;
1508 int phy_package_id; 1479 int phy_package_id;
1509 struct rapl_package *rp; 1480 struct rapl_package *rp;
1481 int lead_cpu;
1510 1482
1511 phy_package_id = topology_physical_package_id(cpu); 1483 phy_package_id = topology_physical_package_id(cpu);
1512 switch (action) { 1484 switch (action) {
@@ -1527,6 +1499,15 @@ static int rapl_cpu_callback(struct notifier_block *nfb,
1527 break; 1499 break;
1528 if (--rp->nr_cpus == 0) 1500 if (--rp->nr_cpus == 0)
1529 rapl_remove_package(rp); 1501 rapl_remove_package(rp);
1502 else if (cpu == rp->lead_cpu) {
1503 /* choose another active cpu in the package */
1504 lead_cpu = cpumask_any_but(topology_core_cpumask(cpu), cpu);
1505 if (lead_cpu < nr_cpu_ids)
1506 rp->lead_cpu = lead_cpu;
1507 else /* should never go here */
1508 pr_err("no active cpu available for package %d\n",
1509 phy_package_id);
1510 }
1530 } 1511 }
1531 1512
1532 return NOTIFY_OK; 1513 return NOTIFY_OK;