Merge branch 'for-davem' of git://gitorious.org/linux-can/linux-can-next

Marc Kleine-Budde says:

====================
this is a pull-request for net-next/master. There is are 9 patches by
Fabio Baltieri and Kurt Van Dijck which add LED infrastructure and
support for CAN devices. Bernd Krumboeck adds a driver for the USB CAN
adapter from 8 devices. Oliver Hartkopp improves the CAN gateway
functionality. There are 4 patches by me, which clean up the CAN's
Kconfig.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2013-01-28 00:19:34 -05:00
commit 61550022b9
27 changed files with 1488 additions and 60 deletions

View File

@ -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

View File

@ -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/

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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), &regs->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);

124
drivers/net/can/led.c Normal file
View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
#include <linux/can.h>
#include <linux/can/netlink.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
/*
* CAN mode
@ -52,6 +53,13 @@ struct can_priv {
unsigned int echo_skb_max;
struct sk_buff **echo_skb;
#ifdef CONFIG_CAN_LEDS
struct led_trigger *tx_led_trig;
char tx_led_trig_name[CAN_LED_NAME_SZ];
struct led_trigger *rx_led_trig;
char rx_led_trig_name[CAN_LED_NAME_SZ];
#endif
};
/*
@ -98,6 +106,9 @@ u8 can_len2dlc(u8 len);
struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max);
void free_candev(struct net_device *dev);
/* a candev safe wrapper around netdev_priv */
struct can_priv *safe_candev_priv(struct net_device *dev);
int open_candev(struct net_device *dev);
void close_candev(struct net_device *dev);

51
include/linux/can/led.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright 2012, Fabio Baltieri <fabio.baltieri@gmail.com>
*
* 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.
*/
#ifndef CAN_LED_H
#define CAN_LED_H
#include <linux/if.h>
#include <linux/leds.h>
enum can_led_event {
CAN_LED_EVENT_OPEN,
CAN_LED_EVENT_STOP,
CAN_LED_EVENT_TX,
CAN_LED_EVENT_RX,
};
#ifdef CONFIG_CAN_LEDS
/* keep space for interface name + "-tx"/"-rx" suffix and null terminator */
#define CAN_LED_NAME_SZ (IFNAMSIZ + 4)
void can_led_event(struct net_device *netdev, enum can_led_event event);
void devm_can_led_init(struct net_device *netdev);
int __init can_led_notifier_init(void);
void __exit can_led_notifier_exit(void);
#else
static inline void can_led_event(struct net_device *netdev,
enum can_led_event event)
{
}
static inline void devm_can_led_init(struct net_device *netdev)
{
}
static inline int can_led_notifier_init(void)
{
return 0;
}
static inline void can_led_notifier_exit(void)
{
}
#endif
#endif

35
include/linux/can/skb.h Normal file
View File

@ -0,0 +1,35 @@
/*
* linux/can/skb.h
*
* Definitions for the CAN network socket buffer
*
* Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net>
*
*/
#ifndef CAN_SKB_H
#define CAN_SKB_H
#include <linux/types.h>
#include <linux/can.h>
/*
* The struct can_skb_priv is used to transport additional information along
* with the stored struct can(fd)_frame that can not be contained in existing
* struct sk_buff elements.
* N.B. that this information must not be modified in cloned CAN sk_buffs.
* To modify the CAN frame content or the struct can_skb_priv content
* skb_copy() needs to be used instead of skb_clone().
*/
/**
* struct can_skb_priv - private additional data inside CAN sk_buffs
* @ifindex: ifindex of the first interface the CAN frame appeared on
* @cf: align to the following CAN frame at skb->data
*/
struct can_skb_priv {
int ifindex;
struct can_frame cf[0];
};
#endif /* CAN_SKB_H */

View File

@ -44,6 +44,7 @@ enum {
CGW_SRC_IF, /* ifindex of source network interface */
CGW_DST_IF, /* ifindex of destination network interface */
CGW_FILTER, /* specify struct can_filter on source CAN device */
CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */
__CGW_MAX
};
@ -51,6 +52,7 @@ enum {
#define CGW_FLAGS_CAN_ECHO 0x01
#define CGW_FLAGS_CAN_SRC_TSTAMP 0x02
#define CGW_FLAGS_CAN_IIF_TX_OK 0x04
#define CGW_MOD_FUNCS 4 /* AND OR XOR SET */

View File

@ -16,10 +16,11 @@ menuconfig CAN
If you want CAN support you should say Y here and also to the
specific driver for your controller(s) below.
if CAN
config CAN_RAW
tristate "Raw CAN Protocol (raw access with CAN-ID filtering)"
depends on CAN
default N
default y
---help---
The raw CAN protocol option offers access to the CAN bus via
the BSD socket API. You probably want to use the raw socket in
@ -29,8 +30,7 @@ config CAN_RAW
config CAN_BCM
tristate "Broadcast Manager CAN Protocol (with content filtering)"
depends on CAN
default N
default y
---help---
The Broadcast Manager offers content filtering, timeout monitoring,
sending of RTR frames, and cyclic CAN messages without permanent user
@ -42,8 +42,7 @@ config CAN_BCM
config CAN_GW
tristate "CAN Gateway/Router (with netlink configuration)"
depends on CAN
default N
default y
---help---
The CAN Gateway/Router is used to route (and modify) CAN frames.
It is based on the PF_CAN core infrastructure for msg filtering and
@ -53,3 +52,5 @@ config CAN_GW
by the netlink configuration interface known e.g. from iptables.
source "drivers/net/can/Kconfig"
endif

View File

@ -54,6 +54,7 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/skb.h>
#include <linux/can/bcm.h>
#include <linux/slab.h>
#include <net/sock.h>
@ -256,10 +257,13 @@ static void bcm_can_tx(struct bcm_op *op)
return;
}
skb = alloc_skb(CFSIZ, gfp_any());
skb = alloc_skb(CFSIZ + sizeof(struct can_skb_priv), gfp_any());
if (!skb)
goto out;
skb_reserve(skb, sizeof(struct can_skb_priv));
((struct can_skb_priv *)(skb->head))->ifindex = dev->ifindex;
memcpy(skb_put(skb, CFSIZ), cf, CFSIZ);
/* send with loopback */
@ -1199,11 +1203,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
if (!ifindex)
return -ENODEV;
skb = alloc_skb(CFSIZ, GFP_KERNEL);
skb = alloc_skb(CFSIZ + sizeof(struct can_skb_priv), GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_reserve(skb, sizeof(struct can_skb_priv));
err = memcpy_fromiovec(skb_put(skb, CFSIZ), msg->msg_iov, CFSIZ);
if (err < 0) {
kfree_skb(skb);
@ -1216,6 +1221,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
return -ENODEV;
}
((struct can_skb_priv *)(skb->head))->ifindex = dev->ifindex;
skb->dev = dev;
skb->sk = sk;
err = can_send(skb, 1); /* send with loopback */

View File

@ -42,6 +42,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
@ -52,19 +53,31 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/skb.h>
#include <linux/can/gw.h>
#include <net/rtnetlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#define CAN_GW_VERSION "20101209"
static __initconst const char banner[] =
KERN_INFO "can: netlink gateway (rev " CAN_GW_VERSION ")\n";
#define CAN_GW_VERSION "20130117"
#define CAN_GW_NAME "can-gw"
MODULE_DESCRIPTION("PF_CAN netlink gateway");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
MODULE_ALIAS("can-gw");
MODULE_ALIAS(CAN_GW_NAME);
#define CGW_MIN_HOPS 1
#define CGW_MAX_HOPS 6
#define CGW_DEFAULT_HOPS 1
static unsigned int max_hops __read_mostly = CGW_DEFAULT_HOPS;
module_param(max_hops, uint, S_IRUGO);
MODULE_PARM_DESC(max_hops,
"maximum " CAN_GW_NAME " routing hops for CAN frames "
"(valid values: " __stringify(CGW_MIN_HOPS) "-"
__stringify(CGW_MAX_HOPS) " hops, "
"default: " __stringify(CGW_DEFAULT_HOPS) ")");
static HLIST_HEAD(cgw_list);
static struct notifier_block notifier;
@ -118,6 +131,7 @@ struct cgw_job {
struct rcu_head rcu;
u32 handled_frames;
u32 dropped_frames;
u32 deleted_frames;
struct cf_mod mod;
union {
/* CAN frame data source */
@ -338,15 +352,40 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
struct sk_buff *nskb;
int modidx = 0;
/* do not handle already routed frames - see comment below */
if (skb_mac_header_was_set(skb))
/*
* Do not handle CAN frames routed more than 'max_hops' times.
* In general we should never catch this delimiter which is intended
* to cover a misconfiguration protection (e.g. circular CAN routes).
*
* The Controller Area Network controllers only accept CAN frames with
* correct CRCs - which are not visible in the controller registers.
* According to skbuff.h documentation the csum_start element for IP
* checksums is undefined/unsued when ip_summed == CHECKSUM_UNNECESSARY.
* Only CAN skbs can be processed here which already have this property.
*/
#define cgw_hops(skb) ((skb)->csum_start)
BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY);
if (cgw_hops(skb) >= max_hops) {
/* indicate deleted frames due to misconfiguration */
gwj->deleted_frames++;
return;
}
if (!(gwj->dst.dev->flags & IFF_UP)) {
gwj->dropped_frames++;
return;
}
/* is sending the skb back to the incoming interface not allowed? */
if (!(gwj->flags & CGW_FLAGS_CAN_IIF_TX_OK) &&
skb_headroom(skb) == sizeof(struct can_skb_priv) &&
(((struct can_skb_priv *)(skb->head))->ifindex ==
gwj->dst.dev->ifindex))
return;
/*
* clone the given skb, which has not been done in can_rcv()
*
@ -363,15 +402,8 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
return;
}
/*
* Mark routed frames by setting some mac header length which is
* not relevant for the CAN frames located in the skb->data section.
*
* As dev->header_ops is not set in CAN netdevices no one is ever
* accessing the various header offsets in the CAN skbuffs anyway.
* E.g. using the packet socket to read CAN frames is still working.
*/
skb_set_mac_header(nskb, 8);
/* put the incremented hop counter in the cloned skb */
cgw_hops(nskb) = cgw_hops(skb) + 1;
nskb->dev = gwj->dst.dev;
/* pointer to modifiable CAN frame */
@ -472,6 +504,11 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type,
goto cancel;
}
if (gwj->deleted_frames) {
if (nla_put_u32(skb, CGW_DELETED, gwj->deleted_frames) < 0)
goto cancel;
}
/* check non default settings of attributes */
if (gwj->mod.modtype.and) {
@ -771,6 +808,7 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,
gwj->handled_frames = 0;
gwj->dropped_frames = 0;
gwj->deleted_frames = 0;
gwj->flags = r->flags;
gwj->gwtype = r->gwtype;
@ -895,7 +933,11 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
static __init int cgw_module_init(void)
{
printk(banner);
/* sanitize given module parameter */
max_hops = clamp_t(unsigned int, max_hops, CGW_MIN_HOPS, CGW_MAX_HOPS);
pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n",
max_hops);
cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job),
0, 0, NULL);

View File

@ -50,6 +50,7 @@
#include <linux/skbuff.h>
#include <linux/can.h>
#include <linux/can/core.h>
#include <linux/can/skb.h>
#include <linux/can/raw.h>
#include <net/sock.h>
#include <net/net_namespace.h>
@ -699,11 +700,14 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
if (!dev)
return -ENXIO;
skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
&err);
skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
goto put_dev;
skb_reserve(skb, sizeof(struct can_skb_priv));
((struct can_skb_priv *)(skb->head))->ifindex = dev->ifindex;
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err < 0)
goto free_skb;