1
From c60b635637f0baadc4cc937519f11634f5a0d0f8 Mon Sep 17 00:00:00 2001
2
From: Sujith Thomas <sujith.thomas@intel.com>
3
Date: Tue, 14 Aug 2007 16:23:56 +0800
4
Subject: [PATCH] Poulsbo: Thottling support from SMI
6
- Generic support for throttling of any component using SMI
7
- Memory throttling for Intel platform Poulsbo
9
Signed-off-by: Sujith Thomas <sujith.thomas@intel.com>
11
drivers/acpi/Kconfig | 13 +++
12
drivers/acpi/Makefile | 2 +
13
drivers/acpi/smi_device_throttle.c | 108 ++++++++++++++++++++
14
drivers/acpi/smi_thermal.c | 193 ++++++++++++++++++++++++++++++++++++
15
include/linux/smi_thermal.h | 60 +++++++++++
16
5 files changed, 376 insertions(+), 0 deletions(-)
17
create mode 100644 drivers/acpi/smi_device_throttle.c
18
create mode 100644 drivers/acpi/smi_thermal.c
19
create mode 100644 include/linux/smi_thermal.h
21
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
22
index c8f50c0..2f65654 100644
23
--- a/drivers/acpi/Kconfig
24
+++ b/drivers/acpi/Kconfig
25
@@ -189,6 +189,19 @@ config THERMAL_SENSOR
27
This driver adds support for AUX trip programming of sensors withing ACPI thermal zones. This is an intel platform specific driver.
30
+ tristate "SMI Thermal driver"
31
+ depends on ACPI_THERMAL
34
+ This driver adds support for AUX trip programming of sensors withing ACPI thermal zones. This is an intel platform specific driver.
36
+config SMI_DEVICE_THROTTLE
37
+ tristate "SMI Device Throttle Driver"
38
+ depends on SMI_THERMAL
41
+ This driver adds support for throttling of device based on SMI. This is an intel platform specific driver.
45
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
46
index 4cda36c..84252a3 100644
47
--- a/drivers/acpi/Makefile
48
+++ b/drivers/acpi/Makefile
49
@@ -52,7 +52,9 @@ obj-$(CONFIG_ACPI_POWER) += power.o
50
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
51
obj-$(CONFIG_ACPI_CONTAINER) += container.o
52
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
53
+obj-$(CONFIG_SMI_THERMAL) += smi_thermal.o
54
obj-$(CONFIG_THERMAL_SENSOR) += thermal_sensor.o
55
+obj-$(CONFIG_SMI_DEVICE_THROTTLE)+= smi_device_throttle.o
56
obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
57
obj-$(CONFIG_ACPI_DEBUG) += debug.o
58
obj-$(CONFIG_ACPI_NUMA) += numa.o
59
diff --git a/drivers/acpi/smi_device_throttle.c b/drivers/acpi/smi_device_throttle.c
61
index 0000000..f0d3861
63
+++ b/drivers/acpi/smi_device_throttle.c
66
+ * smi_device_throttle.c - SMI Device Throttle Driver ($Revision: 1 $)
68
+ * Copyright (C) 2006, 2007 Sujith Thomas <sujith.thomas@intel.com>
69
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71
+ * This program is free software; you can redistribute it and/or modify
72
+ * it under the terms of the GNU General Public License as published by
73
+ * the Free Software Foundation; version 2 of the License.
75
+ * This program is distributed in the hope that it will be useful, but
76
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
77
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
78
+ * General Public License for more details.
80
+ * You should have received a copy of the GNU General Public License along
81
+ * with this program; if not, write to the Free Software Foundation, Inc.,
82
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
84
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
87
+#include <linux/kernel.h>
88
+#include <linux/module.h>
89
+#include <linux/init.h>
90
+#include <linux/types.h>
91
+#include <linux/pci.h>
92
+#include <linux/pm.h>
94
+#include <linux/smi_thermal.h>
96
+MODULE_AUTHOR("Sujith Thomas");
97
+MODULE_DESCRIPTION("SMI throttle driver");
98
+MODULE_LICENSE("GPL");
100
+/*No:of devices using SMI interface for throttling*/
101
+#define SMI_THERMAL_DEVICE_COUNT 1
103
+/*Port and data associated with each device*/
104
+static struct smi_thermal_info smi_thermal_device_info[SMI_THERMAL_DEVICE_COUNT]
109
+ .setthrottlelimit = 0xDC,
110
+ .getthrottlelimit = 0xDD,
111
+ .getmaxthrottle = 0xDD,
114
+ .caps = DEVICE_CAPS_SW_PGM_THERMAL_EVENTS,
117
+ .class = THERMAL_MEM_CLASS,
122
+static int __init smi_devices_init(void)
126
+ struct thermal_device_ops *ops;
128
+ /*Query the ops interface from smi thermal driver*/
129
+ ops = smi_get_thermalops();
132
+ for (i = 0; i < SMI_THERMAL_DEVICE_COUNT; i++) {
133
+ smi_thermal_device_info[i].driver.ops = ops;
135
+ /*Register component driver with thermal zone driver*/
137
+ thermal_register_device_driver(&smi_thermal_device_info[i].
142
+ /*Register singleton device with thermal zone driver*/
144
+ (smi_thermal_device_info[i].td =
145
+ thermal_register_device(smi_thermal_device_info[i].
147
+ smi_thermal_device_info[i].
149
+ &smi_thermal_device_info[i]))) {
153
+ thermal_unregister_device_driver
154
+ (&smi_thermal_device_info[i].driver);
160
+static void __exit smi_devices_exit(void)
163
+ for (i = 0; i < SMI_THERMAL_DEVICE_COUNT; i++) {
164
+ thermal_unregister_device(smi_thermal_device_info[i].td);
165
+ thermal_unregister_device_driver(&smi_thermal_device_info[i].
170
+module_init(smi_devices_init);
171
+module_exit(smi_devices_exit);
172
+MODULE_ALIAS("smi_device_throttle");
173
diff --git a/drivers/acpi/smi_thermal.c b/drivers/acpi/smi_thermal.c
175
index 0000000..21e8e30
177
+++ b/drivers/acpi/smi_thermal.c
180
+ * smi_thermal.c - SMI thermal Driver ($Revision: 1 $)
182
+ * Copyright (C) 2006, 2007 Sujith Thomas <sujith.thomas@intel.com>
183
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185
+ * This program is free software; you can redistribute it and/or modify
186
+ * it under the terms of the GNU General Public License as published by
187
+ * the Free Software Foundation; version 2 of the License.
189
+ * This program is distributed in the hope that it will be useful, but
190
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
191
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
192
+ * General Public License for more details.
194
+ * You should have received a copy of the GNU General Public License along
195
+ * with this program; if not, write to the Free Software Foundation, Inc.,
196
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
198
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201
+#include <linux/kernel.h>
202
+#include <linux/module.h>
203
+#include <linux/init.h>
204
+#include <linux/types.h>
205
+#include <linux/pci.h>
206
+#include <linux/delay.h>
207
+#include <linux/smi_thermal.h>
209
+MODULE_AUTHOR("Sujith Thomas");
210
+MODULE_DESCRIPTION("SMI Device Throttle Driver");
211
+MODULE_LICENSE("GPL");
214
+ * getmaxthrottlestate
215
+ * -----------------------------
216
+ * call back function for getting the device's maximum throttle limit
217
+ * sinfo : smi_thermal_info
219
+static int get_max_throttle_limit(struct smi_thermal_info *sinfo)
221
+ int maxthrottlestate;
223
+ outb(sinfo->maxdat, sinfo->dataport);
224
+ outb(sinfo->getmaxthrottle, sinfo->cmdport);
226
+ maxthrottlestate = inb(sinfo->dataport);
228
+ return maxthrottlestate;
232
+ * smi_thermal_device_get_throttle_limit
233
+ * -----------------------------
234
+ * call back function for getting the device's current throttle limit
235
+ * data : smi_thermal_info
236
+ * buf : sysfs buffer that needs to be filled back
238
+static int smi_thermal_device_get_throttle_limit(void *data, char *buf)
241
+ int throttlevalue = 0;
243
+ struct smi_thermal_info *sinfo = (struct smi_thermal_info *)data;
249
+ outb(sinfo->getdat, sinfo->dataport);
250
+ outb(sinfo->getthrottlelimit, sinfo->cmdport);
252
+ throttlevalue = inb(sinfo->dataport);
254
+ s += sprintf(s, "%d\n", throttlevalue);
260
+ * smi_thermal_device_set_throttle_limit
261
+ * -----------------------------
262
+ * call back function for setting the device's new throttle limit
263
+ * data : smi_thermal_info
264
+ * buf : sysfs buffer that contains the new value
266
+static int smi_thermal_device_set_throttle_limit(enum throttle_set_type type,
267
+ void *data, const char *buf)
270
+ int maxthrottlestate = 0;
272
+ struct smi_thermal_info *sinfo = (struct smi_thermal_info *)data;
277
+ /*Only absolute value throttling is supported for time being*/
278
+ if (THROTTLE_ABS != type)
281
+ maxthrottlestate = get_max_throttle_limit(sinfo);
282
+ new_state = simple_strtol(buf, NULL, 0);
284
+ /* we need to check if state is <= max */
285
+ if (new_state >= maxthrottlestate || new_state < 0) {
288
+ /*Write new value*/
289
+ outb(new_state, sinfo->dataport);
290
+ outb(sinfo->setthrottlelimit, sinfo->cmdport);
296
+ * smi_thermal_device_get_throttle_limit
297
+ * -----------------------------
298
+ * call back function for getting the device's maximum throttle limit
299
+ * data : smi_thermal_info
300
+ * buf : sysfs buffer that needs to be filled back
302
+static int smi_thermal_device_get_maxthrottle_limit(void *data, char *buf)
304
+ int maxthrottlestate = 0;
306
+ struct smi_thermal_info *sinfo = (struct smi_thermal_info *)data;
311
+ maxthrottlestate = get_max_throttle_limit(sinfo);
313
+ s += sprintf(s, "%d\n", maxthrottlestate);
319
+ * smi_thermal_device_get_caps
320
+ * -----------------------------
321
+ * call back function for getting the device's capabilities
322
+ * data : smi_thermal_info
323
+ * buf : sysfs buffer that needs to be filled back
325
+static int smi_thermal_device_get_caps(void *data, char *buf)
328
+ struct smi_thermal_info *sinfo = NULL;
330
+ if (NULL == data || NULL == buf)
333
+ sinfo = (struct smi_thermal_info *)data;
335
+ s += sprintf(buf, "%lu \n", sinfo->caps);
340
+static struct thermal_device_ops smi_thermal_ops = {
341
+ .getthrottlelimit = smi_thermal_device_get_throttle_limit,
342
+ .setthrottlelimit = smi_thermal_device_set_throttle_limit,
343
+ .getmaxthrottlelimit = smi_thermal_device_get_maxthrottle_limit,
344
+ .getcaps = smi_thermal_device_get_caps,
348
+ * smi_get_thermalops
349
+ * -------------------
350
+ * Interface for other drivers which uses SMI for throttling
352
+struct thermal_device_ops *smi_get_thermalops(void)
354
+ return &smi_thermal_ops;
356
+EXPORT_SYMBOL(smi_get_thermalops);
358
+static int __init smi_thermal_init(void)
363
+static void __exit smi_thermal_exit(void)
368
+module_init(smi_thermal_init);
369
+module_exit(smi_thermal_exit);
371
+MODULE_ALIAS("smi_thermal");
372
diff --git a/include/linux/smi_thermal.h b/include/linux/smi_thermal.h
374
index 0000000..ba428ad
376
+++ b/include/linux/smi_thermal.h
379
+* smi_thermal.h - Generic smi driver for thermal extensions ($Revision: 1 $)
381
+* Copyright (C) 2006, 2007 Sujith Thomas <sujith.thomas@intel.com>
382
+* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
384
+* This program is free software; you can redistribute it and/or modify
385
+* it under the terms of the GNU General Public License as published by
386
+* the Free Software Foundation; version 2 of the License.
388
+* This program is distributed in the hope that it will be useful, but
389
+* WITHOUT ANY WARRANTY; without even the implied warranty of
390
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
391
+* General Public License for more details.
393
+* You should have received a copy of the GNU General Public License along
394
+* with this program; if not, write to the Free Software Foundation, Inc.,
395
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
397
+* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
403
+#include <linux/thermal.h>
405
+#define SMI_MAX_THROTTLE_LIMIT 8
407
+struct smi_thermal_info {
408
+ /*ACPI device name (eg:- TZ00)*/
409
+ char name[ACPI_MAX_CHAR];
410
+ /*Command port for SMI driver*/
411
+ unsigned int cmdport;
412
+ /*Data port for SMI driver*/
413
+ unsigned int dataport;
414
+ /*Command code for set new throttle limit*/
415
+ unsigned int setthrottlelimit;
416
+ /*Command code for get current throttle limit*/
417
+ unsigned int getthrottlelimit;
418
+ /*Command code for get max throttle limit*/
419
+ unsigned int getmaxthrottle;
420
+ /*Argument passed for getting max throttle limit*/
421
+ unsigned int maxdat;
422
+ /*Argument passed for getting current throttle limit*/
423
+ unsigned int getdat;
425
+ /*Device capabilities*/
426
+ unsigned long caps;
427
+ struct thermal_device *td;
428
+ struct thermal_device_driver driver;
432
+ * smi_get_thermalops
433
+ * -------------------
434
+ * Interface for other drivers which uses SMI for throttling
435
+ * for getting the callback functions
437
+struct thermal_device_ops *smi_get_thermalops(void);