Skip to content

Commit

Permalink
leds/led-class: Handle LEDs with the same name
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ricardo Ribalda Delgado authored and Bryan Wu committed Mar 30, 2015
1 parent 5ee047f commit a96aa64
Showing 1 changed file with 37 additions and 2 deletions.
39 changes: 37 additions & 2 deletions drivers/leds/led-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,19 +212,54 @@ static const struct dev_pm_ops leds_class_dev_pm_ops = {
.resume = led_resume,
};

static int match_name(struct device *dev, const void *data)
{
if (!dev_name(dev))
return 0;
return !strcmp(dev_name(dev), (char *)data);
}

static int led_classdev_next_name(const char *init_name, char *name,
size_t len)
{
unsigned int i = 0;
int ret = 0;

strlcpy(name, init_name, len);

while (class_find_device(leds_class, NULL, name, match_name) &&
(ret < len))
ret = snprintf(name, len, "%s_%u", init_name, ++i);

if (ret >= len)
return -ENOMEM;

return i;
}

/**
* led_classdev_register - register a new object of led_classdev class.
* @parent: The device to register.
* @led_cdev: the led_classdev structure for this device.
*/
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
char name[64];
int ret;

ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
if (ret < 0)
return ret;

led_cdev->dev = device_create_with_groups(leds_class, parent, 0,
led_cdev, led_cdev->groups,
"%s", led_cdev->name);
led_cdev, led_cdev->groups, name);
if (IS_ERR(led_cdev->dev))
return PTR_ERR(led_cdev->dev);

if (ret)
dev_info(parent, "Led %s renamed to %s due to name collision",
led_cdev->name, dev_name(led_cdev->dev));

#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
#endif
Expand Down

0 comments on commit a96aa64

Please sign in to comment.