diff options
27 files changed, 1488 insertions, 60 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index b56bd9e80957..1cca19f1c490 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -1,9 +1,7 @@ menu "CAN Device Drivers" - depends on CAN config CAN_VCAN tristate "Virtual Local CAN Interface (vcan)" - depends on CAN ---help--- Similar to the network loopback devices, vcan offers a virtual local CAN interface. @@ -13,7 +11,6 @@ config CAN_VCAN config CAN_SLCAN tristate "Serial / USB serial CAN Adaptors (slcan)" - depends on CAN ---help--- CAN driver for several 'low cost' CAN interfaces that are attached via serial lines or via USB-to-serial adapters using the LAWICEL @@ -33,16 +30,16 @@ config CAN_SLCAN config CAN_DEV tristate "Platform CAN drivers with Netlink support" - depends on CAN default y ---help--- Enables the common framework for platform CAN drivers with Netlink support. This is the standard library for CAN drivers. If unsure, say Y. +if CAN_DEV + config CAN_CALC_BITTIMING bool "CAN bit-timing calculation" - depends on CAN_DEV default y ---help--- If enabled, CAN bit-timing parameters will be calculated for the @@ -54,15 +51,26 @@ config CAN_CALC_BITTIMING arguments "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw". If unsure, say Y. +config CAN_LEDS + bool "Enable LED triggers for Netlink based drivers" + depends on LEDS_CLASS + select LEDS_TRIGGERS + ---help--- + This option adds two LED triggers for packet receive and transmit + events on each supported CAN device. + + Say Y here if you are working on a system with led-class supported + LEDs and you want to use them as canbus activity indicators. + config CAN_AT91 tristate "Atmel AT91 onchip CAN controller" - depends on CAN_DEV && (ARCH_AT91SAM9263 || ARCH_AT91SAM9X5) + depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9X5 ---help--- This is a driver for the SoC CAN controller in Atmel's AT91SAM9263 and AT91SAM9X5 processors. config CAN_TI_HECC - depends on CAN_DEV && ARCH_OMAP3 + depends on ARCH_OMAP3 tristate "TI High End CAN Controller" ---help--- Driver for TI HECC (High End CAN Controller) module found on many @@ -70,12 +78,12 @@ config CAN_TI_HECC config CAN_MCP251X tristate "Microchip MCP251x SPI CAN controllers" - depends on CAN_DEV && SPI && HAS_DMA + depends on SPI && HAS_DMA ---help--- Driver for the Microchip MCP251x SPI CAN controllers. config CAN_BFIN - depends on CAN_DEV && (BF534 || BF536 || BF537 || BF538 || BF539 || BF54x) + depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x tristate "Analog Devices Blackfin on-chip CAN" ---help--- Driver for the Analog Devices Blackfin on-chip CAN controllers @@ -85,7 +93,7 @@ config CAN_BFIN config CAN_JANZ_ICAN3 tristate "Janz VMOD-ICAN3 Intelligent CAN controller" - depends on CAN_DEV && MFD_JANZ_CMODIO + depends on MFD_JANZ_CMODIO ---help--- Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which connects to a MODULbus carrier board. @@ -98,13 +106,13 @@ config HAVE_CAN_FLEXCAN config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" - depends on CAN_DEV && HAVE_CAN_FLEXCAN + depends on HAVE_CAN_FLEXCAN ---help--- Say Y here if you want to support for Freescale FlexCAN. config PCH_CAN tristate "Intel EG20T PCH CAN controller" - depends on CAN_DEV && PCI + depends on PCI ---help--- This driver is for PCH CAN of Topcliff (Intel EG20T PCH) which is an IOH for x86 embedded processor (Intel Atom E6xx series). @@ -112,7 +120,7 @@ config PCH_CAN config CAN_GRCAN tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices" - depends on CAN_DEV && OF + depends on OF ---help--- Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN. Note that the driver supports little endian, even though little @@ -131,9 +139,10 @@ source "drivers/net/can/usb/Kconfig" source "drivers/net/can/softing/Kconfig" +endif + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" - depends on CAN ---help--- Say Y here if you want the CAN device drivers to produce a bunch of debug messages to the system log. Select this if you are having 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 obj-$(CONFIG_CAN_DEV) += can-dev.o can-dev-y := dev.o +can-dev-$(CONFIG_CAN_LEDS) += led.o + obj-y += usb/ obj-y += softing/ diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 81baefda037b..44f363792b59 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -37,6 +37,7 @@ #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/can/led.h> #define AT91_MB_MASK(i) ((1 << (i)) - 1) @@ -641,6 +642,8 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb) stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + + can_led_event(dev, CAN_LED_EVENT_RX); } /** @@ -875,6 +878,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) /* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ can_get_echo_skb(dev, mb - get_mb_tx_first(priv)); dev->stats.tx_packets++; + can_led_event(dev, CAN_LED_EVENT_TX); } } @@ -1128,6 +1132,8 @@ static int at91_open(struct net_device *dev) goto out_close; } + can_led_event(dev, CAN_LED_EVENT_OPEN); + /* start chip and queuing */ at91_chip_start(dev); napi_enable(&priv->napi); @@ -1159,6 +1165,8 @@ static int at91_close(struct net_device *dev) close_candev(dev); + can_led_event(dev, CAN_LED_EVENT_STOP); + return 0; } @@ -1321,6 +1329,8 @@ static int at91_can_probe(struct platform_device *pdev) goto exit_free; } + devm_can_led_init(dev); + dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n", priv->reg_base, dev->irq); diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig index 3b83bafcd947..61ffc12d8fd8 100644 --- a/drivers/net/can/c_can/Kconfig +++ b/drivers/net/can/c_can/Kconfig @@ -1,6 +1,6 @@ menuconfig CAN_C_CAN tristate "Bosch C_CAN/D_CAN devices" - depends on CAN_DEV && HAS_IOMEM + depends on HAS_IOMEM if CAN_C_CAN diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 5233b8f58d77..57eb1e77865d 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -39,6 +39,7 @@ #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/can/led.h> #include "c_can.h" @@ -477,6 +478,8 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) stats->rx_packets++; stats->rx_bytes += frame->can_dlc; + can_led_event(dev, CAN_LED_EVENT_RX); + return 0; } @@ -751,6 +754,7 @@ static void c_can_do_tx(struct net_device *dev) C_CAN_IFACE(MSGCTRL_REG, 0)) & IF_MCONT_DLC_MASK; stats->tx_packets++; + can_led_event(dev, CAN_LED_EVENT_TX); c_can_inval_msg_object(dev, 0, msg_obj_no); } else { break; @@ -1115,6 +1119,8 @@ static int c_can_open(struct net_device *dev) napi_enable(&priv->napi); + can_led_event(dev, CAN_LED_EVENT_OPEN); + /* start the c_can controller */ c_can_start(dev); @@ -1143,6 +1149,8 @@ static int c_can_close(struct net_device *dev) c_can_reset_ram(priv, false); c_can_pm_runtime_put_sync(priv); + can_led_event(dev, CAN_LED_EVENT_STOP); + return 0; } @@ -1268,6 +1276,8 @@ int register_c_can_dev(struct net_device *dev) err = register_candev(dev); if (err) c_can_pm_runtime_disable(priv); + else + devm_can_led_init(dev); return err; } diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig index 22c07a8c8b43..6a9a5ba79220 100644 --- a/drivers/net/can/cc770/Kconfig +++ b/drivers/net/can/cc770/Kconfig @@ -1,6 +1,6 @@ menuconfig CAN_CC770 tristate "Bosch CC770 and Intel AN82527 devices" - depends on CAN_DEV && HAS_IOMEM + depends on HAS_IOMEM if CAN_CC770 diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 8233e5ed2939..59ada082a994 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -24,7 +24,9 @@ #include <linux/if_arp.h> #include <linux/can.h> #include <linux/can/dev.h> +#include <linux/can/skb.h> #include <linux/can/netlink.h> +#include <linux/can/led.h> #include <net/rtnetlink.h> #define MOD_DESC "CAN device driver interface" @@ -501,13 +503,18 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) { struct sk_buff *skb; - skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); + skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + + sizeof(struct can_frame)); if (unlikely(!skb)) return NULL; skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb_reserve(skb, sizeof(struct can_skb_priv)); + ((struct can_skb_priv *)(skb->head))->ifindex = dev->ifindex; + *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); memset(*cf, 0, sizeof(struct can_frame)); @@ -794,10 +801,25 @@ void unregister_candev(struct net_device *dev) } EXPORT_SYMBOL_GPL(unregister_candev); +/* + * Test if a network device is a candev based device + * and return the can_priv* if so. + */ +struct can_priv *safe_candev_priv(struct net_device *dev) +{ + if ((dev->type != ARPHRD_CAN) || (dev->rtnl_link_ops != &can_link_ops)) + return NULL; + + return netdev_priv(dev); +} +EXPORT_SYMBOL_GPL(safe_candev_priv); + static __init int can_dev_init(void) { int err; + can_led_notifier_init(); + err = rtnl_link_register(&can_link_ops); if (!err) printk(KERN_INFO MOD_DESC "\n"); @@ -809,6 +831,8 @@ module_init(can_dev_init); static __exit void can_dev_exit(void) { rtnl_link_unregister(&can_link_ops); + + can_led_notifier_exit(); } module_exit(can_dev_exit); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 0289a6d86f66..769d29ed106d 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -23,6 +23,7 @@ #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/can/led.h> #include <linux/can/platform/flexcan.h> #include <linux/clk.h> #include <linux/delay.h> @@ -564,6 +565,8 @@ static int flexcan_read_frame(struct net_device *dev) stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + can_led_event(dev, CAN_LED_EVENT_RX); + return 1; } @@ -652,6 +655,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) { stats->tx_bytes += can_get_echo_skb(dev, 0); stats->tx_packets++; + can_led_event(dev, CAN_LED_EVENT_TX); flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); netif_wake_queue(dev); } @@ -865,6 +869,9 @@ static int flexcan_open(struct net_device *dev) err = flexcan_chip_start(dev); if (err) goto out_close; + + can_led_event(dev, CAN_LED_EVENT_OPEN); + napi_enable(&priv->napi); netif_start_queue(dev); @@ -893,6 +900,8 @@ static int flexcan_close(struct net_device *dev) close_candev(dev); + can_led_event(dev, CAN_LED_EVENT_STOP); + return 0; } @@ -1092,6 +1101,8 @@ static int flexcan_probe(struct platform_device *pdev) goto failed_register; } + devm_can_led_init(dev); + dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n", priv->base, dev->irq); diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c new file mode 100644 index 000000000000..f27fca65dc4a --- /dev/null +++ b/drivers/net/can/led.c @@ -0,0 +1,124 @@ +/* + * Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com> + * Copyright 2012, Kurt Van Dijck <kurt.van.dijck@eia.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/netdevice.h> +#include <linux/can/dev.h> + +#include <linux/can/led.h> + +static unsigned long led_delay = 50; +module_param(led_delay, ulong, 0644); +MODULE_PARM_DESC(led_delay, + "blink delay time for activity leds (msecs, default: 50)."); + +/* Trigger a LED event in response to a CAN device event */ +void can_led_event(struct net_device *netdev, enum can_led_event event) +{ + struct can_priv *priv = netdev_priv(netdev); + + switch (event) { + case CAN_LED_EVENT_OPEN: + led_trigger_event(priv->tx_led_trig, LED_FULL); + led_trigger_event(priv->rx_led_trig, LED_FULL); + break; + case CAN_LED_EVENT_STOP: + led_trigger_event(priv->tx_led_trig, LED_OFF); + led_trigger_event(priv->rx_led_trig, LED_OFF); + break; + case CAN_LED_EVENT_TX: + if (led_delay) + led_trigger_blink_oneshot(priv->tx_led_trig, + &led_delay, &led_delay, 1); + break; + case CAN_LED_EVENT_RX: + if (led_delay) + led_trigger_blink_oneshot(priv->rx_led_trig, + &led_delay, &led_delay, 1); + break; + } +} +EXPORT_SYMBOL_GPL(can_led_event); + +static void can_led_release(struct device *gendev, void *res) +{ + struct can_priv *priv = netdev_priv(to_net_dev(gendev)); + + led_trigger_unregister_simple(priv->tx_led_trig); + led_trigger_unregister_simple(priv->rx_led_trig); +} + +/* Register CAN LED triggers for a CAN device + * + * This is normally called from a driver's probe function + */ +void devm_can_led_init(struct net_device *netdev) +{ + struct can_priv *priv = netdev_priv(netdev); + void *res; + + res = devres_alloc(can_led_release, 0, GFP_KERNEL); + if (!res) { + netdev_err(netdev, "cannot register LED triggers\n"); + return; + } + + snprintf(priv->tx_led_trig_name, sizeof(priv->tx_led_trig_name), + "%s-tx", netdev->name); + snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name), + "%s-rx", netdev->name); + + led_trigger_register_simple(priv->tx_led_trig_name, + &priv->tx_led_trig); + led_trigger_register_simple(priv->rx_led_trig_name, + &priv->rx_led_trig); + + devres_add(&netdev->dev, res); +} +EXPORT_SYMBOL_GPL(devm_can_led_init); + +/* NETDEV rename notifier to rename the associated led triggers too */ +static int can_led_notifier(struct notifier_block *nb, unsigned long msg, + void *data) +{ + struct net_device *netdev = data; + struct can_priv *priv = safe_candev_priv(netdev); + char name[CAN_LED_NAME_SZ]; + + if (!priv) + return NOTIFY_DONE; + + if (msg == NETDEV_CHANGENAME) { + snprintf(name, sizeof(name), "%s-tx", netdev->name); + led_trigger_rename_static(name, priv->tx_led_trig); + + snprintf(name, sizeof(name), "%s-rx", netdev->name); + led_trigger_rename_static(name, priv->rx_led_trig); + } + + return NOTIFY_DONE; +} + +/* notifier block for netdevice event */ +static struct notifier_block can_netdev_notifier __read_mostly = { + .notifier_call = can_led_notifier, +}; + +int __init can_led_notifier_init(void) +{ + return register_netdevice_notifier(&can_netdev_notifier); +} + +void __exit can_led_notifier_exit(void) +{ + unregister_netdevice_notifier(&can_netdev_notifier); +} diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 5eaf47b8e37b..f32b9fc6a983 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -60,6 +60,7 @@ #include <linux/can/core.h> #include <linux/can/dev.h> +#include <linux/can/led.h> #include <linux/can/platform/mcp251x.h> #include <linux/completion.h> #include <linux/delay.h> @@ -494,6 +495,9 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) priv->net->stats.rx_packets++; priv->net->stats.rx_bytes += frame->can_dlc; + + can_led_event(priv->net, CAN_LED_EVENT_RX); + netif_rx_ni(skb); } @@ -707,6 +711,8 @@ static int mcp251x_stop(struct net_device *net) mutex_unlock(&priv->mcp_lock); + can_led_event(net, CAN_LED_EVENT_STOP); + return 0; } @@ -905,6 +911,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) if (intf & CANINTF_TX) { net->stats.tx_packets++; net->stats.tx_bytes += priv->tx_len - 1; + can_led_event(net, CAN_LED_EVENT_TX); if (priv->tx_len) { can_get_echo_skb(net, 0); priv->tx_len = 0; @@ -968,6 +975,9 @@ static int mcp251x_open(struct net_device *net) mcp251x_open_clean(net); goto open_unlock; } + + can_led_event(net, CAN_LED_EVENT_OPEN); + netif_wake_queue(net); open_unlock: @@ -1077,10 +1087,15 @@ static int mcp251x_can_probe(struct spi_device *spi) pdata->transceiver_enable(0); ret = register_candev(net); - if (!ret) { - dev_info(&spi->dev, "probed\n"); - return ret; - } + if (ret) + goto error_probe; + + devm_can_led_init(net); + + dev_info(&spi->dev, "probed\n"); + + return ret; + error_probe: if (!mcp251x_enable_dma) kfree(priv->spi_rx_buf); diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig index d38706958af6..f19be5269e7b 100644 --- a/drivers/net/can/mscan/Kconfig +++ b/drivers/net/can/mscan/Kconfig @@ -1,5 +1,5 @@ config CAN_MSCAN - depends on CAN_DEV && (PPC || M68K) + depends on PPC || M68K tristate "Support for Freescale MSCAN based chips" ---help--- The Motorola Scalable Controller Area Network (MSCAN) definition diff --git a/drivers/net/can/sja1000/Kconfig b/drivers/net/can/sja1000/Kconfig index 92f73c708a3d..b39ca5b3ea7f 100644 --- a/drivers/net/can/sja1000/Kconfig +++ b/drivers/net/can/sja1000/Kconfig @@ -1,6 +1,6 @@ menuconfig CAN_SJA1000 tristate "Philips/NXP SJA1000 devices" - depends on CAN_DEV && HAS_IOMEM + depends on HAS_IOMEM if CAN_SJA1000 @@ -99,11 +99,11 @@ config CAN_TSCAN1 tristate "TS-CAN1 PC104 boards" depends on ISA help - This driver is for Technologic Systems' TSCAN-1 PC104 boards. - http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1 - The driver supports multiple boards and automatically configures them: - PLD IO base addresses are read from jumpers JP1 and JP2, - IRQ numbers are read from jumpers JP4 and JP5, - SJA1000 IO base addresses are chosen heuristically (first that works). + This driver is for Technologic Systems' TSCAN-1 PC104 boards. + http://www.embeddedarm.com/products/board-detail.php?product=TS-CAN1 + The driver supports multiple boards and automatically configures them: + PLD IO base addresses are read from jumpers JP1 and JP2, + IRQ numbers are read from jumpers JP4 and JP5, + SJA1000 IO base addresses are chosen heuristically (first that works). endif diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 83ee11eca0e2..daf4013a8fc7 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -60,6 +60,7 @@ #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/can/led.h> #include "sja1000.h" @@ -368,6 +369,8 @@ static void sja1000_rx(struct net_device *dev) stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + + can_led_event(dev, CAN_LED_EVENT_RX); } static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) @@ -521,6 +524,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) can_get_echo_skb(dev, 0); } netif_wake_queue(dev); + can_led_event(dev, CAN_LED_EVENT_TX); } if (isrc & IRQ_RI) { /* receive interrupt */ @@ -575,6 +579,8 @@ static int sja1000_open(struct net_device *dev) /* init and start chi */ sja1000_start(dev); + can_led_event(dev, CAN_LED_EVENT_OPEN); + netif_start_queue(dev); return 0; @@ -592,6 +598,8 @@ static int sja1000_close(struct net_device *dev) close_candev(dev); + can_led_event(dev, CAN_LED_EVENT_STOP); + return 0; } @@ -639,6 +647,8 @@ static const struct net_device_ops sja1000_netdev_ops = { int register_sja1000dev(struct net_device *dev) { + int ret; + if (!sja1000_probe_chip(dev)) return -ENODEV; @@ -648,7 +658,12 @@ int register_sja1000dev(struct net_device *dev) set_reset_mode(dev); chipset_init(dev); - return register_candev(dev); + ret = register_candev(dev); + + if (!ret) + devm_can_led_init(dev); + + return ret; } EXPORT_SYMBOL_GPL(register_sja1000dev); diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index adc3708d8829..e79a8d10e0fc 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -55,6 +55,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/can.h> +#include <linux/can/skb.h> static __initconst const char banner[] = KERN_INFO "slcan: serial line CAN interface driver\n"; @@ -184,7 +185,8 @@ static void slc_bump(struct slcan *sl) cf.data[i] |= tmp; } - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = dev_alloc_skb(sizeof(struct can_frame) + + sizeof(struct can_skb_priv)); if (!skb) return; @@ -192,6 +194,10 @@ static void slc_bump(struct slcan *sl) skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb_reserve(skb, sizeof(struct can_skb_priv)); + ((struct can_skb_priv *)(skb->head))->ifindex = sl->dev->ifindex; + memcpy(skb_put(skb, sizeof(struct can_frame)), &cf, sizeof(struct can_frame)); netif_rx_ni(skb); diff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig index 5de46a9a77bb..96b6fe158b5b 100644 --- a/drivers/net/can/softing/Kconfig +++ b/drivers/net/can/softing/Kconfig @@ -1,6 +1,6 @@ config CAN_SOFTING tristate "Softing Gmbh CAN generic support" - depends on CAN_DEV && HAS_IOMEM + depends on HAS_IOMEM ---help--- Support for CAN cards from Softing Gmbh & some cards from Vector Gmbh. diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f898c6363729..f52a9755fb3e 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -50,6 +50,7 @@ #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/can/led.h> #include <linux/can/platform/ti_hecc.h> #define DRV_NAME "ti_hecc" @@ -593,6 +594,7 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno) spin_unlock_irqrestore(&priv->mbx_lock, flags); stats->rx_bytes += cf->can_dlc; + can_led_event(priv->ndev, CAN_LED_EVENT_RX); netif_receive_skb(skb); stats->rx_packets++; @@ -796,6 +798,7 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) stats->tx_bytes += hecc_read_mbx(priv, mbxno, HECC_CANMCF) & 0xF; stats->tx_packets++; + can_led_event(ndev, CAN_LED_EVENT_TX); can_get_echo_skb(ndev, mbxno); --priv->tx_tail; } @@ -851,6 +854,8 @@ static int ti_hecc_open(struct net_device *ndev) return err; } + can_led_event(ndev, CAN_LED_EVENT_OPEN); + ti_hecc_start(ndev); napi_enable(&priv->napi); netif_start_queue(ndev); @@ -869,6 +874,8 @@ static int ti_hecc_close(struct net_device *ndev) close_candev(ndev); ti_hecc_transceiver_switch(priv, 0); + can_led_event(ndev, CAN_LED_EVENT_STOP); + return 0; } @@ -961,6 +968,9 @@ static int ti_hecc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "register_candev() failed\n"); goto probe_exit_clk; } + + devm_can_led_init(ndev); + dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n", priv->base, (u32) ndev->irq); diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index a4e4bee35710..fc96a3d83ebe 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -1,5 +1,5 @@ menu "CAN USB interfaces" - depends on USB && CAN_DEV + depends on USB config CAN_EMS_USB tristate "EMS CPC-USB/ARM7 CAN/USB interface" @@ -48,4 +48,10 @@ config CAN_PEAK_USB This driver supports the PCAN-USB and PCAN-USB Pro adapters from PEAK-System Technik (http://www.peak-system.com). +config CAN_8DEV_USB + tristate "8 devices USB2CAN interface" + ---help--- + This driver supports the USB2CAN interface + from 8 devices (http://www.8devices.com). + endmenu diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 80a2ee41fd61..becef460a91a 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/ +obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c new file mode 100644 index 000000000000..f789e6f54a55 --- /dev/null +++ b/drivers/net/can/usb/usb_8dev.c @@ -0,0 +1,1033 @@ +/* + * CAN driver for "8 devices" USB2CAN converter + * + * Copyright (C) 2012 Bernd Krumboeck (krumboeck@universalnet.at) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. + * + * This driver is inspired by the 3.2.0 version of drivers/net/can/usb/ems_usb.c + * and drivers/net/can/usb/esd_usb2.c + * + * Many thanks to Gerhard Bertelsmann (info@gerhard-bertelsmann.de) + * for testing and fixing this driver. Also many thanks to "8 devices", + * who were very cooperative and answered my questions. + */ + +#include <linux/init.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/usb.h> + +#include <linux/can.h> +#include <linux/can/dev.h> |
