diff options
Diffstat (limited to 'drivers/leds/trigger/ledtrig-netdev.c')
-rw-r--r-- | drivers/leds/trigger/ledtrig-netdev.c | 101 |
1 files changed, 33 insertions, 68 deletions
diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 6df4781a6308..3dd3ed46d473 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c | |||
@@ -94,8 +94,7 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) | |||
94 | static ssize_t device_name_show(struct device *dev, | 94 | static ssize_t device_name_show(struct device *dev, |
95 | struct device_attribute *attr, char *buf) | 95 | struct device_attribute *attr, char *buf) |
96 | { | 96 | { |
97 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 97 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
98 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
99 | ssize_t len; | 98 | ssize_t len; |
100 | 99 | ||
101 | spin_lock_bh(&trigger_data->lock); | 100 | spin_lock_bh(&trigger_data->lock); |
@@ -109,8 +108,7 @@ static ssize_t device_name_store(struct device *dev, | |||
109 | struct device_attribute *attr, const char *buf, | 108 | struct device_attribute *attr, const char *buf, |
110 | size_t size) | 109 | size_t size) |
111 | { | 110 | { |
112 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 111 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
113 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
114 | 112 | ||
115 | if (size >= IFNAMSIZ) | 113 | if (size >= IFNAMSIZ) |
116 | return -EINVAL; | 114 | return -EINVAL; |
@@ -150,8 +148,7 @@ static DEVICE_ATTR_RW(device_name); | |||
150 | static ssize_t netdev_led_attr_show(struct device *dev, char *buf, | 148 | static ssize_t netdev_led_attr_show(struct device *dev, char *buf, |
151 | enum netdev_led_attr attr) | 149 | enum netdev_led_attr attr) |
152 | { | 150 | { |
153 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 151 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
154 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
155 | int bit; | 152 | int bit; |
156 | 153 | ||
157 | switch (attr) { | 154 | switch (attr) { |
@@ -174,8 +171,7 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf, | |||
174 | static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, | 171 | static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, |
175 | size_t size, enum netdev_led_attr attr) | 172 | size_t size, enum netdev_led_attr attr) |
176 | { | 173 | { |
177 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 174 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
178 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
179 | unsigned long state; | 175 | unsigned long state; |
180 | int ret; | 176 | int ret; |
181 | int bit; | 177 | int bit; |
@@ -255,8 +251,7 @@ static DEVICE_ATTR_RW(rx); | |||
255 | static ssize_t interval_show(struct device *dev, | 251 | static ssize_t interval_show(struct device *dev, |
256 | struct device_attribute *attr, char *buf) | 252 | struct device_attribute *attr, char *buf) |
257 | { | 253 | { |
258 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 254 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
259 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
260 | 255 | ||
261 | return sprintf(buf, "%u\n", | 256 | return sprintf(buf, "%u\n", |
262 | jiffies_to_msecs(atomic_read(&trigger_data->interval))); | 257 | jiffies_to_msecs(atomic_read(&trigger_data->interval))); |
@@ -266,8 +261,7 @@ static ssize_t interval_store(struct device *dev, | |||
266 | struct device_attribute *attr, const char *buf, | 261 | struct device_attribute *attr, const char *buf, |
267 | size_t size) | 262 | size_t size) |
268 | { | 263 | { |
269 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | 264 | struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); |
270 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | ||
271 | unsigned long value; | 265 | unsigned long value; |
272 | int ret; | 266 | int ret; |
273 | 267 | ||
@@ -288,15 +282,23 @@ static ssize_t interval_store(struct device *dev, | |||
288 | 282 | ||
289 | static DEVICE_ATTR_RW(interval); | 283 | static DEVICE_ATTR_RW(interval); |
290 | 284 | ||
285 | static struct attribute *netdev_trig_attrs[] = { | ||
286 | &dev_attr_device_name.attr, | ||
287 | &dev_attr_link.attr, | ||
288 | &dev_attr_rx.attr, | ||
289 | &dev_attr_tx.attr, | ||
290 | &dev_attr_interval.attr, | ||
291 | NULL | ||
292 | }; | ||
293 | ATTRIBUTE_GROUPS(netdev_trig); | ||
294 | |||
291 | static int netdev_trig_notify(struct notifier_block *nb, | 295 | static int netdev_trig_notify(struct notifier_block *nb, |
292 | unsigned long evt, void *dv) | 296 | unsigned long evt, void *dv) |
293 | { | 297 | { |
294 | struct net_device *dev = | 298 | struct net_device *dev = |
295 | netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); | 299 | netdev_notifier_info_to_dev((struct netdev_notifier_info *)dv); |
296 | struct led_netdev_data *trigger_data = container_of(nb, | 300 | struct led_netdev_data *trigger_data = |
297 | struct | 301 | container_of(nb, struct led_netdev_data, notifier); |
298 | led_netdev_data, | ||
299 | notifier); | ||
300 | 302 | ||
301 | if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE | 303 | if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE |
302 | && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER | 304 | && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER |
@@ -342,10 +344,8 @@ static int netdev_trig_notify(struct notifier_block *nb, | |||
342 | /* here's the real work! */ | 344 | /* here's the real work! */ |
343 | static void netdev_trig_work(struct work_struct *work) | 345 | static void netdev_trig_work(struct work_struct *work) |
344 | { | 346 | { |
345 | struct led_netdev_data *trigger_data = container_of(work, | 347 | struct led_netdev_data *trigger_data = |
346 | struct | 348 | container_of(work, struct led_netdev_data, work.work); |
347 | led_netdev_data, | ||
348 | work.work); | ||
349 | struct rtnl_link_stats64 *dev_stats; | 349 | struct rtnl_link_stats64 *dev_stats; |
350 | unsigned int new_activity; | 350 | unsigned int new_activity; |
351 | struct rtnl_link_stats64 temp; | 351 | struct rtnl_link_stats64 temp; |
@@ -388,14 +388,14 @@ static void netdev_trig_work(struct work_struct *work) | |||
388 | (atomic_read(&trigger_data->interval)*2)); | 388 | (atomic_read(&trigger_data->interval)*2)); |
389 | } | 389 | } |
390 | 390 | ||
391 | static void netdev_trig_activate(struct led_classdev *led_cdev) | 391 | static int netdev_trig_activate(struct led_classdev *led_cdev) |
392 | { | 392 | { |
393 | struct led_netdev_data *trigger_data; | 393 | struct led_netdev_data *trigger_data; |
394 | int rc; | 394 | int rc; |
395 | 395 | ||
396 | trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); | 396 | trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); |
397 | if (!trigger_data) | 397 | if (!trigger_data) |
398 | return; | 398 | return -ENOMEM; |
399 | 399 | ||
400 | spin_lock_init(&trigger_data->lock); | 400 | spin_lock_init(&trigger_data->lock); |
401 | 401 | ||
@@ -412,69 +412,34 @@ static void netdev_trig_activate(struct led_classdev *led_cdev) | |||
412 | atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); | 412 | atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); |
413 | trigger_data->last_activity = 0; | 413 | trigger_data->last_activity = 0; |
414 | 414 | ||
415 | led_cdev->trigger_data = trigger_data; | 415 | led_set_trigger_data(led_cdev, trigger_data); |
416 | 416 | ||
417 | rc = device_create_file(led_cdev->dev, &dev_attr_device_name); | ||
418 | if (rc) | ||
419 | goto err_out; | ||
420 | rc = device_create_file(led_cdev->dev, &dev_attr_link); | ||
421 | if (rc) | ||
422 | goto err_out_device_name; | ||
423 | rc = device_create_file(led_cdev->dev, &dev_attr_rx); | ||
424 | if (rc) | ||
425 | goto err_out_link; | ||
426 | rc = device_create_file(led_cdev->dev, &dev_attr_tx); | ||
427 | if (rc) | ||
428 | goto err_out_rx; | ||
429 | rc = device_create_file(led_cdev->dev, &dev_attr_interval); | ||
430 | if (rc) | ||
431 | goto err_out_tx; | ||
432 | rc = register_netdevice_notifier(&trigger_data->notifier); | 417 | rc = register_netdevice_notifier(&trigger_data->notifier); |
433 | if (rc) | 418 | if (rc) |
434 | goto err_out_interval; | 419 | kfree(trigger_data); |
435 | return; | 420 | |
436 | 421 | return rc; | |
437 | err_out_interval: | ||
438 | device_remove_file(led_cdev->dev, &dev_attr_interval); | ||
439 | err_out_tx: | ||
440 | device_remove_file(led_cdev->dev, &dev_attr_tx); | ||
441 | err_out_rx: | ||
442 | device_remove_file(led_cdev->dev, &dev_attr_rx); | ||
443 | err_out_link: | ||
444 | device_remove_file(led_cdev->dev, &dev_attr_link); | ||
445 | err_out_device_name: | ||
446 | device_remove_file(led_cdev->dev, &dev_attr_device_name); | ||
447 | err_out: | ||
448 | led_cdev->trigger_data = NULL; | ||
449 | kfree(trigger_data); | ||
450 | } | 422 | } |
451 | 423 | ||
452 | static void netdev_trig_deactivate(struct led_classdev *led_cdev) | 424 | static void netdev_trig_deactivate(struct led_classdev *led_cdev) |
453 | { | 425 | { |
454 | struct led_netdev_data *trigger_data = led_cdev->trigger_data; | 426 | struct led_netdev_data *trigger_data = led_get_trigger_data(led_cdev); |
455 | |||
456 | if (trigger_data) { | ||
457 | unregister_netdevice_notifier(&trigger_data->notifier); | ||
458 | 427 | ||
459 | device_remove_file(led_cdev->dev, &dev_attr_device_name); | 428 | unregister_netdevice_notifier(&trigger_data->notifier); |
460 | device_remove_file(led_cdev->dev, &dev_attr_link); | ||
461 | device_remove_file(led_cdev->dev, &dev_attr_rx); | ||
462 | device_remove_file(led_cdev->dev, &dev_attr_tx); | ||
463 | device_remove_file(led_cdev->dev, &dev_attr_interval); | ||
464 | 429 | ||
465 | cancel_delayed_work_sync(&trigger_data->work); | 430 | cancel_delayed_work_sync(&trigger_data->work); |
466 | 431 | ||
467 | if (trigger_data->net_dev) | 432 | if (trigger_data->net_dev) |
468 | dev_put(trigger_data->net_dev); | 433 | dev_put(trigger_data->net_dev); |
469 | 434 | ||
470 | kfree(trigger_data); | 435 | kfree(trigger_data); |
471 | } | ||
472 | } | 436 | } |
473 | 437 | ||
474 | static struct led_trigger netdev_led_trigger = { | 438 | static struct led_trigger netdev_led_trigger = { |
475 | .name = "netdev", | 439 | .name = "netdev", |
476 | .activate = netdev_trig_activate, | 440 | .activate = netdev_trig_activate, |
477 | .deactivate = netdev_trig_deactivate, | 441 | .deactivate = netdev_trig_deactivate, |
442 | .groups = netdev_trig_groups, | ||
478 | }; | 443 | }; |
479 | 444 | ||
480 | static int __init netdev_trig_init(void) | 445 | static int __init netdev_trig_init(void) |