aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>2015-03-30 13:45:59 -0400
committerBryan Wu <cooloney@gmail.com>2015-03-30 14:55:57 -0400
commita96aa64cb5723d941de879a9cd1fea025d6acb1b (patch)
treeb4a69eca7bb9991a1060ed92bd4a5845ca57c9ac
parent5ee047fb7ddd5ce65b804b0888fa32dd8536cda6 (diff)
leds/led-class: Handle LEDs with the same name
The current code expected that every LED had an unique name. This is a legit expectation when the device tree can no be modified or extended. But with device tree overlays this requirement can be easily broken. This patch finds out if the name is already in use and adds the suffix _1, _2... if not. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Bryan Wu <cooloney@gmail.com>
-rw-r--r--drivers/leds/led-class.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 768d33a79881..fc57d9c2e6ad 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -212,6 +212,31 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
212 .resume = led_resume, 212 .resume = led_resume,
213}; 213};
214 214
215static int match_name(struct device *dev, const void *data)
216{
217 if (!dev_name(dev))
218 return 0;
219 return !strcmp(dev_name(dev), (char *)data);
220}
221
222static int led_classdev_next_name(const char *init_name, char *name,
223 size_t len)
224{
225 unsigned int i = 0;
226 int ret = 0;
227
228 strlcpy(name, init_name, len);
229
230 while (class_find_device(leds_class, NULL, name, match_name) &&
231 (ret < len))
232 ret = snprintf(name, len, "%s_%u", init_name, ++i);
233
234 if (ret >= len)
235 return -ENOMEM;
236
237 return i;
238}
239
215/** 240/**
216 * led_classdev_register - register a new object of led_classdev class. 241 * led_classdev_register - register a new object of led_classdev class.
217 * @parent: The device to register. 242 * @parent: The device to register.
@@ -219,12 +244,22 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
219 */ 244 */
220int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) 245int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
221{ 246{
247 char name[64];
248 int ret;
249
250 ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
251 if (ret < 0)
252 return ret;
253
222 led_cdev->dev = device_create_with_groups(leds_class, parent, 0, 254 led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
223 led_cdev, led_cdev->groups, 255 led_cdev, led_cdev->groups, name);
224 "%s", led_cdev->name);
225 if (IS_ERR(led_cdev->dev)) 256 if (IS_ERR(led_cdev->dev))
226 return PTR_ERR(led_cdev->dev); 257 return PTR_ERR(led_cdev->dev);
227 258
259 if (ret)
260 dev_info(parent, "Led %s renamed to %s due to name collision",
261 led_cdev->name, dev_name(led_cdev->dev));
262
228#ifdef CONFIG_LEDS_TRIGGERS 263#ifdef CONFIG_LEDS_TRIGGERS
229 init_rwsem(&led_cdev->trigger_lock); 264 init_rwsem(&led_cdev->trigger_lock);
230#endif 265#endif