Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a582e5f5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull thermal management fixes from Zhang Rui:
 "These are fixes collected over the last week, they fixes several
  problems caused by the x86_pkg_temp_thermal introduced in 3.11-rc1.

  Specifics:

   - the x86_pkg_temp_thermal driver causes crash on systems with no
     package MSR support as there is a bug in the logic to check
     presence of DTHERM and PTS feature together.  Added a change so
     that when there is no PTS support, module doesn't get loaded.

   - fix krealloc() misuse in pkg_temp_thermal_device_add().

     If krealloc() returns NULL, it doesn't free the original.  Thus if
     we want to exit because of the krealloc() failure, we must make
     sure the original one is freed.

   - The error code path of the x86 package temperature thermal driver's
     initialization routine makes an unbalanced call to
     get_online_cpus(), which causes subsequent CPU offline operations,
     and consequently system suspend, to permanently block in
     cpu_hotplug_begin() on systems where get_core_online() returns an
     error code.

     Remove the extra get_online_cpus() to fix the problem"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
  Thermal: Fix lockup of cpu_down()
  Thermal: x86_pkg_temp: Limit number of pkg temp zones
  Thermal: x86_pkg_temp: fix krealloc() misuse in in pkg_temp_thermal_device_add()
  Thermal: x86 package temp thermal crash
parents b7371e31 ace120dc
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -54,6 +54,8 @@ MODULE_PARM_DESC(notify_delay_ms,
* is some wrong values returned by cpuid for number of thresholds.
*/
#define MAX_NUMBER_OF_TRIPS	2
/* Limit number of package temp zones */
#define MAX_PKG_TEMP_ZONE_IDS	256

struct phy_dev_entry {
	struct list_head list;
@@ -394,12 +396,16 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
	char buffer[30];
	int thres_count;
	u32 eax, ebx, ecx, edx;
	u8 *temp;

	cpuid(6, &eax, &ebx, &ecx, &edx);
	thres_count = ebx & 0x07;
	if (!thres_count)
		return -ENODEV;

	if (topology_physical_package_id(cpu) > MAX_PKG_TEMP_ZONE_IDS)
		return -ENODEV;

	thres_count = clamp_val(thres_count, 0, MAX_NUMBER_OF_TRIPS);

	err = get_tj_max(cpu, &tj_max);
@@ -417,13 +423,14 @@ static int pkg_temp_thermal_device_add(unsigned int cpu)
	spin_lock(&pkg_work_lock);
	if (topology_physical_package_id(cpu) > max_phy_id)
		max_phy_id = topology_physical_package_id(cpu);
	pkg_work_scheduled = krealloc(pkg_work_scheduled,
	temp = krealloc(pkg_work_scheduled,
			(max_phy_id+1) * sizeof(u8), GFP_ATOMIC);
	if (!pkg_work_scheduled) {
	if (!temp) {
		spin_unlock(&pkg_work_lock);
		err = -ENOMEM;
		goto err_ret_free;
	}
	pkg_work_scheduled = temp;
	pkg_work_scheduled[topology_physical_package_id(cpu)] = 0;
	spin_unlock(&pkg_work_lock);

@@ -511,7 +518,7 @@ static int get_core_online(unsigned int cpu)

	/* Check if there is already an instance for this package */
	if (!phdev) {
		if (!cpu_has(c, X86_FEATURE_DTHERM) &&
		if (!cpu_has(c, X86_FEATURE_DTHERM) ||
					!cpu_has(c, X86_FEATURE_PTS))
			return -ENODEV;
		if (pkg_temp_thermal_device_add(cpu))
@@ -562,7 +569,7 @@ static struct notifier_block pkg_temp_thermal_notifier __refdata = {
};

static const struct x86_cpu_id __initconst pkg_temp_thermal_ids[] = {
	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM },
	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_PTS },
	{}
};
MODULE_DEVICE_TABLE(x86cpu, pkg_temp_thermal_ids);
@@ -592,7 +599,6 @@ static int __init pkg_temp_thermal_init(void)
	return 0;

err_ret:
	get_online_cpus();
	for_each_online_cpu(i)
		put_core_offline(i);
	put_online_cpus();