led.c revision a1ef7bd9fce8aba8e4701e60208148fb3bc9bdd4
1/* 2 * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com> 3 * Copyright 2012, Kurt Van Dijck <kurt.van.dijck@eia.be> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10#include <linux/module.h> 11#include <linux/device.h> 12#include <linux/kernel.h> 13#include <linux/slab.h> 14#include <linux/netdevice.h> 15#include <linux/can/dev.h> 16 17#include <linux/can/led.h> 18 19static unsigned long led_delay = 50; 20module_param(led_delay, ulong, 0644); 21MODULE_PARM_DESC(led_delay, 22 "blink delay time for activity leds (msecs, default: 50)."); 23 24/* Trigger a LED event in response to a CAN device event */ 25void can_led_event(struct net_device *netdev, enum can_led_event event) 26{ 27 struct can_priv *priv = netdev_priv(netdev); 28 29 switch (event) { 30 case CAN_LED_EVENT_OPEN: 31 led_trigger_event(priv->tx_led_trig, LED_FULL); 32 led_trigger_event(priv->rx_led_trig, LED_FULL); 33 break; 34 case CAN_LED_EVENT_STOP: 35 led_trigger_event(priv->tx_led_trig, LED_OFF); 36 led_trigger_event(priv->rx_led_trig, LED_OFF); 37 break; 38 case CAN_LED_EVENT_TX: 39 if (led_delay) 40 led_trigger_blink_oneshot(priv->tx_led_trig, 41 &led_delay, &led_delay, 1); 42 break; 43 case CAN_LED_EVENT_RX: 44 if (led_delay) 45 led_trigger_blink_oneshot(priv->rx_led_trig, 46 &led_delay, &led_delay, 1); 47 break; 48 } 49} 50EXPORT_SYMBOL_GPL(can_led_event); 51 52static void can_led_release(struct device *gendev, void *res) 53{ 54 struct can_priv *priv = netdev_priv(to_net_dev(gendev)); 55 56 led_trigger_unregister_simple(priv->tx_led_trig); 57 led_trigger_unregister_simple(priv->rx_led_trig); 58} 59 60/* Register CAN LED triggers for a CAN device 61 * 62 * This is normally called from a driver's probe function 63 */ 64void devm_can_led_init(struct net_device *netdev) 65{ 66 struct can_priv *priv = netdev_priv(netdev); 67 void *res; 68 69 res = devres_alloc(can_led_release, 0, GFP_KERNEL); 70 if (!res) { 71 netdev_err(netdev, "cannot register LED triggers\n"); 72 return; 73 } 74 75 snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name), 76 "%s-tx", netdev->name); 77 snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name), 78 "%s-rx", netdev->name); 79 80 led_trigger_register_simple(priv->tx_led_trig_name, 81 &priv->tx_led_trig); 82 led_trigger_register_simple(priv->rx_led_trig_name, 83 &priv->rx_led_trig); 84 85 devres_add(&netdev->dev, res); 86} 87EXPORT_SYMBOL_GPL(devm_can_led_init); 88 89/* NETDEV rename notifier to rename the associated led triggers too */ 90static int can_led_notifier(struct notifier_block *nb, unsigned long msg, 91 void *data) 92{ 93 struct net_device *netdev = data; 94 struct can_priv *priv = safe_candev_priv(netdev); 95 char name[CAN_LED_NAME_SZ]; 96 97 if (!priv) 98 return NOTIFY_DONE; 99 100 if (msg == NETDEV_CHANGENAME) { 101 snprintf(name, sizeof(name), "%s-tx", netdev->name); 102 led_trigger_rename_static(name, priv->tx_led_trig); 103 104 snprintf(name, sizeof(name), "%s-rx", netdev->name); 105 led_trigger_rename_static(name, priv->rx_led_trig); 106 } 107 108 return NOTIFY_DONE; 109} 110 111/* notifier block for netdevice event */ 112static struct notifier_block can_netdev_notifier __read_mostly = { 113 .notifier_call = can_led_notifier, 114}; 115 116int __init can_led_notifier_init(void) 117{ 118 return register_netdevice_notifier(&can_netdev_notifier); 119} 120 121void __exit can_led_notifier_exit(void) 122{ 123 unregister_netdevice_notifier(&can_netdev_notifier); 124} 125