Commit 72f8da329e07ad8a72c1f0e96b8955cfeb7c7329

Authored by Richard Purdie
1 parent e697789d64

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)
... ... @@ -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