aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2007-10-30 15:46:25 -0400
committerLen Brown <len.brown@intel.com>2007-11-05 13:07:11 -0500
commit4273af8d08c823d5898a2b1c2d0f25b4a8b9eaee (patch)
tree822101a563cd5fc7b87ea98498ca9e10ae7f8a02
parentfc589a3ce5f38db6239c147da4f9172a25575ecc (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>
-rw-r--r--drivers/misc/thinkpad_acpi.c34
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
3279static int brightness_update_status(struct backlight_device *bd) 3279static 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 */
3321static int brightness_set(int value) 3324static 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)
3381static int brightness_write(char *buf) 3384static 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
3409static struct ibm_struct brightness_driver_data = { 3417static struct ibm_struct brightness_driver_data = {