Blame view

drivers/acpi/bus.c 33.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   *  acpi_bus.c - ACPI Bus Driver ($Revision: 80 $)
   *
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  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.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/ioport.h>
d568df84f   Randy Dunlap   ACPI: handle firm...
24
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
  #include <linux/list.h>
  #include <linux/sched.h>
  #include <linux/pm.h>
  #include <linux/device.h>
  #include <linux/proc_fs.h>
6697c0529   Harvey Harrison   x86: fix sparse w...
30
  #include <linux/acpi.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
49a12877d   Mark Brown   ACPI / init: Flag...
32
  #include <linux/regulator/machine.h>
baa0c019b   Prakash, Prashanth   ACPI / bus: Suppo...
33
34
35
  #include <linux/workqueue.h>
  #include <linux/reboot.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
  #ifdef CONFIG_X86
  #include <asm/mpspec.h>
  #endif
88ef16d88   Tomasz Nowicki   ACPI: I/O Remappi...
39
  #include <linux/acpi_iort.h>
7752d5cfe   Robert Hancock   x86: validate aga...
40
  #include <linux/pci.h>
eccddd32c   Huang Ying   ACPI, APEI, Add A...
41
  #include <acpi/apei.h>
eb27cae8a   Len Brown   ACPI: linux/acpi....
42
  #include <linux/dmi.h>
cd51e61cf   Rafael J. Wysocki   PM / ACPI: Remove...
43
  #include <linux/suspend.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

e60cc7a6f   Bjorn Helgaas   ACPI: move privat...
45
  #include "internal.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  #define _COMPONENT		ACPI_BUS_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
47
  ACPI_MODULE_NAME("bus");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48

4be44fcd3   Len Brown   [ACPI] Lindent al...
49
50
  struct acpi_device *acpi_root;
  struct proc_dir_entry *acpi_root_dir;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  EXPORT_SYMBOL(acpi_root_dir);
cce4f632d   Lin Ming   ACPI: fix early D...
52
  #ifdef CONFIG_X86
73577d1df   Lv Zheng   ACPI: Fix conflic...
53
54
55
56
57
58
  #ifdef CONFIG_ACPI_CUSTOM_DSDT
  static inline int set_copy_dsdt(const struct dmi_system_id *id)
  {
  	return 0;
  }
  #else
aa2110cb1   Lin Ming   ACPI: add boot op...
59
60
61
62
63
64
65
66
  static int set_copy_dsdt(const struct dmi_system_id *id)
  {
  	printk(KERN_NOTICE "%s detected - "
  		"force copy of DSDT to local memory
  ", id->ident);
  	acpi_gbl_copy_dsdt_locally = 1;
  	return 0;
  }
73577d1df   Lv Zheng   ACPI: Fix conflic...
67
  #endif
b2190cc39   Kai Heng Feng   ACPI / bus: Parse...
68
69
70
71
72
  static int set_gbl_term_list(const struct dmi_system_id *id)
  {
  	acpi_gbl_parse_table_as_term_list = 1;
  	return 0;
  }
aa2110cb1   Lin Ming   ACPI: add boot op...
73

b2190cc39   Kai Heng Feng   ACPI / bus: Parse...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
  	/*
  	 * Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C
  	 * mode.
  	 * https://bugzilla.kernel.org/show_bug.cgi?id=198515
  	 */
  	{
  		.callback = set_gbl_term_list,
  		.ident = "Dell Precision M5530",
  		.matches = {
  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  			DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"),
  		},
  	},
  	{
  		.callback = set_gbl_term_list,
  		.ident = "Dell XPS 15 9570",
  		.matches = {
  			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
  			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"),
  		},
  	},
aa2110cb1   Lin Ming   ACPI: add boot op...
96
  	/*
100cf8778   Len Brown   ACPI: invoke DSDT...
97
  	 * Invoke DSDT corruption work-around on all Toshiba Satellite.
b2190cc39   Kai Heng Feng   ACPI / bus: Parse...
98
  	 * DSDT will be copied to memory.
aa2110cb1   Lin Ming   ACPI: add boot op...
99
100
101
102
  	 * https://bugzilla.kernel.org/show_bug.cgi?id=14679
  	 */
  	{
  	 .callback = set_copy_dsdt,
100cf8778   Len Brown   ACPI: invoke DSDT...
103
  	 .ident = "TOSHIBA Satellite",
aa2110cb1   Lin Ming   ACPI: add boot op...
104
105
  	 .matches = {
  		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
100cf8778   Len Brown   ACPI: invoke DSDT...
106
  		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
aa2110cb1   Lin Ming   ACPI: add boot op...
107
  		},
cce4f632d   Lin Ming   ACPI: fix early D...
108
109
  	},
  	{}
aa2110cb1   Lin Ming   ACPI: add boot op...
110
  };
cce4f632d   Lin Ming   ACPI: fix early D...
111
  #else
b2190cc39   Kai Heng Feng   ACPI / bus: Parse...
112
  static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = {
cce4f632d   Lin Ming   ACPI: fix early D...
113
114
115
  	{}
  };
  #endif
aa2110cb1   Lin Ming   ACPI: add boot op...
116

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
118
119
  /* --------------------------------------------------------------------------
                                  Device Management
     -------------------------------------------------------------------------- */
402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
120
121
  acpi_status acpi_bus_get_status_handle(acpi_handle handle,
  				       unsigned long long *sta)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  {
402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
123
  	acpi_status status;
4be44fcd3   Len Brown   [ACPI] Lindent al...
124

402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
125
126
127
  	status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
  	if (ACPI_SUCCESS(status))
  		return AE_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
129
130
131
132
  	if (status == AE_NOT_FOUND) {
  		*sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
  		       ACPI_STA_DEVICE_UI      | ACPI_STA_DEVICE_FUNCTIONING;
  		return AE_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  	}
402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
134
135
  	return status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
137
138
139
140
  int acpi_bus_get_status(struct acpi_device *device)
  {
  	acpi_status status;
  	unsigned long long sta;
b7ecf663c   Hans de Goede   ACPI / bus: Intro...
141
142
143
144
  	if (acpi_device_always_present(device)) {
  		acpi_set_device_status(device, ACPI_STA_DEFAULT);
  		return 0;
  	}
f920e9148   Hans de Goede   ACPI / bus: Do no...
145
146
147
148
149
  	/* Battery devices must have their deps met before calling _STA */
  	if (acpi_device_is_battery(device) && device->dep_unmet) {
  		acpi_set_device_status(device, 0);
  		return 0;
  	}
402ac5361   Bjorn Helgaas   ACPI: add acpi_bu...
150
151
152
  	status = acpi_bus_get_status_handle(device->handle, &sta);
  	if (ACPI_FAILURE(status))
  		return -ENODEV;
25db115b0   Rafael J. Wysocki   ACPI: Introduce a...
153
  	acpi_set_device_status(device, sta);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
  
  	if (device->status.functional && !device->status.present) {
39a0ad871   Zhao Yakui   ACPI : Load devic...
156
157
158
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
  		       "functional but not present;
  ",
25db115b0   Rafael J. Wysocki   ACPI: Introduce a...
159
  			device->pnp.bus_id, (u32)sta));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
161
162
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]
  ",
25db115b0   Rafael J. Wysocki   ACPI: Introduce a...
163
  			  device->pnp.bus_id, (u32)sta));
d550d98d3   Patrick Mochel   ACPI: delete trac...
164
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
166
  EXPORT_SYMBOL(acpi_bus_get_status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167

207339398   Zhang Rui   ACPI: attach ther...
168
  void acpi_bus_private_data_handler(acpi_handle handle,
8e4319c42   Bob Moore   ACPICA: Fix sever...
169
  				   void *context)
207339398   Zhang Rui   ACPI: attach ther...
170
171
172
173
  {
  	return;
  }
  EXPORT_SYMBOL(acpi_bus_private_data_handler);
72013795a   Lan Tianyu   ACPI: Add acpi_bu...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
  int acpi_bus_attach_private_data(acpi_handle handle, void *data)
  {
  	acpi_status status;
  
  	status = acpi_attach_data(handle,
  			acpi_bus_private_data_handler, data);
  	if (ACPI_FAILURE(status)) {
  		acpi_handle_debug(handle, "Error attaching device data
  ");
  		return -ENODEV;
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(acpi_bus_attach_private_data);
207339398   Zhang Rui   ACPI: attach ther...
189
190
  int acpi_bus_get_private_data(acpi_handle handle, void **data)
  {
6a8c0af6e   Bjorn Helgaas   ACPI: Remove usel...
191
  	acpi_status status;
207339398   Zhang Rui   ACPI: attach ther...
192
193
194
195
196
  
  	if (!*data)
  		return -EINVAL;
  
  	status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
72013795a   Lan Tianyu   ACPI: Add acpi_bu...
197
198
199
  	if (ACPI_FAILURE(status)) {
  		acpi_handle_debug(handle, "No context for object
  ");
207339398   Zhang Rui   ACPI: attach ther...
200
201
202
203
204
  		return -ENODEV;
  	}
  
  	return 0;
  }
72013795a   Lan Tianyu   ACPI: Add acpi_bu...
205
206
207
208
209
210
211
  EXPORT_SYMBOL_GPL(acpi_bus_get_private_data);
  
  void acpi_bus_detach_private_data(acpi_handle handle)
  {
  	acpi_detach_data(handle, acpi_bus_private_data_handler);
  }
  EXPORT_SYMBOL_GPL(acpi_bus_detach_private_data);
207339398   Zhang Rui   ACPI: attach ther...
212

70023de88   Shaohua Li   ACPI: Add a gener...
213
  static void acpi_print_osc_error(acpi_handle handle,
f26f5c8b8   Rafael J. Wysocki   ACPI / bus: Use a...
214
  				 struct acpi_osc_context *context, char *error)
70023de88   Shaohua Li   ACPI: Add a gener...
215
  {
70023de88   Shaohua Li   ACPI: Add a gener...
216
  	int i;
f26f5c8b8   Rafael J. Wysocki   ACPI / bus: Use a...
217
218
219
220
  	acpi_handle_debug(handle, "(%s): %s
  ", context->uuid_str, error);
  
  	pr_debug("_OSC request data:");
70023de88   Shaohua Li   ACPI: Add a gener...
221
  	for (i = 0; i < context->cap.length; i += sizeof(u32))
f26f5c8b8   Rafael J. Wysocki   ACPI / bus: Use a...
222
223
224
225
  		pr_debug(" %x", *((u32 *)(context->cap.pointer + i)));
  
  	pr_debug("
  ");
70023de88   Shaohua Li   ACPI: Add a gener...
226
  }
70023de88   Shaohua Li   ACPI: Add a gener...
227
228
229
230
231
232
  acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
  {
  	acpi_status status;
  	struct acpi_object_list input;
  	union acpi_object in_params[4];
  	union acpi_object *out_obj;
dfcaad8fa   Andy Shevchenko   ACPI / bus: Switc...
233
  	guid_t guid;
70023de88   Shaohua Li   ACPI: Add a gener...
234
  	u32 errors;
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
235
  	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
70023de88   Shaohua Li   ACPI: Add a gener...
236
237
238
  
  	if (!context)
  		return AE_ERROR;
dfcaad8fa   Andy Shevchenko   ACPI / bus: Switc...
239
  	if (guid_parse(context->uuid_str, &guid))
70023de88   Shaohua Li   ACPI: Add a gener...
240
241
242
243
244
245
246
247
248
  		return AE_ERROR;
  	context->ret.length = ACPI_ALLOCATE_BUFFER;
  	context->ret.pointer = NULL;
  
  	/* Setting up input parameters */
  	input.count = 4;
  	input.pointer = in_params;
  	in_params[0].type 		= ACPI_TYPE_BUFFER;
  	in_params[0].buffer.length 	= 16;
dfcaad8fa   Andy Shevchenko   ACPI / bus: Switc...
249
  	in_params[0].buffer.pointer	= (u8 *)&guid;
70023de88   Shaohua Li   ACPI: Add a gener...
250
251
252
253
254
255
256
  	in_params[1].type 		= ACPI_TYPE_INTEGER;
  	in_params[1].integer.value 	= context->rev;
  	in_params[2].type 		= ACPI_TYPE_INTEGER;
  	in_params[2].integer.value	= context->cap.length/sizeof(u32);
  	in_params[3].type		= ACPI_TYPE_BUFFER;
  	in_params[3].buffer.length 	= context->cap.length;
  	in_params[3].buffer.pointer 	= context->cap.pointer;
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
257
  	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
70023de88   Shaohua Li   ACPI: Add a gener...
258
259
  	if (ACPI_FAILURE(status))
  		return status;
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
260
  	if (!output.length)
70023de88   Shaohua Li   ACPI: Add a gener...
261
  		return AE_NULL_OBJECT;
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
262
263
264
  	out_obj = output.pointer;
  	if (out_obj->type != ACPI_TYPE_BUFFER
  		|| out_obj->buffer.length != context->cap.length) {
70023de88   Shaohua Li   ACPI: Add a gener...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  		acpi_print_osc_error(handle, context,
  			"_OSC evaluation returned wrong type");
  		status = AE_TYPE;
  		goto out_kfree;
  	}
  	/* Need to ignore the bit0 in result code */
  	errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
  	if (errors) {
  		if (errors & OSC_REQUEST_ERROR)
  			acpi_print_osc_error(handle, context,
  				"_OSC request failed");
  		if (errors & OSC_INVALID_UUID_ERROR)
  			acpi_print_osc_error(handle, context,
  				"_OSC invalid UUID");
  		if (errors & OSC_INVALID_REVISION_ERROR)
  			acpi_print_osc_error(handle, context,
  				"_OSC invalid revision");
  		if (errors & OSC_CAPABILITIES_MASK_ERROR) {
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
283
  			if (((u32 *)context->cap.pointer)[OSC_QUERY_DWORD]
70023de88   Shaohua Li   ACPI: Add a gener...
284
285
286
287
288
289
290
291
292
  			    & OSC_QUERY_ENABLE)
  				goto out_success;
  			status = AE_SUPPORT;
  			goto out_kfree;
  		}
  		status = AE_ERROR;
  		goto out_kfree;
  	}
  out_success:
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
293
  	context->ret.length = out_obj->buffer.length;
e2cb5f084   Andrei Epure   ACPI: replace kma...
294
295
  	context->ret.pointer = kmemdup(out_obj->buffer.pointer,
  				       context->ret.length, GFP_KERNEL);
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
296
297
298
299
  	if (!context->ret.pointer) {
  		status =  AE_NO_MEMORY;
  		goto out_kfree;
  	}
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
300
  	status =  AE_OK;
70023de88   Shaohua Li   ACPI: Add a gener...
301
302
  
  out_kfree:
9dc130fcc   Shaohua Li   ACPI: fix OSC reg...
303
304
305
  	kfree(output.pointer);
  	if (status != AE_OK)
  		context->ret.pointer = NULL;
70023de88   Shaohua Li   ACPI: Add a gener...
306
307
308
  	return status;
  }
  EXPORT_SYMBOL(acpi_run_osc);
eccddd32c   Huang Ying   ACPI, APEI, Add A...
309
  bool osc_sb_apei_support_acked;
a36a7fecf   Sudeep Holla   ACPI / processor_...
310
311
312
313
314
315
316
  
  /*
   * ACPI 6.0 Section 8.4.4.2 Idle State Coordination
   * OSPM supports platform coordinated low power idle(LPI) states
   */
  bool osc_pc_lpi_support_confirmed;
  EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed);
3563ff964   Shaohua Li   ACPI: Add platfor...
317
318
319
320
321
322
323
324
325
326
327
  static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
  static void acpi_bus_osc_support(void)
  {
  	u32 capbuf[2];
  	struct acpi_osc_context context = {
  		.uuid_str = sb_uuid_str,
  		.rev = 1,
  		.cap.length = 8,
  		.cap.pointer = capbuf,
  	};
  	acpi_handle handle;
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
328
329
  	capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
  	capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
bcb2b0b2b   Sudeep Holla   ACPI: Eliminate C...
330
331
332
333
  	if (IS_ENABLED(CONFIG_ACPI_PROCESSOR_AGGREGATOR))
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
  	if (IS_ENABLED(CONFIG_ACPI_PROCESSOR))
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
eccddd32c   Huang Ying   ACPI, APEI, Add A...
334

b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
335
  	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
a36a7fecf   Sudeep Holla   ACPI / processor_...
336
  	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
c2f4191a9   Toshi Kani   ACPI: Set hotplug...
337

5c2832e91   Srinivas Pandruvada   acpi/bus: Enable ...
338
339
340
341
342
343
  #ifdef CONFIG_X86
  	if (boot_cpu_has(X86_FEATURE_HWP)) {
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_SUPPORT;
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPCV2_SUPPORT;
  	}
  #endif
de966cf4a   Tim Chen   sched/x86: Change...
344
  	if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
8b533a0ee   Srinivas Pandruvada   acpi/bus: Set _OS...
345
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;
eccddd32c   Huang Ying   ACPI, APEI, Add A...
346
  	if (!ghes_disable)
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
347
  		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
3563ff964   Shaohua Li   ACPI: Add platfor...
348
349
  	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
  		return;
eccddd32c   Huang Ying   ACPI, APEI, Add A...
350
351
  	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
  		u32 *capbuf_ret = context.ret.pointer;
a36a7fecf   Sudeep Holla   ACPI / processor_...
352
  		if (context.ret.length > OSC_SUPPORT_DWORD) {
eccddd32c   Huang Ying   ACPI, APEI, Add A...
353
  			osc_sb_apei_support_acked =
b938a229c   Bjorn Helgaas   ACPI: Rename OSC_...
354
  				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
a36a7fecf   Sudeep Holla   ACPI / processor_...
355
356
357
  			osc_pc_lpi_support_confirmed =
  				capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
  		}
3563ff964   Shaohua Li   ACPI: Add platfor...
358
  		kfree(context.ret.pointer);
eccddd32c   Huang Ying   ACPI, APEI, Add A...
359
360
  	}
  	/* do we need to check other returned cap? Sounds no */
3563ff964   Shaohua Li   ACPI: Add platfor...
361
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  /* --------------------------------------------------------------------------
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
                               Notification Handling
     -------------------------------------------------------------------------- */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
369
  /**
   * acpi_bus_notify
   * ---------------
   * Callback for all 'system-level' device notifications (values 0x00-0x7F).
   */
4be44fcd3   Len Brown   [ACPI] Lindent al...
370
  static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  {
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
372
  	struct acpi_device *adev;
6d2781310   Bjorn Helgaas   ACPI: allow drive...
373
  	struct acpi_driver *driver;
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
374
  	u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
d0103387b   Rafael J. Wysocki   ACPI / notify: Cl...
375
  	bool hotplug_event = false;
02c37bd8d   Bjorn Helgaas   ACPI: simplify no...
376

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  	switch (type) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  	case ACPI_NOTIFY_BUS_CHECK:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
379
380
  		acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event
  ");
d0103387b   Rafael J. Wysocki   ACPI / notify: Cl...
381
  		hotplug_event = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
  		break;
  
  	case ACPI_NOTIFY_DEVICE_CHECK:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
385
386
  		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event
  ");
d0103387b   Rafael J. Wysocki   ACPI / notify: Cl...
387
  		hotplug_event = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
  		break;
  
  	case ACPI_NOTIFY_DEVICE_WAKE:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
391
392
  		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_WAKE event
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
  		break;
  
  	case ACPI_NOTIFY_EJECT_REQUEST:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
396
397
  		acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event
  ");
d0103387b   Rafael J. Wysocki   ACPI / notify: Cl...
398
  		hotplug_event = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
400
401
  		break;
  
  	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
402
403
  		acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK_LIGHT event
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
  		/* TBD: Exactly what does 'light' mean? */
  		break;
  
  	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
408
409
410
  		acpi_handle_err(handle, "Device cannot be configured due "
  				"to a frequency mismatch
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
  		break;
  
  	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
414
415
416
  		acpi_handle_err(handle, "Device cannot be configured due "
  				"to a bus mode mismatch
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
  		break;
  
  	case ACPI_NOTIFY_POWER_FAULT:
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
420
421
  		acpi_handle_err(handle, "Device has suffered a power fault
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
  		break;
  
  	default:
f66abe92c   Rafael J. Wysocki   ACPI / notify: Do...
425
426
427
  		acpi_handle_debug(handle, "Unknown event type 0x%x
  ", type);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
  	}
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
429
430
431
  	adev = acpi_bus_get_acpi_device(handle);
  	if (!adev)
  		goto err;
78ea4639a   Rafael J. Wysocki   ACPI / hotplug: F...
432

1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
433
434
435
436
  	driver = adev->driver;
  	if (driver && driver->ops.notify &&
  	    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
  		driver->ops.notify(adev, type);
9a4d8d60d   Lee, Chun-Yi   ACPI / bus: handl...
437
438
439
440
441
442
  	if (!hotplug_event) {
  		acpi_bus_put_acpi_device(adev);
  		return;
  	}
  
  	if (ACPI_SUCCESS(acpi_hotplug_schedule(adev, type)))
d0103387b   Rafael J. Wysocki   ACPI / notify: Cl...
443
  		return;
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
444
  	acpi_bus_put_acpi_device(adev);
1a699476e   Rafael J. Wysocki   ACPI / hotplug / ...
445
446
  
   err:
700b8422f   Rafael J. Wysocki   ACPI: Drop acpi_e...
447
  	acpi_evaluate_ost(handle, type, ost_code, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
  }
5894b0c46   Rafael J. Wysocki   ACPI / scan: Move...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
  static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
  {
  	struct acpi_device *device = data;
  
  	device->driver->ops.notify(device, event);
  }
  
  static void acpi_device_notify_fixed(void *data)
  {
  	struct acpi_device *device = data;
  
  	/* Fixed hardware devices have no handles */
  	acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
  }
  
  static u32 acpi_device_fixed_event(void *data)
  {
  	acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
  	return ACPI_INTERRUPT_HANDLED;
  }
  
  static int acpi_device_install_notify_handler(struct acpi_device *device)
  {
  	acpi_status status;
  
  	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
  		status =
  		    acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
  						     acpi_device_fixed_event,
  						     device);
  	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
  		status =
  		    acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
  						     acpi_device_fixed_event,
  						     device);
  	else
  		status = acpi_install_notify_handler(device->handle,
  						     ACPI_DEVICE_NOTIFY,
  						     acpi_device_notify,
  						     device);
  
  	if (ACPI_FAILURE(status))
  		return -EINVAL;
  	return 0;
  }
  
  static void acpi_device_remove_notify_handler(struct acpi_device *device)
  {
  	if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
  		acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
  						acpi_device_fixed_event);
  	else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
  		acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
  						acpi_device_fixed_event);
  	else
  		acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
  					   acpi_device_notify);
  }
baa0c019b   Prakash, Prashanth   ACPI / bus: Suppo...
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
  /* Handle events targeting \_SB device (at present only graceful shutdown) */
  
  #define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81
  #define ACPI_SB_INDICATE_INTERVAL	10000
  
  static void sb_notify_work(struct work_struct *dummy)
  {
  	acpi_handle sb_handle;
  
  	orderly_poweroff(true);
  
  	/*
  	 * After initiating graceful shutdown, the ACPI spec requires OSPM
  	 * to evaluate _OST method once every 10seconds to indicate that
  	 * the shutdown is in progress
  	 */
  	acpi_get_handle(NULL, "\\_SB", &sb_handle);
  	while (1) {
  		pr_info("Graceful shutdown in progress.
  ");
  		acpi_evaluate_ost(sb_handle, ACPI_OST_EC_OSPM_SHUTDOWN,
  				ACPI_OST_SC_OS_SHUTDOWN_IN_PROGRESS, NULL);
  		msleep(ACPI_SB_INDICATE_INTERVAL);
  	}
  }
  
  static void acpi_sb_notify(acpi_handle handle, u32 event, void *data)
  {
  	static DECLARE_WORK(acpi_sb_work, sb_notify_work);
  
  	if (event == ACPI_SB_NOTIFY_SHUTDOWN_REQUEST) {
  		if (!work_busy(&acpi_sb_work))
  			schedule_work(&acpi_sb_work);
  	} else
  		pr_warn("event %x is not supported by \\_SB device
  ", event);
  }
  
  static int __init acpi_setup_sb_notify_handler(void)
  {
  	acpi_handle sb_handle;
  
  	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &sb_handle)))
  		return -ENXIO;
  
  	if (ACPI_FAILURE(acpi_install_notify_handler(sb_handle, ACPI_DEVICE_NOTIFY,
  						acpi_sb_notify, NULL)))
  		return -EINVAL;
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
  /* --------------------------------------------------------------------------
68c6b148d   Rafael J. Wysocki   ACPI / scan: Move...
559
560
                               Device Matching
     -------------------------------------------------------------------------- */
3b95bd160   Aleksey Makarov   ACPI: introduce a...
561
562
563
564
565
566
567
  /**
   * acpi_get_first_physical_node - Get first physical node of an ACPI device
   * @adev:	ACPI device in question
   *
   * Return: First physical node of ACPI device @adev
   */
  struct device *acpi_get_first_physical_node(struct acpi_device *adev)
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
568
569
  {
  	struct mutex *physical_node_lock = &adev->physical_node_lock;
3b95bd160   Aleksey Makarov   ACPI: introduce a...
570
  	struct device *phys_dev;
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
571
572
573
  
  	mutex_lock(physical_node_lock);
  	if (list_empty(&adev->physical_node_list)) {
3b95bd160   Aleksey Makarov   ACPI: introduce a...
574
  		phys_dev = NULL;
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
575
576
577
578
579
  	} else {
  		const struct acpi_device_physical_node *node;
  
  		node = list_first_entry(&adev->physical_node_list,
  					struct acpi_device_physical_node, node);
3b95bd160   Aleksey Makarov   ACPI: introduce a...
580
581
  
  		phys_dev = node->dev;
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
582
583
  	}
  	mutex_unlock(physical_node_lock);
3b95bd160   Aleksey Makarov   ACPI: introduce a...
584
585
586
587
588
589
590
591
592
  	return phys_dev;
  }
  
  static struct acpi_device *acpi_primary_dev_companion(struct acpi_device *adev,
  						      const struct device *dev)
  {
  	const struct device *phys_dev = acpi_get_first_physical_node(adev);
  
  	return phys_dev && phys_dev == dev ? adev : NULL;
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
593
  }
3431e490b   Rafael J. Wysocki   Merge branch 'acp...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  /**
   * acpi_device_is_first_physical_node - Is given dev first physical node
   * @adev: ACPI companion device
   * @dev: Physical device to check
   *
   * Function checks if given @dev is the first physical devices attached to
   * the ACPI companion device. This distinction is needed in some cases
   * where the same companion device is shared between many physical devices.
   *
   * Note that the caller have to provide valid @adev pointer.
   */
  bool acpi_device_is_first_physical_node(struct acpi_device *adev,
  					const struct device *dev)
  {
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
608
  	return !!acpi_primary_dev_companion(adev, dev);
3431e490b   Rafael J. Wysocki   Merge branch 'acp...
609
  }
68c6b148d   Rafael J. Wysocki   ACPI / scan: Move...
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  /*
   * acpi_companion_match() - Can we match via ACPI companion device
   * @dev: Device in question
   *
   * Check if the given device has an ACPI companion and if that companion has
   * a valid list of PNP IDs, and if the device is the first (primary) physical
   * device associated with it.  Return the companion pointer if that's the case
   * or NULL otherwise.
   *
   * If multiple physical devices are attached to a single ACPI companion, we need
   * to be careful.  The usage scenario for this kind of relationship is that all
   * of the physical devices in question use resources provided by the ACPI
   * companion.  A typical case is an MFD device where all the sub-devices share
   * the parent's ACPI companion.  In such cases we can only allow the primary
   * (first) physical device to be matched with the help of the companion's PNP
   * IDs.
   *
   * Additional physical devices sharing the ACPI companion can still use
   * resources available from it but they will be matched normally using functions
   * provided by their bus types (and analogously for their modalias).
   */
  struct acpi_device *acpi_companion_match(const struct device *dev)
  {
  	struct acpi_device *adev;
68c6b148d   Rafael J. Wysocki   ACPI / scan: Move...
634
635
636
637
638
639
640
  
  	adev = ACPI_COMPANION(dev);
  	if (!adev)
  		return NULL;
  
  	if (list_empty(&adev->pnp.ids))
  		return NULL;
e91a398c3   Rafael J. Wysocki   ACPI / bus: Move ...
641
  	return acpi_primary_dev_companion(adev, dev);
68c6b148d   Rafael J. Wysocki   ACPI / scan: Move...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
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
  }
  
  /**
   * acpi_of_match_device - Match device object using the "compatible" property.
   * @adev: ACPI device object to match.
   * @of_match_table: List of device IDs to match against.
   *
   * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
   * identifiers and a _DSD object with the "compatible" property, use that
   * property to match against the given list of identifiers.
   */
  static bool acpi_of_match_device(struct acpi_device *adev,
  				 const struct of_device_id *of_match_table)
  {
  	const union acpi_object *of_compatible, *obj;
  	int i, nval;
  
  	if (!adev)
  		return false;
  
  	of_compatible = adev->data.of_compatible;
  	if (!of_match_table || !of_compatible)
  		return false;
  
  	if (of_compatible->type == ACPI_TYPE_PACKAGE) {
  		nval = of_compatible->package.count;
  		obj = of_compatible->package.elements;
  	} else { /* Must be ACPI_TYPE_STRING. */
  		nval = 1;
  		obj = of_compatible;
  	}
  	/* Now we can look for the driver DT compatible strings */
  	for (i = 0; i < nval; i++, obj++) {
  		const struct of_device_id *id;
  
  		for (id = of_match_table; id->compatible[0]; id++)
  			if (!strcasecmp(obj->string.pointer, id->compatible))
  				return true;
  	}
  
  	return false;
  }
51ede5d96   Dan O'Donovan   ACPI / bus: Intro...
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
  static bool acpi_of_modalias(struct acpi_device *adev,
  			     char *modalias, size_t len)
  {
  	const union acpi_object *of_compatible;
  	const union acpi_object *obj;
  	const char *str, *chr;
  
  	of_compatible = adev->data.of_compatible;
  	if (!of_compatible)
  		return false;
  
  	if (of_compatible->type == ACPI_TYPE_PACKAGE)
  		obj = of_compatible->package.elements;
  	else /* Must be ACPI_TYPE_STRING. */
  		obj = of_compatible;
  
  	str = obj->string.pointer;
  	chr = strchr(str, ',');
  	strlcpy(modalias, chr ? chr + 1 : str, len);
  
  	return true;
  }
  
  /**
   * acpi_set_modalias - Set modalias using "compatible" property or supplied ID
   * @adev:	ACPI device object to match
   * @default_id:	ID string to use as default if no compatible string found
   * @modalias:   Pointer to buffer that modalias value will be copied into
   * @len:	Length of modalias buffer
   *
   * This is a counterpart of of_modalias_node() for struct acpi_device objects.
   * If there is a compatible string for @adev, it will be copied to @modalias
   * with the vendor prefix stripped; otherwise, @default_id will be used.
   */
  void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
  		       char *modalias, size_t len)
  {
  	if (!acpi_of_modalias(adev, modalias, len))
  		strlcpy(modalias, default_id, len);
  }
  EXPORT_SYMBOL_GPL(acpi_set_modalias);
68c6b148d   Rafael J. Wysocki   ACPI / scan: Move...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
  static bool __acpi_match_device_cls(const struct acpi_device_id *id,
  				    struct acpi_hardware_id *hwid)
  {
  	int i, msk, byte_shift;
  	char buf[3];
  
  	if (!id->cls)
  		return false;
  
  	/* Apply class-code bitmask, before checking each class-code byte */
  	for (i = 1; i <= 3; i++) {
  		byte_shift = 8 * (3 - i);
  		msk = (id->cls_msk >> byte_shift) & 0xFF;
  		if (!msk)
  			continue;
  
  		sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
  		if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
  			return false;
  	}
  	return true;
  }
  
  static const struct acpi_device_id *__acpi_match_device(
  	struct acpi_device *device,
  	const struct acpi_device_id *ids,
  	const struct of_device_id *of_ids)
  {
  	const struct acpi_device_id *id;
  	struct acpi_hardware_id *hwid;
  
  	/*
  	 * If the device is not present, it is unnecessary to load device
  	 * driver for it.
  	 */
  	if (!device || !device->status.present)
  		return NULL;
  
  	list_for_each_entry(hwid, &device->pnp.ids, list) {
  		/* First, check the ACPI/PNP IDs provided by the caller. */
  		for (id = ids; id->id[0] || id->cls; id++) {
  			if (id->id[0] && !strcmp((char *) id->id, hwid->id))
  				return id;
  			else if (id->cls && __acpi_match_device_cls(id, hwid))
  				return id;
  		}
  
  		/*
  		 * Next, check ACPI_DT_NAMESPACE_HID and try to match the
  		 * "compatible" property if found.
  		 *
  		 * The id returned by the below is not valid, but the only
  		 * caller passing non-NULL of_ids here is only interested in
  		 * whether or not the return value is NULL.
  		 */
  		if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
  		    && acpi_of_match_device(device, of_ids))
  			return id;
  	}
  	return NULL;
  }
  
  /**
   * acpi_match_device - Match a struct device against a given list of ACPI IDs
   * @ids: Array of struct acpi_device_id object to match against.
   * @dev: The device structure to match.
   *
   * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
   * object for that handle and use that object to match against a given list of
   * device IDs.
   *
   * Return a pointer to the first matching ID on success or %NULL on failure.
   */
  const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
  					       const struct device *dev)
  {
  	return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
  }
  EXPORT_SYMBOL_GPL(acpi_match_device);
  
  int acpi_match_device_ids(struct acpi_device *device,
  			  const struct acpi_device_id *ids)
  {
  	return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
  }
  EXPORT_SYMBOL(acpi_match_device_ids);
  
  bool acpi_driver_match_device(struct device *dev,
  			      const struct device_driver *drv)
  {
  	if (!drv->acpi_match_table)
  		return acpi_of_match_device(ACPI_COMPANION(dev),
  					    drv->of_match_table);
  
  	return !!__acpi_match_device(acpi_companion_match(dev),
  				     drv->acpi_match_table, drv->of_match_table);
  }
  EXPORT_SYMBOL_GPL(acpi_driver_match_device);
  
  /* --------------------------------------------------------------------------
5894b0c46   Rafael J. Wysocki   ACPI / scan: Move...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
                                ACPI Driver Management
     -------------------------------------------------------------------------- */
  
  /**
   * acpi_bus_register_driver - register a driver with the ACPI bus
   * @driver: driver being registered
   *
   * Registers a driver with the ACPI bus.  Searches the namespace for all
   * devices that match the driver's criteria and binds.  Returns zero for
   * success or a negative error status for failure.
   */
  int acpi_bus_register_driver(struct acpi_driver *driver)
  {
  	int ret;
  
  	if (acpi_disabled)
  		return -ENODEV;
  	driver->drv.name = driver->name;
  	driver->drv.bus = &acpi_bus_type;
  	driver->drv.owner = driver->owner;
  
  	ret = driver_register(&driver->drv);
  	return ret;
  }
  
  EXPORT_SYMBOL(acpi_bus_register_driver);
  
  /**
   * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
   * @driver: driver to unregister
   *
   * Unregisters a driver with the ACPI bus.  Searches the namespace for all
   * devices that match the driver's criteria and unbinds.
   */
  void acpi_bus_unregister_driver(struct acpi_driver *driver)
  {
  	driver_unregister(&driver->drv);
  }
  
  EXPORT_SYMBOL(acpi_bus_unregister_driver);
  
  /* --------------------------------------------------------------------------
                                ACPI Bus operations
     -------------------------------------------------------------------------- */
  
  static int acpi_bus_match(struct device *dev, struct device_driver *drv)
  {
  	struct acpi_device *acpi_dev = to_acpi_device(dev);
  	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
  
  	return acpi_dev->flags.match_driver
  		&& !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
  }
  
  static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
  {
  	return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
  }
  
  static int acpi_device_probe(struct device *dev)
  {
  	struct acpi_device *acpi_dev = to_acpi_device(dev);
  	struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
  	int ret;
  
  	if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
  		return -EINVAL;
  
  	if (!acpi_drv->ops.add)
  		return -ENOSYS;
  
  	ret = acpi_drv->ops.add(acpi_dev);
  	if (ret)
  		return ret;
  
  	acpi_dev->driver = acpi_drv;
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  			  "Driver [%s] successfully bound to device [%s]
  ",
  			  acpi_drv->name, acpi_dev->pnp.bus_id));
  
  	if (acpi_drv->ops.notify) {
  		ret = acpi_device_install_notify_handler(acpi_dev);
  		if (ret) {
  			if (acpi_drv->ops.remove)
  				acpi_drv->ops.remove(acpi_dev);
  
  			acpi_dev->driver = NULL;
  			acpi_dev->driver_data = NULL;
  			return ret;
  		}
  	}
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]
  ",
  			  acpi_drv->name, acpi_dev->pnp.bus_id));
  	get_device(dev);
  	return 0;
  }
  
  static int acpi_device_remove(struct device * dev)
  {
  	struct acpi_device *acpi_dev = to_acpi_device(dev);
  	struct acpi_driver *acpi_drv = acpi_dev->driver;
  
  	if (acpi_drv) {
  		if (acpi_drv->ops.notify)
  			acpi_device_remove_notify_handler(acpi_dev);
  		if (acpi_drv->ops.remove)
  			acpi_drv->ops.remove(acpi_dev);
  	}
  	acpi_dev->driver = NULL;
  	acpi_dev->driver_data = NULL;
  
  	put_device(dev);
  	return 0;
  }
  
  struct bus_type acpi_bus_type = {
  	.name		= "acpi",
  	.match		= acpi_bus_match,
  	.probe		= acpi_device_probe,
  	.remove		= acpi_device_remove,
  	.uevent		= acpi_device_uevent,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
952
  /* --------------------------------------------------------------------------
                               Initialization/Cleanup
     -------------------------------------------------------------------------- */
4be44fcd3   Len Brown   [ACPI] Lindent al...
953
  static int __init acpi_bus_init_irq(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
954
  {
6a8c0af6e   Bjorn Helgaas   ACPI: Remove usel...
955
  	acpi_status status;
4be44fcd3   Len Brown   [ACPI] Lindent al...
956
  	char *message = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958

aafbcd165   Alexey Starikovskiy   ACPI: invoke acpi...
959
  	/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
963
964
965
966
967
968
969
970
971
972
973
  	 * Let the system know what interrupt model we are using by
  	 * evaluating the \_PIC object, if exists.
  	 */
  
  	switch (acpi_irq_model) {
  	case ACPI_IRQ_MODEL_PIC:
  		message = "PIC";
  		break;
  	case ACPI_IRQ_MODEL_IOAPIC:
  		message = "IOAPIC";
  		break;
  	case ACPI_IRQ_MODEL_IOSAPIC:
  		message = "IOSAPIC";
  		break;
fbe61ec71   Hanjun Guo   ARM64 / ACPI: Int...
974
975
976
  	case ACPI_IRQ_MODEL_GIC:
  		message = "GIC";
  		break;
3948ec940   John Keller   ACPI: Altix: ACPI...
977
978
979
  	case ACPI_IRQ_MODEL_PLATFORM:
  		message = "platform specific model";
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  	default:
  		printk(KERN_WARNING PREFIX "Unknown interrupt routing model
  ");
d550d98d3   Patrick Mochel   ACPI: delete trac...
983
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
986
987
  	}
  
  	printk(KERN_INFO PREFIX "Using %s for interrupt routing
  ", message);
0db982026   Jiang Liu   ACPI: introduce h...
988
  	status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
a6fc67202   Thomas Renninger   ACPI: Enable ACPI...
990
  		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
d550d98d3   Patrick Mochel   ACPI: delete trac...
991
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
993
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
994
  }
b064a8fa7   Rafael J. Wysocki   ACPI / init: Swit...
995
996
997
998
999
1000
1001
1002
1003
1004
  /**
   * acpi_early_init - Initialize ACPICA and populate the ACPI namespace.
   *
   * The ACPI tables are accessible after this, but the handling of events has not
   * been initialized and the global lock is not available yet, so AML should not
   * be executed at this point.
   *
   * Doing this before switching the EFI runtime services to virtual mode allows
   * the EfiBootServices memory to be freed slightly earlier on boot.
   */
4be44fcd3   Len Brown   [ACPI] Lindent al...
1005
  void __init acpi_early_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006
  {
6a8c0af6e   Bjorn Helgaas   ACPI: Remove usel...
1007
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
  
  	if (acpi_disabled)
d550d98d3   Patrick Mochel   ACPI: delete trac...
1010
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1011

61686124f   Bob Moore   [ACPI] ACPICA 200...
1012
1013
  	printk(KERN_INFO PREFIX "Core revision %08x
  ", ACPI_CA_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1014
1015
1016
  	/* enable workarounds, unless strict ACPI spec. compliance */
  	if (!acpi_strict)
  		acpi_gbl_enable_interpreter_slack = TRUE;
8d3523fb3   Lv Zheng   ACPI / osl: Remov...
1017
  	acpi_permanent_mmap = true;
ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
1018

b2190cc39   Kai Heng Feng   ACPI / bus: Parse...
1019
1020
  	/* Check machine-specific quirks */
  	dmi_check_system(acpi_quirks_dmi_table);
aa2110cb1   Lin Ming   ACPI: add boot op...
1021

ad71860a1   Alexey Starikovskiy   ACPICA: minimal p...
1022
1023
1024
1025
1026
1027
1028
  	status = acpi_reallocate_root_table();
  	if (ACPI_FAILURE(status)) {
  		printk(KERN_ERR PREFIX
  		       "Unable to reallocate ACPI tables
  ");
  		goto error0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1029
1030
  	status = acpi_initialize_subsystem();
  	if (ACPI_FAILURE(status)) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
1031
1032
1033
  		printk(KERN_ERR PREFIX
  		       "Unable to initialize the ACPI Interpreter
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034
1035
  		goto error0;
  	}
1ef356681   Lv Zheng   ACPI / bus: Adjus...
1036
1037
  	if (!acpi_gbl_parse_table_as_term_list &&
  	    acpi_gbl_group_module_level_code) {
fe6cbea0f   Lv Zheng   ACPI 2.0 / ECDT: ...
1038
1039
1040
1041
1042
1043
1044
  		status = acpi_load_tables();
  		if (ACPI_FAILURE(status)) {
  			printk(KERN_ERR PREFIX
  			       "Unable to load the System Description Tables
  ");
  			goto error0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1045
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
1047
  #ifdef CONFIG_X86
  	if (!acpi_ioapic) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1048
  		/* compatible (0) means level (3) */
5f3b1a8b6   Alexey Starikovskiy   ACPICA: Remove du...
1049
1050
1051
1052
  		if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) {
  			acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK;
  			acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1053
  		/* Set PIC-mode SCI trigger type */
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
1054
  		acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt,
5f3b1a8b6   Alexey Starikovskiy   ACPICA: Remove du...
1055
  					 (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
  		/*
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
1058
  		 * now that acpi_gbl_FADT is initialized,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1059
1060
  		 * update it with result from INT_SRC_OVR parsing
  		 */
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
1061
  		acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
  	}
  #endif
b064a8fa7   Rafael J. Wysocki   ACPI / init: Swit...
1064
1065
1066
1067
1068
1069
1070
1071
1072
  	return;
  
   error0:
  	disable_acpi();
  }
  
  /**
   * acpi_subsystem_init - Finalize the early initialization of ACPI.
   *
3af03f77c   Baoquan He   ACPI / bus: Corre...
1073
   * Switch over the platform to the ACPI mode (if possible).
b064a8fa7   Rafael J. Wysocki   ACPI / init: Swit...
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
   *
   * Doing this too early is generally unsafe, but at the same time it needs to be
   * done before all things that really depend on ACPI.  The right spot appears to
   * be before finalizing the EFI initialization.
   */
  void __init acpi_subsystem_init(void)
  {
  	acpi_status status;
  
  	if (acpi_disabled)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1085

4505a2015   Rafael J. Wysocki   ACPI: Drop ACPI_N...
1086
  	status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087
1088
1089
  	if (ACPI_FAILURE(status)) {
  		printk(KERN_ERR PREFIX "Unable to enable ACPI
  ");
b064a8fa7   Rafael J. Wysocki   ACPI / init: Swit...
1090
1091
1092
1093
1094
1095
1096
1097
1098
  		disable_acpi();
  	} else {
  		/*
  		 * If the system is using ACPI then we can be reasonably
  		 * confident that any regulators are managed by the firmware
  		 * so tell the regulator core it has everything it needs to
  		 * know.
  		 */
  		regulator_has_full_constraints();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1099
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
  }
68bdb6773   Octavian Purdila   ACPI: add support...
1101
1102
1103
1104
1105
1106
  static acpi_status acpi_bus_table_handler(u32 event, void *table, void *context)
  {
  	acpi_scan_table_handler(event, table, context);
  
  	return acpi_sysfs_table_handler(event, table, context);
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
1107
  static int __init acpi_bus_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  {
6a8c0af6e   Bjorn Helgaas   ACPI: Remove usel...
1109
1110
  	int result;
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1111

176f9c180   Jiri Slaby   ACPI: remove doub...
1112
  	acpi_os_initialize1();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1113

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
  	/*
  	 * ACPI 2.0 requires the EC driver to be loaded and work before
fe6cbea0f   Lv Zheng   ACPI 2.0 / ECDT: ...
1116
1117
  	 * the EC device is found in the namespace (i.e. before
  	 * acpi_load_tables() is called).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1118
  	 *
aafbcd165   Alexey Starikovskiy   ACPI: invoke acpi...
1119
  	 * This is accomplished by looking for the ECDT table, and getting
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
1121
1122
1123
  	 * the EC parameters out of that.
  	 */
  	status = acpi_ec_ecdt_probe();
  	/* Ignore result. Not having an ECDT is not fatal. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124

1ef356681   Lv Zheng   ACPI / bus: Adjus...
1125
1126
  	if (acpi_gbl_parse_table_as_term_list ||
  	    !acpi_gbl_group_module_level_code) {
fe6cbea0f   Lv Zheng   ACPI 2.0 / ECDT: ...
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
  		status = acpi_load_tables();
  		if (ACPI_FAILURE(status)) {
  			printk(KERN_ERR PREFIX
  			       "Unable to load the System Description Tables
  ");
  			goto error1;
  		}
  	}
  
  	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
  	if (ACPI_FAILURE(status)) {
  		printk(KERN_ERR PREFIX
  		       "Unable to start the ACPI Interpreter
  ");
  		goto error1;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1143
1144
1145
1146
1147
1148
  	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
  	if (ACPI_FAILURE(status)) {
  		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects
  ");
  		goto error1;
  	}
a21211672   Srinivas Pandruvada   ACPI / processor:...
1149
1150
  	/* Set capability bits for _OSC under processor scope */
  	acpi_early_processor_osc();
b1d248d96   Zhang Rui   ACPI: install ACP...
1151
  	/*
fc54ab729   Lin Ming   ACPI: run _OSC af...
1152
1153
1154
1155
1156
1157
  	 * _OSC method may exist in module level code,
  	 * so it must be run after ACPI_FULL_INITIALIZATION
  	 */
  	acpi_bus_osc_support();
  
  	/*
b1d248d96   Zhang Rui   ACPI: install ACP...
1158
1159
1160
  	 * _PDC control method may load dynamic SSDT tables,
  	 * and we need to install the table handler before that.
  	 */
68bdb6773   Octavian Purdila   ACPI: add support...
1161
  	status = acpi_install_table_handler(acpi_bus_table_handler, NULL);
b1d248d96   Zhang Rui   ACPI: install ACP...
1162
  	acpi_sysfs_init();
78f169965   Alex Chiang   ACPI: processor: ...
1163
  	acpi_early_processor_set_pdc();
455c8793d   Zhao Yakui   ACPI: Enable EC d...
1164
1165
1166
1167
  	/*
  	 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
  	 * is necessary to enable it as early as possible.
  	 */
dcf15cbde   Lv Zheng   ACPI / EC: Fix a ...
1168
  	acpi_ec_dsdt_probe();
455c8793d   Zhao Yakui   ACPI: Enable EC d...
1169

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1170
1171
  	printk(KERN_INFO PREFIX "Interpreter enabled
  ");
aafbcd165   Alexey Starikovskiy   ACPI: invoke acpi...
1172
1173
  	/* Initialize sleep structures */
  	acpi_sleep_init();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
  	/*
  	 * Get the system interrupt model and evaluate \_PIC.
  	 */
  	result = acpi_bus_init_irq();
  	if (result)
  		goto error1;
  
  	/*
  	 * Register the for all standard device notifications.
  	 */
4be44fcd3   Len Brown   [ACPI] Lindent al...
1184
1185
1186
  	status =
  	    acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
  					&acpi_bus_notify, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187
  	if (ACPI_FAILURE(status)) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
1188
1189
1190
  		printk(KERN_ERR PREFIX
  		       "Unable to register for device notifications
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191
1192
1193
1194
1195
1196
1197
  		goto error1;
  	}
  
  	/*
  	 * Create the top ACPI proc directory
  	 */
  	acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);
1dcc3d336   Rafael J. Wysocki   ACPI / bus: Move ...
1198
1199
1200
  	result = bus_register(&acpi_bus_type);
  	if (!result)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
1202
  
  	/* Mimic structured exception handling */
4be44fcd3   Len Brown   [ACPI] Lindent al...
1203
        error1:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
  	acpi_terminate();
d550d98d3   Patrick Mochel   ACPI: delete trac...
1205
  	return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
  }
99e0d2fc6   Greg Kroah-Hartman   kobject: convert ...
1207
  struct kobject *acpi_kobj;
f2d4753fb   Matthew Garrett   ACPI: export acpi...
1208
  EXPORT_SYMBOL_GPL(acpi_kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209

4be44fcd3   Len Brown   [ACPI] Lindent al...
1210
  static int __init acpi_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
  {
6831c6edc   Rafael J. Wysocki   PM: Drop pm_flags...
1212
  	int result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
  	if (acpi_disabled) {
  		printk(KERN_INFO PREFIX "Interpreter disabled.
  ");
d550d98d3   Patrick Mochel   ACPI: delete trac...
1217
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  	}
f62ed9e33   Greg Kroah-Hartman   firmware: change ...
1219
  	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
99e0d2fc6   Greg Kroah-Hartman   kobject: convert ...
1220
  	if (!acpi_kobj) {
96b2dd1f1   Harvey Harrison   ACPI: replace rem...
1221
1222
  		printk(KERN_WARNING "%s: kset create error
  ", __func__);
99e0d2fc6   Greg Kroah-Hartman   kobject: convert ...
1223
1224
  		acpi_kobj = NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1225

0e46517d9   Bjorn Helgaas   ACPI: call init_a...
1226
  	init_acpi_device_notify();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
  	result = acpi_bus_init();
6831c6edc   Rafael J. Wysocki   PM: Drop pm_flags...
1228
  	if (result) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1229
  		disable_acpi();
81d0273df   Bjorn Helgaas   ACPI: skip DMI po...
1230
  		return result;
6831c6edc   Rafael J. Wysocki   PM: Drop pm_flags...
1231
  	}
81d0273df   Bjorn Helgaas   ACPI: skip DMI po...
1232

6831c6edc   Rafael J. Wysocki   PM: Drop pm_flags...
1233
  	pci_mmcfg_late_init();
88ef16d88   Tomasz Nowicki   ACPI: I/O Remappi...
1234
  	acpi_iort_init();
e747f2749   Bjorn Helgaas   ACPI: call acpi_s...
1235
  	acpi_scan_init();
a5f820feb   Bjorn Helgaas   ACPI: call acpi_e...
1236
  	acpi_ec_init();
a25ee9200   Zhang Rui   ACPI: introduce d...
1237
  	acpi_debugfs_init();
9cee43e07   Bjorn Helgaas   ACPI: call acpi_s...
1238
  	acpi_sleep_proc_init();
201b8c655   Bjorn Helgaas   ACPI: call acpi_w...
1239
  	acpi_wakeup_device_init();
836d08301   Lv Zheng   ACPI / debugger: ...
1240
  	acpi_debugger_init();
baa0c019b   Prakash, Prashanth   ACPI / bus: Suppo...
1241
  	acpi_setup_sb_notify_handler();
6831c6edc   Rafael J. Wysocki   PM: Drop pm_flags...
1242
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
  }
  
  subsys_initcall(acpi_init);