Commit b4005e92 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Rafael J. Wysocki

powercap/intel_rapl: Track active CPUs internally

The ability of the CPU hotplug code to stop online/offline at each step
makes it necessary to track the activated CPUs in a package directly,
because outerwise a CPU offline callback can find CPUs which have already
executed the offline callback, but are not yet marked offline in the
topology mask. That could make such a CPU the package leader and in case
that CPU goes fully offline leave the package lead orphaned.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Tested-by: default avatarJacob Pan <jacob.jun.pan@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 58705069
...@@ -189,14 +189,13 @@ struct rapl_package { ...@@ -189,14 +189,13 @@ struct rapl_package {
unsigned int time_unit; unsigned int time_unit;
struct rapl_domain *domains; /* array of domains, sized at runtime */ struct rapl_domain *domains; /* array of domains, sized at runtime */
struct powercap_zone *power_zone; /* keep track of parent zone */ struct powercap_zone *power_zone; /* keep track of parent zone */
int nr_cpus; /* active cpus on the package, topology info is lost during
* cpu hotplug. so we have to track ourselves.
*/
unsigned long power_limit_irq; /* keep track of package power limit unsigned long power_limit_irq; /* keep track of package power limit
* notify interrupt enable status. * notify interrupt enable status.
*/ */
struct list_head plist; struct list_head plist;
int lead_cpu; /* one active cpu per package for access */ int lead_cpu; /* one active cpu per package for access */
/* Track active cpus */
struct cpumask cpumask;
}; };
struct rapl_defaults { struct rapl_defaults {
...@@ -1432,19 +1431,17 @@ static void rapl_remove_package(struct rapl_package *rp) ...@@ -1432,19 +1431,17 @@ static void rapl_remove_package(struct rapl_package *rp)
} }
/* called from CPU hotplug notifier, hotplug lock held */ /* called from CPU hotplug notifier, hotplug lock held */
static int rapl_add_package(int cpu) static struct rapl_package *rapl_add_package(int cpu, int pkgid)
{ {
struct rapl_package *rp; struct rapl_package *rp;
int ret, phy_package_id; int ret;
phy_package_id = topology_physical_package_id(cpu);
rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL); rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
if (!rp) if (!rp)
return -ENOMEM; return ERR_PTR(-ENOMEM);
/* add the new package to the list */ /* add the new package to the list */
rp->id = phy_package_id; rp->id = pkgid;
rp->nr_cpus = 1;
rp->lead_cpu = cpu; rp->lead_cpu = cpu;
/* check if the package contains valid domains */ /* check if the package contains valid domains */
...@@ -1457,14 +1454,13 @@ static int rapl_add_package(int cpu) ...@@ -1457,14 +1454,13 @@ static int rapl_add_package(int cpu)
if (!ret) { if (!ret) {
INIT_LIST_HEAD(&rp->plist); INIT_LIST_HEAD(&rp->plist);
list_add(&rp->plist, &rapl_packages); list_add(&rp->plist, &rapl_packages);
return 0; return rp;
} }
err_free_package: err_free_package:
kfree(rp->domains); kfree(rp->domains);
kfree(rp); kfree(rp);
return ERR_PTR(ret);
return ret;
} }
/* Handles CPU hotplug on multi-socket systems. /* Handles CPU hotplug on multi-socket systems.
...@@ -1476,42 +1472,35 @@ static int rapl_add_package(int cpu) ...@@ -1476,42 +1472,35 @@ static int rapl_add_package(int cpu)
*/ */
static int rapl_cpu_online(unsigned int cpu) static int rapl_cpu_online(unsigned int cpu)
{ {
int pkgid = topology_physical_package_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
int phy_package_id;
phy_package_id = topology_physical_package_id(cpu);
rp = find_package_by_id(phy_package_id); rp = find_package_by_id(pkgid);
if (rp) { if (!rp) {
rp->nr_cpus++; rp = rapl_add_package(cpu, pkgid);
return 0; if (IS_ERR(rp))
return PTR_ERR(rp);
} }
return rapl_add_package(cpu); cpumask_set_cpu(cpu, &rp->cpumask);
return 0;
} }
static int rapl_cpu_down_prep(unsigned int cpu) static int rapl_cpu_down_prep(unsigned int cpu)
{ {
int phy_package_id; int pkgid = topology_physical_package_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
int lead_cpu; int lead_cpu;
phy_package_id = topology_physical_package_id(cpu); rp = find_package_by_id(pkgid);
rp = find_package_by_id(phy_package_id);
if (!rp) if (!rp)
return 0; return 0;
if (--rp->nr_cpus == 0) {
cpumask_clear_cpu(cpu, &rp->cpumask);
lead_cpu = cpumask_first(&rp->cpumask);
if (lead_cpu >= nr_cpu_ids)
rapl_remove_package(rp); rapl_remove_package(rp);
} else if (cpu == rp->lead_cpu) { else if (rp->lead_cpu == cpu)
/* choose another active cpu in the package */ rp->lead_cpu = lead_cpu;
lead_cpu = cpumask_any_but(topology_core_cpumask(cpu), cpu);
if (lead_cpu < nr_cpu_ids) {
rp->lead_cpu = lead_cpu;
} else {
/* should never go here */
pr_err("no active cpu available for package %d\n",
phy_package_id);
}
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment