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>
This commit is contained in:
Henrique de Moraes Holschuh 2007-10-30 17:46:25 -02:00 committed by Len Brown
parent fc589a3ce5
commit 4273af8d08
1 changed files with 21 additions and 13 deletions

View File

@ -3278,6 +3278,8 @@ static void brightness_exit(void)
static int brightness_update_status(struct backlight_device *bd) static int brightness_update_status(struct backlight_device *bd)
{ {
/* it is the backlight class's job (caller) to handle
* EINTR and other errors properly */
return brightness_set( return brightness_set(
(bd->props.fb_blank == FB_BLANK_UNBLANK && (bd->props.fb_blank == FB_BLANK_UNBLANK &&
bd->props.power == FB_BLANK_UNBLANK) ? bd->props.power == FB_BLANK_UNBLANK) ?
@ -3318,6 +3320,7 @@ static int brightness_get(struct backlight_device *bd)
return level; return level;
} }
/* May return EINTR which can always be mapped to ERESTARTSYS */
static int brightness_set(int value) static int brightness_set(int value)
{ {
int cmos_cmd, inc, i, res; int cmos_cmd, inc, i, res;
@ -3381,29 +3384,34 @@ static int brightness_read(char *p)
static int brightness_write(char *buf) static int brightness_write(char *buf)
{ {
int level; int level;
int new_level; int rc;
char *cmd; char *cmd;
int max_level = (tp_features.bright_16levels) ? 15 : 7; int max_level = (tp_features.bright_16levels) ? 15 : 7;
while ((cmd = next_cmd(&buf))) { level = brightness_get(NULL);
if ((level = brightness_get(NULL)) < 0) if (level < 0)
return level; return level;
while ((cmd = next_cmd(&buf))) {
if (strlencmp(cmd, "up") == 0) { if (strlencmp(cmd, "up") == 0) {
new_level = level == (max_level)? if (level < max_level)
max_level : level + 1; level++;
} else if (strlencmp(cmd, "down") == 0) { } else if (strlencmp(cmd, "down") == 0) {
new_level = level == 0? 0 : level - 1; if (level > 0)
} else if (sscanf(cmd, "level %d", &new_level) == 1 && level--;
new_level >= 0 && new_level <= max_level) { } else if (sscanf(cmd, "level %d", &level) == 1 &&
/* new_level set */ level >= 0 && level <= max_level) {
/* new level set */
} else } else
return -EINVAL; return -EINVAL;
brightness_set(new_level);
} }
return 0; /*
* Now we know what the final level should be, so we try to set it.
* Doing it this way makes the syscall restartable in case of EINTR
*/
rc = brightness_set(level);
return (rc == -EINTR)? ERESTARTSYS : rc;
} }
static struct ibm_struct brightness_driver_data = { static struct ibm_struct brightness_driver_data = {