diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 16:07:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-14 16:07:22 -0400 |
commit | c07b3682cd12a017f976ec63bbd4758dc4c5100e (patch) | |
tree | d158994137113f31a30feadaae80d3c5d7109a26 /drivers/leds/trigger/ledtrig-netdev.c | |
parent | 4d88e3d24905eafa98cef0fc29365649ad8977b5 (diff) | |
parent | 2224f2ff9670b899983ff1b42d85530e889cfea1 (diff) |
Merge tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds
Pull LED updates from Jacek Anaszewski:
"LED triggers improvements make the biggest part of this pull request.
The most striking ones, that allowed for nice cleanups in the triggers
are:
- centralized handling of creation and removal of trigger sysfs
attributes via attribute group
- addition of module_led_trigger() helper
The other things that need to be mentioned:
New features and improvements to existing LED class drivers:
- lt3593: add DT support, switch to gpiod interface
- lm3692x: support LED sync configuration, change OF calls to fwnode
calls
- apu: modify PC Engines apu/apu2 driver to support apu3
Change in the drivers/net/can/led.c:
- mark led trigger as broken since it's in the way for the further
cleanups. It implements a subset of the netdev trigger and an Ack
is needed from someone who can actually test and confirm that the
netdev trigger works for can devices"
* tag 'leds-for-4.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds: (32 commits)
leds: ns2: Change unsigned to unsigned int
usb: simplify usbport trigger
leds: gpio trigger: simplifications from core changes
leds: backlight trigger: simplifications from core changes
leds: activity trigger: simplifications from core changes
leds: default-on trigger: make use of module_led_trigger()
leds: heartbeat trigger: simplifications from core changes
leds: oneshot trigger: simplifications from core changes
leds: transient trigger: simplifications from core changes
leds: timer trigger: simplifications from core changes
leds: netdev trigger: simplifications from core changes
leds: triggers: new function led_set_trigger_data()
leds: triggers: define module_led_trigger helper
leds: triggers: handle .trigger_data and .activated() in the core
leds: triggers: add device attribute support
leds: triggers: let struct led_trigger::activate() return an error code
leds: triggers: make the MODULE_LICENSE string match the actual license
leds: lm3692x: Support LED sync configuration
dt: bindings: lm3692x: Update binding for LED sync control
leds: lm3692x: Change DT calls to fwnode calls
...
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) |