Blame view

drivers/acpi/processor_driver.c 7.95 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
ac212b698   Rafael J. Wysocki   ACPI / processor:...
2
   * processor_driver.c - ACPI Processor Driver
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
   *
   *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
   *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
   *  			- Added processor hotplug support
ac212b698   Rafael J. Wysocki   ACPI / processor:...
9
10
   *  Copyright (C) 2013, Intel Corporation
   *                      Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  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; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  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.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
  #include <linux/cpufreq.h>
  #include <linux/cpu.h>
4f86d3a8e   Len Brown   cpuidle: consolid...
36
  #include <linux/cpuidle.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
37
  #include <linux/slab.h>
47db4547f   Toshi Kani   ACPI: Update CPU ...
38
  #include <linux/acpi.h>
ac212b698   Rafael J. Wysocki   ACPI / processor:...
39

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  #include <acpi/processor.h>
ac212b698   Rafael J. Wysocki   ACPI / processor:...
41
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
  #define ACPI_PROCESSOR_NOTIFY_POWER	0x81
01854e697   Luming Yu   ACPI: add ACPI 3....
44
  #define ACPI_PROCESSOR_NOTIFY_THROTTLING	0x82
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
0131aa3dd   Alex Chiang   ACPI: processor: ...
47
  ACPI_MODULE_NAME("processor_driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

f52fd66d2   Len Brown   ACPI: clean up AC...
49
  MODULE_AUTHOR("Paul Diefenbaugh");
7cda93e00   Len Brown   ACPI: delete extr...
50
  MODULE_DESCRIPTION("ACPI Processor Driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  MODULE_LICENSE("GPL");
ac212b698   Rafael J. Wysocki   ACPI / processor:...
52
53
  static int acpi_processor_start(struct device *dev);
  static int acpi_processor_stop(struct device *dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54

1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
55
  static const struct acpi_device_id processor_device_ids[] = {
ad93a765c   Myron Stowe   ACPI: Disambiguat...
56
  	{ACPI_PROCESSOR_OBJECT_HID, 0},
9f324bda9   Toshi Kani   ACPI: Add CPU hot...
57
  	{ACPI_PROCESSOR_DEVICE_HID, 0},
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
58
59
60
  	{"", 0},
  };
  MODULE_DEVICE_TABLE(acpi, processor_device_ids);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
61
  static struct device_driver acpi_processor_driver = {
c2b6705b7   Len Brown   ACPI: fix acpi_dr...
62
  	.name = "processor",
ac212b698   Rafael J. Wysocki   ACPI / processor:...
63
64
65
66
  	.bus = &cpu_subsys,
  	.acpi_match_table = processor_device_ids,
  	.probe = acpi_processor_start,
  	.remove = acpi_processor_stop,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  };
ac212b698   Rafael J. Wysocki   ACPI / processor:...
68
  static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  {
ac212b698   Rafael J. Wysocki   ACPI / processor:...
70
  	struct acpi_device *device = data;
b26e9286f   Myron Stowe   ACPI: Behave uniq...
71
  	struct acpi_processor *pr;
e790cc8bb   Alexey Starikovskiy   ACPI: EC: Workaro...
72
  	int saved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73

ac212b698   Rafael J. Wysocki   ACPI / processor:...
74
75
76
77
  	if (device->handle != handle)
  		return;
  
  	pr = acpi_driver_data(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  	if (!pr)
d550d98d3   Patrick Mochel   ACPI: delete trac...
79
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
  	switch (event) {
  	case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
e790cc8bb   Alexey Starikovskiy   ACPI: EC: Workaro...
83
  		saved = pr->performance_platform_limit;
d81c45e1c   Zhao Yakui   ACPI: Notify the ...
84
  		acpi_processor_ppc_has_changed(pr, 1);
e790cc8bb   Alexey Starikovskiy   ACPI: EC: Workaro...
85
86
  		if (saved == pr->performance_platform_limit)
  			break;
962ce8ca0   Zhang Rui   ACPI: don't dupli...
87
  		acpi_bus_generate_netlink_event(device->pnp.device_class,
0794469da   Kay Sievers   ACPI: struct devi...
88
  						  dev_name(&device->dev), event,
962ce8ca0   Zhang Rui   ACPI: don't dupli...
89
  						  pr->performance_platform_limit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
  		break;
  	case ACPI_PROCESSOR_NOTIFY_POWER:
  		acpi_processor_cst_has_changed(pr);
962ce8ca0   Zhang Rui   ACPI: don't dupli...
93
  		acpi_bus_generate_netlink_event(device->pnp.device_class,
0794469da   Kay Sievers   ACPI: struct devi...
94
  						  dev_name(&device->dev), event, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  		break;
01854e697   Luming Yu   ACPI: add ACPI 3....
96
97
  	case ACPI_PROCESSOR_NOTIFY_THROTTLING:
  		acpi_processor_tstate_has_changed(pr);
962ce8ca0   Zhang Rui   ACPI: don't dupli...
98
  		acpi_bus_generate_netlink_event(device->pnp.device_class,
0794469da   Kay Sievers   ACPI: struct devi...
99
  						  dev_name(&device->dev), event, 0);
879dca019   Alan Cox   ACPI: missing break
100
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
  	default:
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
103
104
  				  "Unsupported event [0x%x]
  ", event));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
  		break;
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
107
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
  }
fe7bf106e   Paul Gortmaker   acpi: delete __cp...
109
  static int __acpi_processor_start(struct acpi_device *device);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
110

fe7bf106e   Paul Gortmaker   acpi: delete __cp...
111
  static int acpi_cpu_soft_notify(struct notifier_block *nfb,
ac212b698   Rafael J. Wysocki   ACPI / processor:...
112
  					  unsigned long action, void *hcpu)
729c6ba33   Venkatesh Pallipadi   ACPI: Reevaluate ...
113
114
  {
  	unsigned int cpu = (unsigned long)hcpu;
706546d02   Mike Travis   ACPI: change proc...
115
  	struct acpi_processor *pr = per_cpu(processors, cpu);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
116
  	struct acpi_device *device;
729c6ba33   Venkatesh Pallipadi   ACPI: Reevaluate ...
117

ac212b698   Rafael J. Wysocki   ACPI / processor:...
118
119
120
121
122
123
124
  	if (!pr || acpi_bus_get_device(pr->handle, &device))
  		return NOTIFY_DONE;
  
  	if (action == CPU_ONLINE) {
  		/*
  		 * CPU got physically hotplugged and onlined for the first time:
  		 * Initialize missing things.
99b725084   Thomas Renninger   ACPI processor ho...
125
126
  		 */
  		if (pr->flags.need_hotplug_init) {
ac212b698   Rafael J. Wysocki   ACPI / processor:...
127
  			int ret;
47db4547f   Toshi Kani   ACPI: Update CPU ...
128
129
130
  			pr_info("Will online and init hotplugged CPU: %d
  ",
  				pr->id);
99b725084   Thomas Renninger   ACPI processor ho...
131
  			pr->flags.need_hotplug_init = 0;
ac212b698   Rafael J. Wysocki   ACPI / processor:...
132
133
134
  			ret = __acpi_processor_start(device);
  			WARN(ret, "Failed to start CPU: %d
  ", pr->id);
99b725084   Thomas Renninger   ACPI processor ho...
135
  		} else {
ac212b698   Rafael J. Wysocki   ACPI / processor:...
136
  			/* Normal CPU soft online event. */
99b725084   Thomas Renninger   ACPI processor ho...
137
  			acpi_processor_ppc_has_changed(pr, 0);
b7db60f45   Feng Tang   ACPI processor: F...
138
  			acpi_processor_hotplug(pr);
99b725084   Thomas Renninger   ACPI processor ho...
139
140
141
  			acpi_processor_reevaluate_tstate(pr, action);
  			acpi_processor_tstate_has_changed(pr);
  		}
ac212b698   Rafael J. Wysocki   ACPI / processor:...
142
143
  	} else if (action == CPU_DEAD) {
  		/* Invalidate flag.throttling after the CPU is offline. */
5a344a505   Zhao Yakui   ACPI: Reevaluate ...
144
145
  		acpi_processor_reevaluate_tstate(pr, action);
  	}
729c6ba33   Venkatesh Pallipadi   ACPI: Reevaluate ...
146
147
  	return NOTIFY_OK;
  }
764d02213   Mathieu Rhéaume   ACPI / processor:...
148
  static struct notifier_block __refdata acpi_cpu_notifier = {
729c6ba33   Venkatesh Pallipadi   ACPI: Reevaluate ...
149
150
  	    .notifier_call = acpi_cpu_soft_notify,
  };
fe7bf106e   Paul Gortmaker   acpi: delete __cp...
151
  static int __acpi_processor_start(struct acpi_device *device)
54d5dcc45   Thomas Renninger   ACPI processor ho...
152
  {
ac212b698   Rafael J. Wysocki   ACPI / processor:...
153
154
  	struct acpi_processor *pr = acpi_driver_data(device);
  	acpi_status status;
54d5dcc45   Thomas Renninger   ACPI processor ho...
155
  	int result = 0;
ac212b698   Rafael J. Wysocki   ACPI / processor:...
156
157
158
159
160
  	if (!pr)
  		return -ENODEV;
  
  	if (pr->flags.need_hotplug_init)
  		return 0;
54d5dcc45   Thomas Renninger   ACPI processor ho...
161
162
163
164
  #ifdef CONFIG_CPU_FREQ
  	acpi_processor_ppc_has_changed(pr, 0);
  #endif
  	acpi_processor_get_throttling_info(pr);
22e7551eb   Lan Tianyu   ACPI / processor:...
165
166
167
  
  	if (pr->flags.throttling)
  		pr->flags.limit = 1;
54d5dcc45   Thomas Renninger   ACPI processor ho...
168
169
  
  	if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
38a991b62   Daniel Lezcano   ACPI / processor:...
170
  		acpi_processor_power_init(pr);
54d5dcc45   Thomas Renninger   ACPI processor ho...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  
  	pr->cdev = thermal_cooling_device_register("Processor", device,
  						   &processor_cooling_ops);
  	if (IS_ERR(pr->cdev)) {
  		result = PTR_ERR(pr->cdev);
  		goto err_power_exit;
  	}
  
  	dev_dbg(&device->dev, "registered as cooling_device%d
  ",
  		pr->cdev->id);
  
  	result = sysfs_create_link(&device->dev.kobj,
  				   &pr->cdev->device.kobj,
  				   "thermal_cooling");
  	if (result) {
47db4547f   Toshi Kani   ACPI: Update CPU ...
187
188
189
  		dev_err(&device->dev,
  			"Failed to create sysfs link 'thermal_cooling'
  ");
54d5dcc45   Thomas Renninger   ACPI processor ho...
190
191
192
193
194
195
  		goto err_thermal_unregister;
  	}
  	result = sysfs_create_link(&pr->cdev->device.kobj,
  				   &device->dev.kobj,
  				   "device");
  	if (result) {
47db4547f   Toshi Kani   ACPI: Update CPU ...
196
197
198
  		dev_err(&pr->cdev->device,
  			"Failed to create sysfs link 'device'
  ");
54d5dcc45   Thomas Renninger   ACPI processor ho...
199
200
  		goto err_remove_sysfs_thermal;
  	}
ac212b698   Rafael J. Wysocki   ACPI / processor:...
201
202
203
204
  	status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
  					     acpi_processor_notify, device);
  	if (ACPI_SUCCESS(status))
  		return 0;
54d5dcc45   Thomas Renninger   ACPI processor ho...
205

ac212b698   Rafael J. Wysocki   ACPI / processor:...
206
207
  	sysfs_remove_link(&pr->cdev->device.kobj, "device");
   err_remove_sysfs_thermal:
54d5dcc45   Thomas Renninger   ACPI processor ho...
208
  	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
ac212b698   Rafael J. Wysocki   ACPI / processor:...
209
   err_thermal_unregister:
54d5dcc45   Thomas Renninger   ACPI processor ho...
210
  	thermal_cooling_device_unregister(pr->cdev);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
211
   err_power_exit:
38a991b62   Daniel Lezcano   ACPI / processor:...
212
  	acpi_processor_power_exit(pr);
54d5dcc45   Thomas Renninger   ACPI processor ho...
213
214
  	return result;
  }
fe7bf106e   Paul Gortmaker   acpi: delete __cp...
215
  static int acpi_processor_start(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  {
d0a7edbb6   Lan Tianyu   ACPI / processor:...
217
  	struct acpi_device *device = ACPI_COMPANION(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

d0a7edbb6   Lan Tianyu   ACPI / processor:...
219
  	if (!device)
ac212b698   Rafael J. Wysocki   ACPI / processor:...
220
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

ac212b698   Rafael J. Wysocki   ACPI / processor:...
222
  	return __acpi_processor_start(device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  }
ac212b698   Rafael J. Wysocki   ACPI / processor:...
224
  static int acpi_processor_stop(struct device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  {
d0a7edbb6   Lan Tianyu   ACPI / processor:...
226
  	struct acpi_device *device = ACPI_COMPANION(dev);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
227
  	struct acpi_processor *pr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

d0a7edbb6   Lan Tianyu   ACPI / processor:...
229
  	if (!device)
ac212b698   Rafael J. Wysocki   ACPI / processor:...
230
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231

ac212b698   Rafael J. Wysocki   ACPI / processor:...
232
233
  	acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
  				   acpi_processor_notify);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234

50dd09697   Jan Engelhardt   ACPI: Remove unne...
235
  	pr = acpi_driver_data(device);
ac212b698   Rafael J. Wysocki   ACPI / processor:...
236
237
  	if (!pr)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
238

38a991b62   Daniel Lezcano   ACPI / processor:...
239
  	acpi_processor_power_exit(pr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240

f28bb45e2   Zhao Yakui   ACPI: thermal: Ch...
241
242
243
244
245
246
  	if (pr->cdev) {
  		sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
  		sysfs_remove_link(&pr->cdev->device.kobj, "device");
  		thermal_cooling_device_unregister(pr->cdev);
  		pr->cdev = NULL;
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
247
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
252
253
  /*
   * We keep the driver loaded even when ACPI is not running.
   * This is needed for the powernow-k8 driver, that works even without
   * ACPI, but needs symbols from this driver
   */
ac212b698   Rafael J. Wysocki   ACPI / processor:...
254
  static int __init acpi_processor_driver_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
256
  	int result = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

ce8442b55   Yinghai Lu   acpi: don't call ...
258
259
  	if (acpi_disabled)
  		return 0;
ac212b698   Rafael J. Wysocki   ACPI / processor:...
260
  	result = driver_register(&acpi_processor_driver);
4f86d3a8e   Len Brown   cpuidle: consolid...
261
  	if (result < 0)
46bcfad7a   Deepthi Dharwar   cpuidle: Single/G...
262
  		return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

0a3b15ac3   Rafael J. Wysocki   ACPI / PM: Move p...
264
  	acpi_processor_syscore_init();
ac212b698   Rafael J. Wysocki   ACPI / processor:...
265
  	register_hotcpu_notifier(&acpi_cpu_notifier);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
  	acpi_thermal_cpufreq_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  	acpi_processor_ppc_init();
1180509f6   Zhao Yakui   ACPI : Update T-s...
268
  	acpi_processor_throttling_init();
d550d98d3   Patrick Mochel   ACPI: delete trac...
269
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  }
ac212b698   Rafael J. Wysocki   ACPI / processor:...
271
  static void __exit acpi_processor_driver_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  {
ce8442b55   Yinghai Lu   acpi: don't call ...
273
274
  	if (acpi_disabled)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  	acpi_processor_ppc_exit();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  	acpi_thermal_cpufreq_exit();
ac212b698   Rafael J. Wysocki   ACPI / processor:...
277
  	unregister_hotcpu_notifier(&acpi_cpu_notifier);
0a3b15ac3   Rafael J. Wysocki   ACPI / PM: Move p...
278
  	acpi_processor_syscore_exit();
ac212b698   Rafael J. Wysocki   ACPI / processor:...
279
  	driver_unregister(&acpi_processor_driver);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  }
ac212b698   Rafael J. Wysocki   ACPI / processor:...
281
282
  module_init(acpi_processor_driver_init);
  module_exit(acpi_processor_driver_exit);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  MODULE_ALIAS("processor");