diff options
author | Michael Grzeschik <m.grzeschik@pengutronix.de> | 2014-09-18 00:12:50 +0200 |
---|---|---|
committer | Michael Grzeschik <m.grzeschik@pengutronix.de> | 2015-10-26 09:10:56 +0100 |
commit | 8890624a4e8c2c7046d63bfd15d7331af9f55f10 (patch) | |
tree | c99553d5963e353f9375206f1654fcc920d2da1b /drivers/net/arcnet/arcnet.c | |
parent | arcnet: com20020-pci: add rotary index support (diff) | |
download | linux-8890624a4e8c2c7046d63bfd15d7331af9f55f10.tar.xz linux-8890624a4e8c2c7046d63bfd15d7331af9f55f10.zip |
arcnet: com20020-pci: add led trigger support
The EAE PLX-PCI card has special leds on the the main io pci resource
bar. This patch adds support to trigger the conflict and data leds with
the packages.
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Diffstat (limited to 'drivers/net/arcnet/arcnet.c')
-rw-r--r-- | drivers/net/arcnet/arcnet.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 542e2b46b9eb..4242522ae86b 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -52,6 +52,8 @@ #include <linux/init.h> #include <linux/jiffies.h> +#include <linux/leds.h> + #include "arcdevice.h" #include "com9026.h" @@ -189,6 +191,71 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum, #endif +/* Trigger a LED event in response to a ARCNET device event */ +void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event) +{ + struct arcnet_local *lp = netdev_priv(dev); + unsigned long led_delay = 350; + unsigned long tx_delay = 50; + + switch (event) { + case ARCNET_LED_EVENT_RECON: + led_trigger_blink_oneshot(lp->recon_led_trig, + &led_delay, &led_delay, 0); + break; + case ARCNET_LED_EVENT_OPEN: + led_trigger_event(lp->tx_led_trig, LED_OFF); + led_trigger_event(lp->recon_led_trig, LED_OFF); + break; + case ARCNET_LED_EVENT_STOP: + led_trigger_event(lp->tx_led_trig, LED_OFF); + led_trigger_event(lp->recon_led_trig, LED_OFF); + break; + case ARCNET_LED_EVENT_TX: + led_trigger_blink_oneshot(lp->tx_led_trig, + &tx_delay, &tx_delay, 0); + break; + } +} +EXPORT_SYMBOL_GPL(arcnet_led_event); + +static void arcnet_led_release(struct device *gendev, void *res) +{ + struct arcnet_local *lp = netdev_priv(to_net_dev(gendev)); + + led_trigger_unregister_simple(lp->tx_led_trig); + led_trigger_unregister_simple(lp->recon_led_trig); +} + +/* Register ARCNET LED triggers for a arcnet device + * + * This is normally called from a driver's probe function + */ +void devm_arcnet_led_init(struct net_device *netdev, int index, int subid) +{ + struct arcnet_local *lp = netdev_priv(netdev); + void *res; + + res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL); + if (!res) { + netdev_err(netdev, "cannot register LED triggers\n"); + return; + } + + snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name), + "arc%d-%d-tx", index, subid); + snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name), + "arc%d-%d-recon", index, subid); + + led_trigger_register_simple(lp->tx_led_trig_name, + &lp->tx_led_trig); + led_trigger_register_simple(lp->recon_led_trig_name, + &lp->recon_led_trig); + + devres_add(&netdev->dev, res); +} +EXPORT_SYMBOL_GPL(devm_arcnet_led_init); + /* Unregister a protocol driver from the arc_proto_map. Protocol drivers * are responsible for registering themselves, but the unregister routine * is pretty generic so we'll do it here. @@ -425,6 +492,7 @@ int arcnet_open(struct net_device *dev) netif_start_queue(dev); + arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN); return 0; out_module_put: @@ -438,6 +506,7 @@ int arcnet_close(struct net_device *dev) { struct arcnet_local *lp = netdev_priv(dev); + arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); netif_stop_queue(dev); /* flush TX and disable RX */ @@ -585,6 +654,8 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb, arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n", __FILE__, __LINE__, __func__, lp->hw.status(dev)); + arcnet_led_event(dev, ARCNET_LED_EVENT_TX); + spin_unlock_irqrestore(&lp->lock, flags); return retval; /* no need to try again */ } @@ -837,6 +908,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", status); + arcnet_led_event(dev, ARCNET_LED_EVENT_RECON); /* MYRECON bit is at bit 7 of diagstatus */ if (diagstatus & 0x80) arc_printk(D_RECON, dev, "Put out that recon myself\n"); |