Skip to content

Commit

Permalink
cpumask: convert shared_cpu_map in acpi_processor* structs to cpumask…
Browse files Browse the repository at this point in the history
…_var_t

Impact: Reduce memory usage, use new API.

This is part of an effort to reduce structure sizes for machines
configured with large NR_CPUS.  cpumask_t gets replaced by
cpumask_var_t, which is either struct cpumask[1] (small NR_CPUS) or
struct cpumask * (large NR_CPUS).

(Changes to powernow-k* by <travis>.)

Signed-off-by: Rusty Russell <[email protected]>
Signed-off-by: Mike Travis <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
rustyrussell authored and Ingo Molnar committed Jan 3, 2009
1 parent ee943a8 commit 2fdf66b
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 58 deletions.
27 changes: 24 additions & 3 deletions arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,17 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
}
}

static void free_acpi_perf_data(void)
{
unsigned int i;

/* Freeing a NULL pointer is OK, and alloc_percpu zeroes. */
for_each_possible_cpu(i)
free_cpumask_var(per_cpu_ptr(acpi_perf_data, i)
->shared_cpu_map);
free_percpu(acpi_perf_data);
}

/*
* acpi_cpufreq_early_init - initialize ACPI P-States library
*
Expand All @@ -527,13 +538,23 @@ acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
*/
static int __init acpi_cpufreq_early_init(void)
{
unsigned int i;
dprintk("acpi_cpufreq_early_init\n");

acpi_perf_data = alloc_percpu(struct acpi_processor_performance);
if (!acpi_perf_data) {
dprintk("Memory allocation error for acpi_perf_data.\n");
return -ENOMEM;
}
for_each_possible_cpu(i) {
if (!alloc_cpumask_var(&per_cpu_ptr(acpi_perf_data, i)
->shared_cpu_map, GFP_KERNEL)) {

/* Freeing a NULL pointer is OK: alloc_percpu zeroes. */
free_acpi_perf_data();
return -ENOMEM;
}
}

/* Do initialization in ACPI core */
acpi_processor_preregister_performance(acpi_perf_data);
Expand Down Expand Up @@ -604,9 +625,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
*/
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
policy->cpus = perf->shared_cpu_map;
cpumask_copy(&policy->cpus, perf->shared_cpu_map);
}
policy->related_cpus = perf->shared_cpu_map;
cpumask_copy(&policy->related_cpus, perf->shared_cpu_map);

#ifdef CONFIG_SMP
dmi_check_system(sw_any_bug_dmi_table);
Expand Down Expand Up @@ -795,7 +816,7 @@ static int __init acpi_cpufreq_init(void)

ret = cpufreq_register_driver(&acpi_cpufreq_driver);
if (ret)
free_percpu(acpi_perf_data);
free_acpi_perf_data();

return ret;
}
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/kernel/cpu/cpufreq/powernow-k7.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ static int powernow_acpi_init(void)
goto err0;
}

if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
GFP_KERNEL)) {
retval = -ENOMEM;
goto err05;
}

if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
retval = -EIO;
goto err1;
Expand Down Expand Up @@ -412,6 +418,8 @@ static int powernow_acpi_init(void)
err2:
acpi_processor_unregister_performance(acpi_processor_perf, 0);
err1:
free_cpumask_var(acpi_processor_perf->shared_cpu_map);
err05:
kfree(acpi_processor_perf);
err0:
printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
Expand Down Expand Up @@ -652,6 +660,7 @@ static int powernow_cpu_exit (struct cpufreq_policy *policy) {
#ifdef CONFIG_X86_POWERNOW_K7_ACPI
if (acpi_processor_perf) {
acpi_processor_unregister_performance(acpi_processor_perf, 0);
free_cpumask_var(acpi_processor_perf->shared_cpu_map);
kfree(acpi_processor_perf);
}
#endif
Expand Down
24 changes: 15 additions & 9 deletions arch/x86/kernel/cpu/cpufreq/powernow-k8.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned
static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
{
struct cpufreq_frequency_table *powernow_table;
int ret_val;
int ret_val = -ENODEV;

if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
dprintk("register performance failed: bad ACPI data\n");
Expand Down Expand Up @@ -815,6 +815,13 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);

if (!alloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) {
printk(KERN_ERR PFX
"unable to alloc powernow_k8_data cpumask\n");
ret_val = -ENOMEM;
goto err_out_mem;
}

return 0;

err_out_mem:
Expand All @@ -826,7 +833,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
data->acpi_data.state_count = 0;

return -ENODEV;
return ret_val;
}

static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
Expand Down Expand Up @@ -929,6 +936,7 @@ static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
{
if (data->acpi_data.state_count)
acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
free_cpumask_var(data->acpi_data.shared_cpu_map);
}

#else
Expand Down Expand Up @@ -1134,7 +1142,8 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
data->cpu = pol->cpu;
data->currpstate = HW_PSTATE_INVALID;

if (powernow_k8_cpu_init_acpi(data)) {
rc = powernow_k8_cpu_init_acpi(data);
if (rc) {
/*
* Use the PSB BIOS structure. This is only availabe on
* an UP version, and is deprecated by AMD.
Expand All @@ -1152,20 +1161,17 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
"ACPI maintainers and complain to your BIOS "
"vendor.\n");
#endif
kfree(data);
return -ENODEV;
goto err_out;
}
if (pol->cpu != 0) {
printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
"CPU other than CPU0. Complain to your BIOS "
"vendor.\n");
kfree(data);
return -ENODEV;
goto err_out;
}
rc = find_psb_table(data);
if (rc) {
kfree(data);
return -ENODEV;
goto err_out;
}
}

Expand Down
14 changes: 10 additions & 4 deletions drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,11 @@ static int acpi_processor_add(struct acpi_device *device)
if (!pr)
return -ENOMEM;

if (!alloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
kfree(pr);
return -ENOMEM;
}

pr->handle = device->handle;
strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
Expand All @@ -845,10 +850,8 @@ static int acpi_processor_remove(struct acpi_device *device, int type)

pr = acpi_driver_data(device);

if (pr->id >= nr_cpu_ids) {
kfree(pr);
return 0;
}
if (pr->id >= nr_cpu_ids)
goto free;

if (type == ACPI_BUS_REMOVAL_EJECT) {
if (acpi_processor_handle_eject(pr))
Expand All @@ -873,6 +876,9 @@ static int acpi_processor_remove(struct acpi_device *device, int type)

per_cpu(processors, pr->id) = NULL;
per_cpu(processor_device_array, pr->id) = NULL;

free:
free_cpumask_var(pr->throttling.shared_cpu_map);
kfree(pr);

return 0;
Expand Down
28 changes: 16 additions & 12 deletions drivers/acpi/processor_perflib.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,15 @@ int acpi_processor_preregister_performance(
int count, count_target;
int retval = 0;
unsigned int i, j;
cpumask_t covered_cpus;
cpumask_var_t covered_cpus;
struct acpi_processor *pr;
struct acpi_psd_package *pdomain;
struct acpi_processor *match_pr;
struct acpi_psd_package *match_pdomain;

if (!alloc_cpumask_var(&covered_cpus, GFP_KERNEL))
return -ENOMEM;

mutex_lock(&performance_mutex);

retval = 0;
Expand All @@ -617,7 +620,7 @@ int acpi_processor_preregister_performance(
}

pr->performance = percpu_ptr(performance, i);
cpu_set(i, pr->performance->shared_cpu_map);
cpumask_set_cpu(i, pr->performance->shared_cpu_map);
if (acpi_processor_get_psd(pr)) {
retval = -EINVAL;
continue;
Expand Down Expand Up @@ -650,18 +653,18 @@ int acpi_processor_preregister_performance(
}
}

cpus_clear(covered_cpus);
cpumask_clear(covered_cpus);
for_each_possible_cpu(i) {
pr = per_cpu(processors, i);
if (!pr)
continue;

if (cpu_isset(i, covered_cpus))
if (cpumask_test_cpu(i, covered_cpus))
continue;

pdomain = &(pr->performance->domain_info);
cpu_set(i, pr->performance->shared_cpu_map);
cpu_set(i, covered_cpus);
cpumask_set_cpu(i, pr->performance->shared_cpu_map);
cpumask_set_cpu(i, covered_cpus);
if (pdomain->num_processors <= 1)
continue;

Expand Down Expand Up @@ -699,8 +702,8 @@ int acpi_processor_preregister_performance(
goto err_ret;
}

cpu_set(j, covered_cpus);
cpu_set(j, pr->performance->shared_cpu_map);
cpumask_set_cpu(j, covered_cpus);
cpumask_set_cpu(j, pr->performance->shared_cpu_map);
count++;
}

Expand All @@ -718,8 +721,8 @@ int acpi_processor_preregister_performance(

match_pr->performance->shared_type =
pr->performance->shared_type;
match_pr->performance->shared_cpu_map =
pr->performance->shared_cpu_map;
cpumask_copy(match_pr->performance->shared_cpu_map,
pr->performance->shared_cpu_map);
}
}

Expand All @@ -731,14 +734,15 @@ int acpi_processor_preregister_performance(

/* Assume no coordination on any error parsing domain info */
if (retval) {
cpus_clear(pr->performance->shared_cpu_map);
cpu_set(i, pr->performance->shared_cpu_map);
cpumask_clear(pr->performance->shared_cpu_map);
cpumask_set_cpu(i, pr->performance->shared_cpu_map);
pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
}
pr->performance = NULL; /* Will be set for real in register */
}

mutex_unlock(&performance_mutex);
free_cpumask_var(covered_cpus);
return retval;
}
EXPORT_SYMBOL(acpi_processor_preregister_performance);
Expand Down
Loading

0 comments on commit 2fdf66b

Please sign in to comment.