Mon Jul 6 00:54:01 2009 UTC ()
Add a pmf(9) shutdown hook to acpiec(4) to use polling on shutdown.

This fixes DIAGNOSTIC's assertion failure:

cpu_switchto(): switching above IPL_SCHED

during ACPI shutdown.

OK'd by joerg@


(alc)
diff -r1.55 -r1.56 src/sys/dev/acpi/acpi_ec.c

cvs diff -r1.55 -r1.56 src/sys/dev/acpi/acpi_ec.c (expand / switch to unified diff)

--- src/sys/dev/acpi/acpi_ec.c 2009/05/12 09:29:46 1.55
+++ src/sys/dev/acpi/acpi_ec.c 2009/07/06 00:54:00 1.56
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: acpi_ec.c,v 1.55 2009/05/12 09:29:46 cegger Exp $ */ 1/* $NetBSD: acpi_ec.c,v 1.56 2009/07/06 00:54:00 alc Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. 4 * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 10 *
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in 14 * notice, this list of conditions and the following disclaimer in
@@ -49,27 +49,27 @@ @@ -49,27 +49,27 @@
49 * working and the handlers just busy loop. 49 * working and the handlers just busy loop.
50 * 50 *
51 * A callout is scheduled to compensate for missing interrupts on some 51 * A callout is scheduled to compensate for missing interrupts on some
52 * hardware. If the EC doesn't process a request for 5s, it is most likely 52 * hardware. If the EC doesn't process a request for 5s, it is most likely
53 * in a wedged state. No method to reset the EC is currently known. 53 * in a wedged state. No method to reset the EC is currently known.
54 * 54 *
55 * Special care has to be taken to not poll the EC in a busy loop without 55 * Special care has to be taken to not poll the EC in a busy loop without
56 * delay. This can prevent processing of Power Button events. At least some 56 * delay. This can prevent processing of Power Button events. At least some
57 * Lenovo Thinkpads seem to be implement the Power Button Override in the EC 57 * Lenovo Thinkpads seem to be implement the Power Button Override in the EC
58 * and the only option to recover on those models is to cut off all power. 58 * and the only option to recover on those models is to cut off all power.
59 */ 59 */
60 60
61#include <sys/cdefs.h> 61#include <sys/cdefs.h>
62__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.55 2009/05/12 09:29:46 cegger Exp $"); 62__KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.56 2009/07/06 00:54:00 alc Exp $");
63 63
64#include <sys/param.h> 64#include <sys/param.h>
65#include <sys/systm.h> 65#include <sys/systm.h>
66#include <sys/condvar.h> 66#include <sys/condvar.h>
67#include <sys/device.h> 67#include <sys/device.h>
68#include <sys/kernel.h> 68#include <sys/kernel.h>
69#include <sys/kthread.h> 69#include <sys/kthread.h>
70#include <sys/mutex.h> 70#include <sys/mutex.h>
71 71
72#include <sys/bus.h> 72#include <sys/bus.h>
73 73
74#include <dev/acpi/acpivar.h> 74#include <dev/acpi/acpivar.h>
75#include <dev/acpi/acpi_ecvar.h> 75#include <dev/acpi/acpi_ecvar.h>
@@ -138,28 +138,29 @@ struct acpiec_softc { @@ -138,28 +138,29 @@ struct acpiec_softc {
138 138
139 uint8_t sc_cur_addr, sc_cur_val; 139 uint8_t sc_cur_addr, sc_cur_val;
140}; 140};
141 141
142static int acpiecdt_match(device_t, cfdata_t, void *); 142static int acpiecdt_match(device_t, cfdata_t, void *);
143static void acpiecdt_attach(device_t, device_t, void *); 143static void acpiecdt_attach(device_t, device_t, void *);
144 144
145static int acpiec_match(device_t, cfdata_t, void *); 145static int acpiec_match(device_t, cfdata_t, void *);
146static void acpiec_attach(device_t, device_t, void *); 146static void acpiec_attach(device_t, device_t, void *);
147 147
148static void acpiec_common_attach(device_t, device_t, ACPI_HANDLE, 148static void acpiec_common_attach(device_t, device_t, ACPI_HANDLE,
149 bus_addr_t, bus_addr_t, ACPI_HANDLE, uint8_t); 149 bus_addr_t, bus_addr_t, ACPI_HANDLE, uint8_t);
150 150
151static bool acpiec_resume(device_t PMF_FN_PROTO); 
152static bool acpiec_suspend(device_t PMF_FN_PROTO); 151static bool acpiec_suspend(device_t PMF_FN_PROTO);
 152static bool acpiec_resume(device_t PMF_FN_PROTO);
 153static bool acpiec_shutdown(device_t, int);
153 154
154static bool acpiec_parse_gpe_package(device_t, ACPI_HANDLE, 155static bool acpiec_parse_gpe_package(device_t, ACPI_HANDLE,
155 ACPI_HANDLE *, uint8_t *); 156 ACPI_HANDLE *, uint8_t *);
156 157
157static void acpiec_callout(void *); 158static void acpiec_callout(void *);
158static void acpiec_gpe_query(void *); 159static void acpiec_gpe_query(void *);
159static UINT32 acpiec_gpe_handler(void *); 160static UINT32 acpiec_gpe_handler(void *);
160static ACPI_STATUS acpiec_space_setup(ACPI_HANDLE, UINT32, void *, void **); 161static ACPI_STATUS acpiec_space_setup(ACPI_HANDLE, UINT32, void *, void **);
161static ACPI_STATUS acpiec_space_handler(UINT32, ACPI_PHYSICAL_ADDRESS, 162static ACPI_STATUS acpiec_space_handler(UINT32, ACPI_PHYSICAL_ADDRESS,
162 UINT32, ACPI_INTEGER *, void *, void *); 163 UINT32, ACPI_INTEGER *, void *, void *);
163 164
164static void acpiec_gpe_state_machine(device_t); 165static void acpiec_gpe_state_machine(device_t);
165 166
@@ -367,27 +368,28 @@ acpiec_common_attach(device_t parent, de @@ -367,27 +368,28 @@ acpiec_common_attach(device_t parent, de
367 aprint_error_dev(self, "unable to enable GPE: %s\n", 368 aprint_error_dev(self, "unable to enable GPE: %s\n",
368 AcpiFormatException(rv)); 369 AcpiFormatException(rv));
369 goto post_csr_map; 370 goto post_csr_map;
370 } 371 }
371 372
372 if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, acpiec_gpe_query, 373 if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, acpiec_gpe_query,
373 self, NULL, "acpiec sci thread")) { 374 self, NULL, "acpiec sci thread")) {
374 aprint_error_dev(self, "unable to create query kthread\n"); 375 aprint_error_dev(self, "unable to create query kthread\n");
375 goto post_csr_map; 376 goto post_csr_map;
376 } 377 }
377 378
378 ec_singleton = self; 379 ec_singleton = self;
379 380
380 if (!pmf_device_register(self, acpiec_suspend, acpiec_resume)) 381 if (!pmf_device_register1(self, acpiec_suspend, acpiec_resume,
 382 acpiec_shutdown))
381 aprint_error_dev(self, "couldn't establish power handler\n"); 383 aprint_error_dev(self, "couldn't establish power handler\n");
382 384
383 return; 385 return;
384 386
385post_csr_map: 387post_csr_map:
386 (void)AcpiRemoveGpeHandler(sc->sc_gpeh, sc->sc_gpebit, 388 (void)AcpiRemoveGpeHandler(sc->sc_gpeh, sc->sc_gpebit,
387 acpiec_gpe_handler); 389 acpiec_gpe_handler);
388 (void)AcpiRemoveAddressSpaceHandler(sc->sc_ech, 390 (void)AcpiRemoveAddressSpaceHandler(sc->sc_ech,
389 ACPI_ADR_SPACE_EC, acpiec_space_handler); 391 ACPI_ADR_SPACE_EC, acpiec_space_handler);
390 bus_space_unmap(sc->sc_csr_st, sc->sc_csr_sh, 1); 392 bus_space_unmap(sc->sc_csr_st, sc->sc_csr_sh, 1);
391post_data_map: 393post_data_map:
392 bus_space_unmap(sc->sc_data_st, sc->sc_data_sh, 1); 394 bus_space_unmap(sc->sc_data_st, sc->sc_data_sh, 1);
393} 395}
@@ -399,26 +401,34 @@ acpiec_suspend(device_t dv PMF_FN_ARGS) @@ -399,26 +401,34 @@ acpiec_suspend(device_t dv PMF_FN_ARGS)
399 401
400 return true; 402 return true;
401} 403}
402 404
403static bool 405static bool
404acpiec_resume(device_t dv PMF_FN_ARGS) 406acpiec_resume(device_t dv PMF_FN_ARGS)
405{ 407{
406 acpiec_cold = false; 408 acpiec_cold = false;
407 409
408 return true; 410 return true;
409} 411}
410 412
411static bool 413static bool
 414acpiec_shutdown(device_t dv, int how)
 415{
 416
 417 acpiec_cold = true;
 418 return true;
 419}
 420
 421static bool
412acpiec_parse_gpe_package(device_t self, ACPI_HANDLE ec_handle, 422acpiec_parse_gpe_package(device_t self, ACPI_HANDLE ec_handle,
413 ACPI_HANDLE *gpe_handle, uint8_t *gpebit) 423 ACPI_HANDLE *gpe_handle, uint8_t *gpebit)
414{ 424{
415 ACPI_BUFFER buf; 425 ACPI_BUFFER buf;
416 ACPI_OBJECT *p, *c; 426 ACPI_OBJECT *p, *c;
417 ACPI_STATUS rv; 427 ACPI_STATUS rv;
418 428
419 rv = acpi_eval_struct(ec_handle, "_GPE", &buf); 429 rv = acpi_eval_struct(ec_handle, "_GPE", &buf);
420 if (rv != AE_OK) { 430 if (rv != AE_OK) {
421 aprint_error_dev(self, "unable to evaluate _GPE: %s\n", 431 aprint_error_dev(self, "unable to evaluate _GPE: %s\n",
422 AcpiFormatException(rv)); 432 AcpiFormatException(rv));
423 return false; 433 return false;
424 } 434 }