Allocate per-LED data structure and initialize with default values Create /sys/class/leds/<led>/block_devices directory Increment module reference count. Module can only be removed when no LEDs are associated with the trigger. Signed-off-by: Ian Pilcher <arequipeno@xxxxxxxxx> --- drivers/leds/trigger/ledtrig-blkdev.c | 54 +++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/leds/trigger/ledtrig-blkdev.c b/drivers/leds/trigger/ledtrig-blkdev.c index 37ba9bb3542e..bbf71ff18057 100644 --- a/drivers/leds/trigger/ledtrig-blkdev.c +++ b/drivers/leds/trigger/ledtrig-blkdev.c @@ -198,3 +198,57 @@ static void blkdev_process(struct work_struct *const work) delay = READ_ONCE(ledtrig_blkdev_interval); WARN_ON_ONCE(!schedule_delayed_work(&ledtrig_blkdev_work, delay)); } + + +/* + * + * Associate an LED with the blkdev trigger + * + */ + +static int blkdev_activate(struct led_classdev *const led_dev) +{ + struct ledtrig_blkdev_led *led; + int ret; + + if (WARN_ON(!try_module_get(THIS_MODULE))) { + ret = -ENODEV; /* -ESHOULDNEVERHAPPEN */ + goto exit_return; + } + + led = kmalloc(sizeof(*led), GFP_KERNEL); + if (led == NULL) { + ret = -ENOMEM; + goto exit_put_module; + } + + led->led_dev = led_dev; + led->blink_msec = LEDTRIG_BLKDEV_BLINK_MSEC; + led->mode = LEDTRIG_BLKDEV_MODE_RW; + INIT_HLIST_HEAD(&led->disks); + + ret = mutex_lock_interruptible(&ledtrig_blkdev_mutex); + if (ret != 0) + goto exit_free; + + led->dir = kobject_create_and_add("block_devices", &led_dev->dev->kobj); + if (led->dir == NULL) { + ret = -ENOMEM; + goto exit_unlock; + } + + hlist_add_head(&led->leds_node, &ledtrig_blkdev_leds); + led_set_trigger_data(led_dev, led); + ret = 0; + +exit_unlock: + mutex_unlock(&ledtrig_blkdev_mutex); +exit_free: + if (ret != 0) + kfree(led); +exit_put_module: + if (ret != 0) + module_put(THIS_MODULE); +exit_return: + return ret; +} -- 2.31.1