diff options
Diffstat (limited to 'drivers/hwmon/coretemp.c')
| -rw-r--r-- | drivers/hwmon/coretemp.c | 221 | 
1 files changed, 53 insertions, 168 deletions
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 411257676133..932383786642 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -36,17 +36,25 @@  #include <linux/cpu.h>  #include <linux/pci.h>  #include <linux/smp.h> +#include <linux/moduleparam.h>  #include <asm/msr.h>  #include <asm/processor.h>  #define DRVNAME	"coretemp" +/* + * force_tjmax only matters when TjMax can't be read from the CPU itself. + * When set, it replaces the driver's suboptimal heuristic. + */ +static int force_tjmax; +module_param_named(tjmax, force_tjmax, int, 0444); +MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); +  #define BASE_SYSFS_ATTR_NO	2	/* Sysfs Base attr no for coretemp */  #define NUM_REAL_CORES		16	/* Number of Real cores per cpu */  #define CORETEMP_NAME_LENGTH	17	/* String Length of attrs */  #define MAX_CORE_ATTRS		4	/* Maximum no of basic attrs */ -#define MAX_THRESH_ATTRS	3	/* Maximum no of Threshold attrs */ -#define TOTAL_ATTRS		(MAX_CORE_ATTRS + MAX_THRESH_ATTRS) +#define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)  #define MAX_CORE_DATA		(NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)  #ifdef CONFIG_SMP @@ -69,8 +77,6 @@   *		This value is passed as "id" field to rdmsr/wrmsr functions.   * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS,   *		from where the temperature values should be read. - * @intrpt_reg: One of IA32_THERM_INTERRUPT or IA32_PACKAGE_THERM_INTERRUPT, - *		from where the thresholds are read.   * @attr_size:  Total number of pre-core attrs displayed in the sysfs.   * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.   *		Otherwise, temp_data holds coretemp data. @@ -79,13 +85,11 @@  struct temp_data {  	int temp;  	int ttarget; -	int tmin;  	int tjmax;  	unsigned long last_updated;  	unsigned int cpu;  	u32 cpu_core_id;  	u32 status_reg; -	u32 intrpt_reg;  	int attr_size;  	bool is_pkg_data;  	bool valid; @@ -143,19 +147,6 @@ static ssize_t show_crit_alarm(struct device *dev,  	return sprintf(buf, "%d\n", (eax >> 5) & 1);  } -static ssize_t show_max_alarm(struct device *dev, -				struct device_attribute *devattr, char *buf) -{ -	u32 eax, edx; -	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -	struct platform_data *pdata = dev_get_drvdata(dev); -	struct temp_data *tdata = pdata->core_data[attr->index]; - -	rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); - -	return sprintf(buf, "%d\n", !!(eax & THERM_STATUS_THRESHOLD1)); -} -  static ssize_t show_tjmax(struct device *dev,  			struct device_attribute *devattr, char *buf)  { @@ -174,83 +165,6 @@ static ssize_t show_ttarget(struct device *dev,  	return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);  } -static ssize_t store_ttarget(struct device *dev, -				struct device_attribute *devattr, -				const char *buf, size_t count) -{ -	struct platform_data *pdata = dev_get_drvdata(dev); -	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -	struct temp_data *tdata = pdata->core_data[attr->index]; -	u32 eax, edx; -	unsigned long val; -	int diff; - -	if (strict_strtoul(buf, 10, &val)) -		return -EINVAL; - -	/* -	 * THERM_MASK_THRESHOLD1 is 7 bits wide. Values are entered in terms -	 * of milli degree celsius. Hence don't accept val > (127 * 1000) -	 */ -	if (val > tdata->tjmax || val > 127000) -		return -EINVAL; - -	diff = (tdata->tjmax - val) / 1000; - -	mutex_lock(&tdata->update_lock); -	rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); -	eax = (eax & ~THERM_MASK_THRESHOLD1) | -				(diff << THERM_SHIFT_THRESHOLD1); -	wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); -	tdata->ttarget = val; -	mutex_unlock(&tdata->update_lock); - -	return count; -} - -static ssize_t show_tmin(struct device *dev, -			struct device_attribute *devattr, char *buf) -{ -	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -	struct platform_data *pdata = dev_get_drvdata(dev); - -	return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tmin); -} - -static ssize_t store_tmin(struct device *dev, -				struct device_attribute *devattr, -				const char *buf, size_t count) -{ -	struct platform_data *pdata = dev_get_drvdata(dev); -	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); -	struct temp_data *tdata = pdata->core_data[attr->index]; -	u32 eax, edx; -	unsigned long val; -	int diff; - -	if (strict_strtoul(buf, 10, &val)) -		return -EINVAL; - -	/* -	 * THERM_MASK_THRESHOLD0 is 7 bits wide. Values are entered in terms -	 * of milli degree celsius. Hence don't accept val > (127 * 1000) -	 */ -	if (val > tdata->tjmax || val > 127000) -		return -EINVAL; - -	diff = (tdata->tjmax - val) / 1000; - -	mutex_lock(&tdata->update_lock); -	rdmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, &eax, &edx); -	eax = (eax & ~THERM_MASK_THRESHOLD0) | -				(diff << THERM_SHIFT_THRESHOLD0); -	wrmsr_on_cpu(tdata->cpu, tdata->intrpt_reg, eax, edx); -	tdata->tmin = val; -	mutex_unlock(&tdata->update_lock); - -	return count; -} -  static ssize_t show_temp(struct device *dev,  			struct device_attribute *devattr, char *buf)  { @@ -374,7 +288,6 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  { -	/* The 100C is default for both mobile and non mobile CPUs */  	int err;  	u32 eax, edx;  	u32 val; @@ -385,7 +298,8 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  	 */  	err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);  	if (err) { -		dev_warn(dev, "Unable to read TjMax from CPU.\n"); +		if (c->x86_model > 0xe && c->x86_model != 0x1c) +			dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);  	} else {  		val = (eax >> 16) & 0xff;  		/* @@ -393,11 +307,17 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)  		 * will be used  		 */  		if (val) { -			dev_info(dev, "TjMax is %d C.\n", val); +			dev_dbg(dev, "TjMax is %d degrees C\n", val);  			return val * 1000;  		}  	} +	if (force_tjmax) { +		dev_notice(dev, "TjMax forced to %d degrees C by user\n", +			   force_tjmax); +		return force_tjmax * 1000; +	} +  	/*  	 * An assumption is made for early CPUs and unreadable MSR.  	 * NOTE: the calculated value may not be correct. @@ -414,21 +334,6 @@ static void __devinit get_ucode_rev_on_cpu(void *edx)  	rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);  } -static int get_pkg_tjmax(unsigned int cpu, struct device *dev) -{ -	int err; -	u32 eax, edx, val; - -	err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); -	if (!err) { -		val = (eax >> 16) & 0xff; -		if (val) -			return val * 1000; -	} -	dev_warn(dev, "Unable to read Pkg-TjMax from CPU:%u\n", cpu); -	return 100000; /* Default TjMax: 100 degree celsius */ -} -  static int create_name_attr(struct platform_data *pdata, struct device *dev)  {  	sysfs_attr_init(&pdata->name_attr.attr); @@ -442,19 +347,14 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,  				int attr_no)  {  	int err, i; -	static ssize_t (*rd_ptr[TOTAL_ATTRS]) (struct device *dev, +	static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,  			struct device_attribute *devattr, char *buf) = {  			show_label, show_crit_alarm, show_temp, show_tjmax, -			show_max_alarm, show_ttarget, show_tmin }; -	static ssize_t (*rw_ptr[TOTAL_ATTRS]) (struct device *dev, -			struct device_attribute *devattr, const char *buf, -			size_t count) = { NULL, NULL, NULL, NULL, NULL, -					store_ttarget, store_tmin }; -	static const char *names[TOTAL_ATTRS] = { +			show_ttarget }; +	static const char *const names[TOTAL_ATTRS] = {  					"temp%d_label", "temp%d_crit_alarm",  					"temp%d_input", "temp%d_crit", -					"temp%d_max_alarm", "temp%d_max", -					"temp%d_max_hyst" }; +					"temp%d_max" };  	for (i = 0; i < tdata->attr_size; i++) {  		snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], @@ -462,10 +362,6 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,  		sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);  		tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];  		tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; -		if (rw_ptr[i]) { -			tdata->sd_attrs[i].dev_attr.attr.mode |= S_IWUSR; -			tdata->sd_attrs[i].dev_attr.store = rw_ptr[i]; -		}  		tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];  		tdata->sd_attrs[i].index = attr_no;  		err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); @@ -481,9 +377,9 @@ exit_free:  } -static int __devinit chk_ucode_version(struct platform_device *pdev) +static int __cpuinit chk_ucode_version(unsigned int cpu)  { -	struct cpuinfo_x86 *c = &cpu_data(pdev->id); +	struct cpuinfo_x86 *c = &cpu_data(cpu);  	int err;  	u32 edx; @@ -494,17 +390,15 @@ static int __devinit chk_ucode_version(struct platform_device *pdev)  	 */  	if (c->x86_model == 0xe && c->x86_mask < 0xc) {  		/* check for microcode update */ -		err = smp_call_function_single(pdev->id, get_ucode_rev_on_cpu, +		err = smp_call_function_single(cpu, get_ucode_rev_on_cpu,  					       &edx, 1);  		if (err) { -			dev_err(&pdev->dev, -				"Cannot determine microcode revision of " -				"CPU#%u (%d)!\n", pdev->id, err); +			pr_err("Cannot determine microcode revision of " +			       "CPU#%u (%d)!\n", cpu, err);  			return -ENODEV;  		} else if (edx < 0x39) { -			dev_err(&pdev->dev, -				"Errata AE18 not fixed, update BIOS or " -				"microcode of the CPU!\n"); +			pr_err("Errata AE18 not fixed, update BIOS or " +			       "microcode of the CPU!\n");  			return -ENODEV;  		}  	} @@ -538,8 +432,6 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)  	tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :  							MSR_IA32_THERM_STATUS; -	tdata->intrpt_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_INTERRUPT : -						MSR_IA32_THERM_INTERRUPT;  	tdata->is_pkg_data = pkg_flag;  	tdata->cpu = cpu;  	tdata->cpu_core_id = TO_CORE_ID(cpu); @@ -548,11 +440,11 @@ static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag)  	return tdata;  } -static int create_core_data(struct platform_data *pdata, -				struct platform_device *pdev, +static int create_core_data(struct platform_device *pdev,  				unsigned int cpu, int pkg_flag)  {  	struct temp_data *tdata; +	struct platform_data *pdata = platform_get_drvdata(pdev);  	struct cpuinfo_x86 *c = &cpu_data(cpu);  	u32 eax, edx;  	int err, attr_no; @@ -588,25 +480,21 @@ static int create_core_data(struct platform_data *pdata,  		goto exit_free;  	/* We can access status register. Get Critical Temperature */ -	if (pkg_flag) -		tdata->tjmax = get_pkg_tjmax(pdev->id, &pdev->dev); -	else -		tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); +	tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);  	/* -	 * Test if we can access the intrpt register. If so, increase the -	 * 'size' enough to have ttarget/tmin/max_alarm interfaces. -	 * Initialize ttarget with bits 16:22 of MSR_IA32_THERM_INTERRUPT +	 * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. +	 * The target temperature is available on older CPUs but not in this +	 * register. Atoms don't have the register at all.  	 */ -	err = rdmsr_safe_on_cpu(cpu, tdata->intrpt_reg, &eax, &edx); -	if (!err) { -		tdata->attr_size += MAX_THRESH_ATTRS; -		tdata->tmin = tdata->tjmax - -			      ((eax & THERM_MASK_THRESHOLD0) >> -			       THERM_SHIFT_THRESHOLD0) * 1000; -		tdata->ttarget = tdata->tjmax - -				 ((eax & THERM_MASK_THRESHOLD1) >> -				  THERM_SHIFT_THRESHOLD1) * 1000; +	if (c->x86_model > 0xe && c->x86_model != 0x1c) { +		err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, +					&eax, &edx); +		if (!err) { +			tdata->ttarget +			  = tdata->tjmax - ((eax >> 8) & 0xff) * 1000; +			tdata->attr_size++; +		}  	}  	pdata->core_data[attr_no] = tdata; @@ -618,22 +506,20 @@ static int create_core_data(struct platform_data *pdata,  	return 0;  exit_free: +	pdata->core_data[attr_no] = NULL;  	kfree(tdata);  	return err;  }  static void coretemp_add_core(unsigned int cpu, int pkg_flag)  { -	struct platform_data *pdata;  	struct platform_device *pdev = coretemp_get_pdev(cpu);  	int err;  	if (!pdev)  		return; -	pdata = platform_get_drvdata(pdev); - -	err = create_core_data(pdata, pdev, cpu, pkg_flag); +	err = create_core_data(pdev, cpu, pkg_flag);  	if (err)  		dev_err(&pdev->dev, "Adding Core %u failed\n", cpu);  } @@ -657,11 +543,6 @@ static int __devinit coretemp_probe(struct platform_device *pdev)  	struct platform_data *pdata;  	int err; -	/* Check the microcode version of the CPU */ -	err = chk_ucode_version(pdev); -	if (err) -		return err; -  	/* Initialize the per-package data structures */  	pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL);  	if (!pdata) @@ -671,7 +552,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev)  	if (err)  		goto exit_free; -	pdata->phys_proc_id = TO_PHYS_ID(pdev->id); +	pdata->phys_proc_id = pdev->id;  	platform_set_drvdata(pdev, pdata);  	pdata->hwmon_dev = hwmon_device_register(&pdev->dev); @@ -723,7 +604,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)  	mutex_lock(&pdev_list_mutex); -	pdev = platform_device_alloc(DRVNAME, cpu); +	pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));  	if (!pdev) {  		err = -ENOMEM;  		pr_err("Device allocation failed\n"); @@ -743,7 +624,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)  	}  	pdev_entry->pdev = pdev; -	pdev_entry->phys_proc_id = TO_PHYS_ID(cpu); +	pdev_entry->phys_proc_id = pdev->id;  	list_add_tail(&pdev_entry->list, &pdev_list);  	mutex_unlock(&pdev_list_mutex); @@ -804,6 +685,10 @@ static void __cpuinit get_core_online(unsigned int cpu)  		return;  	if (!pdev) { +		/* Check the microcode version of the CPU */ +		if (chk_ucode_version(cpu)) +			return; +  		/*  		 * Alright, we have DTS support.  		 * We are bringing the _first_ core in this pkg  |