diff options
| author | Micha? K?pie? <kernel@kempniu.pl> | 2016-12-23 04:00:08 -0500 |
|---|---|---|
| committer | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2016-12-28 05:38:10 -0500 |
| commit | a608a9d52fa4168efd478d684039ed545a69dbcd (patch) | |
| tree | 778dbb5f6f0e0851d9ae837e43d0da4b0ec0e45a | |
| parent | f6c5c1f96d976e1fb9d71fb824629c450ee0a122 (diff) | |
platform/x86: fujitsu-laptop: use brightness_set_blocking for LED-setting callbacks
All LED-setting functions in fujitsu-laptop are currently assigned to
the brightness_set callback, which is incorrect because they can sleep
(due to their use of call_fext_func(), which in turn issues ACPI calls)
and the documentation (in include/linux/leds.h) clearly states they must
not. Assign them to brightness_set_blocking instead and change them to
match the expected function prototype.
This change makes it possible to use Fujitsu-specific LEDs with "heavy"
triggers, like disk-activity or phy0rx.
Fixes: 3a407086090b ("fujitsu-laptop: Add BL power, LED control and radio state information")
Fixes: 4f62568c1fcf ("fujitsu-laptop: Support radio LED")
Fixes: d6b88f64b0d4 ("fujitsu-laptop: Add support for eco LED")
Signed-off-by: Michał Kępień <kernel@kempniu.pl>
Acked-by: Jonathan Woithe <jwoithe@just42.net>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
| -rw-r--r-- | drivers/platform/x86/fujitsu-laptop.c | 42 |
1 files changed, 21 insertions, 21 deletions
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 61f39abf5dc8..82d67715ce76 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c | |||
| @@ -177,43 +177,43 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event); | |||
| 177 | 177 | ||
| 178 | #if IS_ENABLED(CONFIG_LEDS_CLASS) | 178 | #if IS_ENABLED(CONFIG_LEDS_CLASS) |
| 179 | static enum led_brightness logolamp_get(struct led_classdev *cdev); | 179 | static enum led_brightness logolamp_get(struct led_classdev *cdev); |
| 180 | static void logolamp_set(struct led_classdev *cdev, | 180 | static int logolamp_set(struct led_classdev *cdev, |
| 181 | enum led_brightness brightness); | 181 | enum led_brightness brightness); |
| 182 | 182 | ||
| 183 | static struct led_classdev logolamp_led = { | 183 | static struct led_classdev logolamp_led = { |
| 184 | .name = "fujitsu::logolamp", | 184 | .name = "fujitsu::logolamp", |
| 185 | .brightness_get = logolamp_get, | 185 | .brightness_get = logolamp_get, |
| 186 | .brightness_set = logolamp_set | 186 | .brightness_set_blocking = logolamp_set |
| 187 | }; | 187 | }; |
| 188 | 188 | ||
| 189 | static enum led_brightness kblamps_get(struct led_classdev *cdev); | 189 | static enum led_brightness kblamps_get(struct led_classdev *cdev); |
| 190 | static void kblamps_set(struct led_classdev *cdev, | 190 | static int kblamps_set(struct led_classdev *cdev, |
| 191 | enum led_brightness brightness); | 191 | enum led_brightness brightness); |
| 192 | 192 | ||
| 193 | static struct led_classdev kblamps_led = { | 193 | static struct led_classdev kblamps_led = { |
| 194 | .name = "fujitsu::kblamps", | 194 | .name = "fujitsu::kblamps", |
| 195 | .brightness_get = kblamps_get, | 195 | .brightness_get = kblamps_get, |
| 196 | .brightness_set = kblamps_set | 196 | .brightness_set_blocking = kblamps_set |
| 197 | }; | 197 | }; |
| 198 | 198 | ||
| 199 | static enum led_brightness radio_led_get(struct led_classdev *cdev); | 199 | static enum led_brightness radio_led_get(struct led_classdev *cdev); |
| 200 | static void radio_led_set(struct led_classdev *cdev, | 200 | static int radio_led_set(struct led_classdev *cdev, |
| 201 | enum led_brightness brightness); | 201 | enum led_brightness brightness); |
| 202 | 202 | ||
| 203 | static struct led_classdev radio_led = { | 203 | static struct led_classdev radio_led = { |
| 204 | .name = "fujitsu::radio_led", | 204 | .name = "fujitsu::radio_led", |
| 205 | .brightness_get = radio_led_get, | 205 | .brightness_get = radio_led_get, |
| 206 | .brightness_set = radio_led_set | 206 | .brightness_set_blocking = radio_led_set |
| 207 | }; | 207 | }; |
| 208 | 208 | ||
| 209 | static enum led_brightness eco_led_get(struct led_classdev *cdev); | 209 | static enum led_brightness eco_led_get(struct led_classdev *cdev); |
| 210 | static void eco_led_set(struct led_classdev *cdev, | 210 | static int eco_led_set(struct led_classdev *cdev, |
| 211 | enum led_brightness brightness); | 211 | enum led_brightness brightness); |
| 212 | 212 | ||
| 213 | static struct led_classdev eco_led = { | 213 | static struct led_classdev eco_led = { |
| 214 | .name = "fujitsu::eco_led", | 214 | .name = "fujitsu::eco_led", |
| 215 | .brightness_get = eco_led_get, | 215 | .brightness_get = eco_led_get, |
| 216 | .brightness_set = eco_led_set | 216 | .brightness_set_blocking = eco_led_set |
| 217 | }; | 217 | }; |
| 218 | #endif | 218 | #endif |
| 219 | 219 | ||
| @@ -267,48 +267,48 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) | |||
| 267 | #if IS_ENABLED(CONFIG_LEDS_CLASS) | 267 | #if IS_ENABLED(CONFIG_LEDS_CLASS) |
| 268 | /* LED class callbacks */ | 268 | /* LED class callbacks */ |
| 269 | 269 | ||
| 270 | static void logolamp_set(struct led_classdev *cdev, | 270 | static int logolamp_set(struct led_classdev *cdev, |
| 271 | enum led_brightness brightness) | 271 | enum led_brightness brightness) |
| 272 | { | 272 | { |
| 273 | if (brightness >= LED_FULL) { | 273 | if (brightness >= LED_FULL) { |
| 274 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); | 274 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); |
| 275 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON); | 275 | return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_ON); |
| 276 | } else if (brightness >= LED_HALF) { | 276 | } else if (brightness >= LED_HALF) { |
| 277 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); | 277 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_ON); |
| 278 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF); | 278 | return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_ALWAYS, FUNC_LED_OFF); |
| 279 | } else { | 279 | } else { |
| 280 | call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF); | 280 | return call_fext_func(FUNC_LEDS, 0x1, LOGOLAMP_POWERON, FUNC_LED_OFF); |
| 281 | } | 281 | } |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | static void kblamps_set(struct led_classdev *cdev, | 284 | static int kblamps_set(struct led_classdev *cdev, |
| 285 | enum led_brightness brightness) | 285 | enum led_brightness brightness) |
| 286 | { | 286 | { |
| 287 | if (brightness >= LED_FULL) | 287 | if (brightness >= LED_FULL) |
| 288 | call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON); | 288 | return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_ON); |
| 289 | else | 289 | else |
| 290 | call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); | 290 | return call_fext_func(FUNC_LEDS, 0x1, KEYBOARD_LAMPS, FUNC_LED_OFF); |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | static void radio_led_set(struct led_classdev *cdev, | 293 | static int radio_led_set(struct led_classdev *cdev, |
| 294 | enum led_brightness brightness) | 294 | enum led_brightness brightness) |
| 295 | { | 295 | { |
| 296 | if (brightness >= LED_FULL) | 296 | if (brightness >= LED_FULL) |
| 297 | call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON); | 297 | return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, RADIO_LED_ON); |
| 298 | else | 298 | else |
| 299 | call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0); | 299 | return call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static void eco_led_set(struct led_classdev *cdev, | 302 | static int eco_led_set(struct led_classdev *cdev, |
| 303 | enum led_brightness brightness) | 303 | enum led_brightness brightness) |
| 304 | { | 304 | { |
| 305 | int curr; | 305 | int curr; |
| 306 | 306 | ||
| 307 | curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0); | 307 | curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0); |
| 308 | if (brightness >= LED_FULL) | 308 | if (brightness >= LED_FULL) |
| 309 | call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON); | 309 | return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON); |
| 310 | else | 310 | else |
| 311 | call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON); | 311 | return call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON); |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | static enum led_brightness logolamp_get(struct led_classdev *cdev) | 314 | static enum led_brightness logolamp_get(struct led_classdev *cdev) |
