aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabio Baltieri <fabio.baltieri@gmail.com>2012-12-18 12:50:55 -0500
committerMarc Kleine-Budde <mkl@pengutronix.de>2013-01-26 10:58:59 -0500
commit996a953de02ffb852c9ac736f4e892008ed68884 (patch)
treedcf301c575ee47331f34c961c36f5658ce32da32
parent0024d8ad1639e32d717445c69ca813fd19c2a91c (diff)
can: add tx/rx LED trigger support
This patch implements the functions to add two LED triggers, named <ifname>-tx and <ifname>-rx, to a canbus device driver. Triggers are called from specific handlers by each CAN device driver and can be disabled altogether with a Kconfig option. The implementation keeps the LED on when the interface is UP and blinks the LED on network activity at a configurable rate. This only supports can-dev based drivers, as it uses some support field in the can_priv structure. Supported drivers should call devm_can_led_init() and can_led_event() as needed. Cleanup is handled automatically by devres, so no *_exit function is needed. Supported events are: - CAN_LED_EVENT_OPEN: turn on tx/rx LEDs - CAN_LED_EVENT_STOP: turn off tx/rx LEDs - CAN_LED_EVENT_TX: trigger tx LED blink - CAN_LED_EVENT_RX: trigger tx LED blink Cc: Wolfgang Grandegger <wg@grandegger.com> Cc: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Fabio Baltieri <fabio.baltieri@gmail.com> Acked-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/net/can/Kconfig11
-rw-r--r--drivers/net/can/Makefile2
-rw-r--r--drivers/net/can/led.c86
-rw-r--r--include/linux/can/dev.h8
-rw-r--r--include/linux/can/led.h42
5 files changed, 149 insertions, 0 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 0c5a65682d01..1cca19f1c490 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -51,6 +51,17 @@ config CAN_CALC_BITTIMING
51 arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw". 51 arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
52 If unsure, say Y. 52 If unsure, say Y.
53 53
54config CAN_LEDS
55 bool "Enable LED triggers for Netlink based drivers"
56 depends on LEDS_CLASS
57 select LEDS_TRIGGERS
58 ---help---
59 This option adds two LED triggers for packet receive and transmit
60 events on each supported CAN device.
61
62 Say Y here if you are working on a system with led-class supported
63 LEDs and you want to use them as canbus activity indicators.
64
54config CAN_AT91 65config CAN_AT91
55 tristate "Atmel AT91 onchip CAN controller" 66 tristate "Atmel AT91 onchip CAN controller"
56 depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5 67 depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 7de59862bbe9..c7440392adbb 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -8,6 +8,8 @@ obj-$(CONFIG_CAN_SLCAN) += slcan.o
8obj-$(CONFIG_CAN_DEV) += can-dev.o 8obj-$(CONFIG_CAN_DEV) += can-dev.o
9can-dev-y := dev.o 9can-dev-y := dev.o
10 10
11can-dev-$(CONFIG_CAN_LEDS) += led.o
12
11obj-y += usb/ 13obj-y += usb/
12obj-y += softing/ 14obj-y += softing/
13 15
diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c
new file mode 100644
index 000000000000..c50a0d741c57
--- /dev/null
+++ b/drivers/net/can/led.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/device.h>
11#include <linux/kernel.h>
12#include <linux/slab.h>
13#include <linux/netdevice.h>
14#include <linux/can/dev.h>
15
16#include <linux/can/led.h>
17
18static unsigned long led_delay = 50;
19module_param(led_delay, ulong, 0644);
20MODULE_PARM_DESC(led_delay,
21 "blink delay time for activity leds (msecs, default: 50).");
22
23/* Trigger a LED event in response to a CAN device event */
24void can_led_event(struct net_device *netdev, enum can_led_event event)
25{
26 struct can_priv *priv = netdev_priv(netdev);
27
28 switch (event) {
29 case CAN_LED_EVENT_OPEN:
30 led_trigger_event(priv->tx_led_trig, LED_FULL);
31 led_trigger_event(priv->rx_led_trig, LED_FULL);
32 break;
33 case CAN_LED_EVENT_STOP:
34 led_trigger_event(priv->tx_led_trig, LED_OFF);
35 led_trigger_event(priv->rx_led_trig, LED_OFF);
36 break;
37 case CAN_LED_EVENT_TX:
38 if (led_delay)
39 led_trigger_blink_oneshot(priv->tx_led_trig,
40 &led_delay, &led_delay, 1);
41 break;
42 case CAN_LED_EVENT_RX:
43 if (led_delay)
44 led_trigger_blink_oneshot(priv->rx_led_trig,
45 &led_delay, &led_delay, 1);
46 break;
47 }
48}
49EXPORT_SYMBOL_GPL(can_led_event);
50
51static void can_led_release(struct device *gendev, void *res)
52{
53 struct can_priv *priv = netdev_priv(to_net_dev(gendev));
54
55 led_trigger_unregister_simple(priv->tx_led_trig);
56 led_trigger_unregister_simple(priv->rx_led_trig);
57}
58
59/* Register CAN LED triggers for a CAN device
60 *
61 * This is normally called from a driver's probe function
62 */
63void devm_can_led_init(struct net_device *netdev)
64{
65 struct can_priv *priv = netdev_priv(netdev);
66 void *res;
67
68 res = devres_alloc(can_led_release, 0, GFP_KERNEL);
69 if (!res) {
70 netdev_err(netdev, "cannot register LED triggers\n");
71 return;
72 }
73
74 snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name),
75 "%s-tx", netdev->name);
76 snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name),
77 "%s-rx", netdev->name);
78
79 led_trigger_register_simple(priv->tx_led_trig_name,
80 &priv->tx_led_trig);
81 led_trigger_register_simple(priv->rx_led_trig_name,
82 &priv->rx_led_trig);
83
84 devres_add(&netdev->dev, res);
85}
86EXPORT_SYMBOL_GPL(devm_can_led_init);
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 2b2fc345afca..7747d9bcdc84 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -16,6 +16,7 @@
16#include <linux/can.h> 16#include <linux/can.h>
17#include <linux/can/netlink.h> 17#include <linux/can/netlink.h>
18#include <linux/can/error.h> 18#include <linux/can/error.h>
19#include <linux/can/led.h>
19 20
20/* 21/*
21 * CAN mode 22 * CAN mode
@@ -52,6 +53,13 @@ struct can_priv {
52 53
53 unsigned int echo_skb_max; 54 unsigned int echo_skb_max;
54 struct sk_buff **echo_skb; 55 struct sk_buff **echo_skb;
56
57#ifdef CONFIG_CAN_LEDS
58 struct led_trigger *tx_led_trig;
59 char tx_led_trig_name[CAN_LED_NAME_SZ];
60 struct led_trigger *rx_led_trig;
61 char rx_led_trig_name[CAN_LED_NAME_SZ];
62#endif
55}; 63};
56 64
57/* 65/*
diff --git a/include/linux/can/led.h b/include/linux/can/led.h
new file mode 100644
index 000000000000..12d5549abb95
--- /dev/null
+++ b/include/linux/can/led.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef CAN_LED_H
10#define CAN_LED_H
11
12#include <linux/if.h>
13#include <linux/leds.h>
14
15enum can_led_event {
16 CAN_LED_EVENT_OPEN,
17 CAN_LED_EVENT_STOP,
18 CAN_LED_EVENT_TX,
19 CAN_LED_EVENT_RX,
20};
21
22#ifdef CONFIG_CAN_LEDS
23
24/* keep space for interface name + "-tx"/"-rx" suffix and null terminator */
25#define CAN_LED_NAME_SZ (IFNAMSIZ + 4)
26
27void can_led_event(struct net_device *netdev, enum can_led_event event);
28void devm_can_led_init(struct net_device *netdev);
29
30#else
31
32static inline void can_led_event(struct net_device *netdev,
33 enum can_led_event event)
34{
35}
36static inline void devm_can_led_init(struct net_device *netdev)
37{
38}
39
40#endif
41
42#endif