The trigger core learned error handling for the activate callback and to handle device attributes. This allows to simplify the driver considerably. Note that .deactivate is only called when .new_activate succeeded, so the check for trigger_data being non-NULL can go away. (It was broken before because the core didn't clear trigger_data, so it might have been non-NULL even if .activate failed before.) Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> --- drivers/leds/trigger/ledtrig-netdev.c | 69 +++++++++------------------ 1 file changed, 22 insertions(+), 47 deletions(-) diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 6df4781a6308..bbdeaa468f9c 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -288,6 +288,16 @@ static ssize_t interval_store(struct device *dev, static DEVICE_ATTR_RW(interval); +static struct attribute *netdev_trig_attrs[] = { + &dev_attr_device_name.attr, + &dev_attr_link.attr, + &dev_attr_rx.attr, + &dev_attr_tx.attr, + &dev_attr_interval.attr, + NULL +}; +ATTRIBUTE_GROUPS(netdev_trig); + static int netdev_trig_notify(struct notifier_block *nb, unsigned long evt, void *dv) { @@ -388,14 +398,14 @@ static void netdev_trig_work(struct work_struct *work) (atomic_read(&trigger_data->interval)*2)); } -static void netdev_trig_activate(struct led_classdev *led_cdev) +static int netdev_trig_activate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data; int rc; trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) - return; + return -ENOMEM; spin_lock_init(&trigger_data->lock); @@ -414,67 +424,32 @@ static void netdev_trig_activate(struct led_classdev *led_cdev) led_cdev->trigger_data = trigger_data; - rc = device_create_file(led_cdev->dev, &dev_attr_device_name); - if (rc) - goto err_out; - rc = device_create_file(led_cdev->dev, &dev_attr_link); - if (rc) - goto err_out_device_name; - rc = device_create_file(led_cdev->dev, &dev_attr_rx); - if (rc) - goto err_out_link; - rc = device_create_file(led_cdev->dev, &dev_attr_tx); - if (rc) - goto err_out_rx; - rc = device_create_file(led_cdev->dev, &dev_attr_interval); - if (rc) - goto err_out_tx; rc = register_netdevice_notifier(&trigger_data->notifier); if (rc) - goto err_out_interval; - return; - -err_out_interval: - device_remove_file(led_cdev->dev, &dev_attr_interval); -err_out_tx: - device_remove_file(led_cdev->dev, &dev_attr_tx); -err_out_rx: - device_remove_file(led_cdev->dev, &dev_attr_rx); -err_out_link: - device_remove_file(led_cdev->dev, &dev_attr_link); -err_out_device_name: - device_remove_file(led_cdev->dev, &dev_attr_device_name); -err_out: - led_cdev->trigger_data = NULL; - kfree(trigger_data); + kfree(trigger_data); + + return rc; } static void netdev_trig_deactivate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data = led_cdev->trigger_data; - if (trigger_data) { - unregister_netdevice_notifier(&trigger_data->notifier); - - device_remove_file(led_cdev->dev, &dev_attr_device_name); - device_remove_file(led_cdev->dev, &dev_attr_link); - device_remove_file(led_cdev->dev, &dev_attr_rx); - device_remove_file(led_cdev->dev, &dev_attr_tx); - device_remove_file(led_cdev->dev, &dev_attr_interval); + unregister_netdevice_notifier(&trigger_data->notifier); - cancel_delayed_work_sync(&trigger_data->work); + cancel_delayed_work_sync(&trigger_data->work); - if (trigger_data->net_dev) - dev_put(trigger_data->net_dev); + if (trigger_data->net_dev) + dev_put(trigger_data->net_dev); - kfree(trigger_data); - } + kfree(trigger_data); } static struct led_trigger netdev_led_trigger = { .name = "netdev", - .activate = netdev_trig_activate, + .new_activate = netdev_trig_activate, .deactivate = netdev_trig_deactivate, + .groups = netdev_trig_groups, }; static int __init netdev_trig_init(void) -- 2.17.0