1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
4 * Copyright 2012, Kurt Van Dijck <kurt.van.dijck@eia.be>
7 #include <linux/module.h>
8 #include <linux/device.h>
9 #include <linux/kernel.h>
10 #include <linux/slab.h>
11 #include <linux/netdevice.h>
12 #include <linux/can/dev.h>
14 #include <linux/can/led.h>
16 static unsigned long led_delay
= 50;
17 module_param(led_delay
, ulong
, 0644);
18 MODULE_PARM_DESC(led_delay
,
19 "blink delay time for activity leds (msecs, default: 50).");
21 /* Trigger a LED event in response to a CAN device event */
22 void can_led_event(struct net_device
*netdev
, enum can_led_event event
)
24 struct can_priv
*priv
= netdev_priv(netdev
);
27 case CAN_LED_EVENT_OPEN
:
28 led_trigger_event(priv
->tx_led_trig
, LED_FULL
);
29 led_trigger_event(priv
->rx_led_trig
, LED_FULL
);
30 led_trigger_event(priv
->rxtx_led_trig
, LED_FULL
);
32 case CAN_LED_EVENT_STOP
:
33 led_trigger_event(priv
->tx_led_trig
, LED_OFF
);
34 led_trigger_event(priv
->rx_led_trig
, LED_OFF
);
35 led_trigger_event(priv
->rxtx_led_trig
, LED_OFF
);
37 case CAN_LED_EVENT_TX
:
39 led_trigger_blink_oneshot(priv
->tx_led_trig
,
40 &led_delay
, &led_delay
, 1);
41 led_trigger_blink_oneshot(priv
->rxtx_led_trig
,
42 &led_delay
, &led_delay
, 1);
45 case CAN_LED_EVENT_RX
:
47 led_trigger_blink_oneshot(priv
->rx_led_trig
,
48 &led_delay
, &led_delay
, 1);
49 led_trigger_blink_oneshot(priv
->rxtx_led_trig
,
50 &led_delay
, &led_delay
, 1);
55 EXPORT_SYMBOL_GPL(can_led_event
);
57 static void can_led_release(struct device
*gendev
, void *res
)
59 struct can_priv
*priv
= netdev_priv(to_net_dev(gendev
));
61 led_trigger_unregister_simple(priv
->tx_led_trig
);
62 led_trigger_unregister_simple(priv
->rx_led_trig
);
63 led_trigger_unregister_simple(priv
->rxtx_led_trig
);
66 /* Register CAN LED triggers for a CAN device
68 * This is normally called from a driver's probe function
70 void devm_can_led_init(struct net_device
*netdev
)
72 struct can_priv
*priv
= netdev_priv(netdev
);
75 res
= devres_alloc(can_led_release
, 0, GFP_KERNEL
);
77 netdev_err(netdev
, "cannot register LED triggers\n");
81 snprintf(priv
->tx_led_trig_name
, sizeof(priv
->tx_led_trig_name
),
82 "%s-tx", netdev
->name
);
83 snprintf(priv
->rx_led_trig_name
, sizeof(priv
->rx_led_trig_name
),
84 "%s-rx", netdev
->name
);
85 snprintf(priv
->rxtx_led_trig_name
, sizeof(priv
->rxtx_led_trig_name
),
86 "%s-rxtx", netdev
->name
);
88 led_trigger_register_simple(priv
->tx_led_trig_name
,
90 led_trigger_register_simple(priv
->rx_led_trig_name
,
92 led_trigger_register_simple(priv
->rxtx_led_trig_name
,
93 &priv
->rxtx_led_trig
);
95 devres_add(&netdev
->dev
, res
);
97 EXPORT_SYMBOL_GPL(devm_can_led_init
);
99 /* NETDEV rename notifier to rename the associated led triggers too */
100 static int can_led_notifier(struct notifier_block
*nb
, unsigned long msg
,
103 struct net_device
*netdev
= netdev_notifier_info_to_dev(ptr
);
104 struct can_priv
*priv
= safe_candev_priv(netdev
);
105 char name
[CAN_LED_NAME_SZ
];
110 if (!priv
->tx_led_trig
|| !priv
->rx_led_trig
|| !priv
->rxtx_led_trig
)
113 if (msg
== NETDEV_CHANGENAME
) {
114 snprintf(name
, sizeof(name
), "%s-tx", netdev
->name
);
115 led_trigger_rename_static(name
, priv
->tx_led_trig
);
117 snprintf(name
, sizeof(name
), "%s-rx", netdev
->name
);
118 led_trigger_rename_static(name
, priv
->rx_led_trig
);
120 snprintf(name
, sizeof(name
), "%s-rxtx", netdev
->name
);
121 led_trigger_rename_static(name
, priv
->rxtx_led_trig
);
127 /* notifier block for netdevice event */
128 static struct notifier_block can_netdev_notifier __read_mostly
= {
129 .notifier_call
= can_led_notifier
,
132 int __init
can_led_notifier_init(void)
134 return register_netdevice_notifier(&can_netdev_notifier
);
137 void __exit
can_led_notifier_exit(void)
139 unregister_netdevice_notifier(&can_netdev_notifier
);