mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-13 14:24:11 +08:00
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: Thomas Gleixner <tglx@linutronix.de> Tested-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
5870506920
commit
b4005e9278
@ -189,14 +189,13 @@ struct rapl_package {
|
||||
unsigned int time_unit;
|
||||
struct rapl_domain *domains; /* array of domains, sized at runtime */
|
||||
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
|
||||
* notify interrupt enable status.
|
||||
*/
|
||||
struct list_head plist;
|
||||
int lead_cpu; /* one active cpu per package for access */
|
||||
/* Track active cpus */
|
||||
struct cpumask cpumask;
|
||||
};
|
||||
|
||||
struct rapl_defaults {
|
||||
@ -1432,19 +1431,17 @@ static void rapl_remove_package(struct rapl_package *rp)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int ret, phy_package_id;
|
||||
int ret;
|
||||
|
||||
phy_package_id = topology_physical_package_id(cpu);
|
||||
rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
|
||||
if (!rp)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* add the new package to the list */
|
||||
rp->id = phy_package_id;
|
||||
rp->nr_cpus = 1;
|
||||
rp->id = pkgid;
|
||||
rp->lead_cpu = cpu;
|
||||
|
||||
/* check if the package contains valid domains */
|
||||
@ -1457,14 +1454,13 @@ static int rapl_add_package(int cpu)
|
||||
if (!ret) {
|
||||
INIT_LIST_HEAD(&rp->plist);
|
||||
list_add(&rp->plist, &rapl_packages);
|
||||
return 0;
|
||||
return rp;
|
||||
}
|
||||
|
||||
err_free_package:
|
||||
kfree(rp->domains);
|
||||
kfree(rp);
|
||||
|
||||
return ret;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/* Handles CPU hotplug on multi-socket systems.
|
||||
@ -1476,42 +1472,35 @@ err_free_package:
|
||||
*/
|
||||
static int rapl_cpu_online(unsigned int cpu)
|
||||
{
|
||||
int pkgid = topology_physical_package_id(cpu);
|
||||
struct rapl_package *rp;
|
||||
int phy_package_id;
|
||||
|
||||
phy_package_id = topology_physical_package_id(cpu);
|
||||
|
||||
rp = find_package_by_id(phy_package_id);
|
||||
if (rp) {
|
||||
rp->nr_cpus++;
|
||||
return 0;
|
||||
rp = find_package_by_id(pkgid);
|
||||
if (!rp) {
|
||||
rp = rapl_add_package(cpu, pkgid);
|
||||
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)
|
||||
{
|
||||
int phy_package_id;
|
||||
int pkgid = topology_physical_package_id(cpu);
|
||||
struct rapl_package *rp;
|
||||
int lead_cpu;
|
||||
|
||||
phy_package_id = topology_physical_package_id(cpu);
|
||||
rp = find_package_by_id(phy_package_id);
|
||||
rp = find_package_by_id(pkgid);
|
||||
if (!rp)
|
||||
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);
|
||||
} else if (cpu == rp->lead_cpu) {
|
||||
/* choose another active cpu in the package */
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if (rp->lead_cpu == cpu)
|
||||
rp->lead_cpu = lead_cpu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user