Commit 72f8da329e07ad8a72c1f0e96b8955cfeb7c7329
1 parent
e697789d64
Exists in
master
and in
7 other branches
leds: Fix leds_list_lock locking issues
Covert leds_list_lock to a rw_sempahore to match previous LED trigger locking fixes, fixing lock ordering. Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
Showing 4 changed files with 12 additions and 11 deletions Side-by-side Diff
drivers/leds/led-class.c
... | ... | @@ -106,9 +106,9 @@ |
106 | 106 | goto err_out; |
107 | 107 | |
108 | 108 | /* add to the list of leds */ |
109 | - write_lock(&leds_list_lock); | |
109 | + down_write(&leds_list_lock); | |
110 | 110 | list_add_tail(&led_cdev->node, &leds_list); |
111 | - write_unlock(&leds_list_lock); | |
111 | + up_write(&leds_list_lock); | |
112 | 112 | |
113 | 113 | #ifdef CONFIG_LEDS_TRIGGERS |
114 | 114 | init_rwsem(&led_cdev->trigger_lock); |
115 | 115 | |
... | ... | @@ -155,9 +155,9 @@ |
155 | 155 | |
156 | 156 | device_unregister(led_cdev->dev); |
157 | 157 | |
158 | - write_lock(&leds_list_lock); | |
158 | + down_write(&leds_list_lock); | |
159 | 159 | list_del(&led_cdev->node); |
160 | - write_unlock(&leds_list_lock); | |
160 | + up_write(&leds_list_lock); | |
161 | 161 | } |
162 | 162 | EXPORT_SYMBOL_GPL(led_classdev_unregister); |
163 | 163 |
drivers/leds/led-core.c
... | ... | @@ -14,11 +14,11 @@ |
14 | 14 | #include <linux/kernel.h> |
15 | 15 | #include <linux/list.h> |
16 | 16 | #include <linux/module.h> |
17 | -#include <linux/spinlock.h> | |
17 | +#include <linux/rwsem.h> | |
18 | 18 | #include <linux/leds.h> |
19 | 19 | #include "leds.h" |
20 | 20 | |
21 | -DEFINE_RWLOCK(leds_list_lock); | |
21 | +DECLARE_RWSEM(leds_list_lock); | |
22 | 22 | LIST_HEAD(leds_list); |
23 | 23 | |
24 | 24 | EXPORT_SYMBOL_GPL(leds_list); |
drivers/leds/led-triggers.c
... | ... | @@ -169,7 +169,7 @@ |
169 | 169 | up_write(&triggers_list_lock); |
170 | 170 | |
171 | 171 | /* Register with any LEDs that have this as a default trigger */ |
172 | - read_lock(&leds_list_lock); | |
172 | + down_read(&leds_list_lock); | |
173 | 173 | list_for_each_entry(led_cdev, &leds_list, node) { |
174 | 174 | down_write(&led_cdev->trigger_lock); |
175 | 175 | if (!led_cdev->trigger && led_cdev->default_trigger && |
... | ... | @@ -177,7 +177,7 @@ |
177 | 177 | led_trigger_set(led_cdev, trigger); |
178 | 178 | up_write(&led_cdev->trigger_lock); |
179 | 179 | } |
180 | - read_unlock(&leds_list_lock); | |
180 | + up_read(&leds_list_lock); | |
181 | 181 | |
182 | 182 | return 0; |
183 | 183 | } |
184 | 184 | |
... | ... | @@ -212,14 +212,14 @@ |
212 | 212 | up_write(&triggers_list_lock); |
213 | 213 | |
214 | 214 | /* Remove anyone actively using this trigger */ |
215 | - read_lock(&leds_list_lock); | |
215 | + down_read(&leds_list_lock); | |
216 | 216 | list_for_each_entry(led_cdev, &leds_list, node) { |
217 | 217 | down_write(&led_cdev->trigger_lock); |
218 | 218 | if (led_cdev->trigger == trigger) |
219 | 219 | led_trigger_set(led_cdev, NULL); |
220 | 220 | up_write(&led_cdev->trigger_lock); |
221 | 221 | } |
222 | - read_unlock(&leds_list_lock); | |
222 | + up_read(&leds_list_lock); | |
223 | 223 | } |
224 | 224 | |
225 | 225 | void led_trigger_unregister_simple(struct led_trigger *trigger) |
drivers/leds/leds.h
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | #define __LEDS_H_INCLUDED |
15 | 15 | |
16 | 16 | #include <linux/device.h> |
17 | +#include <linux/rwsem.h> | |
17 | 18 | #include <linux/leds.h> |
18 | 19 | |
19 | 20 | static inline void led_set_brightness(struct led_classdev *led_cdev, |
... | ... | @@ -26,7 +27,7 @@ |
26 | 27 | led_cdev->brightness_set(led_cdev, value); |
27 | 28 | } |
28 | 29 | |
29 | -extern rwlock_t leds_list_lock; | |
30 | +extern struct rw_semaphore leds_list_lock; | |
30 | 31 | extern struct list_head leds_list; |
31 | 32 | |
32 | 33 | #ifdef CONFIG_LEDS_TRIGGERS |