diff options
author | philip <philip@FreeBSD.org> | 2005-03-30 15:06:11 +0000 |
---|---|---|
committer | philip <philip@FreeBSD.org> | 2005-03-30 15:06:11 +0000 |
commit | eedd5656c1fa34fd0801cedb9125b3b2ba844bc1 (patch) | |
tree | 10b8789d415fd57c911beb699274e44df3930852 /sys/dev/acpi_support | |
parent | 074c435b0d344424ffcb073fa7766df8c8469030 (diff) | |
download | FreeBSD-src-eedd5656c1fa34fd0801cedb9125b3b2ba844bc1.zip FreeBSD-src-eedd5656c1fa34fd0801cedb9125b3b2ba844bc1.tar.gz |
Use a taskqueue for led-handling to prevent a potential panic.
Submitted by: pjd
Diffstat (limited to 'sys/dev/acpi_support')
-rw-r--r-- | sys/dev/acpi_support/acpi_asus.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/sys/dev/acpi_support/acpi_asus.c b/sys/dev/acpi_support/acpi_asus.c index ee28043..c3dfdb0 100644 --- a/sys/dev/acpi_support/acpi_asus.c +++ b/sys/dev/acpi_support/acpi_asus.c @@ -79,8 +79,10 @@ struct acpi_asus_model { }; struct acpi_asus_led { + struct acpi_asus_softc *sc; struct cdev *cdev; - device_t dev; + int busy; + int state; enum { ACPI_ASUS_LED_MLED, ACPI_ASUS_LED_TLED, @@ -255,6 +257,7 @@ static int acpi_asus_attach(device_t dev); static int acpi_asus_detach(device_t dev); static void acpi_asus_led(struct acpi_asus_led *led, int state); +static void acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused); static int acpi_asus_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_asus_sysctl_init(struct acpi_asus_softc *sc, int method); @@ -401,21 +404,24 @@ acpi_asus_attach(device_t dev) /* Attach leds */ if (sc->model->mled_set) { - sc->s_mled.dev = dev; + sc->s_mled.busy = 0; + sc->s_mled.sc = sc; sc->s_mled.type = ACPI_ASUS_LED_MLED; sc->s_mled.cdev = led_create((led_t *)acpi_asus_led, &sc->s_mled, "mled"); } if (sc->model->tled_set) { - sc->s_tled.dev = dev; + sc->s_tled.busy = 0; + sc->s_tled.sc = sc; sc->s_tled.type = ACPI_ASUS_LED_TLED; sc->s_tled.cdev = led_create((led_t *)acpi_asus_led, &sc->s_tled, "tled"); } if (sc->model->wled_set) { - sc->s_wled.dev = dev; + sc->s_wled.busy = 0; + sc->s_wled.sc = sc; sc->s_wled.type = ACPI_ASUS_LED_WLED; sc->s_wled.cdev = led_create((led_t *)acpi_asus_led, &sc->s_wled, "wled"); @@ -461,27 +467,30 @@ acpi_asus_detach(device_t dev) } static void -acpi_asus_led(struct acpi_asus_led *led, int state) +acpi_asus_led_task(struct acpi_asus_led *led, int pending __unused) { struct acpi_asus_softc *sc; char *method; - + int state; + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); - sc = device_get_softc(led->dev); + sc = led->sc; switch (led->type) { case ACPI_ASUS_LED_MLED: method = sc->model->mled_set; /* Note: inverted */ - state = !state; + state = !led->state; break; case ACPI_ASUS_LED_TLED: method = sc->model->tled_set; + state = led->state; break; case ACPI_ASUS_LED_WLED: method = sc->model->wled_set; + state = led->state; break; default: printf("acpi_asus_led: invalid LED type %d\n", @@ -490,6 +499,23 @@ acpi_asus_led(struct acpi_asus_led *led, int state) } acpi_SetInteger(sc->handle, method, state); + led->busy = 0; +} + +static void +acpi_asus_led(struct acpi_asus_led *led, int state) +{ + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (led->busy) + return; + + led->busy = 1; + led->state = state; + + AcpiOsQueueForExecution(OSD_PRIORITY_LO, + (void *)acpi_asus_led_task, led); } static int |