Skip to content

Commit

Permalink
Merge branch 'cpu-package-thermal' of .git into next
Browse files Browse the repository at this point in the history
Conflicts:
	drivers/thermal/Kconfig
	drivers/thermal/Makefile
  • Loading branch information
Zhang Rui committed Jun 17, 2013
2 parents 30072fb + 23be63f commit f157f59
Show file tree
Hide file tree
Showing 6 changed files with 769 additions and 4 deletions.
47 changes: 47 additions & 0 deletions Documentation/thermal/x86_pkg_temperature_thermal
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Kernel driver: x86_pkg_temp_thermal
===================

Supported chips:
* x86: with package level thermal management
(Verify using: CPUID.06H:EAX[bit 6] =1)

Authors: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

Reference
---
Intel® 64 and IA-32 Architectures Software Developer’s Manual (Jan, 2013):
Chapter 14.6: PACKAGE LEVEL THERMAL MANAGEMENT

Description
---------

This driver register CPU digital temperature package level sensor as a thermal
zone with maximum two user mode configurable trip points. Number of trip points
depends on the capability of the package. Once the trip point is violated,
user mode can receive notification via thermal notification mechanism and can
take any action to control temperature.


Threshold management
--------------------
Each package will register as a thermal zone under /sys/class/thermal.
Example:
/sys/class/thermal/thermal_zone1

This contains two trip points:
- trip_point_0_temp
- trip_point_1_temp

User can set any temperature between 0 to TJ-Max temperature. Temperature units
are in milli-degree Celsius. Refer to "Documentation/thermal/sysfs-api.txt" for
thermal sys-fs details.

Any value other than 0 in these trip points, can trigger thermal notifications.
Setting 0, stops sending thermal notifications.

Thermal notifications: To get kobject-uevent notifications, set the thermal zone
policy to "user_space". For example: echo -n "user_space" > policy




7 changes: 7 additions & 0 deletions arch/x86/include/asm/mce.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ void mce_log_therm_throt_event(__u64 status);
/* Interrupt Handler for core thermal thresholds */
extern int (*platform_thermal_notify)(__u64 msr_val);

/* Interrupt Handler for package thermal thresholds */
extern int (*platform_thermal_package_notify)(__u64 msr_val);

/* Callback support of rate control, return true, if
* callback has rate control */
extern bool (*platform_thermal_package_rate_control)(void);

#ifdef CONFIG_X86_THERMAL_VECTOR
extern void mcheck_intel_therm_init(void);
#else
Expand Down
63 changes: 59 additions & 4 deletions arch/x86/kernel/cpu/mcheck/therm_throt.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,24 @@ struct thermal_state {
struct _thermal_state package_power_limit;
struct _thermal_state core_thresh0;
struct _thermal_state core_thresh1;
struct _thermal_state pkg_thresh0;
struct _thermal_state pkg_thresh1;
};

/* Callback to handle core threshold interrupts */
int (*platform_thermal_notify)(__u64 msr_val);
EXPORT_SYMBOL(platform_thermal_notify);

/* Callback to handle core package threshold_interrupts */
int (*platform_thermal_package_notify)(__u64 msr_val);
EXPORT_SYMBOL_GPL(platform_thermal_package_notify);

/* Callback support of rate control, return true, if
* callback has rate control */
bool (*platform_thermal_package_rate_control)(void);
EXPORT_SYMBOL_GPL(platform_thermal_package_rate_control);


static DEFINE_PER_CPU(struct thermal_state, thermal_state);

static atomic_t therm_throt_en = ATOMIC_INIT(0);
Expand Down Expand Up @@ -203,19 +215,25 @@ static int therm_throt_process(bool new_event, int event, int level)
return 0;
}

static int thresh_event_valid(int event)
static int thresh_event_valid(int level, int event)
{
struct _thermal_state *state;
unsigned int this_cpu = smp_processor_id();
struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu);
u64 now = get_jiffies_64();

state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1;
if (level == PACKAGE_LEVEL)
state = (event == 0) ? &pstate->pkg_thresh0 :
&pstate->pkg_thresh1;
else
state = (event == 0) ? &pstate->core_thresh0 :
&pstate->core_thresh1;

if (time_before64(now, state->next_check))
return 0;

state->next_check = now + CHECK_INTERVAL;

return 1;
}

Expand Down Expand Up @@ -321,6 +339,39 @@ device_initcall(thermal_throttle_init_device);

#endif /* CONFIG_SYSFS */

static void notify_package_thresholds(__u64 msr_val)
{
bool notify_thres_0 = false;
bool notify_thres_1 = false;

if (!platform_thermal_package_notify)
return;

/* lower threshold check */
if (msr_val & THERM_LOG_THRESHOLD0)
notify_thres_0 = true;
/* higher threshold check */
if (msr_val & THERM_LOG_THRESHOLD1)
notify_thres_1 = true;

if (!notify_thres_0 && !notify_thres_1)
return;

if (platform_thermal_package_rate_control &&
platform_thermal_package_rate_control()) {
/* Rate control is implemented in callback */
platform_thermal_package_notify(msr_val);
return;
}

/* lower threshold reached */
if (notify_thres_0 && thresh_event_valid(PACKAGE_LEVEL, 0))
platform_thermal_package_notify(msr_val);
/* higher threshold reached */
if (notify_thres_1 && thresh_event_valid(PACKAGE_LEVEL, 1))
platform_thermal_package_notify(msr_val);
}

static void notify_thresholds(__u64 msr_val)
{
/* check whether the interrupt handler is defined;
Expand All @@ -330,10 +381,12 @@ static void notify_thresholds(__u64 msr_val)
return;

/* lower threshold reached */
if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0))
if ((msr_val & THERM_LOG_THRESHOLD0) &&
thresh_event_valid(CORE_LEVEL, 0))
platform_thermal_notify(msr_val);
/* higher threshold reached */
if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1))
if ((msr_val & THERM_LOG_THRESHOLD1) &&
thresh_event_valid(CORE_LEVEL, 1))
platform_thermal_notify(msr_val);
}

Expand All @@ -359,6 +412,8 @@ static void intel_thermal_interrupt(void)

if (this_cpu_has(X86_FEATURE_PTS)) {
rdmsrl(MSR_IA32_PACKAGE_THERM_STATUS, msr_val);
/* check violations of package thermal thresholds */
notify_package_thresholds(msr_val);
therm_throt_process(msr_val & PACKAGE_THERM_STATUS_PROCHOT,
THERMAL_THROTTLING_EVENT,
PACKAGE_LEVEL);
Expand Down
13 changes: 13 additions & 0 deletions drivers/thermal/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,20 @@ config INTEL_POWERCLAMP
enforce idle time which results in more package C-state residency. The
user interface is exposed via generic thermal framework.

config X86_PKG_TEMP_THERMAL
tristate "X86 package temperature thermal driver"
depends on THERMAL
depends on X86
select THERMAL_GOV_USER_SPACE
default m
help
Enable this to register CPU digital sensor for package temperature as
thermal zone. Each package will have its own thermal zone. There are
two trip points which can be set by user to get notifications via thermal
notification methods.

menu "Texas Instruments thermal drivers"
source "drivers/thermal/ti-soc-thermal/Kconfig"
endmenu

endif
1 change: 1 addition & 0 deletions drivers/thermal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o
obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o
obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o
obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
obj-$(CONFIG_X86_PKG_TEMP_THERMAL) += x86_pkg_temp_thermal.o
obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
Loading

0 comments on commit f157f59

Please sign in to comment.