bus.c 25.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 *  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.
 *
 *  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.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
28
#include <linux/kernel.h>
L
Linus Torvalds 已提交
29 30 31 32 33
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/device.h>
#include <linux/proc_fs.h>
34
#include <linux/acpi.h>
35
#include <linux/slab.h>
L
Linus Torvalds 已提交
36 37 38
#ifdef CONFIG_X86
#include <asm/mpspec.h>
#endif
39
#include <linux/pci.h>
L
Linus Torvalds 已提交
40 41
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
42
#include <acpi/apei.h>
43
#include <linux/dmi.h>
44
#include <linux/suspend.h>
L
Linus Torvalds 已提交
45

46 47
#include "internal.h"

L
Linus Torvalds 已提交
48
#define _COMPONENT		ACPI_BUS_COMPONENT
49
ACPI_MODULE_NAME("bus");
L
Linus Torvalds 已提交
50

L
Len Brown 已提交
51 52
struct acpi_device *acpi_root;
struct proc_dir_entry *acpi_root_dir;
L
Linus Torvalds 已提交
53 54 55 56
EXPORT_SYMBOL(acpi_root_dir);

#define STRUCT_TO_INT(s)	(*((int*)&s))

57

58
#ifdef CONFIG_X86
59 60 61 62 63 64 65 66 67 68
static int set_copy_dsdt(const struct dmi_system_id *id)
{
	printk(KERN_NOTICE "%s detected - "
		"force copy of DSDT to local memory\n", id->ident);
	acpi_gbl_copy_dsdt_locally = 1;
	return 0;
}

static struct dmi_system_id dsdt_dmi_table[] __initdata = {
	/*
69
	 * Invoke DSDT corruption work-around on all Toshiba Satellite.
70 71 72 73
	 * https://bugzilla.kernel.org/show_bug.cgi?id=14679
	 */
	{
	 .callback = set_copy_dsdt,
74
	 .ident = "TOSHIBA Satellite",
75 76
	 .matches = {
		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
77
		DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
78
		},
79 80
	},
	{}
81
};
82 83 84 85 86
#else
static struct dmi_system_id dsdt_dmi_table[] __initdata = {
	{}
};
#endif
87

L
Linus Torvalds 已提交
88 89 90 91
/* --------------------------------------------------------------------------
                                Device Management
   -------------------------------------------------------------------------- */

L
Len Brown 已提交
92
int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
L
Linus Torvalds 已提交
93
{
L
Len Brown 已提交
94
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
95 96 97


	if (!device)
98
		return -EINVAL;
L
Linus Torvalds 已提交
99 100 101

	/* TBD: Support fixed-feature devices */

L
Len Brown 已提交
102
	status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
L
Linus Torvalds 已提交
103
	if (ACPI_FAILURE(status) || !*device) {
104 105
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
				  handle));
106
		return -ENODEV;
L
Linus Torvalds 已提交
107 108
	}

109
	return 0;
L
Linus Torvalds 已提交
110
}
L
Len Brown 已提交
111

L
Linus Torvalds 已提交
112 113
EXPORT_SYMBOL(acpi_bus_get_device);

114 115
acpi_status acpi_bus_get_status_handle(acpi_handle handle,
				       unsigned long long *sta)
L
Linus Torvalds 已提交
116
{
117
	acpi_status status;
L
Len Brown 已提交
118

119 120 121
	status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
	if (ACPI_SUCCESS(status))
		return AE_OK;
L
Linus Torvalds 已提交
122

123 124 125 126
	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;
L
Linus Torvalds 已提交
127
	}
128 129
	return status;
}
L
Linus Torvalds 已提交
130

131 132 133 134 135 136 137 138 139 140
int acpi_bus_get_status(struct acpi_device *device)
{
	acpi_status status;
	unsigned long long sta;

	status = acpi_bus_get_status_handle(device->handle, &sta);
	if (ACPI_FAILURE(status))
		return -ENODEV;

	STRUCT_TO_INT(device->status) = (int) sta;
L
Linus Torvalds 已提交
141 142

	if (device->status.functional && !device->status.present) {
143 144 145 146
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
		       "functional but not present;\n",
			device->pnp.bus_id,
			(u32) STRUCT_TO_INT(device->status)));
L
Linus Torvalds 已提交
147 148
	}

L
Len Brown 已提交
149 150 151
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
			  device->pnp.bus_id,
			  (u32) STRUCT_TO_INT(device->status)));
152
	return 0;
L
Linus Torvalds 已提交
153
}
L
Len Brown 已提交
154
EXPORT_SYMBOL(acpi_bus_get_status);
L
Linus Torvalds 已提交
155

Z
Zhang Rui 已提交
156
void acpi_bus_private_data_handler(acpi_handle handle,
157
				   void *context)
Z
Zhang Rui 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
{
	return;
}
EXPORT_SYMBOL(acpi_bus_private_data_handler);

int acpi_bus_get_private_data(acpi_handle handle, void **data)
{
	acpi_status status = AE_OK;

	if (!*data)
		return -EINVAL;

	status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
	if (ACPI_FAILURE(status) || !*data) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
				handle));
		return -ENODEV;
	}

	return 0;
}
EXPORT_SYMBOL(acpi_bus_get_private_data);

L
Linus Torvalds 已提交
181 182 183 184
/* --------------------------------------------------------------------------
                                 Power Management
   -------------------------------------------------------------------------- */

185
static int __acpi_bus_get_power(struct acpi_device *device, int *state)
L
Linus Torvalds 已提交
186
{
L
Len Brown 已提交
187 188
	int result = 0;
	acpi_status status = 0;
189
	unsigned long long psc = 0;
L
Linus Torvalds 已提交
190

191 192
	if (!device || !state)
		return -EINVAL;
L
Linus Torvalds 已提交
193 194 195

	*state = ACPI_STATE_UNKNOWN;

196
	if (device->flags.power_manageable) {
L
Linus Torvalds 已提交
197
		/*
198
		 * Get the device's power state either directly (via _PSC) or
L
Linus Torvalds 已提交
199 200
		 * indirectly (via power resources).
		 */
201
		if (device->power.flags.power_resources) {
202
			result = acpi_power_get_inferred_state(device, state);
203 204 205
			if (result)
				return result;
		} else if (device->power.flags.explicit_get) {
L
Len Brown 已提交
206 207
			status = acpi_evaluate_integer(device->handle, "_PSC",
						       NULL, &psc);
L
Linus Torvalds 已提交
208
			if (ACPI_FAILURE(status))
209
				return -ENODEV;
210
			*state = (int)psc;
L
Linus Torvalds 已提交
211
		}
212 213 214 215
	} else {
		/* TBD: Non-recursive algorithm for walking up hierarchy. */
		*state = device->parent ?
			device->parent->power.state : ACPI_STATE_D0;
L
Linus Torvalds 已提交
216 217 218
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] power state is D%d\n",
219
			  device->pnp.bus_id, *state));
L
Linus Torvalds 已提交
220

221
	return 0;
L
Linus Torvalds 已提交
222 223
}

224

225
static int __acpi_bus_set_power(struct acpi_device *device, int state)
L
Linus Torvalds 已提交
226
{
L
Len Brown 已提交
227 228 229
	int result = 0;
	acpi_status status = AE_OK;
	char object_name[5] = { '_', 'P', 'S', '0' + state, '\0' };
L
Linus Torvalds 已提交
230

L
Lin Ming 已提交
231
	if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
232
		return -EINVAL;
L
Linus Torvalds 已提交
233 234 235

	/* Make sure this is a valid target state */

236
	if (state == device->power.state) {
237 238 239
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
				  state));
		return 0;
L
Linus Torvalds 已提交
240
	}
241

L
Linus Torvalds 已提交
242
	if (!device->power.states[state].flags.valid) {
243
		printk(KERN_WARNING PREFIX "Device does not support D%d\n", state);
244
		return -ENODEV;
L
Linus Torvalds 已提交
245 246
	}
	if (device->parent && (state < device->parent->power.state)) {
247
		printk(KERN_WARNING PREFIX
248
			      "Cannot set device to a higher-powered"
249
			      " state than parent\n");
250
		return -ENODEV;
L
Linus Torvalds 已提交
251 252 253 254 255 256 257 258
	}

	/*
	 * Transition Power
	 * ----------------
	 * On transitions to a high-powered state we first apply power (via
	 * power resources) then evalute _PSx.  Conversly for transitions to
	 * a lower-powered state.
259
	 */
L
Linus Torvalds 已提交
260 261 262 263 264 265 266
	if (state < device->power.state) {
		if (device->power.flags.power_resources) {
			result = acpi_power_transition(device, state);
			if (result)
				goto end;
		}
		if (device->power.states[state].flags.explicit_set) {
L
Len Brown 已提交
267 268
			status = acpi_evaluate_object(device->handle,
						      object_name, NULL, NULL);
L
Linus Torvalds 已提交
269 270 271 272 273
			if (ACPI_FAILURE(status)) {
				result = -ENODEV;
				goto end;
			}
		}
L
Len Brown 已提交
274
	} else {
L
Linus Torvalds 已提交
275
		if (device->power.states[state].flags.explicit_set) {
L
Len Brown 已提交
276 277
			status = acpi_evaluate_object(device->handle,
						      object_name, NULL, NULL);
L
Linus Torvalds 已提交
278 279 280 281 282 283 284 285 286 287 288 289
			if (ACPI_FAILURE(status)) {
				result = -ENODEV;
				goto end;
			}
		}
		if (device->power.flags.power_resources) {
			result = acpi_power_transition(device, state);
			if (result)
				goto end;
		}
	}

L
Len Brown 已提交
290
      end:
L
Linus Torvalds 已提交
291
	if (result)
292
		printk(KERN_WARNING PREFIX
L
Len Brown 已提交
293
			      "Device [%s] failed to transition to D%d\n",
294
			      device->pnp.bus_id, state);
295 296
	else {
		device->power.state = state;
L
Len Brown 已提交
297 298 299
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Device [%s] transitioned to D%d\n",
				  device->pnp.bus_id, state));
300
	}
L
Linus Torvalds 已提交
301

302
	return result;
L
Linus Torvalds 已提交
303 304
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323

int acpi_bus_set_power(acpi_handle handle, int state)
{
	struct acpi_device *device;
	int result;

	result = acpi_bus_get_device(handle, &device);
	if (result)
		return result;

	if (!device->flags.power_manageable) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				"Device [%s] is not power manageable\n",
				dev_name(&device->dev)));
		return -ENODEV;
	}

	return __acpi_bus_set_power(device, state);
}
L
Len Brown 已提交
324
EXPORT_SYMBOL(acpi_bus_set_power);
L
Linus Torvalds 已提交
325

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350

int acpi_bus_init_power(struct acpi_device *device)
{
	int state;
	int result;

	if (!device)
		return -EINVAL;

	device->power.state = ACPI_STATE_UNKNOWN;

	result = __acpi_bus_get_power(device, &state);
	if (result)
		return result;

	if (device->power.flags.power_resources)
		result = acpi_power_on_resources(device, state);

	if (!result)
		device->power.state = state;

	return result;
}


351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
int acpi_bus_update_power(acpi_handle handle, int *state_p)
{
	struct acpi_device *device;
	int state;
	int result;

	result = acpi_bus_get_device(handle, &device);
	if (result)
		return result;

	result = __acpi_bus_get_power(device, &state);
	if (result)
		return result;

	result = __acpi_bus_set_power(device, state);
	if (!result && state_p)
		*state_p = state;

	return result;
}
EXPORT_SYMBOL_GPL(acpi_bus_update_power);


374 375 376 377 378 379 380 381 382 383 384
bool acpi_bus_power_manageable(acpi_handle handle)
{
	struct acpi_device *device;
	int result;

	result = acpi_bus_get_device(handle, &device);
	return result ? false : device->flags.power_manageable;
}

EXPORT_SYMBOL(acpi_bus_power_manageable);

385 386 387 388 389 390 391 392 393 394 395
bool acpi_bus_can_wakeup(acpi_handle handle)
{
	struct acpi_device *device;
	int result;

	result = acpi_bus_get_device(handle, &device);
	return result ? false : device->wakeup.flags.valid;
}

EXPORT_SYMBOL(acpi_bus_can_wakeup);

S
Shaohua Li 已提交
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
static void acpi_print_osc_error(acpi_handle handle,
	struct acpi_osc_context *context, char *error)
{
	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
	int i;

	if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
		printk(KERN_DEBUG "%s\n", error);
	else {
		printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
		kfree(buffer.pointer);
	}
	printk(KERN_DEBUG"_OSC request data:");
	for (i = 0; i < context->cap.length; i += sizeof(u32))
		printk("%x ", *((u32 *)(context->cap.pointer + i)));
	printk("\n");
}

static acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
{
	int i;
	static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
		24, 26, 28, 30, 32, 34};

	if (strlen(str) != 36)
		return AE_BAD_PARAMETER;
	for (i = 0; i < 36; i++) {
		if (i == 8 || i == 13 || i == 18 || i == 23) {
			if (str[i] != '-')
				return AE_BAD_PARAMETER;
		} else if (!isxdigit(str[i]))
			return AE_BAD_PARAMETER;
	}
	for (i = 0; i < 16; i++) {
430 431
		uuid[i] = hex_to_bin(str[opc_map_to_uuid[i]]) << 4;
		uuid[i] |= hex_to_bin(str[opc_map_to_uuid[i] + 1]);
S
Shaohua Li 已提交
432 433 434 435 436 437 438 439 440 441 442 443
	}
	return AE_OK;
}

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;
	u8 uuid[16];
	u32 errors;
444
	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
S
Shaohua Li 已提交
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

	if (!context)
		return AE_ERROR;
	if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
		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;
	in_params[0].buffer.pointer	= uuid;
	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;

467
	status = acpi_evaluate_object(handle, "_OSC", &input, &output);
S
Shaohua Li 已提交
468 469 470
	if (ACPI_FAILURE(status))
		return status;

471
	if (!output.length)
S
Shaohua Li 已提交
472 473
		return AE_NULL_OBJECT;

474 475 476
	out_obj = output.pointer;
	if (out_obj->type != ACPI_TYPE_BUFFER
		|| out_obj->buffer.length != context->cap.length) {
S
Shaohua Li 已提交
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
		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) {
			if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
			    & OSC_QUERY_ENABLE)
				goto out_success;
			status = AE_SUPPORT;
			goto out_kfree;
		}
		status = AE_ERROR;
		goto out_kfree;
	}
out_success:
505 506 507 508 509 510 511 512 513
	context->ret.length = out_obj->buffer.length;
	context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL);
	if (!context->ret.pointer) {
		status =  AE_NO_MEMORY;
		goto out_kfree;
	}
	memcpy(context->ret.pointer, out_obj->buffer.pointer,
		context->ret.length);
	status =  AE_OK;
S
Shaohua Li 已提交
514 515

out_kfree:
516 517 518
	kfree(output.pointer);
	if (status != AE_OK)
		context->ret.pointer = NULL;
S
Shaohua Li 已提交
519 520 521 522
	return status;
}
EXPORT_SYMBOL(acpi_run_osc);

523
bool osc_sb_apei_support_acked;
S
Shaohua Li 已提交
524 525 526 527 528 529 530 531 532 533 534 535 536 537
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;

	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
538 539
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
S
Shaohua Li 已提交
540 541
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
#endif
542 543 544 545

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
#endif
546 547 548

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
S
Shaohua Li 已提交
549 550
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
551 552 553 554 555
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;
		if (context.ret.length > OSC_SUPPORT_TYPE)
			osc_sb_apei_support_acked =
				capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
S
Shaohua Li 已提交
556
		kfree(context.ret.pointer);
557 558
	}
	/* do we need to check other returned cap? Sounds no */
S
Shaohua Li 已提交
559 560
}

L
Linus Torvalds 已提交
561 562 563 564
/* --------------------------------------------------------------------------
                                Event Management
   -------------------------------------------------------------------------- */

565
#ifdef CONFIG_ACPI_PROC_EVENT
L
Linus Torvalds 已提交
566 567 568 569 570
static DEFINE_SPINLOCK(acpi_bus_event_lock);

LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);

L
Len Brown 已提交
571
extern int event_is_open;
L
Linus Torvalds 已提交
572

573
int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
L
Linus Torvalds 已提交
574
{
575
	struct acpi_bus_event *event;
L
Len Brown 已提交
576
	unsigned long flags = 0;
L
Linus Torvalds 已提交
577 578 579

	/* drop event on the floor if no one's listening */
	if (!event_is_open)
580
		return 0;
L
Linus Torvalds 已提交
581

582
	event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
L
Linus Torvalds 已提交
583
	if (!event)
584
		return -ENOMEM;
L
Linus Torvalds 已提交
585

586 587
	strcpy(event->device_class, device_class);
	strcpy(event->bus_id, bus_id);
L
Linus Torvalds 已提交
588 589 590 591 592 593 594 595 596
	event->type = type;
	event->data = data;

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	list_add_tail(&event->node, &acpi_bus_event_list);
	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);

	wake_up_interruptible(&acpi_bus_event_queue);

597
	return 0;
598 599 600 601 602 603 604 605 606 607 608

}

EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);

int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{
	if (!device)
		return -EINVAL;
	return acpi_bus_generate_proc_event4(device->pnp.device_class,
					     device->pnp.bus_id, type, data);
L
Linus Torvalds 已提交
609
}
L
Len Brown 已提交
610

611
EXPORT_SYMBOL(acpi_bus_generate_proc_event);
L
Linus Torvalds 已提交
612

L
Len Brown 已提交
613
int acpi_bus_receive_event(struct acpi_bus_event *event)
L
Linus Torvalds 已提交
614
{
L
Len Brown 已提交
615 616
	unsigned long flags = 0;
	struct acpi_bus_event *entry = NULL;
L
Linus Torvalds 已提交
617 618 619 620 621

	DECLARE_WAITQUEUE(wait, current);


	if (!event)
622
		return -EINVAL;
L
Linus Torvalds 已提交
623 624 625 626 627 628 629 630 631 632 633 634 635

	if (list_empty(&acpi_bus_event_list)) {

		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&acpi_bus_event_queue, &wait);

		if (list_empty(&acpi_bus_event_list))
			schedule();

		remove_wait_queue(&acpi_bus_event_queue, &wait);
		set_current_state(TASK_RUNNING);

		if (signal_pending(current))
636
			return -ERESTARTSYS;
L
Linus Torvalds 已提交
637 638 639
	}

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
640 641 642
	if (!list_empty(&acpi_bus_event_list)) {
		entry = list_entry(acpi_bus_event_list.next,
				   struct acpi_bus_event, node);
L
Linus Torvalds 已提交
643
		list_del(&entry->node);
644
	}
L
Linus Torvalds 已提交
645 646 647
	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);

	if (!entry)
648
		return -ENODEV;
L
Linus Torvalds 已提交
649 650 651 652 653

	memcpy(event, entry, sizeof(struct acpi_bus_event));

	kfree(entry);

654
	return 0;
L
Linus Torvalds 已提交
655 656
}

657
#endif	/* CONFIG_ACPI_PROC_EVENT */
L
Linus Torvalds 已提交
658 659 660 661 662

/* --------------------------------------------------------------------------
                             Notification Handling
   -------------------------------------------------------------------------- */

663
static void acpi_bus_check_device(acpi_handle handle)
L
Linus Torvalds 已提交
664
{
665
	struct acpi_device *device;
666
	acpi_status status;
L
Linus Torvalds 已提交
667 668
	struct acpi_device_status old_status;

669 670
	if (acpi_bus_get_device(handle, &device))
		return;
L
Linus Torvalds 已提交
671
	if (!device)
672
		return;
L
Linus Torvalds 已提交
673 674 675 676 677 678 679 680 681

	old_status = device->status;

	/*
	 * Make sure this device's parent is present before we go about
	 * messing with the device.
	 */
	if (device->parent && !device->parent->status.present) {
		device->status = device->parent->status;
682
		return;
L
Linus Torvalds 已提交
683 684 685 686
	}

	status = acpi_bus_get_status(device);
	if (ACPI_FAILURE(status))
687
		return;
L
Linus Torvalds 已提交
688 689

	if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
690
		return;
L
Linus Torvalds 已提交
691 692 693 694 695 696 697

	/*
	 * Device Insertion/Removal
	 */
	if ((device->status.present) && !(old_status.present)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
		/* TBD: Handle device insertion */
L
Len Brown 已提交
698
	} else if (!(device->status.present) && (old_status.present)) {
L
Linus Torvalds 已提交
699 700 701 702 703
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
		/* TBD: Handle device removal */
	}
}

704
static void acpi_bus_check_scope(acpi_handle handle)
L
Linus Torvalds 已提交
705 706
{
	/* Status Change? */
707
	acpi_bus_check_device(handle);
L
Linus Torvalds 已提交
708 709 710 711 712 713 714

	/*
	 * TBD: Enumerate child devices within this device's scope and
	 *       run acpi_bus_check_device()'s on them.
	 */
}

715 716 717 718 719 720 721 722 723 724 725 726 727
static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list);
int register_acpi_bus_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_register(&acpi_bus_notify_list, nb);
}
EXPORT_SYMBOL_GPL(register_acpi_bus_notifier);

void unregister_acpi_bus_notifier(struct notifier_block *nb)
{
	blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb);
}
EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier);

L
Linus Torvalds 已提交
728 729 730 731 732
/**
 * acpi_bus_notify
 * ---------------
 * Callback for all 'system-level' device notifications (values 0x00-0x7F).
 */
L
Len Brown 已提交
733
static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)
L
Linus Torvalds 已提交
734
{
L
Len Brown 已提交
735
	struct acpi_device *device = NULL;
736
	struct acpi_driver *driver;
L
Linus Torvalds 已提交
737

738 739 740
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n",
			  type, handle));

741 742
	blocking_notifier_call_chain(&acpi_bus_notify_list,
		type, (void *)handle);
L
Linus Torvalds 已提交
743 744 745 746

	switch (type) {

	case ACPI_NOTIFY_BUS_CHECK:
747
		acpi_bus_check_scope(handle);
748
		/*
L
Linus Torvalds 已提交
749
		 * TBD: We'll need to outsource certain events to non-ACPI
L
Len Brown 已提交
750
		 *      drivers via the device manager (device.c).
L
Linus Torvalds 已提交
751 752 753 754
		 */
		break;

	case ACPI_NOTIFY_DEVICE_CHECK:
755
		acpi_bus_check_device(handle);
756
		/*
L
Linus Torvalds 已提交
757
		 * TBD: We'll need to outsource certain events to non-ACPI
L
Len Brown 已提交
758
		 *      drivers via the device manager (device.c).
L
Linus Torvalds 已提交
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
		 */
		break;

	case ACPI_NOTIFY_DEVICE_WAKE:
		/* TBD */
		break;

	case ACPI_NOTIFY_EJECT_REQUEST:
		/* TBD */
		break;

	case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
		/* TBD: Exactly what does 'light' mean? */
		break;

	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
		/* TBD */
		break;

	case ACPI_NOTIFY_BUS_MODE_MISMATCH:
		/* TBD */
		break;

	case ACPI_NOTIFY_POWER_FAULT:
		/* TBD */
		break;

	default:
L
Len Brown 已提交
787 788 789
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Received unknown/unsupported notification [%08x]\n",
				  type));
L
Linus Torvalds 已提交
790 791 792
		break;
	}

793 794 795 796 797 798 799
	acpi_bus_get_device(handle, &device);
	if (device) {
		driver = device->driver;
		if (driver && driver->ops.notify &&
		    (driver->flags & ACPI_DRIVER_ALL_NOTIFY_EVENTS))
			driver->ops.notify(device, type);
	}
L
Linus Torvalds 已提交
800 801 802 803 804 805
}

/* --------------------------------------------------------------------------
                             Initialization/Cleanup
   -------------------------------------------------------------------------- */

L
Len Brown 已提交
806
static int __init acpi_bus_init_irq(void)
L
Linus Torvalds 已提交
807
{
L
Len Brown 已提交
808 809 810 811
	acpi_status status = AE_OK;
	union acpi_object arg = { ACPI_TYPE_INTEGER };
	struct acpi_object_list arg_list = { 1, &arg };
	char *message = NULL;
L
Linus Torvalds 已提交
812 813


814
	/*
L
Linus Torvalds 已提交
815 816 817 818 819 820 821 822 823 824 825 826 827 828
	 * 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;
J
John Keller 已提交
829 830 831
	case ACPI_IRQ_MODEL_PLATFORM:
		message = "platform specific model";
		break;
L
Linus Torvalds 已提交
832 833
	default:
		printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
834
		return -ENODEV;
L
Linus Torvalds 已提交
835 836 837 838 839 840 841 842
	}

	printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message);

	arg.integer.value = acpi_irq_model;

	status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL);
	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
843
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC"));
844
		return -ENODEV;
L
Linus Torvalds 已提交
845 846
	}

847
	return 0;
L
Linus Torvalds 已提交
848 849
}

850
u8 acpi_gbl_permanent_mmap;
851 852


L
Len Brown 已提交
853
void __init acpi_early_init(void)
L
Linus Torvalds 已提交
854
{
L
Len Brown 已提交
855
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
856 857

	if (acpi_disabled)
858
		return;
L
Linus Torvalds 已提交
859

B
Bob Moore 已提交
860 861
	printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION);

L
Linus Torvalds 已提交
862 863 864 865
	/* enable workarounds, unless strict ACPI spec. compliance */
	if (!acpi_strict)
		acpi_gbl_enable_interpreter_slack = TRUE;

866 867
	acpi_gbl_permanent_mmap = 1;

868 869 870 871 872 873
	/*
	 * If the machine falls into the DMI check table,
	 * DSDT will be copied to memory
	 */
	dmi_check_system(dsdt_dmi_table);

874 875 876 877 878 879 880
	status = acpi_reallocate_root_table();
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR PREFIX
		       "Unable to reallocate ACPI tables\n");
		goto error0;
	}

L
Linus Torvalds 已提交
881 882
	status = acpi_initialize_subsystem();
	if (ACPI_FAILURE(status)) {
L
Len Brown 已提交
883 884
		printk(KERN_ERR PREFIX
		       "Unable to initialize the ACPI Interpreter\n");
L
Linus Torvalds 已提交
885 886 887 888 889
		goto error0;
	}

	status = acpi_load_tables();
	if (ACPI_FAILURE(status)) {
L
Len Brown 已提交
890 891
		printk(KERN_ERR PREFIX
		       "Unable to load the System Description Tables\n");
L
Linus Torvalds 已提交
892 893 894 895 896 897
		goto error0;
	}

#ifdef CONFIG_X86
	if (!acpi_ioapic) {
		/* compatible (0) means level (3) */
898 899 900 901
		if (!(acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)) {
			acpi_sci_flags &= ~ACPI_MADT_TRIGGER_MASK;
			acpi_sci_flags |= ACPI_MADT_TRIGGER_LEVEL;
		}
L
Linus Torvalds 已提交
902
		/* Set PIC-mode SCI trigger type */
903
		acpi_pic_sci_set_trigger(acpi_gbl_FADT.sci_interrupt,
904
					 (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
L
Linus Torvalds 已提交
905 906
	} else {
		/*
907
		 * now that acpi_gbl_FADT is initialized,
L
Linus Torvalds 已提交
908 909
		 * update it with result from INT_SRC_OVR parsing
		 */
910
		acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi;
L
Linus Torvalds 已提交
911 912 913
	}
#endif

914
	status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
L
Linus Torvalds 已提交
915 916 917 918 919
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
		goto error0;
	}

920
	return;
L
Linus Torvalds 已提交
921

L
Len Brown 已提交
922
      error0:
L
Linus Torvalds 已提交
923
	disable_acpi();
924
	return;
L
Linus Torvalds 已提交
925 926
}

L
Len Brown 已提交
927
static int __init acpi_bus_init(void)
L
Linus Torvalds 已提交
928
{
L
Len Brown 已提交
929 930 931
	int result = 0;
	acpi_status status = AE_OK;
	extern acpi_status acpi_os_initialize1(void);
L
Linus Torvalds 已提交
932

933
	acpi_os_initialize1();
L
Linus Torvalds 已提交
934

935
	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
L
Linus Torvalds 已提交
936
	if (ACPI_FAILURE(status)) {
L
Len Brown 已提交
937 938
		printk(KERN_ERR PREFIX
		       "Unable to start the ACPI Interpreter\n");
L
Linus Torvalds 已提交
939 940 941 942 943 944 945 946
		goto error1;
	}

	/*
	 * ACPI 2.0 requires the EC driver to be loaded and work before
	 * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
	 * is called).
	 *
947
	 * This is accomplished by looking for the ECDT table, and getting
L
Linus Torvalds 已提交
948 949 950 951 952
	 * the EC parameters out of that.
	 */
	status = acpi_ec_ecdt_probe();
	/* Ignore result. Not having an ECDT is not fatal. */

S
Shaohua Li 已提交
953 954
	acpi_bus_osc_support();

L
Linus Torvalds 已提交
955 956 957 958 959 960
	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
		goto error1;
	}

961 962 963 964 965 966
	/*
	 * _PDC control method may load dynamic SSDT tables,
	 * and we need to install the table handler before that.
	 */
	acpi_sysfs_init();

A
Alex Chiang 已提交
967 968
	acpi_early_processor_set_pdc();

969 970 971 972 973 974
	/*
	 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
	 * is necessary to enable it as early as possible.
	 */
	acpi_boot_ec_enable();

L
Linus Torvalds 已提交
975 976
	printk(KERN_INFO PREFIX "Interpreter enabled\n");

977 978 979
	/* Initialize sleep structures */
	acpi_sleep_init();

L
Linus Torvalds 已提交
980 981 982 983 984 985 986 987 988 989
	/*
	 * Get the system interrupt model and evaluate \_PIC.
	 */
	result = acpi_bus_init_irq();
	if (result)
		goto error1;

	/*
	 * Register the for all standard device notifications.
	 */
L
Len Brown 已提交
990 991 992
	status =
	    acpi_install_notify_handler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
					&acpi_bus_notify, NULL);
L
Linus Torvalds 已提交
993
	if (ACPI_FAILURE(status)) {
L
Len Brown 已提交
994 995
		printk(KERN_ERR PREFIX
		       "Unable to register for device notifications\n");
L
Linus Torvalds 已提交
996 997 998 999 1000 1001 1002 1003
		goto error1;
	}

	/*
	 * Create the top ACPI proc directory
	 */
	acpi_root_dir = proc_mkdir(ACPI_BUS_FILE_ROOT, NULL);

1004
	return 0;
L
Linus Torvalds 已提交
1005 1006

	/* Mimic structured exception handling */
L
Len Brown 已提交
1007
      error1:
L
Linus Torvalds 已提交
1008
	acpi_terminate();
1009
	return -ENODEV;
L
Linus Torvalds 已提交
1010 1011
}

1012
struct kobject *acpi_kobj;
L
Linus Torvalds 已提交
1013

L
Len Brown 已提交
1014
static int __init acpi_init(void)
L
Linus Torvalds 已提交
1015
{
1016
	int result;
L
Linus Torvalds 已提交
1017 1018 1019

	if (acpi_disabled) {
		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
1020
		return -ENODEV;
L
Linus Torvalds 已提交
1021 1022
	}

1023
	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
1024
	if (!acpi_kobj) {
1025
		printk(KERN_WARNING "%s: kset create error\n", __func__);
1026 1027
		acpi_kobj = NULL;
	}
L
Linus Torvalds 已提交
1028

1029
	init_acpi_device_notify();
L
Linus Torvalds 已提交
1030
	result = acpi_bus_init();
1031
	if (result) {
L
Linus Torvalds 已提交
1032
		disable_acpi();
1033
		return result;
1034
	}
1035

1036
	pci_mmcfg_late_init();
1037
	acpi_scan_init();
1038
	acpi_ec_init();
1039
	acpi_debugfs_init();
1040
	acpi_sleep_proc_init();
1041
	acpi_wakeup_device_init();
1042
	return 0;
L
Linus Torvalds 已提交
1043 1044 1045
}

subsys_initcall(acpi_init);