osl.c 25.5 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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*
 *  acpi_osl.c - OS-dependent functions ($Revision: 83 $)
 *
 *  Copyright (C) 2000       Andrew Henroid
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 *  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/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
#include <acpi/acpi.h>
#include <asm/io.h>
#include <acpi/acpi_bus.h>
#include <acpi/processor.h>
#include <asm/uaccess.h>

#include <linux/efi.h>

#define _COMPONENT		ACPI_OS_SERVICES
L
Len Brown 已提交
49
ACPI_MODULE_NAME("osl")
L
Linus Torvalds 已提交
50
#define PREFIX		"ACPI: "
L
Len Brown 已提交
51 52 53
struct acpi_os_dpc {
	acpi_osd_exec_callback function;
	void *context;
L
Linus Torvalds 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67
};

#ifdef CONFIG_ACPI_CUSTOM_DSDT
#include CONFIG_ACPI_CUSTOM_DSDT_FILE
#endif

#ifdef ENABLE_DEBUGGER
#include <linux/kdb.h>

/* stuff for debugger support */
int acpi_in_debugger;
EXPORT_SYMBOL(acpi_in_debugger);

extern char line_buf[80];
L
Len Brown 已提交
68
#endif				/*ENABLE_DEBUGGER */
L
Linus Torvalds 已提交
69

70
int acpi_specific_hotkey_enabled = TRUE;
L
Luming Yu 已提交
71 72
EXPORT_SYMBOL(acpi_specific_hotkey_enabled);

L
Linus Torvalds 已提交
73 74 75 76 77
static unsigned int acpi_irq_irq;
static acpi_osd_handler acpi_irq_handler;
static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;

L
Len Brown 已提交
78
acpi_status acpi_os_initialize(void)
L
Linus Torvalds 已提交
79 80 81 82
{
	return AE_OK;
}

L
Len Brown 已提交
83
acpi_status acpi_os_initialize1(void)
L
Linus Torvalds 已提交
84 85 86 87 88 89
{
	/*
	 * Initialize PCI configuration space access, as we'll need to access
	 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
	 */
	if (!raw_pci_ops) {
L
Len Brown 已提交
90 91
		printk(KERN_ERR PREFIX
		       "Access to PCI configuration space unavailable\n");
L
Linus Torvalds 已提交
92 93 94 95 96 97 98 99
		return AE_NULL_ENTRY;
	}
	kacpid_wq = create_singlethread_workqueue("kacpid");
	BUG_ON(!kacpid_wq);

	return AE_OK;
}

L
Len Brown 已提交
100
acpi_status acpi_os_terminate(void)
L
Linus Torvalds 已提交
101 102 103 104 105 106 107 108 109 110 111
{
	if (acpi_irq_handler) {
		acpi_os_remove_interrupt_handler(acpi_irq_irq,
						 acpi_irq_handler);
	}

	destroy_workqueue(kacpid_wq);

	return AE_OK;
}

L
Len Brown 已提交
112
void acpi_os_printf(const char *fmt, ...)
L
Linus Torvalds 已提交
113 114 115 116 117 118
{
	va_list args;
	va_start(args, fmt);
	acpi_os_vprintf(fmt, args);
	va_end(args);
}
L
Len Brown 已提交
119

L
Linus Torvalds 已提交
120 121
EXPORT_SYMBOL(acpi_os_printf);

L
Len Brown 已提交
122
void acpi_os_vprintf(const char *fmt, va_list args)
L
Linus Torvalds 已提交
123 124
{
	static char buffer[512];
L
Len Brown 已提交
125

L
Linus Torvalds 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138
	vsprintf(buffer, fmt, args);

#ifdef ENABLE_DEBUGGER
	if (acpi_in_debugger) {
		kdb_printf("%s", buffer);
	} else {
		printk("%s", buffer);
	}
#else
	printk("%s", buffer);
#endif
}

139
extern int acpi_in_resume;
L
Len Brown 已提交
140
void *acpi_os_allocate(acpi_size size)
L
Linus Torvalds 已提交
141
{
142 143 144 145
	if (acpi_in_resume)
		return kmalloc(size, GFP_ATOMIC);
	else
		return kmalloc(size, GFP_KERNEL);
L
Linus Torvalds 已提交
146 147
}

L
Len Brown 已提交
148
void acpi_os_free(void *ptr)
L
Linus Torvalds 已提交
149 150 151
{
	kfree(ptr);
}
L
Len Brown 已提交
152

L
Linus Torvalds 已提交
153 154
EXPORT_SYMBOL(acpi_os_free);

L
Len Brown 已提交
155
acpi_status acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
L
Linus Torvalds 已提交
156 157 158 159 160
{
	if (efi_enabled) {
		addr->pointer_type = ACPI_PHYSICAL_POINTER;
		if (efi.acpi20)
			addr->pointer.physical =
L
Len Brown 已提交
161
			    (acpi_physical_address) virt_to_phys(efi.acpi20);
L
Linus Torvalds 已提交
162 163
		else if (efi.acpi)
			addr->pointer.physical =
L
Len Brown 已提交
164
			    (acpi_physical_address) virt_to_phys(efi.acpi);
L
Linus Torvalds 已提交
165
		else {
L
Len Brown 已提交
166 167
			printk(KERN_ERR PREFIX
			       "System description tables not found\n");
L
Linus Torvalds 已提交
168 169 170 171
			return AE_NOT_FOUND;
		}
	} else {
		if (ACPI_FAILURE(acpi_find_root_pointer(flags, addr))) {
L
Len Brown 已提交
172 173
			printk(KERN_ERR PREFIX
			       "System description tables not found\n");
L
Linus Torvalds 已提交
174 175 176 177 178 179 180 181
			return AE_NOT_FOUND;
		}
	}

	return AE_OK;
}

acpi_status
L
Len Brown 已提交
182 183
acpi_os_map_memory(acpi_physical_address phys, acpi_size size,
		   void __iomem ** virt)
L
Linus Torvalds 已提交
184 185 186
{
	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
L
Len Brown 已提交
187
			*virt = (void __iomem *)phys_to_virt(phys);
L
Linus Torvalds 已提交
188 189 190 191 192 193 194 195 196
		} else {
			*virt = ioremap(phys, size);
		}
	} else {
		if (phys > ULONG_MAX) {
			printk(KERN_ERR PREFIX "Cannot map memory that high\n");
			return AE_BAD_PARAMETER;
		}
		/*
L
Len Brown 已提交
197 198 199
		 * ioremap checks to ensure this is in reserved space
		 */
		*virt = ioremap((unsigned long)phys, size);
L
Linus Torvalds 已提交
200 201 202 203 204 205 206 207
	}

	if (!*virt)
		return AE_NO_MEMORY;

	return AE_OK;
}

L
Len Brown 已提交
208
void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
L
Linus Torvalds 已提交
209 210 211 212 213 214
{
	iounmap(virt);
}

#ifdef ACPI_FUTURE_USAGE
acpi_status
L
Len Brown 已提交
215
acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
L
Linus Torvalds 已提交
216
{
L
Len Brown 已提交
217
	if (!phys || !virt)
L
Linus Torvalds 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230
		return AE_BAD_PARAMETER;

	*phys = virt_to_phys(virt);

	return AE_OK;
}
#endif

#define ACPI_MAX_OVERRIDE_LEN 100

static char acpi_os_name[ACPI_MAX_OVERRIDE_LEN];

acpi_status
L
Len Brown 已提交
231 232
acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
			    acpi_string * new_val)
L
Linus Torvalds 已提交
233 234 235 236 237
{
	if (!init_val || !new_val)
		return AE_BAD_PARAMETER;

	*new_val = NULL;
L
Len Brown 已提交
238
	if (!memcmp(init_val->name, "_OS_", 4) && strlen(acpi_os_name)) {
L
Linus Torvalds 已提交
239
		printk(KERN_INFO PREFIX "Overriding _OS definition to '%s'\n",
L
Len Brown 已提交
240
		       acpi_os_name);
L
Linus Torvalds 已提交
241 242 243 244 245 246 247
		*new_val = acpi_os_name;
	}

	return AE_OK;
}

acpi_status
L
Len Brown 已提交
248 249
acpi_os_table_override(struct acpi_table_header * existing_table,
		       struct acpi_table_header ** new_table)
L
Linus Torvalds 已提交
250 251 252 253 254 255
{
	if (!existing_table || !new_table)
		return AE_BAD_PARAMETER;

#ifdef CONFIG_ACPI_CUSTOM_DSDT
	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
L
Len Brown 已提交
256
		*new_table = (struct acpi_table_header *)AmlCode;
L
Linus Torvalds 已提交
257 258 259 260 261 262 263 264
	else
		*new_table = NULL;
#else
	*new_table = NULL;
#endif
	return AE_OK;
}

L
Len Brown 已提交
265
static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
L
Linus Torvalds 已提交
266
{
L
Len Brown 已提交
267
	return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE;
L
Linus Torvalds 已提交
268 269 270
}

acpi_status
L
Len Brown 已提交
271 272
acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
				  void *context)
L
Linus Torvalds 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
{
	unsigned int irq;

	/*
	 * Ignore the GSI from the core, and use the value in our copy of the
	 * FADT. It may not be the same if an interrupt source override exists
	 * for the SCI.
	 */
	gsi = acpi_fadt.sci_int;
	if (acpi_gsi_to_irq(gsi, &irq) < 0) {
		printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
		       gsi);
		return AE_OK;
	}

	acpi_irq_handler = handler;
	acpi_irq_context = context;
	if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) {
		printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
		return AE_NOT_ACQUIRED;
	}
	acpi_irq_irq = irq;

	return AE_OK;
}

L
Len Brown 已提交
299
acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
L
Linus Torvalds 已提交
300 301 302 303 304 305 306 307 308 309 310 311 312 313
{
	if (irq) {
		free_irq(irq, acpi_irq);
		acpi_irq_handler = NULL;
		acpi_irq_irq = 0;
	}

	return AE_OK;
}

/*
 * Running in interpreter thread context, safe to sleep
 */

L
Len Brown 已提交
314
void acpi_os_sleep(acpi_integer ms)
L
Linus Torvalds 已提交
315 316
{
	current->state = TASK_INTERRUPTIBLE;
L
Len Brown 已提交
317
	schedule_timeout(((signed long)ms * HZ) / 1000);
L
Linus Torvalds 已提交
318
}
L
Len Brown 已提交
319

L
Linus Torvalds 已提交
320 321
EXPORT_SYMBOL(acpi_os_sleep);

L
Len Brown 已提交
322
void acpi_os_stall(u32 us)
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330 331 332 333
{
	while (us) {
		u32 delay = 1000;

		if (delay > us)
			delay = us;
		udelay(delay);
		touch_nmi_watchdog();
		us -= delay;
	}
}
L
Len Brown 已提交
334

L
Linus Torvalds 已提交
335 336 337 338 339 340 341
EXPORT_SYMBOL(acpi_os_stall);

/*
 * Support ACPI 3.0 AML Timer operand
 * Returns 64-bit free-running, monotonically increasing timer
 * with 100ns granularity
 */
L
Len Brown 已提交
342
u64 acpi_os_get_timer(void)
L
Linus Torvalds 已提交
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
{
	static u64 t;

#ifdef	CONFIG_HPET
	/* TBD: use HPET if available */
#endif

#ifdef	CONFIG_X86_PM_TIMER
	/* TBD: default to PM timer if HPET was not available */
#endif
	if (!t)
		printk(KERN_ERR PREFIX "acpi_os_get_timer() TBD\n");

	return ++t;
}

L
Len Brown 已提交
359
acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
L
Linus Torvalds 已提交
360 361 362 363 364 365
{
	u32 dummy;

	if (!value)
		value = &dummy;

L
Len Brown 已提交
366
	switch (width) {
L
Linus Torvalds 已提交
367
	case 8:
L
Len Brown 已提交
368
		*(u8 *) value = inb(port);
L
Linus Torvalds 已提交
369 370
		break;
	case 16:
L
Len Brown 已提交
371
		*(u16 *) value = inw(port);
L
Linus Torvalds 已提交
372 373
		break;
	case 32:
L
Len Brown 已提交
374
		*(u32 *) value = inl(port);
L
Linus Torvalds 已提交
375 376 377 378 379 380 381
		break;
	default:
		BUG();
	}

	return AE_OK;
}
L
Len Brown 已提交
382

L
Linus Torvalds 已提交
383 384
EXPORT_SYMBOL(acpi_os_read_port);

L
Len Brown 已提交
385
acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
L
Linus Torvalds 已提交
386
{
L
Len Brown 已提交
387
	switch (width) {
L
Linus Torvalds 已提交
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
	case 8:
		outb(value, port);
		break;
	case 16:
		outw(value, port);
		break;
	case 32:
		outl(value, port);
		break;
	default:
		BUG();
	}

	return AE_OK;
}
L
Len Brown 已提交
403

L
Linus Torvalds 已提交
404 405 406
EXPORT_SYMBOL(acpi_os_write_port);

acpi_status
L
Len Brown 已提交
407
acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
L
Linus Torvalds 已提交
408
{
L
Len Brown 已提交
409 410 411
	u32 dummy;
	void __iomem *virt_addr;
	int iomem = 0;
L
Linus Torvalds 已提交
412 413 414 415

	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
			/* HACK ALERT! We can use readb/w/l on real memory too.. */
L
Len Brown 已提交
416
			virt_addr = (void __iomem *)phys_to_virt(phys_addr);
L
Linus Torvalds 已提交
417 418 419 420 421
		} else {
			iomem = 1;
			virt_addr = ioremap(phys_addr, width);
		}
	} else
L
Len Brown 已提交
422
		virt_addr = (void __iomem *)phys_to_virt(phys_addr);
L
Linus Torvalds 已提交
423 424 425 426 427
	if (!value)
		value = &dummy;

	switch (width) {
	case 8:
L
Len Brown 已提交
428
		*(u8 *) value = readb(virt_addr);
L
Linus Torvalds 已提交
429 430
		break;
	case 16:
L
Len Brown 已提交
431
		*(u16 *) value = readw(virt_addr);
L
Linus Torvalds 已提交
432 433
		break;
	case 32:
L
Len Brown 已提交
434
		*(u32 *) value = readl(virt_addr);
L
Linus Torvalds 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448
		break;
	default:
		BUG();
	}

	if (efi_enabled) {
		if (iomem)
			iounmap(virt_addr);
	}

	return AE_OK;
}

acpi_status
L
Len Brown 已提交
449
acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
L
Linus Torvalds 已提交
450
{
L
Len Brown 已提交
451 452
	void __iomem *virt_addr;
	int iomem = 0;
L
Linus Torvalds 已提交
453 454 455 456

	if (efi_enabled) {
		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
			/* HACK ALERT! We can use writeb/w/l on real memory too */
L
Len Brown 已提交
457
			virt_addr = (void __iomem *)phys_to_virt(phys_addr);
L
Linus Torvalds 已提交
458 459 460 461 462
		} else {
			iomem = 1;
			virt_addr = ioremap(phys_addr, width);
		}
	} else
L
Len Brown 已提交
463
		virt_addr = (void __iomem *)phys_to_virt(phys_addr);
L
Linus Torvalds 已提交
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485

	switch (width) {
	case 8:
		writeb(value, virt_addr);
		break;
	case 16:
		writew(value, virt_addr);
		break;
	case 32:
		writel(value, virt_addr);
		break;
	default:
		BUG();
	}

	if (iomem)
		iounmap(virt_addr);

	return AE_OK;
}

acpi_status
L
Len Brown 已提交
486 487
acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
			       void *value, u32 width)
L
Linus Torvalds 已提交
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
{
	int result, size;

	if (!value)
		return AE_BAD_PARAMETER;

	switch (width) {
	case 8:
		size = 1;
		break;
	case 16:
		size = 2;
		break;
	case 32:
		size = 4;
		break;
	default:
		return AE_ERROR;
	}

	BUG_ON(!raw_pci_ops);

	result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
L
Len Brown 已提交
511 512
				   PCI_DEVFN(pci_id->device, pci_id->function),
				   reg, size, value);
L
Linus Torvalds 已提交
513 514 515

	return (result ? AE_ERROR : AE_OK);
}
L
Len Brown 已提交
516

L
Linus Torvalds 已提交
517 518 519
EXPORT_SYMBOL(acpi_os_read_pci_configuration);

acpi_status
L
Len Brown 已提交
520 521
acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
				acpi_integer value, u32 width)
L
Linus Torvalds 已提交
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
{
	int result, size;

	switch (width) {
	case 8:
		size = 1;
		break;
	case 16:
		size = 2;
		break;
	case 32:
		size = 4;
		break;
	default:
		return AE_ERROR;
	}

	BUG_ON(!raw_pci_ops);

	result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
L
Len Brown 已提交
542 543
				    PCI_DEVFN(pci_id->device, pci_id->function),
				    reg, size, value);
L
Linus Torvalds 已提交
544 545 546 547 548

	return (result ? AE_ERROR : AE_OK);
}

/* TODO: Change code to take advantage of driver model more */
L
Len Brown 已提交
549 550 551 552
static void acpi_os_derive_pci_id_2(acpi_handle rhandle,	/* upper bound  */
				    acpi_handle chandle,	/* current node */
				    struct acpi_pci_id **id,
				    int *is_bridge, u8 * bus_number)
L
Linus Torvalds 已提交
553
{
L
Len Brown 已提交
554 555 556 557 558 559
	acpi_handle handle;
	struct acpi_pci_id *pci_id = *id;
	acpi_status status;
	unsigned long temp;
	acpi_object_type type;
	u8 tu8;
L
Linus Torvalds 已提交
560 561 562

	acpi_get_parent(chandle, &handle);
	if (handle != rhandle) {
L
Len Brown 已提交
563 564
		acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
					bus_number);
L
Linus Torvalds 已提交
565 566

		status = acpi_get_type(handle, &type);
L
Len Brown 已提交
567
		if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
L
Linus Torvalds 已提交
568 569
			return;

L
Len Brown 已提交
570 571 572
		status =
		    acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
					  &temp);
L
Linus Torvalds 已提交
573
		if (ACPI_SUCCESS(status)) {
L
Len Brown 已提交
574 575
			pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
			pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
L
Linus Torvalds 已提交
576 577 578 579 580

			if (*is_bridge)
				pci_id->bus = *bus_number;

			/* any nicer way to get bus number of bridge ? */
L
Len Brown 已提交
581 582 583 584 585 586 587 588
			status =
			    acpi_os_read_pci_configuration(pci_id, 0x0e, &tu8,
							   8);
			if (ACPI_SUCCESS(status)
			    && ((tu8 & 0x7f) == 1 || (tu8 & 0x7f) == 2)) {
				status =
				    acpi_os_read_pci_configuration(pci_id, 0x18,
								   &tu8, 8);
L
Linus Torvalds 已提交
589 590 591 592 593 594
				if (!ACPI_SUCCESS(status)) {
					/* Certainly broken...  FIX ME */
					return;
				}
				*is_bridge = 1;
				pci_id->bus = tu8;
L
Len Brown 已提交
595 596 597
				status =
				    acpi_os_read_pci_configuration(pci_id, 0x19,
								   &tu8, 8);
L
Linus Torvalds 已提交
598 599 600 601 602 603 604 605 606
				if (ACPI_SUCCESS(status)) {
					*bus_number = tu8;
				}
			} else
				*is_bridge = 0;
		}
	}
}

L
Len Brown 已提交
607 608 609
void acpi_os_derive_pci_id(acpi_handle rhandle,	/* upper bound  */
			   acpi_handle chandle,	/* current node */
			   struct acpi_pci_id **id)
L
Linus Torvalds 已提交
610 611 612 613 614 615 616
{
	int is_bridge = 1;
	u8 bus_number = (*id)->bus;

	acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
}

L
Len Brown 已提交
617
static void acpi_os_execute_deferred(void *context)
L
Linus Torvalds 已提交
618
{
L
Len Brown 已提交
619
	struct acpi_os_dpc *dpc = NULL;
L
Linus Torvalds 已提交
620

L
Len Brown 已提交
621
	ACPI_FUNCTION_TRACE("os_execute_deferred");
L
Linus Torvalds 已提交
622

L
Len Brown 已提交
623
	dpc = (struct acpi_os_dpc *)context;
L
Linus Torvalds 已提交
624
	if (!dpc) {
L
Len Brown 已提交
625
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
L
Linus Torvalds 已提交
626 627 628 629 630 631 632 633 634 635 636
		return_VOID;
	}

	dpc->function(dpc->context);

	kfree(dpc);

	return_VOID;
}

acpi_status
L
Len Brown 已提交
637 638
acpi_os_queue_for_execution(u32 priority,
			    acpi_osd_exec_callback function, void *context)
L
Linus Torvalds 已提交
639
{
L
Len Brown 已提交
640 641 642
	acpi_status status = AE_OK;
	struct acpi_os_dpc *dpc;
	struct work_struct *task;
L
Linus Torvalds 已提交
643

L
Len Brown 已提交
644
	ACPI_FUNCTION_TRACE("os_queue_for_execution");
L
Linus Torvalds 已提交
645

L
Len Brown 已提交
646 647 648
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
			  "Scheduling function [%p(%p)] for deferred execution.\n",
			  function, context));
L
Linus Torvalds 已提交
649 650

	if (!function)
L
Len Brown 已提交
651
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
652 653 654 655 656 657 658 659 660 661 662 663

	/*
	 * Allocate/initialize DPC structure.  Note that this memory will be
	 * freed by the callee.  The kernel handles the tq_struct list  in a
	 * way that allows us to also free its memory inside the callee.
	 * Because we may want to schedule several tasks with different
	 * parameters we can't use the approach some kernel code uses of
	 * having a static tq_struct.
	 * We can save time and code by allocating the DPC and tq_structs
	 * from the same memory.
	 */

L
Len Brown 已提交
664 665 666
	dpc =
	    kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
		    GFP_ATOMIC);
L
Linus Torvalds 已提交
667
	if (!dpc)
L
Len Brown 已提交
668
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
669 670 671 672

	dpc->function = function;
	dpc->context = context;

L
Len Brown 已提交
673 674
	task = (void *)(dpc + 1);
	INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
L
Linus Torvalds 已提交
675 676

	if (!queue_work(kacpid_wq, task)) {
L
Len Brown 已提交
677 678
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Call to queue_work() failed.\n"));
L
Linus Torvalds 已提交
679 680 681 682
		kfree(dpc);
		status = AE_ERROR;
	}

L
Len Brown 已提交
683
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
684
}
L
Len Brown 已提交
685

L
Linus Torvalds 已提交
686 687
EXPORT_SYMBOL(acpi_os_queue_for_execution);

L
Len Brown 已提交
688
void acpi_os_wait_events_complete(void *context)
L
Linus Torvalds 已提交
689 690 691
{
	flush_workqueue(kacpid_wq);
}
L
Len Brown 已提交
692

L
Linus Torvalds 已提交
693 694 695 696 697
EXPORT_SYMBOL(acpi_os_wait_events_complete);

/*
 * Allocate the memory for a spinlock and initialize it.
 */
L
Len Brown 已提交
698
acpi_status acpi_os_create_lock(acpi_handle * out_handle)
L
Linus Torvalds 已提交
699 700 701
{
	spinlock_t *lock_ptr;

L
Len Brown 已提交
702
	ACPI_FUNCTION_TRACE("os_create_lock");
L
Linus Torvalds 已提交
703 704 705 706 707

	lock_ptr = acpi_os_allocate(sizeof(spinlock_t));

	spin_lock_init(lock_ptr);

L
Len Brown 已提交
708
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating spinlock[%p].\n", lock_ptr));
L
Linus Torvalds 已提交
709 710 711

	*out_handle = lock_ptr;

L
Len Brown 已提交
712
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
713 714 715 716 717
}

/*
 * Deallocate the memory for a spinlock.
 */
L
Len Brown 已提交
718
void acpi_os_delete_lock(acpi_handle handle)
L
Linus Torvalds 已提交
719
{
L
Len Brown 已提交
720
	ACPI_FUNCTION_TRACE("os_create_lock");
L
Linus Torvalds 已提交
721

L
Len Brown 已提交
722
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting spinlock[%p].\n", handle));
L
Linus Torvalds 已提交
723 724 725 726 727 728 729

	acpi_os_free(handle);

	return_VOID;
}

acpi_status
L
Len Brown 已提交
730
acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle)
L
Linus Torvalds 已提交
731
{
L
Len Brown 已提交
732
	struct semaphore *sem = NULL;
L
Linus Torvalds 已提交
733

L
Len Brown 已提交
734
	ACPI_FUNCTION_TRACE("os_create_semaphore");
L
Linus Torvalds 已提交
735 736 737

	sem = acpi_os_allocate(sizeof(struct semaphore));
	if (!sem)
L
Len Brown 已提交
738
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
739 740 741 742
	memset(sem, 0, sizeof(struct semaphore));

	sema_init(sem, initial_units);

L
Len Brown 已提交
743
	*handle = (acpi_handle *) sem;
L
Linus Torvalds 已提交
744

L
Len Brown 已提交
745 746
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Creating semaphore[%p|%d].\n",
			  *handle, initial_units));
L
Linus Torvalds 已提交
747

L
Len Brown 已提交
748
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
749 750
}

L
Len Brown 已提交
751
EXPORT_SYMBOL(acpi_os_create_semaphore);
L
Linus Torvalds 已提交
752 753 754 755 756 757 758 759

/*
 * TODO: A better way to delete semaphores?  Linux doesn't have a
 * 'delete_semaphore()' function -- may result in an invalid
 * pointer dereference for non-synchronized consumers.	Should
 * we at least check for blocked threads and signal/cancel them?
 */

L
Len Brown 已提交
760
acpi_status acpi_os_delete_semaphore(acpi_handle handle)
L
Linus Torvalds 已提交
761
{
L
Len Brown 已提交
762
	struct semaphore *sem = (struct semaphore *)handle;
L
Linus Torvalds 已提交
763

L
Len Brown 已提交
764
	ACPI_FUNCTION_TRACE("os_delete_semaphore");
L
Linus Torvalds 已提交
765 766

	if (!sem)
L
Len Brown 已提交
767
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
768

L
Len Brown 已提交
769
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Deleting semaphore[%p].\n", handle));
L
Linus Torvalds 已提交
770

L
Len Brown 已提交
771 772
	acpi_os_free(sem);
	sem = NULL;
L
Linus Torvalds 已提交
773

L
Len Brown 已提交
774
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
775 776
}

L
Len Brown 已提交
777
EXPORT_SYMBOL(acpi_os_delete_semaphore);
L
Linus Torvalds 已提交
778 779 780 781 782 783 784 785 786 787

/*
 * TODO: The kernel doesn't have a 'down_timeout' function -- had to
 * improvise.  The process is to sleep for one scheduler quantum
 * until the semaphore becomes available.  Downside is that this
 * may result in starvation for timeout-based waits when there's
 * lots of semaphore activity.
 *
 * TODO: Support for units > 1?
 */
L
Len Brown 已提交
788
acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
L
Linus Torvalds 已提交
789
{
L
Len Brown 已提交
790 791 792
	acpi_status status = AE_OK;
	struct semaphore *sem = (struct semaphore *)handle;
	int ret = 0;
L
Linus Torvalds 已提交
793

L
Len Brown 已提交
794
	ACPI_FUNCTION_TRACE("os_wait_semaphore");
L
Linus Torvalds 已提交
795 796

	if (!sem || (units < 1))
L
Len Brown 已提交
797
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
798 799

	if (units > 1)
L
Len Brown 已提交
800
		return_ACPI_STATUS(AE_SUPPORT);
L
Linus Torvalds 已提交
801

L
Len Brown 已提交
802 803
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
			  handle, units, timeout));
L
Linus Torvalds 已提交
804 805 806 807

	if (in_atomic())
		timeout = 0;

L
Len Brown 已提交
808
	switch (timeout) {
L
Linus Torvalds 已提交
809 810 811 812 813 814 815
		/*
		 * No Wait:
		 * --------
		 * A zero timeout value indicates that we shouldn't wait - just
		 * acquire the semaphore if available otherwise return AE_TIME
		 * (a.k.a. 'would block').
		 */
L
Len Brown 已提交
816 817
	case 0:
		if (down_trylock(sem))
L
Linus Torvalds 已提交
818 819 820 821 822 823 824
			status = AE_TIME;
		break;

		/*
		 * Wait Indefinitely:
		 * ------------------
		 */
L
Len Brown 已提交
825
	case ACPI_WAIT_FOREVER:
L
Linus Torvalds 已提交
826 827 828 829 830 831 832
		down(sem);
		break;

		/*
		 * Wait w/ Timeout:
		 * ----------------
		 */
L
Len Brown 已提交
833
	default:
L
Linus Torvalds 已提交
834 835 836
		// TODO: A better timeout algorithm?
		{
			int i = 0;
L
Len Brown 已提交
837
			static const int quantum_ms = 1000 / HZ;
L
Linus Torvalds 已提交
838 839 840 841 842 843 844

			ret = down_trylock(sem);
			for (i = timeout; (i > 0 && ret < 0); i -= quantum_ms) {
				current->state = TASK_INTERRUPTIBLE;
				schedule_timeout(1);
				ret = down_trylock(sem);
			}
L
Len Brown 已提交
845

L
Linus Torvalds 已提交
846 847 848 849 850 851 852
			if (ret != 0)
				status = AE_TIME;
		}
		break;
	}

	if (ACPI_FAILURE(status)) {
L
Len Brown 已提交
853 854 855 856 857 858 859 860
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Failed to acquire semaphore[%p|%d|%d], %s\n",
				  handle, units, timeout,
				  acpi_format_exception(status)));
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
				  "Acquired semaphore[%p|%d|%d]\n", handle,
				  units, timeout));
L
Linus Torvalds 已提交
861 862
	}

L
Len Brown 已提交
863
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
864 865
}

L
Len Brown 已提交
866
EXPORT_SYMBOL(acpi_os_wait_semaphore);
L
Linus Torvalds 已提交
867 868 869 870

/*
 * TODO: Support for units > 1?
 */
L
Len Brown 已提交
871
acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units)
L
Linus Torvalds 已提交
872
{
L
Len Brown 已提交
873
	struct semaphore *sem = (struct semaphore *)handle;
L
Linus Torvalds 已提交
874

L
Len Brown 已提交
875
	ACPI_FUNCTION_TRACE("os_signal_semaphore");
L
Linus Torvalds 已提交
876 877

	if (!sem || (units < 1))
L
Len Brown 已提交
878
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
879 880

	if (units > 1)
L
Len Brown 已提交
881
		return_ACPI_STATUS(AE_SUPPORT);
L
Linus Torvalds 已提交
882

L
Len Brown 已提交
883 884
	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Signaling semaphore[%p|%d]\n", handle,
			  units));
L
Linus Torvalds 已提交
885 886 887

	up(sem);

L
Len Brown 已提交
888
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
889
}
L
Len Brown 已提交
890

L
Linus Torvalds 已提交
891 892 893
EXPORT_SYMBOL(acpi_os_signal_semaphore);

#ifdef ACPI_FUTURE_USAGE
L
Len Brown 已提交
894
u32 acpi_os_get_line(char *buffer)
L
Linus Torvalds 已提交
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
{

#ifdef ENABLE_DEBUGGER
	if (acpi_in_debugger) {
		u32 chars;

		kdb_read(buffer, sizeof(line_buf));

		/* remove the CR kdb includes */
		chars = strlen(buffer) - 1;
		buffer[chars] = '\0';
	}
#endif

	return 0;
}
L
Len Brown 已提交
911
#endif				/*  ACPI_FUTURE_USAGE  */
L
Linus Torvalds 已提交
912 913

/* Assumes no unreadable holes inbetween */
L
Len Brown 已提交
914
u8 acpi_os_readable(void *ptr, acpi_size len)
L
Linus Torvalds 已提交
915
{
L
Len Brown 已提交
916
#if defined(__i386__) || defined(__x86_64__)
L
Linus Torvalds 已提交
917
	char tmp;
L
Len Brown 已提交
918 919
	return !__get_user(tmp, (char __user *)ptr)
	    && !__get_user(tmp, (char __user *)ptr + len - 1);
L
Linus Torvalds 已提交
920 921 922 923 924
#endif
	return 1;
}

#ifdef ACPI_FUTURE_USAGE
L
Len Brown 已提交
925
u8 acpi_os_writable(void *ptr, acpi_size len)
L
Linus Torvalds 已提交
926 927 928 929 930 931 932
{
	/* could do dummy write (racy) or a kernel page table lookup.
	   The later may be difficult at early boot when kmap doesn't work yet. */
	return 1;
}
#endif

L
Len Brown 已提交
933
u32 acpi_os_get_thread_id(void)
L
Linus Torvalds 已提交
934 935 936 937 938 939 940
{
	if (!in_atomic())
		return current->pid;

	return 0;
}

L
Len Brown 已提交
941
acpi_status acpi_os_signal(u32 function, void *info)
L
Linus Torvalds 已提交
942
{
L
Len Brown 已提交
943
	switch (function) {
L
Linus Torvalds 已提交
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
	case ACPI_SIGNAL_FATAL:
		printk(KERN_ERR PREFIX "Fatal opcode executed\n");
		break;
	case ACPI_SIGNAL_BREAKPOINT:
		/*
		 * AML Breakpoint
		 * ACPI spec. says to treat it as a NOP unless
		 * you are debugging.  So if/when we integrate
		 * AML debugger into the kernel debugger its
		 * hook will go here.  But until then it is
		 * not useful to print anything on breakpoints.
		 */
		break;
	default:
		break;
	}

	return AE_OK;
}
L
Len Brown 已提交
963

L
Linus Torvalds 已提交
964 965
EXPORT_SYMBOL(acpi_os_signal);

L
Len Brown 已提交
966
static int __init acpi_os_name_setup(char *str)
L
Linus Torvalds 已提交
967 968
{
	char *p = acpi_os_name;
L
Len Brown 已提交
969
	int count = ACPI_MAX_OVERRIDE_LEN - 1;
L
Linus Torvalds 已提交
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984

	if (!str || !*str)
		return 0;

	for (; count-- && str && *str; str++) {
		if (isalnum(*str) || *str == ' ' || *str == ':')
			*p++ = *str;
		else if (*str == '\'' || *str == '"')
			continue;
		else
			break;
	}
	*p = 0;

	return 1;
L
Len Brown 已提交
985

L
Linus Torvalds 已提交
986 987 988 989 990 991 992 993 994
}

__setup("acpi_os_name=", acpi_os_name_setup);

/*
 * _OSI control
 * empty string disables _OSI
 * TBD additional string adds to _OSI
 */
L
Len Brown 已提交
995
static int __init acpi_osi_setup(char *str)
L
Linus Torvalds 已提交
996 997 998 999
{
	if (str == NULL || *str == '\0') {
		printk(KERN_INFO PREFIX "_OSI method disabled\n");
		acpi_gbl_create_osi_method = FALSE;
L
Len Brown 已提交
1000
	} else {
L
Linus Torvalds 已提交
1001
		/* TBD */
L
Len Brown 已提交
1002 1003
		printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
		       str);
L
Linus Torvalds 已提交
1004 1005 1006 1007 1008 1009 1010 1011
	}

	return 1;
}

__setup("acpi_osi=", acpi_osi_setup);

/* enable serialization to combat AE_ALREADY_EXISTS errors */
L
Len Brown 已提交
1012
static int __init acpi_serialize_setup(char *str)
L
Linus Torvalds 已提交
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
{
	printk(KERN_INFO PREFIX "serialize enabled\n");

	acpi_gbl_all_methods_serialized = TRUE;

	return 1;
}

__setup("acpi_serialize", acpi_serialize_setup);

/*
 * Wake and Run-Time GPES are expected to be separate.
 * We disable wake-GPEs at run-time to prevent spurious
 * interrupts.
 *
 * However, if a system exists that shares Wake and
 * Run-time events on the same GPE this flag is available
 * to tell Linux to keep the wake-time GPEs enabled at run-time.
 */
L
Len Brown 已提交
1032
static int __init acpi_wake_gpes_always_on_setup(char *str)
L
Linus Torvalds 已提交
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
{
	printk(KERN_INFO PREFIX "wake GPEs not disabled\n");

	acpi_gbl_leave_wake_gpes_disabled = FALSE;

	return 1;
}

__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);

L
Len Brown 已提交
1043
int __init acpi_hotkey_setup(char *str)
L
Luming Yu 已提交
1044
{
1045
	acpi_specific_hotkey_enabled = FALSE;
L
Luming Yu 已提交
1046 1047 1048
	return 1;
}

1049
__setup("acpi_generic_hotkey", acpi_hotkey_setup);
L
Luming Yu 已提交
1050

L
Linus Torvalds 已提交
1051 1052 1053 1054 1055 1056 1057
/*
 * max_cstate is defined in the base kernel so modules can
 * change it w/o depending on the state of the processor module.
 */
unsigned int max_cstate = ACPI_PROCESSOR_MAX_POWER;

EXPORT_SYMBOL(max_cstate);
1058 1059 1060 1061 1062 1063 1064 1065 1066

/*
 * Acquire a spinlock.
 *
 * handle is a pointer to the spinlock_t.
 * flags is *not* the result of save_flags - it is an ACPI-specific flag variable
 *   that indicates whether we are at interrupt level.
 */

L
Len Brown 已提交
1067
unsigned long acpi_os_acquire_lock(acpi_handle handle)
1068 1069
{
	unsigned long flags;
L
Len Brown 已提交
1070
	spin_lock_irqsave((spinlock_t *) handle, flags);
1071 1072 1073 1074 1075 1076 1077
	return flags;
}

/*
 * Release a spinlock. See above.
 */

L
Len Brown 已提交
1078
void acpi_os_release_lock(acpi_handle handle, unsigned long flags)
1079
{
L
Len Brown 已提交
1080
	spin_unlock_irqrestore((spinlock_t *) handle, flags);
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
}

#ifndef ACPI_USE_LOCAL_CACHE

/*******************************************************************************
 *
 * FUNCTION:    acpi_os_create_cache
 *
 * PARAMETERS:  CacheName       - Ascii name for the cache
 *              ObjectSize      - Size of each cached object
 *              MaxDepth        - Maximum depth of the cache (in objects)
 *              ReturnCache     - Where the new cache object is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Create a cache object
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
1101
acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
1102
{
L
Len Brown 已提交
1103
	*cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
	return AE_OK;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_os_purge_cache
 *
 * PARAMETERS:  Cache           - Handle to cache object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Free all objects within the requested cache.
 *
 ******************************************************************************/

L
Len Brown 已提交
1119
acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
1120
{
L
Len Brown 已提交
1121 1122
	(void)kmem_cache_shrink(cache);
	return (AE_OK);
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_os_delete_cache
 *
 * PARAMETERS:  Cache           - Handle to cache object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Free all objects within the requested cache and delete the
 *              cache object.
 *
 ******************************************************************************/

L
Len Brown 已提交
1138
acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
1139
{
L
Len Brown 已提交
1140 1141
	(void)kmem_cache_destroy(cache);
	return (AE_OK);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_os_release_object
 *
 * PARAMETERS:  Cache       - Handle to cache object
 *              Object      - The object to be released
 *
 * RETURN:      None
 *
 * DESCRIPTION: Release an object to the specified cache.  If cache is full,
 *              the object is deleted.
 *
 ******************************************************************************/

L
Len Brown 已提交
1158
acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1159
{
L
Len Brown 已提交
1160 1161
	kmem_cache_free(cache, object);
	return (AE_OK);
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_os_acquire_object
 *
 * PARAMETERS:  Cache           - Handle to cache object
 *              ReturnObject    - Where the object is returned
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get an object from the specified cache.  If cache is empty,
 *              the object is allocated.
 *
 ******************************************************************************/

L
Len Brown 已提交
1178
void *acpi_os_acquire_object(acpi_cache_t * cache)
1179
{
L
Len Brown 已提交
1180 1181 1182
	void *object = kmem_cache_alloc(cache, GFP_KERNEL);
	WARN_ON(!object);
	return object;
1183 1184 1185
}

#endif