diff options
| author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2007-10-30 15:46:25 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2007-11-05 13:07:11 -0500 |
| commit | 4273af8d08c823d5898a2b1c2d0f25b4a8b9eaee (patch) | |
| tree | 822101a563cd5fc7b87ea98498ca9e10ae7f8a02 /drivers/misc | |
| parent | fc589a3ce5f38db6239c147da4f9172a25575ecc (diff) | |
ACPI: thinkpad-acpi: fix brightness_set error paths
The code calling brightness_set() can't handle EINTR/ERESTARTSYS well, nor
is it checking brightness_set() return status properly.
Fix it.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/misc')
| -rw-r--r-- | drivers/misc/thinkpad_acpi.c | 34 |
1 files changed, 21 insertions, 13 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 306daa524c03..8c9430775285 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -3278,6 +3278,8 @@ static void brightness_exit(void) | |||
| 3278 | 3278 | ||
| 3279 | static int brightness_update_status(struct backlight_device *bd) | 3279 | static int brightness_update_status(struct backlight_device *bd) |
| 3280 | { | 3280 | { |
| 3281 | /* it is the backlight class's job (caller) to handle | ||
| 3282 | * EINTR and other errors properly */ | ||
| 3281 | return brightness_set( | 3283 | return brightness_set( |
| 3282 | (bd->props.fb_blank == FB_BLANK_UNBLANK && | 3284 | (bd->props.fb_blank == FB_BLANK_UNBLANK && |
| 3283 | bd->props.power == FB_BLANK_UNBLANK) ? | 3285 | bd->props.power == FB_BLANK_UNBLANK) ? |
| @@ -3318,6 +3320,7 @@ static int brightness_get(struct backlight_device *bd) | |||
| 3318 | return level; | 3320 | return level; |
| 3319 | } | 3321 | } |
| 3320 | 3322 | ||
| 3323 | /* May return EINTR which can always be mapped to ERESTARTSYS */ | ||
| 3321 | static int brightness_set(int value) | 3324 | static int brightness_set(int value) |
| 3322 | { | 3325 | { |
| 3323 | int cmos_cmd, inc, i, res; | 3326 | int cmos_cmd, inc, i, res; |
| @@ -3381,29 +3384,34 @@ static int brightness_read(char *p) | |||
| 3381 | static int brightness_write(char *buf) | 3384 | static int brightness_write(char *buf) |
| 3382 | { | 3385 | { |
| 3383 | int level; | 3386 | int level; |
| 3384 | int new_level; | 3387 | int rc; |
| 3385 | char *cmd; | 3388 | char *cmd; |
| 3386 | int max_level = (tp_features.bright_16levels) ? 15 : 7; | 3389 | int max_level = (tp_features.bright_16levels) ? 15 : 7; |
| 3387 | 3390 | ||
| 3388 | while ((cmd = next_cmd(&buf))) { | 3391 | level = brightness_get(NULL); |
| 3389 | if ((level = brightness_get(NULL)) < 0) | 3392 | if (level < 0) |
| 3390 | return level; | 3393 | return level; |
| 3391 | 3394 | ||
| 3395 | while ((cmd = next_cmd(&buf))) { | ||
| 3392 | if (strlencmp(cmd, "up") == 0) { | 3396 | if (strlencmp(cmd, "up") == 0) { |
| 3393 | new_level = level == (max_level)? | 3397 | if (level < max_level) |
| 3394 | max_level : level + 1; | 3398 | level++; |
| 3395 | } else if (strlencmp(cmd, "down") == 0) { | 3399 | } else if (strlencmp(cmd, "down") == 0) { |
| 3396 | new_level = level == 0? 0 : level - 1; | 3400 | if (level > 0) |
| 3397 | } else if (sscanf(cmd, "level %d", &new_level) == 1 && | 3401 | level--; |
| 3398 | new_level >= 0 && new_level <= max_level) { | 3402 | } else if (sscanf(cmd, "level %d", &level) == 1 && |
| 3399 | /* new_level set */ | 3403 | level >= 0 && level <= max_level) { |
| 3404 | /* new level set */ | ||
| 3400 | } else | 3405 | } else |
| 3401 | return -EINVAL; | 3406 | return -EINVAL; |
| 3402 | |||
| 3403 | brightness_set(new_level); | ||
| 3404 | } | 3407 | } |
| 3405 | 3408 | ||
| 3406 | return 0; | 3409 | /* |
| 3410 | * Now we know what the final level should be, so we try to set it. | ||
| 3411 | * Doing it this way makes the syscall restartable in case of EINTR | ||
| 3412 | */ | ||
| 3413 | rc = brightness_set(level); | ||
| 3414 | return (rc == -EINTR)? ERESTARTSYS : rc; | ||
| 3407 | } | 3415 | } |
| 3408 | 3416 | ||
| 3409 | static struct ibm_struct brightness_driver_data = { | 3417 | static struct ibm_struct brightness_driver_data = { |
