aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2014-06-25 13:08:47 -0400
committerBryan Wu <cooloney@gmail.com>2014-06-25 18:10:54 -0400
commit0d25376c326220687a2dccb5c40b785a7499326c (patch)
tree7ff26332ab553647fa143ea55cf40bf98a716d37 /drivers/leds
parent9db9386016c6cfc6a6af3bacc7043cab8ff04ecf (diff)
leds: lm355x: fix attribute-creation race
Use the attribute groups of the led-class to create the indicator-LED attributes during probe in order to avoid racing with userspace. Note that the comment about the pattern attribute only being for LM3554 was incorrect and did not match the code (the original leds-lm3556 driver had the attribute before LM3554 support was added). Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Bryan Wu <cooloney@gmail.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/leds-lm355x.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 591eb5e58ae3..f5112cb2d991 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -413,6 +413,12 @@ out:
413 413
414static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); 414static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store);
415 415
416static struct attribute *lm355x_indicator_attrs[] = {
417 &dev_attr_pattern.attr,
418 NULL
419};
420ATTRIBUTE_GROUPS(lm355x_indicator);
421
416static const struct regmap_config lm355x_regmap = { 422static const struct regmap_config lm355x_regmap = {
417 .reg_bits = 8, 423 .reg_bits = 8,
418 .val_bits = 8, 424 .val_bits = 8,
@@ -501,25 +507,18 @@ static int lm355x_probe(struct i2c_client *client,
501 else 507 else
502 chip->cdev_indicator.max_brightness = 8; 508 chip->cdev_indicator.max_brightness = 8;
503 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set; 509 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
510 /* indicator pattern control only for LM3556 */
511 if (id->driver_data == CHIP_LM3556)
512 chip->cdev_indicator.groups = lm355x_indicator_groups;
504 err = led_classdev_register((struct device *) 513 err = led_classdev_register((struct device *)
505 &client->dev, &chip->cdev_indicator); 514 &client->dev, &chip->cdev_indicator);
506 if (err < 0) 515 if (err < 0)
507 goto err_create_indicator_file; 516 goto err_create_indicator_file;
508 /* indicator pattern control only for LM3554 */
509 if (id->driver_data == CHIP_LM3556) {
510 err =
511 device_create_file(chip->cdev_indicator.dev,
512 &dev_attr_pattern);
513 if (err < 0)
514 goto err_create_pattern_file;
515 }
516 517
517 dev_info(&client->dev, "%s is initialized\n", 518 dev_info(&client->dev, "%s is initialized\n",
518 lm355x_name[id->driver_data]); 519 lm355x_name[id->driver_data]);
519 return 0; 520 return 0;
520 521
521err_create_pattern_file:
522 led_classdev_unregister(&chip->cdev_indicator);
523err_create_indicator_file: 522err_create_indicator_file:
524 led_classdev_unregister(&chip->cdev_torch); 523 led_classdev_unregister(&chip->cdev_torch);
525err_create_torch_file: 524err_create_torch_file:
@@ -534,8 +533,6 @@ static int lm355x_remove(struct i2c_client *client)
534 struct lm355x_reg_data *preg = chip->regs; 533 struct lm355x_reg_data *preg = chip->regs;
535 534
536 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 535 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
537 if (chip->type == CHIP_LM3556)
538 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
539 led_classdev_unregister(&chip->cdev_indicator); 536 led_classdev_unregister(&chip->cdev_indicator);
540 flush_work(&chip->work_indicator); 537 flush_work(&chip->work_indicator);
541 led_classdev_unregister(&chip->cdev_torch); 538 led_classdev_unregister(&chip->cdev_torch);