The embedded controller handled timeouts wrong in several ways:
* It confused ms and usecs for ec_timeout * It tried to handle waiting like on platforms that can't do better timing than ms. Haiku can do much better, which simplifies the code a lot. This should fix #4623 and #5825. At least on my laptop BatteryStatus never shows weirdness or reports errors in syslog. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36511 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -50,9 +50,6 @@
|
|||||||
// name of pnp generator of path ids
|
// name of pnp generator of path ids
|
||||||
#define ACPI_EC_PATHID_GENERATOR "embedded_controller/path_id"
|
#define ACPI_EC_PATHID_GENERATOR "embedded_controller/path_id"
|
||||||
|
|
||||||
// cpu frequency in Hz
|
|
||||||
int64 gHz;
|
|
||||||
|
|
||||||
|
|
||||||
uint8
|
uint8
|
||||||
bus_space_read_1(int address)
|
bus_space_read_1(int address)
|
||||||
@@ -259,12 +256,6 @@ static status_t
|
|||||||
embedded_controller_init_driver(device_node* dev, void** _driverCookie)
|
embedded_controller_init_driver(device_node* dev, void** _driverCookie)
|
||||||
{
|
{
|
||||||
TRACE("init driver\n");
|
TRACE("init driver\n");
|
||||||
// first get the cpu speed, needed to calculate a timeout
|
|
||||||
// ToDo: catch frequency changes
|
|
||||||
system_info systemInfo;
|
|
||||||
if (get_system_info(&systemInfo) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
gHz = systemInfo.cpu_clock_speed;
|
|
||||||
|
|
||||||
acpi_ec_cookie* sc;
|
acpi_ec_cookie* sc;
|
||||||
sc = (acpi_ec_cookie*) malloc(sizeof(acpi_ec_cookie));
|
sc = (acpi_ec_cookie*) malloc(sizeof(acpi_ec_cookie));
|
||||||
@@ -716,26 +707,17 @@ EcWaitEvent(struct acpi_ec_cookie* sc, EC_EVENT event, int32 gen_count)
|
|||||||
|
|
||||||
/* Wait for event by polling or GPE (interrupt). */
|
/* Wait for event by polling or GPE (interrupt). */
|
||||||
if (need_poll) {
|
if (need_poll) {
|
||||||
count = ec_timeout / EC_POLL_DELAY;
|
count = (ec_timeout * 1000) / EC_POLL_DELAY;
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
count = 1;
|
count = 1;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
status = EcCheckStatus(sc, "poll", event);
|
status = EcCheckStatus(sc, "poll", event);
|
||||||
if (status == B_OK)
|
if (status == AE_OK)
|
||||||
break;
|
break;
|
||||||
spin(EC_POLL_DELAY);
|
spin(EC_POLL_DELAY);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bigtime_t slp_ival = gHz / 1000000;
|
bigtime_t slp_ival = system_time() + ec_timeout * 1000;
|
||||||
if (slp_ival != 0) {
|
|
||||||
count = ec_timeout;
|
|
||||||
} else {
|
|
||||||
/* hz has less than 1 ms resolution so scale timeout. */
|
|
||||||
slp_ival = 1;
|
|
||||||
count = ec_timeout / (1000 / gHz);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = ec_timeout;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for the GPE to signal the status changed, checking the
|
* Wait for the GPE to signal the status changed, checking the
|
||||||
@@ -743,7 +725,8 @@ EcWaitEvent(struct acpi_ec_cookie* sc, EC_EVENT event, int32 gen_count)
|
|||||||
* GPE for an event we're not interested in here (i.e., SCI for
|
* GPE for an event we're not interested in here (i.e., SCI for
|
||||||
* EC query).
|
* EC query).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < count; i++) {
|
status_t waitStatus = B_NO_ERROR;
|
||||||
|
while (waitStatus != B_TIMED_OUT) {
|
||||||
if (gen_count != sc->ec_gencount) {
|
if (gen_count != sc->ec_gencount) {
|
||||||
/*
|
/*
|
||||||
* Record new generation count. It's possible the GPE was
|
* Record new generation count. It's possible the GPE was
|
||||||
@@ -756,7 +739,8 @@ EcWaitEvent(struct acpi_ec_cookie* sc, EC_EVENT event, int32 gen_count)
|
|||||||
if (status == AE_OK)
|
if (status == AE_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sc->ec_condition_var.Wait(B_RELATIVE_TIMEOUT, slp_ival);
|
waitStatus = sc->ec_condition_var.Wait(B_ABSOLUTE_TIMEOUT,
|
||||||
|
slp_ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -768,7 +752,7 @@ EcWaitEvent(struct acpi_ec_cookie* sc, EC_EVENT event, int32 gen_count)
|
|||||||
if (status != AE_OK) {
|
if (status != AE_OK) {
|
||||||
status = EcCheckStatus(sc, "sleep_end", event);
|
status = EcCheckStatus(sc, "sleep_end", event);
|
||||||
TRACE("wait timed out (%sresponse), forcing polled mode\n",
|
TRACE("wait timed out (%sresponse), forcing polled mode\n",
|
||||||
status == B_OK ? "" : "no ");
|
status == AE_OK ? "" : "no ");
|
||||||
ec_polled_mode = TRUE;
|
ec_polled_mode = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ struct acpi_ec_cookie {
|
|||||||
((status) & EC_FLAG_INPUT_BUFFER) == 0))
|
((status) & EC_FLAG_INPUT_BUFFER) == 0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int ec_burst_mode = 1;
|
static int ec_burst_mode = 1;
|
||||||
static int ec_polled_mode = 0;
|
static int ec_polled_mode = 0;
|
||||||
|
|
||||||
@@ -188,11 +189,8 @@ static int ec_timeout = EC_TIMEOUT;
|
|||||||
static status_t
|
static status_t
|
||||||
EcLock(struct acpi_ec_cookie *sc)
|
EcLock(struct acpi_ec_cookie *sc)
|
||||||
{
|
{
|
||||||
status_t status;
|
|
||||||
|
|
||||||
|
|
||||||
/* If _GLK is non-zero, acquire the global lock. */
|
/* If _GLK is non-zero, acquire the global lock. */
|
||||||
status = B_OK;
|
status_t status = B_OK;
|
||||||
if (sc->ec_glk) {
|
if (sc->ec_glk) {
|
||||||
status = sc->ec_acpi_module->acquire_global_lock(EC_LOCK_TIMEOUT,
|
status = sc->ec_acpi_module->acquire_global_lock(EC_LOCK_TIMEOUT,
|
||||||
&sc->ec_glkhandle);
|
&sc->ec_glkhandle);
|
||||||
|
|||||||
Reference in New Issue
Block a user