diff options
author | Jacek Anaszewski <j.anaszewski@samsung.com> | 2015-08-20 09:52:32 -0400 |
---|---|---|
committer | Jacek Anaszewski <j.anaszewski@samsung.com> | 2016-01-04 03:57:35 -0500 |
commit | d5b8a09000da3dcd79649293121afe4439153c7a (patch) | |
tree | d5e32f5e6600ec3ecaa945fd12581744c6de55b7 /drivers/leds/leds-gpio.c | |
parent | 0dd756f7677a519a1d52a94e74d179e0af39e2ec (diff) |
leds: gpio: Remove work queue
Now the core implements the work queue, remove it from the drivers,
and switch to using brightness_set_blocking op.
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Cc: Raphael Assenat <raph@8d.com>
Diffstat (limited to 'drivers/leds/leds-gpio.c')
-rw-r--r-- | drivers/leds/leds-gpio.c | 62 |
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 5db4515a4fd7..7bc53280dbfd 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -20,32 +20,16 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/property.h> | 21 | #include <linux/property.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/workqueue.h> | ||
24 | 23 | ||
25 | struct gpio_led_data { | 24 | struct gpio_led_data { |
26 | struct led_classdev cdev; | 25 | struct led_classdev cdev; |
27 | struct gpio_desc *gpiod; | 26 | struct gpio_desc *gpiod; |
28 | struct work_struct work; | ||
29 | u8 new_level; | ||
30 | u8 can_sleep; | 27 | u8 can_sleep; |
31 | u8 blinking; | 28 | u8 blinking; |
32 | int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state, | 29 | int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state, |
33 | unsigned long *delay_on, unsigned long *delay_off); | 30 | unsigned long *delay_on, unsigned long *delay_off); |
34 | }; | 31 | }; |
35 | 32 | ||
36 | static void gpio_led_work(struct work_struct *work) | ||
37 | { | ||
38 | struct gpio_led_data *led_dat = | ||
39 | container_of(work, struct gpio_led_data, work); | ||
40 | |||
41 | if (led_dat->blinking) { | ||
42 | led_dat->platform_gpio_blink_set(led_dat->gpiod, | ||
43 | led_dat->new_level, NULL, NULL); | ||
44 | led_dat->blinking = 0; | ||
45 | } else | ||
46 | gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level); | ||
47 | } | ||
48 | |||
49 | static void gpio_led_set(struct led_classdev *led_cdev, | 33 | static void gpio_led_set(struct led_classdev *led_cdev, |
50 | enum led_brightness value) | 34 | enum led_brightness value) |
51 | { | 35 | { |
@@ -58,23 +42,25 @@ static void gpio_led_set(struct led_classdev *led_cdev, | |||
58 | else | 42 | else |
59 | level = 1; | 43 | level = 1; |
60 | 44 | ||
61 | /* Setting GPIOs with I2C/etc requires a task context, and we don't | 45 | if (led_dat->blinking) { |
62 | * seem to have a reliable way to know if we're already in one; so | 46 | led_dat->platform_gpio_blink_set(led_dat->gpiod, level, |
63 | * let's just assume the worst. | 47 | NULL, NULL); |
64 | */ | 48 | led_dat->blinking = 0; |
65 | if (led_dat->can_sleep) { | ||
66 | led_dat->new_level = level; | ||
67 | schedule_work(&led_dat->work); | ||
68 | } else { | 49 | } else { |
69 | if (led_dat->blinking) { | 50 | if (led_dat->can_sleep) |
70 | led_dat->platform_gpio_blink_set(led_dat->gpiod, level, | 51 | gpiod_set_value_cansleep(led_dat->gpiod, level); |
71 | NULL, NULL); | 52 | else |
72 | led_dat->blinking = 0; | ||
73 | } else | ||
74 | gpiod_set_value(led_dat->gpiod, level); | 53 | gpiod_set_value(led_dat->gpiod, level); |
75 | } | 54 | } |
76 | } | 55 | } |
77 | 56 | ||
57 | static int gpio_led_set_blocking(struct led_classdev *led_cdev, | ||
58 | enum led_brightness value) | ||
59 | { | ||
60 | gpio_led_set(led_cdev, value); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
78 | static int gpio_blink_set(struct led_classdev *led_cdev, | 64 | static int gpio_blink_set(struct led_classdev *led_cdev, |
79 | unsigned long *delay_on, unsigned long *delay_off) | 65 | unsigned long *delay_on, unsigned long *delay_off) |
80 | { | 66 | { |
@@ -125,12 +111,15 @@ static int create_gpio_led(const struct gpio_led *template, | |||
125 | led_dat->cdev.name = template->name; | 111 | led_dat->cdev.name = template->name; |
126 | led_dat->cdev.default_trigger = template->default_trigger; | 112 | led_dat->cdev.default_trigger = template->default_trigger; |
127 | led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); | 113 | led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); |
114 | if (!led_dat->can_sleep) | ||
115 | led_dat->cdev.brightness_set = gpio_led_set; | ||
116 | else | ||
117 | led_dat->cdev.brightness_set_blocking = gpio_led_set_blocking; | ||
128 | led_dat->blinking = 0; | 118 | led_dat->blinking = 0; |
129 | if (blink_set) { | 119 | if (blink_set) { |
130 | led_dat->platform_gpio_blink_set = blink_set; | 120 | led_dat->platform_gpio_blink_set = blink_set; |
131 | led_dat->cdev.blink_set = gpio_blink_set; | 121 | led_dat->cdev.blink_set = gpio_blink_set; |
132 | } | 122 | } |
133 | led_dat->cdev.brightness_set = gpio_led_set; | ||
134 | if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) | 123 | if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) |
135 | state = !!gpiod_get_value_cansleep(led_dat->gpiod); | 124 | state = !!gpiod_get_value_cansleep(led_dat->gpiod); |
136 | else | 125 | else |
@@ -143,17 +132,9 @@ static int create_gpio_led(const struct gpio_led *template, | |||
143 | if (ret < 0) | 132 | if (ret < 0) |
144 | return ret; | 133 | return ret; |
145 | 134 | ||
146 | INIT_WORK(&led_dat->work, gpio_led_work); | ||
147 | |||
148 | return led_classdev_register(parent, &led_dat->cdev); | 135 | return led_classdev_register(parent, &led_dat->cdev); |
149 | } | 136 | } |
150 | 137 | ||
151 | static void delete_gpio_led(struct gpio_led_data *led) | ||
152 | { | ||
153 | led_classdev_unregister(&led->cdev); | ||
154 | cancel_work_sync(&led->work); | ||
155 | } | ||
156 | |||
157 | struct gpio_leds_priv { | 138 | struct gpio_leds_priv { |
158 | int num_leds; | 139 | int num_leds; |
159 | struct gpio_led_data leds[]; | 140 | struct gpio_led_data leds[]; |
@@ -233,7 +214,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) | |||
233 | 214 | ||
234 | err: | 215 | err: |
235 | for (count = priv->num_leds - 1; count >= 0; count--) | 216 | for (count = priv->num_leds - 1; count >= 0; count--) |
236 | delete_gpio_led(&priv->leds[count]); | 217 | led_classdev_unregister(&priv->leds[count].cdev); |
237 | return ERR_PTR(ret); | 218 | return ERR_PTR(ret); |
238 | } | 219 | } |
239 | 220 | ||
@@ -265,7 +246,8 @@ static int gpio_led_probe(struct platform_device *pdev) | |||
265 | if (ret < 0) { | 246 | if (ret < 0) { |
266 | /* On failure: unwind the led creations */ | 247 | /* On failure: unwind the led creations */ |
267 | for (i = i - 1; i >= 0; i--) | 248 | for (i = i - 1; i >= 0; i--) |
268 | delete_gpio_led(&priv->leds[i]); | 249 | led_classdev_unregister( |
250 | &priv->leds[i].cdev); | ||
269 | return ret; | 251 | return ret; |
270 | } | 252 | } |
271 | } | 253 | } |
@@ -286,7 +268,7 @@ static int gpio_led_remove(struct platform_device *pdev) | |||
286 | int i; | 268 | int i; |
287 | 269 | ||
288 | for (i = 0; i < priv->num_leds; i++) | 270 | for (i = 0; i < priv->num_leds; i++) |
289 | delete_gpio_led(&priv->leds[i]); | 271 | led_classdev_unregister(&priv->leds[i].cdev); |
290 | 272 | ||
291 | return 0; | 273 | return 0; |
292 | } | 274 | } |