Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: convert blink timer to workqueue

This patch converts the blink timer from led-core to workqueue which is more
suitable for this kind of non-priority operations. Moreover, timer may lead to
errors when a LED setting function use a scheduling function such as pinctrl
which is using mutex.

Signed-off-by: Vincent Donnefort <vdonnefort@gmail.com>
Signed-off-by: Bryan Wu <cooloney@gmail.com>

authored by

Vincent Donnefort and committed by
Bryan Wu
8b37e1be 7e774390

+14 -14
+7 -7
drivers/leds/led-class.c
··· 15 15 #include <linux/list.h> 16 16 #include <linux/spinlock.h> 17 17 #include <linux/device.h> 18 - #include <linux/timer.h> 19 18 #include <linux/err.h> 20 19 #include <linux/ctype.h> 21 20 #include <linux/leds.h> 21 + #include <linux/workqueue.h> 22 22 #include "leds.h" 23 23 24 24 static struct class *leds_class; ··· 97 97 NULL, 98 98 }; 99 99 100 - static void led_timer_function(unsigned long data) 100 + static void led_work_function(struct work_struct *ws) 101 101 { 102 - struct led_classdev *led_cdev = (void *)data; 102 + struct led_classdev *led_cdev = 103 + container_of(ws, struct led_classdev, blink_work.work); 103 104 unsigned long brightness; 104 105 unsigned long delay; 105 106 ··· 144 143 } 145 144 } 146 145 147 - mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); 146 + queue_delayed_work(system_wq, &led_cdev->blink_work, 147 + msecs_to_jiffies(delay)); 148 148 } 149 149 150 150 static void set_brightness_delayed(struct work_struct *ws) ··· 233 231 234 232 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed); 235 233 236 - init_timer(&led_cdev->blink_timer); 237 - led_cdev->blink_timer.function = led_timer_function; 238 - led_cdev->blink_timer.data = (unsigned long)led_cdev; 234 + INIT_DELAYED_WORK(&led_cdev->blink_work, led_work_function); 239 235 240 236 #ifdef CONFIG_LEDS_TRIGGERS 241 237 led_trigger_set_default(led_cdev);
+6 -5
drivers/leds/led-core.c
··· 16 16 #include <linux/module.h> 17 17 #include <linux/rwsem.h> 18 18 #include <linux/leds.h> 19 + #include <linux/workqueue.h> 19 20 #include "leds.h" 20 21 21 22 DECLARE_RWSEM(leds_list_lock); ··· 52 51 return; 53 52 } 54 53 55 - mod_timer(&led_cdev->blink_timer, jiffies + 1); 54 + queue_delayed_work(system_wq, &led_cdev->blink_work, 1); 56 55 } 57 56 58 57 ··· 76 75 unsigned long *delay_on, 77 76 unsigned long *delay_off) 78 77 { 79 - del_timer_sync(&led_cdev->blink_timer); 78 + cancel_delayed_work_sync(&led_cdev->blink_work); 80 79 81 80 led_cdev->flags &= ~LED_BLINK_ONESHOT; 82 81 led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP; ··· 91 90 int invert) 92 91 { 93 92 if ((led_cdev->flags & LED_BLINK_ONESHOT) && 94 - timer_pending(&led_cdev->blink_timer)) 93 + delayed_work_pending(&led_cdev->blink_work)) 95 94 return; 96 95 97 96 led_cdev->flags |= LED_BLINK_ONESHOT; ··· 108 107 109 108 void led_stop_software_blink(struct led_classdev *led_cdev) 110 109 { 111 - del_timer_sync(&led_cdev->blink_timer); 110 + cancel_delayed_work_sync(&led_cdev->blink_work); 112 111 led_cdev->blink_delay_on = 0; 113 112 led_cdev->blink_delay_off = 0; 114 113 } ··· 117 116 void led_set_brightness(struct led_classdev *led_cdev, 118 117 enum led_brightness brightness) 119 118 { 120 - /* delay brightness setting if need to stop soft-blink timer */ 119 + /* delay brightness setting if need to stop soft-blink work */ 121 120 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) { 122 121 led_cdev->delayed_set_value = brightness; 123 122 schedule_work(&led_cdev->set_brightness_work);
+1 -2
include/linux/leds.h
··· 15 15 #include <linux/list.h> 16 16 #include <linux/spinlock.h> 17 17 #include <linux/rwsem.h> 18 - #include <linux/timer.h> 19 18 #include <linux/workqueue.h> 20 19 21 20 struct device; ··· 68 69 const char *default_trigger; /* Trigger to use */ 69 70 70 71 unsigned long blink_delay_on, blink_delay_off; 71 - struct timer_list blink_timer; 72 + struct delayed_work blink_work; 72 73 int blink_brightness; 73 74 74 75 struct work_struct set_brightness_work;