Simplify and clean:
* Semantics. * Remove ACPI_ACAD_DEBUG. * Reduce the amount of error reporting. * Remove the internal bookkeeping flags and variables; instead operate only with a single state variable. * Trust that the notify handler is doing its job; remove the refresh routine from the sensor. * Queue a status check upon resume; we want to know if the status has changed when in suspend (and it is unclear if a notify is sent to us).
This commit is contained in:
parent
748a0d77b1
commit
d9ca089d6e
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: acpi_acad.c,v 1.38 2010/01/31 07:34:10 jruoho Exp $ */
|
||||
/* $NetBSD: acpi_acad.c,v 1.39 2010/01/31 11:16:18 jruoho Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright 2001 Wasabi Systems, Inc.
|
||||
@ -35,16 +35,12 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define ACPI_ACAD_DEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ACPI AC Adapter driver.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.38 2010/01/31 07:34:10 jruoho Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.39 2010/01/31 11:16:18 jruoho Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -57,20 +53,16 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_acad.c,v 1.38 2010/01/31 07:34:10 jruoho Exp $"
|
||||
|
||||
#include <dev/sysmon/sysmonvar.h>
|
||||
|
||||
#define _COMPONENT ACPI_ACAD_COMPONENT
|
||||
ACPI_MODULE_NAME ("acpi_acad")
|
||||
#define _COMPONENT ACPI_ACAD_COMPONENT
|
||||
ACPI_MODULE_NAME ("acpi_acad")
|
||||
|
||||
struct acpiacad_softc {
|
||||
struct acpi_devnode *sc_node; /* our ACPI devnode */
|
||||
int sc_flags; /* see below */
|
||||
int sc_status; /* status changed/not changed */
|
||||
int sc_notifysent; /* notify message sent */
|
||||
|
||||
struct sysmon_envsys *sc_sme;
|
||||
struct sysmon_pswitch sc_smpsw; /* our sysmon glue */
|
||||
envsys_data_t sc_sensor;
|
||||
|
||||
kmutex_t sc_mtx;
|
||||
struct acpi_devnode *sc_node;
|
||||
struct sysmon_envsys *sc_sme;
|
||||
struct sysmon_pswitch sc_smpsw;
|
||||
envsys_data_t sc_sensor;
|
||||
kmutex_t sc_mutex;
|
||||
int sc_status;
|
||||
};
|
||||
|
||||
static const char * const acad_hid[] = {
|
||||
@ -78,23 +70,13 @@ static const char * const acad_hid[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
#define AACAD_F_VERBOSE 0x01 /* verbose events */
|
||||
#define AACAD_F_AVAILABLE 0x02 /* information is available */
|
||||
#define AACAD_F_STCHANGED 0x04 /* status changed */
|
||||
|
||||
#define AACAD_SET(sc, f) (void)((sc)->sc_flags |= (f))
|
||||
#define AACAD_CLEAR(sc, f) (void)((sc)->sc_flags &= ~(f))
|
||||
#define AACAD_ISSET(sc, f) ((sc)->sc_flags & (f))
|
||||
|
||||
static int acpiacad_match(device_t, cfdata_t, void *);
|
||||
static void acpiacad_attach(device_t, device_t, void *);
|
||||
static int acpiacad_detach(device_t, int);
|
||||
static void acpiacad_get_status(void *);
|
||||
static void acpiacad_clear_status(struct acpiacad_softc *);
|
||||
static void acpiacad_notify_handler(ACPI_HANDLE, UINT32, void *);
|
||||
static void acpiacad_init_envsys(device_t);
|
||||
static void acpiacad_refresh(struct sysmon_envsys *, envsys_data_t *);
|
||||
static bool acpiacad_resume(device_t, pmf_qual_t);
|
||||
static int acpiacad_match(device_t, cfdata_t, void *);
|
||||
static void acpiacad_attach(device_t, device_t, void *);
|
||||
static int acpiacad_detach(device_t, int);
|
||||
static bool acpiacad_resume(device_t, pmf_qual_t);
|
||||
static void acpiacad_get_status(void *);
|
||||
static void acpiacad_notify_handler(ACPI_HANDLE, uint32_t, void *);
|
||||
static void acpiacad_init_envsys(device_t);
|
||||
|
||||
CFATTACH_DECL_NEW(acpiacad, sizeof(struct acpiacad_softc),
|
||||
acpiacad_match, acpiacad_attach, acpiacad_detach, NULL);
|
||||
@ -130,36 +112,23 @@ acpiacad_attach(device_t parent, device_t self, void *aux)
|
||||
aprint_naive(": ACPI AC Adapter\n");
|
||||
aprint_normal(": ACPI AC Adapter\n");
|
||||
|
||||
sc->sc_sme = NULL;
|
||||
sc->sc_status = -1;
|
||||
sc->sc_node = aa->aa_node;
|
||||
mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
sc->sc_smpsw.smpsw_name = device_xname(self);
|
||||
sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_ACADAPTER;
|
||||
if (sysmon_pswitch_register(&sc->sc_smpsw) != 0) {
|
||||
aprint_error_dev(self, "unable to register with sysmon\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_sme = NULL;
|
||||
sc->sc_status = -1;
|
||||
(void)sysmon_pswitch_register(&sc->sc_smpsw);
|
||||
(void)pmf_device_register(self, NULL, acpiacad_resume);
|
||||
|
||||
rv = AcpiInstallNotifyHandler(sc->sc_node->ad_handle,
|
||||
ACPI_ALL_NOTIFY, acpiacad_notify_handler, self);
|
||||
if (ACPI_FAILURE(rv)) {
|
||||
aprint_error_dev(self, "unable to register DEVICE and SYSTEM "
|
||||
"NOTIFY handler: %s\n", AcpiFormatException(rv));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ACPI_ACAD_DEBUG
|
||||
/* Display the current state. */
|
||||
sc->sc_flags = AACAD_F_VERBOSE;
|
||||
#endif
|
||||
|
||||
if (!pmf_device_register(self, NULL, acpiacad_resume))
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
|
||||
acpiacad_init_envsys(self);
|
||||
if (ACPI_SUCCESS(rv))
|
||||
acpiacad_init_envsys(self);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -179,7 +148,7 @@ acpiacad_detach(device_t self, int flags)
|
||||
if (ACPI_FAILURE(rv))
|
||||
return EBUSY;
|
||||
|
||||
mutex_destroy(&sc->sc_mtx);
|
||||
mutex_destroy(&sc->sc_mutex);
|
||||
|
||||
if (sc->sc_sme != NULL)
|
||||
sysmon_envsys_unregister(sc->sc_sme);
|
||||
@ -193,14 +162,14 @@ acpiacad_detach(device_t self, int flags)
|
||||
/*
|
||||
* acpiacad_resume:
|
||||
*
|
||||
* Clear status after resuming to fetch new status.
|
||||
* Queue a new status check.
|
||||
*/
|
||||
static bool
|
||||
acpiacad_resume(device_t dv, pmf_qual_t qual)
|
||||
{
|
||||
struct acpiacad_softc *sc = device_private(dv);
|
||||
|
||||
acpiacad_clear_status(sc);
|
||||
(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -217,48 +186,49 @@ acpiacad_get_status(void *arg)
|
||||
ACPI_INTEGER status;
|
||||
ACPI_STATUS rv;
|
||||
|
||||
mutex_enter(&sc->sc_mutex);
|
||||
|
||||
rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PSR", &status);
|
||||
|
||||
if (ACPI_FAILURE(rv))
|
||||
return;
|
||||
goto fail;
|
||||
|
||||
if (status != 0 && status != 1) {
|
||||
rv = AE_BAD_VALUE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mutex_enter(&sc->sc_mtx);
|
||||
sc->sc_notifysent = 0;
|
||||
if (sc->sc_status != status) {
|
||||
sc->sc_status = status;
|
||||
if (status)
|
||||
sc->sc_sensor.value_cur = 1;
|
||||
else
|
||||
sc->sc_sensor.value_cur = 0;
|
||||
AACAD_SET(sc, AACAD_F_STCHANGED);
|
||||
}
|
||||
|
||||
sc->sc_sensor.state = ENVSYS_SVALID;
|
||||
AACAD_SET(sc, AACAD_F_AVAILABLE);
|
||||
/*
|
||||
* If status has changed, send the event.
|
||||
*
|
||||
* PSWITCH_EVENT_RELEASED : AC offline
|
||||
* PSWITCH_EVENT_PRESSED : AC online
|
||||
*/
|
||||
if (AACAD_ISSET(sc, AACAD_F_STCHANGED)) {
|
||||
sysmon_pswitch_event(&sc->sc_smpsw, status ?
|
||||
/*
|
||||
* If status has changed, send the event:
|
||||
*
|
||||
* PSWITCH_EVENT_PRESSED : _PSR = 1 : AC online.
|
||||
* PSWITCH_EVENT_RELEASED : _PSR = 0 : AC offline.
|
||||
*/
|
||||
sysmon_pswitch_event(&sc->sc_smpsw, (status != 0) ?
|
||||
PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
|
||||
if (AACAD_ISSET(sc, AACAD_F_VERBOSE))
|
||||
aprint_verbose_dev(dv, "AC adapter %sconnected\n",
|
||||
status == 0 ? "not " : "");
|
||||
}
|
||||
mutex_exit(&sc->sc_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear status
|
||||
*/
|
||||
static void
|
||||
acpiacad_clear_status(struct acpiacad_softc *sc)
|
||||
{
|
||||
aprint_debug_dev(dv, "AC adapter %sconnected\n",
|
||||
status == 0 ? "not " : "");
|
||||
}
|
||||
|
||||
sc->sc_status = status;
|
||||
sc->sc_sensor.state = ENVSYS_SVALID;
|
||||
sc->sc_sensor.value_cur = sc->sc_status;
|
||||
|
||||
mutex_exit(&sc->sc_mutex);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
sc->sc_status = -1;
|
||||
sc->sc_sensor.state = ENVSYS_SINVALID;
|
||||
AACAD_CLEAR(sc, AACAD_F_AVAILABLE);
|
||||
AACAD_CLEAR(sc, AACAD_F_STCHANGED);
|
||||
|
||||
aprint_debug_dev(dv, "failed to evaluate _PSR: %s\n",
|
||||
AcpiFormatException(rv));
|
||||
|
||||
mutex_exit(&sc->sc_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -267,11 +237,10 @@ acpiacad_clear_status(struct acpiacad_softc *sc)
|
||||
* Callback from ACPI interrupt handler to notify us of an event.
|
||||
*/
|
||||
static void
|
||||
acpiacad_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context)
|
||||
acpiacad_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *context)
|
||||
{
|
||||
static const int handler = OSL_NOTIFY_HANDLER;
|
||||
device_t dv = context;
|
||||
struct acpiacad_softc *sc = device_private(dv);
|
||||
ACPI_STATUS rv;
|
||||
|
||||
switch (notify) {
|
||||
/*
|
||||
@ -293,27 +262,11 @@ acpiacad_notify_handler(ACPI_HANDLE handle, UINT32 notify, void *context)
|
||||
case ACPI_NOTIFY_DeviceCheck:
|
||||
case ACPI_NOTIFY_PowerSourceStatusChanged:
|
||||
case ACPI_NOTIFY_BatteryInformationChanged:
|
||||
mutex_enter(&sc->sc_mtx);
|
||||
acpiacad_clear_status(sc);
|
||||
mutex_exit(&sc->sc_mtx);
|
||||
if (sc->sc_status == -1 || !sc->sc_notifysent) {
|
||||
rv = AcpiOsExecute(OSL_NOTIFY_HANDLER,
|
||||
acpiacad_get_status, dv);
|
||||
if (ACPI_FAILURE(rv))
|
||||
aprint_error_dev(dv,
|
||||
"unable to queue status check: %s\n",
|
||||
AcpiFormatException(rv));
|
||||
sc->sc_notifysent = 1;
|
||||
#ifdef ACPI_ACAD_DEBUG
|
||||
aprint_debug_dev(dv, "received notify message: 0x%x\n",
|
||||
notify);
|
||||
#endif
|
||||
}
|
||||
(void)AcpiOsExecute(handler, acpiacad_get_status, dv);
|
||||
break;
|
||||
|
||||
default:
|
||||
aprint_error_dev(dv, "received unknown notify message: 0x%x\n",
|
||||
notify);
|
||||
aprint_error_dev(dv, "unknown notify 0x%02X\n", notify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,22 +276,24 @@ acpiacad_init_envsys(device_t dv)
|
||||
struct acpiacad_softc *sc = device_private(dv);
|
||||
|
||||
sc->sc_sme = sysmon_envsys_create();
|
||||
sc->sc_sensor.state = ENVSYS_SVALID;
|
||||
|
||||
sc->sc_sensor.state = ENVSYS_SINVALID;
|
||||
sc->sc_sensor.units = ENVSYS_INDICATOR;
|
||||
strlcpy(sc->sc_sensor.desc, "connected", sizeof(sc->sc_sensor.desc));
|
||||
|
||||
(void)strlcpy(sc->sc_sensor.desc, "connected", ENVSYS_DESCLEN);
|
||||
|
||||
if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor) != 0)
|
||||
goto fail;
|
||||
|
||||
sc->sc_sme->sme_name = device_xname(dv);
|
||||
sc->sc_sme->sme_cookie = dv;
|
||||
sc->sc_sme->sme_refresh = acpiacad_refresh;
|
||||
sc->sc_sme->sme_class = SME_CLASS_ACADAPTER;
|
||||
sc->sc_sme->sme_flags = SME_INIT_REFRESH;
|
||||
sc->sc_sme->sme_flags = SME_DISABLE_REFRESH;
|
||||
|
||||
if (sysmon_envsys_register(sc->sc_sme) != 0)
|
||||
goto fail;
|
||||
|
||||
(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, acpiacad_get_status, dv);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
@ -346,13 +301,3 @@ fail:
|
||||
sysmon_envsys_destroy(sc->sc_sme);
|
||||
sc->sc_sme = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
acpiacad_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
|
||||
{
|
||||
device_t dv = sme->sme_cookie;
|
||||
struct acpiacad_softc *sc = device_private(dv);
|
||||
|
||||
if (!AACAD_ISSET(sc, AACAD_F_AVAILABLE))
|
||||
acpiacad_get_status(dv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user