Blame view

drivers/hwmon/coretemp.c 20.6 KB
bebe46782   Rudolf Marek   hwmon: New corete...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /*
   * coretemp.c - Linux kernel module for hardware monitoring
   *
   * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
   *
   * Inspired from many hwmon drivers
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; version 2 of the License.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301 USA.
   */
f8bb89256   Joe Perches   hwmon: (coretemp)...
22
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
bebe46782   Rudolf Marek   hwmon: New corete...
23
  #include <linux/module.h>
bebe46782   Rudolf Marek   hwmon: New corete...
24
25
26
27
28
29
30
31
32
33
34
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/jiffies.h>
  #include <linux/hwmon.h>
  #include <linux/sysfs.h>
  #include <linux/hwmon-sysfs.h>
  #include <linux/err.h>
  #include <linux/mutex.h>
  #include <linux/list.h>
  #include <linux/platform_device.h>
  #include <linux/cpu.h>
1fe63ab47   Yong Wang   hwmon: (coretemp)...
35
  #include <linux/pci.h>
4cc452758   Guenter Roeck   hwmon: (coretemp)...
36
  #include <linux/smp.h>
a45a8c857   Jean Delvare   hwmon: (coretemp)...
37
  #include <linux/moduleparam.h>
bebe46782   Rudolf Marek   hwmon: New corete...
38
39
40
41
  #include <asm/msr.h>
  #include <asm/processor.h>
  
  #define DRVNAME	"coretemp"
a45a8c857   Jean Delvare   hwmon: (coretemp)...
42
43
44
45
46
47
48
  /*
   * 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");
199e0de7f   Durgadoss R   hwmon: (coretemp)...
49
50
51
  #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 */
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
52
  #define MAX_CORE_ATTRS		4	/* Maximum no of basic attrs */
f4af6fd6e   Guenter Roeck   hwmon: (coretemp)...
53
  #define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
54
  #define MAX_CORE_DATA		(NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
55
56
  #define TO_PHYS_ID(cpu)		cpu_data(cpu).phys_proc_id
  #define TO_CORE_ID(cpu)		cpu_data(cpu).cpu_core_id
141168c36   Kevin Winchester   x86: Simplify cod...
57
58
59
  #define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
  
  #ifdef CONFIG_SMP
bb74e8ca3   Guenter Roeck   hwmon: (coretemp)...
60
  #define for_each_sibling(i, cpu)	for_each_cpu(i, cpu_sibling_mask(cpu))
199e0de7f   Durgadoss R   hwmon: (coretemp)...
61
  #else
bb74e8ca3   Guenter Roeck   hwmon: (coretemp)...
62
  #define for_each_sibling(i, cpu)	for (i = 0; false; )
199e0de7f   Durgadoss R   hwmon: (coretemp)...
63
  #endif
bebe46782   Rudolf Marek   hwmon: New corete...
64
65
  
  /*
199e0de7f   Durgadoss R   hwmon: (coretemp)...
66
67
68
69
70
71
72
   * Per-Core Temperature Data
   * @last_updated: The time when the current temperature value was updated
   *		earlier (in jiffies).
   * @cpu_core_id: The CPU Core from which temperature values should be read
   *		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.
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
73
   * @attr_size:  Total number of pre-core attrs displayed in the sysfs.
199e0de7f   Durgadoss R   hwmon: (coretemp)...
74
75
76
   * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
   *		Otherwise, temp_data holds coretemp data.
   * @valid: If this is 1, the current temperature is valid.
bebe46782   Rudolf Marek   hwmon: New corete...
77
   */
199e0de7f   Durgadoss R   hwmon: (coretemp)...
78
  struct temp_data {
bebe46782   Rudolf Marek   hwmon: New corete...
79
  	int temp;
6369a2887   Rudolf Marek   hwmon: (coretemp)...
80
  	int ttarget;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
81
82
83
84
85
  	int tjmax;
  	unsigned long last_updated;
  	unsigned int cpu;
  	u32 cpu_core_id;
  	u32 status_reg;
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
86
  	int attr_size;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
87
88
  	bool is_pkg_data;
  	bool valid;
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
89
90
  	struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
  	char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
199e0de7f   Durgadoss R   hwmon: (coretemp)...
91
  	struct mutex update_lock;
bebe46782   Rudolf Marek   hwmon: New corete...
92
  };
199e0de7f   Durgadoss R   hwmon: (coretemp)...
93
94
95
96
97
98
99
  /* Platform Data per Physical CPU */
  struct platform_data {
  	struct device *hwmon_dev;
  	u16 phys_proc_id;
  	struct temp_data *core_data[MAX_CORE_DATA];
  	struct device_attribute name_attr;
  };
bebe46782   Rudolf Marek   hwmon: New corete...
100

199e0de7f   Durgadoss R   hwmon: (coretemp)...
101
102
103
  struct pdev_entry {
  	struct list_head list;
  	struct platform_device *pdev;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
104
  	u16 phys_proc_id;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  };
  
  static LIST_HEAD(pdev_list);
  static DEFINE_MUTEX(pdev_list_mutex);
  
  static ssize_t show_name(struct device *dev,
  			struct device_attribute *devattr, char *buf)
  {
  	return sprintf(buf, "%s
  ", DRVNAME);
  }
  
  static ssize_t show_label(struct device *dev,
  				struct device_attribute *devattr, char *buf)
bebe46782   Rudolf Marek   hwmon: New corete...
119
  {
bebe46782   Rudolf Marek   hwmon: New corete...
120
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
121
122
123
124
125
126
  	struct platform_data *pdata = dev_get_drvdata(dev);
  	struct temp_data *tdata = pdata->core_data[attr->index];
  
  	if (tdata->is_pkg_data)
  		return sprintf(buf, "Physical id %u
  ", pdata->phys_proc_id);
bebe46782   Rudolf Marek   hwmon: New corete...
127

199e0de7f   Durgadoss R   hwmon: (coretemp)...
128
129
  	return sprintf(buf, "Core %u
  ", tdata->cpu_core_id);
bebe46782   Rudolf Marek   hwmon: New corete...
130
  }
199e0de7f   Durgadoss R   hwmon: (coretemp)...
131
132
  static ssize_t show_crit_alarm(struct device *dev,
  				struct device_attribute *devattr, char *buf)
bebe46782   Rudolf Marek   hwmon: New corete...
133
  {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
134
135
136
137
138
139
140
141
142
  	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
  ", (eax >> 5) & 1);
bebe46782   Rudolf Marek   hwmon: New corete...
143
  }
199e0de7f   Durgadoss R   hwmon: (coretemp)...
144
145
  static ssize_t show_tjmax(struct device *dev,
  			struct device_attribute *devattr, char *buf)
bebe46782   Rudolf Marek   hwmon: New corete...
146
147
  {
  	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
148
  	struct platform_data *pdata = dev_get_drvdata(dev);
bebe46782   Rudolf Marek   hwmon: New corete...
149

199e0de7f   Durgadoss R   hwmon: (coretemp)...
150
151
  	return sprintf(buf, "%d
  ", pdata->core_data[attr->index]->tjmax);
bebe46782   Rudolf Marek   hwmon: New corete...
152
  }
199e0de7f   Durgadoss R   hwmon: (coretemp)...
153
154
155
156
157
  static ssize_t show_ttarget(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);
bebe46782   Rudolf Marek   hwmon: New corete...
158

199e0de7f   Durgadoss R   hwmon: (coretemp)...
159
160
161
  	return sprintf(buf, "%d
  ", pdata->core_data[attr->index]->ttarget);
  }
bebe46782   Rudolf Marek   hwmon: New corete...
162

199e0de7f   Durgadoss R   hwmon: (coretemp)...
163
164
  static ssize_t show_temp(struct device *dev,
  			struct device_attribute *devattr, char *buf)
bebe46782   Rudolf Marek   hwmon: New corete...
165
  {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
166
167
168
169
  	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];
bebe46782   Rudolf Marek   hwmon: New corete...
170

199e0de7f   Durgadoss R   hwmon: (coretemp)...
171
  	mutex_lock(&tdata->update_lock);
bebe46782   Rudolf Marek   hwmon: New corete...
172

199e0de7f   Durgadoss R   hwmon: (coretemp)...
173
174
175
176
177
  	/* Check whether the time interval has elapsed */
  	if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) {
  		rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
  		tdata->valid = 0;
  		/* Check whether the data is valid */
bebe46782   Rudolf Marek   hwmon: New corete...
178
  		if (eax & 0x80000000) {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
179
  			tdata->temp = tdata->tjmax -
4cc452758   Guenter Roeck   hwmon: (coretemp)...
180
  					((eax >> 16) & 0x7f) * 1000;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
181
  			tdata->valid = 1;
bebe46782   Rudolf Marek   hwmon: New corete...
182
  		}
199e0de7f   Durgadoss R   hwmon: (coretemp)...
183
  		tdata->last_updated = jiffies;
bebe46782   Rudolf Marek   hwmon: New corete...
184
  	}
199e0de7f   Durgadoss R   hwmon: (coretemp)...
185
186
187
  	mutex_unlock(&tdata->update_lock);
  	return tdata->valid ? sprintf(buf, "%d
  ", tdata->temp) : -EAGAIN;
bebe46782   Rudolf Marek   hwmon: New corete...
188
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
189
190
  static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
  				  struct device *dev)
118a88718   Rudolf Marek   hwmon: (coretemp)...
191
192
193
194
  {
  	/* The 100C is default for both mobile and non mobile CPUs */
  
  	int tjmax = 100000;
eccfed422   Rudolf Marek   hwmon: (coretemp)...
195
  	int tjmax_ee = 85000;
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
196
  	int usemsr_ee = 1;
118a88718   Rudolf Marek   hwmon: (coretemp)...
197
198
  	int err;
  	u32 eax, edx;
1fe63ab47   Yong Wang   hwmon: (coretemp)...
199
  	struct pci_dev *host_bridge;
118a88718   Rudolf Marek   hwmon: (coretemp)...
200
201
  
  	/* Early chips have no MSR for TjMax */
4cc452758   Guenter Roeck   hwmon: (coretemp)...
202
  	if (c->x86_model == 0xf && c->x86_mask < 4)
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
203
  		usemsr_ee = 0;
118a88718   Rudolf Marek   hwmon: (coretemp)...
204

1fe63ab47   Yong Wang   hwmon: (coretemp)...
205
  	/* Atom CPUs */
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
206
207
208
  
  	if (c->x86_model == 0x1c) {
  		usemsr_ee = 0;
1fe63ab47   Yong Wang   hwmon: (coretemp)...
209
210
211
212
213
214
215
216
217
218
219
  
  		host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
  
  		if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL
  		    && (host_bridge->device == 0xa000	/* NM10 based nettop */
  		    || host_bridge->device == 0xa010))	/* NM10 based netbook */
  			tjmax = 100000;
  		else
  			tjmax = 90000;
  
  		pci_dev_put(host_bridge);
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
220
  	}
4cc452758   Guenter Roeck   hwmon: (coretemp)...
221
  	if (c->x86_model > 0xe && usemsr_ee) {
eccfed422   Rudolf Marek   hwmon: (coretemp)...
222
  		u8 platform_id;
118a88718   Rudolf Marek   hwmon: (coretemp)...
223

4cc452758   Guenter Roeck   hwmon: (coretemp)...
224
225
226
227
228
  		/*
  		 * Now we can detect the mobile CPU using Intel provided table
  		 * http://softwarecommunity.intel.com/Wiki/Mobility/720.htm
  		 * For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU
  		 */
118a88718   Rudolf Marek   hwmon: (coretemp)...
229
230
231
232
233
234
  		err = rdmsr_safe_on_cpu(id, 0x17, &eax, &edx);
  		if (err) {
  			dev_warn(dev,
  				 "Unable to access MSR 0x17, assuming desktop"
  				 " CPU
  ");
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
235
  			usemsr_ee = 0;
eccfed422   Rudolf Marek   hwmon: (coretemp)...
236
  		} else if (c->x86_model < 0x17 && !(eax & 0x10000000)) {
4cc452758   Guenter Roeck   hwmon: (coretemp)...
237
238
239
240
241
  			/*
  			 * Trust bit 28 up to Penryn, I could not find any
  			 * documentation on that; if you happen to know
  			 * someone at Intel please ask
  			 */
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
242
  			usemsr_ee = 0;
eccfed422   Rudolf Marek   hwmon: (coretemp)...
243
244
245
  		} else {
  			/* Platform ID bits 52:50 (EDX starts at bit 32) */
  			platform_id = (edx >> 18) & 0x7;
4cc452758   Guenter Roeck   hwmon: (coretemp)...
246
247
248
249
250
251
252
253
254
255
  			/*
  			 * Mobile Penryn CPU seems to be platform ID 7 or 5
  			 * (guesswork)
  			 */
  			if (c->x86_model == 0x17 &&
  			    (platform_id == 5 || platform_id == 7)) {
  				/*
  				 * If MSR EE bit is set, set it to 90 degrees C,
  				 * otherwise 105 degrees C
  				 */
eccfed422   Rudolf Marek   hwmon: (coretemp)...
256
257
258
  				tjmax_ee = 90000;
  				tjmax = 105000;
  			}
118a88718   Rudolf Marek   hwmon: (coretemp)...
259
260
  		}
  	}
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
261
  	if (usemsr_ee) {
118a88718   Rudolf Marek   hwmon: (coretemp)...
262
263
264
265
  		err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx);
  		if (err) {
  			dev_warn(dev,
  				 "Unable to access MSR 0xEE, for Tjmax, left"
4d7a5644e   Dean Nelson   hwmon: (coretemp)...
266
267
  				 " at default
  ");
118a88718   Rudolf Marek   hwmon: (coretemp)...
268
  		} else if (eax & 0x40000000) {
eccfed422   Rudolf Marek   hwmon: (coretemp)...
269
  			tjmax = tjmax_ee;
118a88718   Rudolf Marek   hwmon: (coretemp)...
270
  		}
708a62bcd   Rudolf Marek   hwmon: (coretemp)...
271
  	} else if (tjmax == 100000) {
4cc452758   Guenter Roeck   hwmon: (coretemp)...
272
273
274
275
  		/*
  		 * If we don't use msr EE it means we are desktop CPU
  		 * (with exeception of Atom)
  		 */
118a88718   Rudolf Marek   hwmon: (coretemp)...
276
277
278
279
280
281
  		dev_warn(dev, "Using relative temperature scale!
  ");
  	}
  
  	return tjmax;
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
282
283
  static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
  			       struct device *dev)
a321cedb1   Carsten Emde   drivers/hwmon/cor...
284
  {
a321cedb1   Carsten Emde   drivers/hwmon/cor...
285
286
287
  	int err;
  	u32 eax, edx;
  	u32 val;
4cc452758   Guenter Roeck   hwmon: (coretemp)...
288
289
290
291
  	/*
  	 * A new feature of current Intel(R) processors, the
  	 * IA32_TEMPERATURE_TARGET contains the TjMax value
  	 */
a321cedb1   Carsten Emde   drivers/hwmon/cor...
292
293
  	err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
  	if (err) {
6bf9e9b09   Jean Delvare   hwmon: (coretemp)...
294
295
296
  		if (c->x86_model > 0xe && c->x86_model != 0x1c)
  			dev_warn(dev, "Unable to read TjMax from CPU %u
  ", id);
a321cedb1   Carsten Emde   drivers/hwmon/cor...
297
298
299
300
301
302
  	} else {
  		val = (eax >> 16) & 0xff;
  		/*
  		 * If the TjMax is not plausible, an assumption
  		 * will be used
  		 */
bb9973e4e   Guenter Roeck   hwmon: (coretemp)...
303
  		if (val) {
6bf9e9b09   Jean Delvare   hwmon: (coretemp)...
304
305
  			dev_dbg(dev, "TjMax is %d degrees C
  ", val);
a321cedb1   Carsten Emde   drivers/hwmon/cor...
306
307
308
  			return val * 1000;
  		}
  	}
a45a8c857   Jean Delvare   hwmon: (coretemp)...
309
310
311
312
313
314
  	if (force_tjmax) {
  		dev_notice(dev, "TjMax forced to %d degrees C by user
  ",
  			   force_tjmax);
  		return force_tjmax * 1000;
  	}
a321cedb1   Carsten Emde   drivers/hwmon/cor...
315
316
  	/*
  	 * An assumption is made for early CPUs and unreadable MSR.
4f5f71a7a   Guenter Roeck   hwmon: (coretemp)...
317
  	 * NOTE: the calculated value may not be correct.
a321cedb1   Carsten Emde   drivers/hwmon/cor...
318
  	 */
4f5f71a7a   Guenter Roeck   hwmon: (coretemp)...
319
  	return adjust_tjmax(c, id, dev);
a321cedb1   Carsten Emde   drivers/hwmon/cor...
320
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
321
322
  static int __devinit create_name_attr(struct platform_data *pdata,
  				      struct device *dev)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
323
  {
4258781ac   Sergey Senozhatsky   hwmon: (coretemp)...
324
  	sysfs_attr_init(&pdata->name_attr.attr);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
325
326
327
328
329
  	pdata->name_attr.attr.name = "name";
  	pdata->name_attr.attr.mode = S_IRUGO;
  	pdata->name_attr.show = show_name;
  	return device_create_file(dev, &pdata->name_attr);
  }
bebe46782   Rudolf Marek   hwmon: New corete...
330

d6db23c7c   Jean Delvare   hwmon: (coretemp)...
331
332
  static int __cpuinit create_core_attrs(struct temp_data *tdata,
  				       struct device *dev, int attr_no)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
333
334
  {
  	int err, i;
e3204ed3a   Jan Beulich   hwmon: (coretemp)...
335
  	static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
199e0de7f   Durgadoss R   hwmon: (coretemp)...
336
  			struct device_attribute *devattr, char *buf) = {
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
337
  			show_label, show_crit_alarm, show_temp, show_tjmax,
f4af6fd6e   Guenter Roeck   hwmon: (coretemp)...
338
  			show_ttarget };
e3204ed3a   Jan Beulich   hwmon: (coretemp)...
339
  	static const char *const names[TOTAL_ATTRS] = {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
340
  					"temp%d_label", "temp%d_crit_alarm",
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
341
  					"temp%d_input", "temp%d_crit",
f4af6fd6e   Guenter Roeck   hwmon: (coretemp)...
342
  					"temp%d_max" };
199e0de7f   Durgadoss R   hwmon: (coretemp)...
343

c814a4c7c   Durgadoss R   hwmon: (coretemp)...
344
  	for (i = 0; i < tdata->attr_size; i++) {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
345
346
  		snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i],
  			attr_no);
4258781ac   Sergey Senozhatsky   hwmon: (coretemp)...
347
  		sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
348
349
350
  		tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
  		tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO;
  		tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
199e0de7f   Durgadoss R   hwmon: (coretemp)...
351
352
353
354
  		tdata->sd_attrs[i].index = attr_no;
  		err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr);
  		if (err)
  			goto exit_free;
bebe46782   Rudolf Marek   hwmon: New corete...
355
  	}
199e0de7f   Durgadoss R   hwmon: (coretemp)...
356
357
358
359
360
361
362
  	return 0;
  
  exit_free:
  	while (--i >= 0)
  		device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
  	return err;
  }
199e0de7f   Durgadoss R   hwmon: (coretemp)...
363

0eb9782ad   Jean Delvare   hwmon: (coretemp)...
364
  static int __cpuinit chk_ucode_version(unsigned int cpu)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
365
  {
0eb9782ad   Jean Delvare   hwmon: (coretemp)...
366
  	struct cpuinfo_x86 *c = &cpu_data(cpu);
67f363b1f   Rudolf Marek   hwmon/coretemp: A...
367

199e0de7f   Durgadoss R   hwmon: (coretemp)...
368
369
370
371
372
  	/*
  	 * Check if we have problem with errata AE18 of Core processors:
  	 * Readings might stop update when processor visited too deep sleep,
  	 * fixed for stepping D0 (6EC).
  	 */
ca8bc8dc0   Andi Kleen   coretemp: Get mic...
373
374
375
376
377
  	if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) {
  		pr_err("Errata AE18 not fixed, update BIOS or "
  		       "microcode of the CPU!
  ");
  		return -ENODEV;
67f363b1f   Rudolf Marek   hwmon/coretemp: A...
378
  	}
199e0de7f   Durgadoss R   hwmon: (coretemp)...
379
380
  	return 0;
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
381
  static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
  {
  	u16 phys_proc_id = TO_PHYS_ID(cpu);
  	struct pdev_entry *p;
  
  	mutex_lock(&pdev_list_mutex);
  
  	list_for_each_entry(p, &pdev_list, list)
  		if (p->phys_proc_id == phys_proc_id) {
  			mutex_unlock(&pdev_list_mutex);
  			return p->pdev;
  		}
  
  	mutex_unlock(&pdev_list_mutex);
  	return NULL;
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
397
398
  static struct temp_data __cpuinit *init_temp_data(unsigned int cpu,
  						  int pkg_flag)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
399
400
401
402
403
404
405
406
407
408
409
410
  {
  	struct temp_data *tdata;
  
  	tdata = kzalloc(sizeof(struct temp_data), GFP_KERNEL);
  	if (!tdata)
  		return NULL;
  
  	tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS :
  							MSR_IA32_THERM_STATUS;
  	tdata->is_pkg_data = pkg_flag;
  	tdata->cpu = cpu;
  	tdata->cpu_core_id = TO_CORE_ID(cpu);
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
411
  	tdata->attr_size = MAX_CORE_ATTRS;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
412
413
414
  	mutex_init(&tdata->update_lock);
  	return tdata;
  }
67f363b1f   Rudolf Marek   hwmon/coretemp: A...
415

d6db23c7c   Jean Delvare   hwmon: (coretemp)...
416
  static int __cpuinit create_core_data(struct platform_device *pdev,
199e0de7f   Durgadoss R   hwmon: (coretemp)...
417
418
419
  				unsigned int cpu, int pkg_flag)
  {
  	struct temp_data *tdata;
2f1c3db0a   Jan Beulich   hwmon: (coretemp)...
420
  	struct platform_data *pdata = platform_get_drvdata(pdev);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
421
422
423
  	struct cpuinfo_x86 *c = &cpu_data(cpu);
  	u32 eax, edx;
  	int err, attr_no;
bebe46782   Rudolf Marek   hwmon: New corete...
424

a321cedb1   Carsten Emde   drivers/hwmon/cor...
425
  	/*
199e0de7f   Durgadoss R   hwmon: (coretemp)...
426
427
428
429
  	 * Find attr number for sysfs:
  	 * We map the attr number to core id of the CPU
  	 * The attr number is always core id + 2
  	 * The Pkgtemp will always show up as temp1_*, if available
a321cedb1   Carsten Emde   drivers/hwmon/cor...
430
  	 */
199e0de7f   Durgadoss R   hwmon: (coretemp)...
431
  	attr_no = pkg_flag ? 1 : TO_ATTR_NO(cpu);
6369a2887   Rudolf Marek   hwmon: (coretemp)...
432

199e0de7f   Durgadoss R   hwmon: (coretemp)...
433
434
  	if (attr_no > MAX_CORE_DATA - 1)
  		return -ERANGE;
f4e0bcf06   Guenter Roeck   hwmon: (coretemp)...
435
436
437
  	/*
  	 * Provide a single set of attributes for all HT siblings of a core
  	 * to avoid duplicate sensors (the processor ID and core ID of all
6777b9e47   Guenter Roeck   hwmon: (coretemp)...
438
439
  	 * HT siblings of a core are the same).
  	 * Skip if a HT sibling of this core is already registered.
f4e0bcf06   Guenter Roeck   hwmon: (coretemp)...
440
441
  	 * This is not an error.
  	 */
199e0de7f   Durgadoss R   hwmon: (coretemp)...
442
443
  	if (pdata->core_data[attr_no] != NULL)
  		return 0;
6369a2887   Rudolf Marek   hwmon: (coretemp)...
444

199e0de7f   Durgadoss R   hwmon: (coretemp)...
445
446
447
  	tdata = init_temp_data(cpu, pkg_flag);
  	if (!tdata)
  		return -ENOMEM;
bebe46782   Rudolf Marek   hwmon: New corete...
448

199e0de7f   Durgadoss R   hwmon: (coretemp)...
449
450
451
452
453
454
  	/* Test if we can access the status register */
  	err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx);
  	if (err)
  		goto exit_free;
  
  	/* We can access status register. Get Critical Temperature */
6bf9e9b09   Jean Delvare   hwmon: (coretemp)...
455
  	tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
456

c814a4c7c   Durgadoss R   hwmon: (coretemp)...
457
  	/*
f4af6fd6e   Guenter Roeck   hwmon: (coretemp)...
458
459
460
  	 * 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.
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
461
  	 */
f4af6fd6e   Guenter Roeck   hwmon: (coretemp)...
462
463
464
465
466
467
468
469
  	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++;
  		}
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
470
  	}
199e0de7f   Durgadoss R   hwmon: (coretemp)...
471
472
473
474
475
476
  	pdata->core_data[attr_no] = tdata;
  
  	/* Create sysfs interfaces */
  	err = create_core_attrs(tdata, &pdev->dev, attr_no);
  	if (err)
  		goto exit_free;
bebe46782   Rudolf Marek   hwmon: New corete...
477
478
  
  	return 0;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
479
  exit_free:
20ecb499f   Guenter Roeck   hwmon: (coretemp)...
480
  	pdata->core_data[attr_no] = NULL;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
481
482
483
  	kfree(tdata);
  	return err;
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
484
  static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
485
  {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
486
487
488
489
490
  	struct platform_device *pdev = coretemp_get_pdev(cpu);
  	int err;
  
  	if (!pdev)
  		return;
2f1c3db0a   Jan Beulich   hwmon: (coretemp)...
491
  	err = create_core_data(pdev, cpu, pkg_flag);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
492
493
494
495
496
497
498
499
500
501
502
503
  	if (err)
  		dev_err(&pdev->dev, "Adding Core %u failed
  ", cpu);
  }
  
  static void coretemp_remove_core(struct platform_data *pdata,
  				struct device *dev, int indx)
  {
  	int i;
  	struct temp_data *tdata = pdata->core_data[indx];
  
  	/* Remove the sysfs attributes */
c814a4c7c   Durgadoss R   hwmon: (coretemp)...
504
  	for (i = 0; i < tdata->attr_size; i++)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
505
506
507
508
509
510
511
512
513
514
  		device_remove_file(dev, &tdata->sd_attrs[i].dev_attr);
  
  	kfree(pdata->core_data[indx]);
  	pdata->core_data[indx] = NULL;
  }
  
  static int __devinit coretemp_probe(struct platform_device *pdev)
  {
  	struct platform_data *pdata;
  	int err;
bebe46782   Rudolf Marek   hwmon: New corete...
515

199e0de7f   Durgadoss R   hwmon: (coretemp)...
516
517
518
519
520
521
522
523
  	/* Initialize the per-package data structures */
  	pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL);
  	if (!pdata)
  		return -ENOMEM;
  
  	err = create_name_attr(pdata, &pdev->dev);
  	if (err)
  		goto exit_free;
b3a242a6e   Jan Beulich   hwmon: (coretemp)...
524
  	pdata->phys_proc_id = pdev->id;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  	platform_set_drvdata(pdev, pdata);
  
  	pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
  	if (IS_ERR(pdata->hwmon_dev)) {
  		err = PTR_ERR(pdata->hwmon_dev);
  		dev_err(&pdev->dev, "Class registration failed (%d)
  ", err);
  		goto exit_name;
  	}
  	return 0;
  
  exit_name:
  	device_remove_file(&pdev->dev, &pdata->name_attr);
  	platform_set_drvdata(pdev, NULL);
bebe46782   Rudolf Marek   hwmon: New corete...
539
  exit_free:
199e0de7f   Durgadoss R   hwmon: (coretemp)...
540
  	kfree(pdata);
bebe46782   Rudolf Marek   hwmon: New corete...
541
542
543
544
545
  	return err;
  }
  
  static int __devexit coretemp_remove(struct platform_device *pdev)
  {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
546
547
  	struct platform_data *pdata = platform_get_drvdata(pdev);
  	int i;
bebe46782   Rudolf Marek   hwmon: New corete...
548

199e0de7f   Durgadoss R   hwmon: (coretemp)...
549
550
551
552
553
554
  	for (i = MAX_CORE_DATA - 1; i >= 0; --i)
  		if (pdata->core_data[i])
  			coretemp_remove_core(pdata, &pdev->dev, i);
  
  	device_remove_file(&pdev->dev, &pdata->name_attr);
  	hwmon_device_unregister(pdata->hwmon_dev);
bebe46782   Rudolf Marek   hwmon: New corete...
555
  	platform_set_drvdata(pdev, NULL);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
556
  	kfree(pdata);
bebe46782   Rudolf Marek   hwmon: New corete...
557
558
559
560
561
562
563
564
565
566
567
  	return 0;
  }
  
  static struct platform_driver coretemp_driver = {
  	.driver = {
  		.owner = THIS_MODULE,
  		.name = DRVNAME,
  	},
  	.probe = coretemp_probe,
  	.remove = __devexit_p(coretemp_remove),
  };
bebe46782   Rudolf Marek   hwmon: New corete...
568
569
570
571
572
  static int __cpuinit coretemp_device_add(unsigned int cpu)
  {
  	int err;
  	struct platform_device *pdev;
  	struct pdev_entry *pdev_entry;
d883b9f09   Jean Delvare   hwmon: (coretemp)...
573
574
  
  	mutex_lock(&pdev_list_mutex);
b3a242a6e   Jan Beulich   hwmon: (coretemp)...
575
  	pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));
bebe46782   Rudolf Marek   hwmon: New corete...
576
577
  	if (!pdev) {
  		err = -ENOMEM;
f8bb89256   Joe Perches   hwmon: (coretemp)...
578
579
  		pr_err("Device allocation failed
  ");
bebe46782   Rudolf Marek   hwmon: New corete...
580
581
582
583
584
585
586
587
588
589
590
  		goto exit;
  	}
  
  	pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
  	if (!pdev_entry) {
  		err = -ENOMEM;
  		goto exit_device_put;
  	}
  
  	err = platform_device_add(pdev);
  	if (err) {
f8bb89256   Joe Perches   hwmon: (coretemp)...
591
592
  		pr_err("Device addition failed (%d)
  ", err);
bebe46782   Rudolf Marek   hwmon: New corete...
593
594
595
596
  		goto exit_device_free;
  	}
  
  	pdev_entry->pdev = pdev;
0eb9782ad   Jean Delvare   hwmon: (coretemp)...
597
  	pdev_entry->phys_proc_id = pdev->id;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
598

bebe46782   Rudolf Marek   hwmon: New corete...
599
600
601
602
603
604
605
606
607
608
  	list_add_tail(&pdev_entry->list, &pdev_list);
  	mutex_unlock(&pdev_list_mutex);
  
  	return 0;
  
  exit_device_free:
  	kfree(pdev_entry);
  exit_device_put:
  	platform_device_put(pdev);
  exit:
d883b9f09   Jean Delvare   hwmon: (coretemp)...
609
  	mutex_unlock(&pdev_list_mutex);
bebe46782   Rudolf Marek   hwmon: New corete...
610
611
  	return err;
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
612
  static void __cpuinit coretemp_device_remove(unsigned int cpu)
bebe46782   Rudolf Marek   hwmon: New corete...
613
  {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
614
615
  	struct pdev_entry *p, *n;
  	u16 phys_proc_id = TO_PHYS_ID(cpu);
e40cc4bdf   Jan Beulich   x86/hwmon: regist...
616

bebe46782   Rudolf Marek   hwmon: New corete...
617
  	mutex_lock(&pdev_list_mutex);
199e0de7f   Durgadoss R   hwmon: (coretemp)...
618
619
  	list_for_each_entry_safe(p, n, &pdev_list, list) {
  		if (p->phys_proc_id != phys_proc_id)
e40cc4bdf   Jan Beulich   x86/hwmon: regist...
620
  			continue;
e40cc4bdf   Jan Beulich   x86/hwmon: regist...
621
622
  		platform_device_unregister(p->pdev);
  		list_del(&p->list);
e40cc4bdf   Jan Beulich   x86/hwmon: regist...
623
  		kfree(p);
bebe46782   Rudolf Marek   hwmon: New corete...
624
625
626
  	}
  	mutex_unlock(&pdev_list_mutex);
  }
d6db23c7c   Jean Delvare   hwmon: (coretemp)...
627
  static bool __cpuinit is_any_core_online(struct platform_data *pdata)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  {
  	int i;
  
  	/* Find online cores, except pkgtemp data */
  	for (i = MAX_CORE_DATA - 1; i >= 0; --i) {
  		if (pdata->core_data[i] &&
  			!pdata->core_data[i]->is_pkg_data) {
  			return true;
  		}
  	}
  	return false;
  }
  
  static void __cpuinit get_core_online(unsigned int cpu)
  {
  	struct cpuinfo_x86 *c = &cpu_data(cpu);
  	struct platform_device *pdev = coretemp_get_pdev(cpu);
  	int err;
  
  	/*
  	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
  	 * sensors. We check this bit only, all the early CPUs
  	 * without thermal sensors will be filtered out.
  	 */
  	if (!cpu_has(c, X86_FEATURE_DTS))
  		return;
  
  	if (!pdev) {
0eb9782ad   Jean Delvare   hwmon: (coretemp)...
656
657
658
  		/* Check the microcode version of the CPU */
  		if (chk_ucode_version(cpu))
  			return;
199e0de7f   Durgadoss R   hwmon: (coretemp)...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
  		/*
  		 * Alright, we have DTS support.
  		 * We are bringing the _first_ core in this pkg
  		 * online. So, initialize per-pkg data structures and
  		 * then bring this core online.
  		 */
  		err = coretemp_device_add(cpu);
  		if (err)
  			return;
  		/*
  		 * Check whether pkgtemp support is available.
  		 * If so, add interfaces for pkgtemp.
  		 */
  		if (cpu_has(c, X86_FEATURE_PTS))
  			coretemp_add_core(cpu, 1);
  	}
  	/*
  	 * Physical CPU device already exists.
  	 * So, just add interfaces for this core.
  	 */
  	coretemp_add_core(cpu, 0);
  }
  
  static void __cpuinit put_core_offline(unsigned int cpu)
  {
  	int i, indx;
  	struct platform_data *pdata;
  	struct platform_device *pdev = coretemp_get_pdev(cpu);
  
  	/* If the physical CPU device does not exist, just return */
  	if (!pdev)
  		return;
  
  	pdata = platform_get_drvdata(pdev);
  
  	indx = TO_ATTR_NO(cpu);
  
  	if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
  		coretemp_remove_core(pdata, &pdev->dev, indx);
f4e0bcf06   Guenter Roeck   hwmon: (coretemp)...
698
  	/*
6777b9e47   Guenter Roeck   hwmon: (coretemp)...
699
700
701
702
  	 * If a HT sibling of a core is taken offline, but another HT sibling
  	 * of the same core is still online, register the alternate sibling.
  	 * This ensures that exactly one set of attributes is provided as long
  	 * as at least one HT sibling of a core is online.
f4e0bcf06   Guenter Roeck   hwmon: (coretemp)...
703
  	 */
bb74e8ca3   Guenter Roeck   hwmon: (coretemp)...
704
  	for_each_sibling(i, cpu) {
199e0de7f   Durgadoss R   hwmon: (coretemp)...
705
706
  		if (i != cpu) {
  			get_core_online(i);
f4e0bcf06   Guenter Roeck   hwmon: (coretemp)...
707
708
709
710
711
  			/*
  			 * Display temperature sensor data for one HT sibling
  			 * per core only, so abort the loop after one such
  			 * sibling has been found.
  			 */
199e0de7f   Durgadoss R   hwmon: (coretemp)...
712
713
714
715
716
717
718
719
720
721
722
723
  			break;
  		}
  	}
  	/*
  	 * If all cores in this pkg are offline, remove the device.
  	 * coretemp_device_remove calls unregister_platform_device,
  	 * which in turn calls coretemp_remove. This removes the
  	 * pkgtemp entry and does other clean ups.
  	 */
  	if (!is_any_core_online(pdata))
  		coretemp_device_remove(cpu);
  }
ba7c1927a   Sam Ravnborg   hwmon: (coretemp)...
724
  static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb,
bebe46782   Rudolf Marek   hwmon: New corete...
725
726
727
728
729
730
  				 unsigned long action, void *hcpu)
  {
  	unsigned int cpu = (unsigned long) hcpu;
  
  	switch (action) {
  	case CPU_ONLINE:
561d9a969   Rafael J. Wysocki   HWMON: coretemp, ...
731
  	case CPU_DOWN_FAILED:
199e0de7f   Durgadoss R   hwmon: (coretemp)...
732
  		get_core_online(cpu);
bebe46782   Rudolf Marek   hwmon: New corete...
733
  		break;
561d9a969   Rafael J. Wysocki   HWMON: coretemp, ...
734
  	case CPU_DOWN_PREPARE:
199e0de7f   Durgadoss R   hwmon: (coretemp)...
735
  		put_core_offline(cpu);
bebe46782   Rudolf Marek   hwmon: New corete...
736
737
738
739
  		break;
  	}
  	return NOTIFY_OK;
  }
ba7c1927a   Sam Ravnborg   hwmon: (coretemp)...
740
  static struct notifier_block coretemp_cpu_notifier __refdata = {
bebe46782   Rudolf Marek   hwmon: New corete...
741
742
  	.notifier_call = coretemp_cpu_callback,
  };
bebe46782   Rudolf Marek   hwmon: New corete...
743
744
745
746
  
  static int __init coretemp_init(void)
  {
  	int i, err = -ENODEV;
bebe46782   Rudolf Marek   hwmon: New corete...
747

bebe46782   Rudolf Marek   hwmon: New corete...
748
  	/* quick check if we run Intel */
92cb7612a   Mike Travis   x86: convert cpui...
749
  	if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
bebe46782   Rudolf Marek   hwmon: New corete...
750
751
752
753
754
  		goto exit;
  
  	err = platform_driver_register(&coretemp_driver);
  	if (err)
  		goto exit;
a46590533   Jan Beulich   x86/hwmon: fix in...
755
  	for_each_online_cpu(i)
199e0de7f   Durgadoss R   hwmon: (coretemp)...
756
  		get_core_online(i);
89a3fd35b   Jan Beulich   x86/hwmon: fix mo...
757
758
  
  #ifndef CONFIG_HOTPLUG_CPU
bebe46782   Rudolf Marek   hwmon: New corete...
759
760
761
762
  	if (list_empty(&pdev_list)) {
  		err = -ENODEV;
  		goto exit_driver_unreg;
  	}
89a3fd35b   Jan Beulich   x86/hwmon: fix mo...
763
  #endif
bebe46782   Rudolf Marek   hwmon: New corete...
764

bebe46782   Rudolf Marek   hwmon: New corete...
765
  	register_hotcpu_notifier(&coretemp_cpu_notifier);
bebe46782   Rudolf Marek   hwmon: New corete...
766
  	return 0;
0dca94bae   Chen Gong   hwmon: coretemp: ...
767
  #ifndef CONFIG_HOTPLUG_CPU
89a3fd35b   Jan Beulich   x86/hwmon: fix mo...
768
  exit_driver_unreg:
bebe46782   Rudolf Marek   hwmon: New corete...
769
  	platform_driver_unregister(&coretemp_driver);
0dca94bae   Chen Gong   hwmon: coretemp: ...
770
  #endif
bebe46782   Rudolf Marek   hwmon: New corete...
771
772
773
774
775
776
777
  exit:
  	return err;
  }
  
  static void __exit coretemp_exit(void)
  {
  	struct pdev_entry *p, *n;
17c10d61c   Chen Gong   hwmon: ({core, pk...
778

bebe46782   Rudolf Marek   hwmon: New corete...
779
  	unregister_hotcpu_notifier(&coretemp_cpu_notifier);
bebe46782   Rudolf Marek   hwmon: New corete...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
  	mutex_lock(&pdev_list_mutex);
  	list_for_each_entry_safe(p, n, &pdev_list, list) {
  		platform_device_unregister(p->pdev);
  		list_del(&p->list);
  		kfree(p);
  	}
  	mutex_unlock(&pdev_list_mutex);
  	platform_driver_unregister(&coretemp_driver);
  }
  
  MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
  MODULE_DESCRIPTION("Intel Core temperature monitor");
  MODULE_LICENSE("GPL");
  
  module_init(coretemp_init)
  module_exit(coretemp_exit)