Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 84143
b: refs/heads/master
c: d9460fd
h: refs/heads/master
i:
  84141: 920c7a1
  84139: 516a874
  84135: 44188c1
  84127: 554afde
v: v3
  • Loading branch information
Zhang Rui authored and Len Brown committed Feb 2, 2008
1 parent c4aa4d2 commit 40fc190
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 05a83d972293f39a66bc2aa409a5e7996bba585d
refs/heads/master: d9460fd227ed2ce52941b6a12ad4de05c195f6aa
23 changes: 23 additions & 0 deletions trunk/drivers/acpi/processor_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,24 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)

acpi_processor_power_init(pr, device);

pr->cdev = thermal_cooling_device_register("Processor", device,
&processor_cooling_ops);
if (pr->cdev)
printk(KERN_INFO PREFIX
"%s is registered as cooling_device%d\n",
device->dev.bus_id, pr->cdev->id);
else
goto end;

result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj,
"thermal_cooling");
if (result)
return result;
result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj,
"device");
if (result)
return result;

if (pr->flags.throttling) {
printk(KERN_INFO PREFIX "%s [%s] (supports",
acpi_device_name(device), acpi_device_bid(device));
Expand Down Expand Up @@ -791,6 +809,11 @@ static int acpi_processor_remove(struct acpi_device *device, int type)

acpi_processor_remove_fs(device);

sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
sysfs_remove_link(&pr->cdev->device.kobj, "device");
thermal_cooling_device_unregister(pr->cdev);
pr->cdev = NULL;

processors[pr->id] = NULL;

kfree(pr);
Expand Down
134 changes: 129 additions & 5 deletions trunk/drivers/acpi/processor_thermal.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <linux/cpufreq.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/sysdev.h>

#include <asm/uaccess.h>

Expand Down Expand Up @@ -93,6 +94,9 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
* _any_ cpufreq driver and not only the acpi-cpufreq driver.
*/

#define CPUFREQ_THERMAL_MIN_STEP 0
#define CPUFREQ_THERMAL_MAX_STEP 3

static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS];
static unsigned int acpi_thermal_cpufreq_is_init = 0;

Expand All @@ -109,8 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return -ENODEV;

if (cpufreq_thermal_reduction_pctg[cpu] < 60) {
cpufreq_thermal_reduction_pctg[cpu] += 20;
if (cpufreq_thermal_reduction_pctg[cpu] <
CPUFREQ_THERMAL_MAX_STEP) {
cpufreq_thermal_reduction_pctg[cpu]++;
cpufreq_update_policy(cpu);
return 0;
}
Expand All @@ -123,8 +128,9 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return -ENODEV;

if (cpufreq_thermal_reduction_pctg[cpu] > 20)
cpufreq_thermal_reduction_pctg[cpu] -= 20;
if (cpufreq_thermal_reduction_pctg[cpu] >
(CPUFREQ_THERMAL_MIN_STEP + 1))
cpufreq_thermal_reduction_pctg[cpu]--;
else
cpufreq_thermal_reduction_pctg[cpu] = 0;
cpufreq_update_policy(cpu);
Expand All @@ -143,7 +149,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,

max_freq =
(policy->cpuinfo.max_freq *
(100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100;
(100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100;

cpufreq_verify_within_limits(policy, 0, max_freq);

Expand All @@ -155,6 +161,32 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = {
.notifier_call = acpi_thermal_cpufreq_notifier,
};

static int cpufreq_get_max_state(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
return 0;

return CPUFREQ_THERMAL_MAX_STEP;
}

static int cpufreq_get_cur_state(unsigned int cpu)
{
if (!cpu_has_cpufreq(cpu))
return 0;

return cpufreq_thermal_reduction_pctg[cpu];
}

static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
if (!cpu_has_cpufreq(cpu))
return 0;

cpufreq_thermal_reduction_pctg[cpu] = state;
cpufreq_update_policy(cpu);
return 0;
}

void acpi_thermal_cpufreq_init(void)
{
int i;
Expand All @@ -179,6 +211,20 @@ void acpi_thermal_cpufreq_exit(void)
}

#else /* ! CONFIG_CPU_FREQ */
static int cpufreq_get_max_state(unsigned int cpu)
{
return 0;
}

static int cpufreq_get_cur_state(unsigned int cpu)
{
return 0;
}

static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
return 0;
}

static int acpi_thermal_cpufreq_increase(unsigned int cpu)
{
Expand Down Expand Up @@ -310,6 +356,84 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr)
return 0;
}

/* thermal coolign device callbacks */
static int acpi_processor_max_state(struct acpi_processor *pr)
{
int max_state = 0;

/*
* There exists four states according to
* cpufreq_thermal_reduction_ptg. 0, 1, 2, 3
*/
max_state += cpufreq_get_max_state(pr->id);
if (pr->flags.throttling)
max_state += (pr->throttling.state_count -1);

return max_state;
}
static int
processor_get_max_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);

if (!device || !pr)
return -EINVAL;

return sprintf(buf, "%d\n", acpi_processor_max_state(pr));
}

static int
processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);
int cur_state;

if (!device || !pr)
return -EINVAL;

cur_state = cpufreq_get_cur_state(pr->id);
if (pr->flags.throttling)
cur_state += pr->throttling.state;

return sprintf(buf, "%d\n", cur_state);
}

static int
processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state)
{
struct acpi_device *device = cdev->devdata;
struct acpi_processor *pr = acpi_driver_data(device);
int result = 0;
int max_pstate;

if (!device || !pr)
return -EINVAL;

max_pstate = cpufreq_get_max_state(pr->id);

if (state > acpi_processor_max_state(pr))
return -EINVAL;

if (state <= max_pstate) {
if (pr->flags.throttling && pr->throttling.state)
result = acpi_processor_set_throttling(pr, 0);
cpufreq_set_cur_state(pr->id, state);
} else {
cpufreq_set_cur_state(pr->id, max_pstate);
result = acpi_processor_set_throttling(pr,
state - max_pstate);
}
return result;
}

struct thermal_cooling_device_ops processor_cooling_ops = {
.get_max_state = processor_get_max_state,
.get_cur_state = processor_get_cur_state,
.set_cur_state = processor_set_cur_state,
};

/* /proc interface */

static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset)
Expand Down
6 changes: 3 additions & 3 deletions trunk/include/acpi/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <linux/kernel.h>
#include <linux/cpu.h>
#include <linux/cpuidle.h>

#include <linux/thermal.h>
#include <asm/acpi.h>

#define ACPI_PROCESSOR_BUSY_METRIC 10
Expand Down Expand Up @@ -218,7 +218,7 @@ struct acpi_processor {
struct acpi_processor_performance *performance;
struct acpi_processor_throttling throttling;
struct acpi_processor_limit limit;

struct thermal_cooling_device *cdev;
/* the _PDC objects for this processor, if any */
struct acpi_object_list *pdc;
};
Expand Down Expand Up @@ -330,7 +330,7 @@ extern struct cpuidle_driver acpi_idle_driver;
/* in processor_thermal.c */
int acpi_processor_get_limit_info(struct acpi_processor *pr);
extern struct file_operations acpi_processor_limit_fops;

extern struct thermal_cooling_device_ops processor_cooling_ops;
#ifdef CONFIG_CPU_FREQ
void acpi_thermal_cpufreq_init(void);
void acpi_thermal_cpufreq_exit(void);
Expand Down

0 comments on commit 40fc190

Please sign in to comment.