Patchwork [3/8] can: CAN Network device driver and SYSFS interface

login
register
mail settings
Submitter Wolfgang Grandegger
Date Feb. 19, 2009, 7:01 p.m.
Message ID <1235070082-7069-4-git-send-email-wg@grandegger.com>
Download mbox | patch
Permalink /patch/23440/
State Changes Requested
Delegated to: David Miller
Headers show

Comments

Wolfgang Grandegger - Feb. 19, 2009, 7:01 p.m.
The CAN network device driver interface provides a generic interface to
setup, configure and monitor CAN network devices. It exports a set of
common data structures and functions, which all real CAN network device
drivers should use. Please have a look to the SJA1000 or MSCAN driver
to understand how to use them. The name of the module is can-dev.ko.

Furthermore adds a SYSFS interface to set and get CAN device properties.
When the CAN device is registered, a set of SYSFS files is created in
"/sys/class/net/canX/". These files allow to set and get device
properties like bit-timing parameters, state, controller mode and CAN
statistics.

For further information please check "Documentation/networking/can.txt"

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
---
 drivers/net/can/Kconfig  |   23 ++
 drivers/net/can/Makefile |    5 +
 drivers/net/can/dev.c    |  528 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/can/sysfs.c  |  509 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/can/sysfs.h  |   24 ++
 include/linux/can/dev.h  |  136 ++++++++++++
 6 files changed, 1225 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/dev.c
 create mode 100644 drivers/net/can/sysfs.c
 create mode 100644 drivers/net/can/sysfs.h
 create mode 100644 include/linux/can/dev.h
Jonathan Corbet - Feb. 19, 2009, 11:49 p.m.
On Thu, 19 Feb 2009 20:01:17 +0100
Wolfgang Grandegger <wg@grandegger.com> wrote:

> +/*
> + * Bit-timing calculation derived from:
> + *
> + * Code based on LinCAN sources and H8S2638 project
> + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
> + * Copyright 2005      Stanislav Marek
> + * email: pisa@cmp.felk.cvut.cz
> + */
> +static int can_update_spt(const struct can_bittiming_const *btc,
> +			  int sampl_pt, int tseg, int *tseg1, int *tseg2)
> +{
> +	*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
> +	if (*tseg2 < btc->tseg2_min)
> +		*tseg2 = btc->tseg2_min;
> +	if (*tseg2 > btc->tseg2_max)
> +		*tseg2 = btc->tseg2_max;
> +	*tseg1 = tseg - *tseg2;
> +	if (*tseg1 > btc->tseg1_max) {
> +		*tseg1 = btc->tseg1_max;
> +		*tseg2 = tseg - *tseg1;
> +	}
> +	return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
> +}

I can only assume that this calculation means something to somebody.  I
guess there's no hope for those of use too lazy to go read the Bosch spec,
where, I assume, this kind of stuff is described.

> +static int can_calc_bittiming(struct net_device *dev)

This function, too, is pretty well impenetrable.  I couldn't possibly try
to tell you if it's even remotely correct.  Some comments might be nice.

> +/*
> + * Allocate and setup space for the CAN network device
> + */
> +struct net_device *alloc_candev(int sizeof_priv)
> +{
> +	struct net_device *dev;
> +	struct can_priv *priv;
> +
> +	dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
> +	if (!dev)
> +		return NULL;
> +
> +	priv = netdev_priv(dev);
> +
> +	priv->state = CAN_STATE_STOPPED;
> +	spin_lock_init(&priv->irq_lock);

This is the first mention I see of a lock in this file.  What are your
locking rules?  There doesn't seem to be a lot of locking going on...  In
particular, nothing in this file uses irq_lock.

> +	init_timer(&priv->timer);
> +	priv->timer.expires = 0;
> +
> +	return dev;
> +}
> +EXPORT_SYMBOL_GPL(alloc_candev);

> +/*
> + * Allocate space of the CAN network device
> + */
> +void free_candev(struct net_device *dev)
> +{
> +	free_netdev(dev);
> +}
> +EXPORT_SYMBOL_GPL(free_candev);

I do believe that function is *freeing* space...?  

The allocation function initializes a timer, but here we do nothing to
ensure that the timer is not running.  Is there a rule somewhere that I
missed?

> +/*
> + * Local echo of CAN messages
> + *
> + * CAN network devices *should* support a local echo functionality
> + * (see Documentation/networking/can.txt). To test the handling of CAN
> + * interfaces that do not support the local echo both driver types are
> + * implemented. In the case that the driver does not support the echo
> + * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
> + * to perform the echo as a fallback solution.
> + */
> +
> +static void can_flush_echo_skb(struct net_device *dev)
> +{
> +	struct can_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	int i;
> +
> +	for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
> +		if (priv->echo_skb[i]) {
> +			kfree_skb(priv->echo_skb[i]);
> +			priv->echo_skb[i] = NULL;
> +			stats->tx_dropped++;
> +			stats->tx_aborted_errors++;
> +		}
> +	}
> +}

What lock is protecting priv->echo_skb?

> +/*
> + * Put the skb on the stack to be looped backed locally lateron
> + *
> + * The function is typically called in the start_xmit function
> + * of the device driver.
> + */
> +void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
> +{
> +	struct can_priv *priv = netdev_priv(dev);
> +
> +	/* set flag whether this packet has to be looped back */
> +	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
> +		kfree_skb(skb);
> +		return;
> +	}

The comment says "set flag", but the code potentially frees the skb and aborts.

[...]

> +/*
> + * CAN device restart for bus-off recovery
> + */
> +int can_restart_now(struct net_device *dev)
> +{
> +	struct can_priv *priv = netdev_priv(dev);
> +	struct net_device_stats *stats = &dev->stats;
> +	struct sk_buff *skb;
> +	struct can_frame *cf;
> +	int err;
> +
> +	if (netif_carrier_ok(dev))
> +		netif_carrier_off(dev);
> +
> +	/* Cancel restart in progress */
> +	if (priv->timer.expires) {
> +		del_timer(&priv->timer);
> +		priv->timer.expires = 0; /* mark inactive timer */
> +	}

Are you sure you don't want del_timer_sync() there?  What keeps you from
racing with the timer?

[...]

> +/*
> + * Cleanup function before the device gets closed.
> + *
> + * This functions should be called in the close function of the device
> + * driver.
> + */
> +void can_close_cleanup(struct net_device *dev)
> +{
> +	struct can_priv *priv = netdev_priv(dev);
> +
> +	if (priv->timer.expires) {
> +		del_timer(&priv->timer);
> +		priv->timer.expires = 0;
> +	}
> +
> +	can_flush_echo_skb(dev);
> +}
> +EXPORT_SYMBOL_GPL(can_close_cleanup);

You definitely want del_timer_sync() here.  You could potentially return
with the timer still running.

> diff --git a/drivers/net/can/sysfs.c b/drivers/net/can/sysfs.c
> new file mode 100644
> index 0000000..746f641
> --- /dev/null
> +++ b/drivers/net/can/sysfs.c

Most of this file looks like typical sysfs cruft.  Again, though, I wonder
about your locking...

> +/* use same locking rules as GIF* ioctl's */
> +static ssize_t can_dev_show(struct device *d,
> +			    struct device_attribute *attr, char *buf,
> +			    ssize_t (*fmt)(struct net_device *, char *))
> +{
> +	struct net_device *dev = to_net_dev(d);
> +	ssize_t ret = -EINVAL;
> +
> +	read_lock(&dev_base_lock);
> +	if (dev_isalive(dev))
> +		ret = (*fmt)(dev, buf);
> +	read_unlock(&dev_base_lock);
> +
> +	return ret;
> +}

I'm not sure what the GIF* ioctl() locking rules are, but do they really
give you properly-serialized access to your device?  dev_base_lock seems
like an unlikely choice, somehow, but maybe I'm missing something.

[...]

> +/* use same locking and permission rules as SIF* ioctl's */
> +static ssize_t can_dev_store(struct device *d, struct device_attribute *attr,
> +			     const char *buf, size_t len,
> +			     int (*set)(struct net_device *, unsigned long))
> +{
> +	struct net_device *dev = to_net_dev(d);
> +	unsigned long new;
> +	int ret = -EINVAL;
> +
> +	if (!capable(CAP_NET_ADMIN))
> +		return -EPERM;
> +
> +	ret = strict_strtoul(buf, 0, &new);
> +	if (ret)
> +		goto out;
> +
> +	rtnl_lock();
> +	if (dev_isalive(dev)) {
> +		ret = (*set)(dev, new);
> +		if (!ret)
> +			ret = len;
> +	}
> +	rtnl_unlock();
> +out:
> +	return ret;
> +}

Here we're using a different (global) lock?  Me confused...

[...]

> diff --git a/drivers/net/can/sysfs.h b/drivers/net/can/sysfs.h
> new file mode 100644
> index 0000000..e21f2fa
> --- /dev/null
> +++ b/drivers/net/can/sysfs.h
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + *
> + * 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; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +#ifndef CAN_SYSFS_H
> +#define CAN_SYSFS_H
> +
> +void can_create_sysfs(struct net_device *dev);
> +void can_remove_sysfs(struct net_device *dev);
> +
> +#endif /* CAN_SYSFS_H */
> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
> new file mode 100644
> index 0000000..078ac03
> --- /dev/null
> +++ b/include/linux/can/dev.h
> @@ -0,0 +1,136 @@
> +/*
> + * linux/can/dev.h
> + *
> + * Definitions for the CAN network device driver interface
> + *
> + * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
> + *               Varma Electronics Oy
> + *
> + * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>

Nothing in 2009? :)

> + *
> + * Send feedback to <socketcan-users@lists.berlios.de>
> + */
> +
> +#ifndef CAN_DEV_H
> +#define CAN_DEV_H
> +
> +#include <linux/can/error.h>
> +
> +/*
> + * CAN bitrate and bit-timing
> + */
> +struct can_bittiming {
> +	u32 bitrate;
> +	u32 sample_point;
> +	u32 tq;
> +	u32 prop_seg;
> +	u32 phase_seg1;
> +	u32 phase_seg2;
> +	u32 sjw;
> +	u32 clock;
> +	u32 brp;
> +};

It sure would be nice (again) to know what all these parameters are.

> +struct can_bittiming_const {
> +	u32 tseg1_min;
> +	u32 tseg1_max;
> +	u32 tseg2_min;
> +	u32 tseg2_max;
> +	u32 sjw_max;
> +	u32 brp_min;
> +	u32 brp_max;
> +	u32 brp_inc;
> +};

Ditto.

[...]

> +/*
> + * CAN common private data
> + */
> +#define CAN_ECHO_SKB_MAX  4
> +
> +struct can_priv {
> +	struct can_device_stats can_stats;
> +
> +	struct can_bittiming bittiming;
> +	struct can_bittiming_const *bittiming_const;
> +
> +	spinlock_t irq_lock;

...protecting what...?

> +	enum can_state state;
> +	u32 ctrlmode;
> +
> +	int restart_ms;
> +	struct timer_list timer;
> +
> +	struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
> +
> +	int (*do_set_bittiming)(struct net_device *dev);
> +	int (*do_get_state)(struct net_device *dev, enum can_state *state);
> +	int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
> +	int (*do_set_ctrlmode)(struct net_device *dev, u32 ctrlmode);
> +	int (*do_get_ctrlmode)(struct net_device *dev, u32 *ctrlmode);
> +};
> +
> +#define ND2D(_ndev)	(_ndev->dev.parent)

Does this macro really improve the clarity of the code?

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfgang Grandegger - Feb. 20, 2009, 8:39 a.m.
Jonathan Corbet wrote:
> On Thu, 19 Feb 2009 20:01:17 +0100
> Wolfgang Grandegger <wg@grandegger.com> wrote:
> 
>> +/*
>> + * Bit-timing calculation derived from:
>> + *
>> + * Code based on LinCAN sources and H8S2638 project
>> + * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
>> + * Copyright 2005      Stanislav Marek
>> + * email: pisa@cmp.felk.cvut.cz
>> + */
>> +static int can_update_spt(const struct can_bittiming_const *btc,
>> +			  int sampl_pt, int tseg, int *tseg1, int *tseg2)
>> +{
>> +	*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
>> +	if (*tseg2 < btc->tseg2_min)
>> +		*tseg2 = btc->tseg2_min;
>> +	if (*tseg2 > btc->tseg2_max)
>> +		*tseg2 = btc->tseg2_max;
>> +	*tseg1 = tseg - *tseg2;
>> +	if (*tseg1 > btc->tseg1_max) {
>> +		*tseg1 = btc->tseg1_max;
>> +		*tseg2 = tseg - *tseg1;
>> +	}
>> +	return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
>> +}
> 
> I can only assume that this calculation means something to somebody.  I
> guess there's no hope for those of use too lazy to go read the Bosch spec,
> where, I assume, this kind of stuff is described.

The purpose and quirks of this bit-timing calculation are described
briefly in the Kconfig entry for CONFIG_CAN_CALC_BITTIMING and in
Documentation/networking/can.txt which I quote below:

 "6.5.2 Setting the CAN bit-timing

  The CAN bit-timing parameters can always be specified in a hardware
  independent format as proposed in the Bosch CAN 2.0 specification
  using the SYSFS files "tq", "prop_seg", "phase_seg1", "phase_seg2"
  and "sjw". The SYSFS files are described in the previous chapter.

  If the kernel option CONFIG_CAN_CALC_BITTIMING is enabled, CIA
  recommended CAN bit-timing parameters will be calculated for the bit-
  rate written to the SYSFS file "bitrate" when the device gets started.
  Note that this works fine for the most common CAN controllers with
  standard bit-rates but may *fail* for exotic bit-rates or CAN source
  clock frequencies. Disabling CONFIG_CAN_CALC_BITTIMING saves some
  space and allows user space tools to solely determine and set the
  bit-timing parameters. The CAN controller specific bit-timing
  constants can be used for that purpose. They are available in the
  SYSFS directory "can_bittiming" as well with the name prefix "hw_"."

The user just sets the bit-rate and this function will determine proper
bit-timing parameters.

>> +static int can_calc_bittiming(struct net_device *dev)
> 
> This function, too, is pretty well impenetrable.  I couldn't possibly try
> to tell you if it's even remotely correct.  Some comments might be nice.

Unfortunately, there are no simple speed settings like 100 bps FD for
Ethernet. Setting proper CAN bit-timing might be tricky and in rare
cases you even may need the help of a real CAN expert, including myself
:-(. Furthermore, setting the hardware bit-timing is very hardware
*dependent* and we tried to address this issue using a hardware
*independent* format as proposed by the Bosch specification. Well, maybe
I should document our approach in more detail.

>> +/*
>> + * Allocate and setup space for the CAN network device
>> + */
>> +struct net_device *alloc_candev(int sizeof_priv)
>> +{
>> +	struct net_device *dev;
>> +	struct can_priv *priv;
>> +
>> +	dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
>> +	if (!dev)
>> +		return NULL;
>> +
>> +	priv = netdev_priv(dev);
>> +
>> +	priv->state = CAN_STATE_STOPPED;
>> +	spin_lock_init(&priv->irq_lock);
> 
> This is the first mention I see of a lock in this file.  What are your
> locking rules?  There doesn't seem to be a lot of locking going on...  In
> particular, nothing in this file uses irq_lock.

I see, the locking needs some more careful analysis. Thanks for pointing
that out.

> 
>> +	init_timer(&priv->timer);
>> +	priv->timer.expires = 0;
>> +
>> +	return dev;
>> +}
>> +EXPORT_SYMBOL_GPL(alloc_candev);
> 
>> +/*
>> + * Allocate space of the CAN network device
>> + */
>> +void free_candev(struct net_device *dev)
>> +{
>> +	free_netdev(dev);
>> +}
>> +EXPORT_SYMBOL_GPL(free_candev);
> 
> I do believe that function is *freeing* space...?  

Of course, will fix.

> The allocation function initializes a timer, but here we do nothing to
> ensure that the timer is not running.  Is there a rule somewhere that I
> missed?

If the device is freed when its still open, the network layer calls the
close function of the device, which will do to proper cleanup including
deleting the timer.

>> +/*
>> + * Local echo of CAN messages
>> + *
>> + * CAN network devices *should* support a local echo functionality
>> + * (see Documentation/networking/can.txt). To test the handling of CAN
>> + * interfaces that do not support the local echo both driver types are
>> + * implemented. In the case that the driver does not support the echo
>> + * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
>> + * to perform the echo as a fallback solution.
>> + */
>> +
>> +static void can_flush_echo_skb(struct net_device *dev)
>> +{
>> +	struct can_priv *priv = netdev_priv(dev);
>> +	struct net_device_stats *stats = &dev->stats;
>> +	int i;
>> +
>> +	for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
>> +		if (priv->echo_skb[i]) {
>> +			kfree_skb(priv->echo_skb[i]);
>> +			priv->echo_skb[i] = NULL;
>> +			stats->tx_dropped++;
>> +			stats->tx_aborted_errors++;
>> +		}
>> +	}
>> +}
> 
> What lock is protecting priv->echo_skb?

This code is called when the device is stopped, but I need to double-check.

> 
>> +/*
>> + * Put the skb on the stack to be looped backed locally lateron
>> + *
>> + * The function is typically called in the start_xmit function
>> + * of the device driver.
>> + */
>> +void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
>> +{
>> +	struct can_priv *priv = netdev_priv(dev);
>> +
>> +	/* set flag whether this packet has to be looped back */
>> +	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
>> +		kfree_skb(skb);
>> +		return;
>> +	}
> 
> The comment says "set flag", but the code potentially frees the skb and aborts.

Will fix the comment.

> [...]
> 
>> +/*
>> + * CAN device restart for bus-off recovery
>> + */
>> +int can_restart_now(struct net_device *dev)
>> +{
>> +	struct can_priv *priv = netdev_priv(dev);
>> +	struct net_device_stats *stats = &dev->stats;
>> +	struct sk_buff *skb;
>> +	struct can_frame *cf;
>> +	int err;
>> +
>> +	if (netif_carrier_ok(dev))
>> +		netif_carrier_off(dev);
>> +
>> +	/* Cancel restart in progress */
>> +	if (priv->timer.expires) {
>> +		del_timer(&priv->timer);
>> +		priv->timer.expires = 0; /* mark inactive timer */
>> +	}
> 
> Are you sure you don't want del_timer_sync() there?  What keeps you from
> racing with the timer?

Right, will fix.

> [...]
> 
>> +/*
>> + * Cleanup function before the device gets closed.
>> + *
>> + * This functions should be called in the close function of the device
>> + * driver.
>> + */
>> +void can_close_cleanup(struct net_device *dev)
>> +{
>> +	struct can_priv *priv = netdev_priv(dev);
>> +
>> +	if (priv->timer.expires) {
>> +		del_timer(&priv->timer);
>> +		priv->timer.expires = 0;
>> +	}
>> +
>> +	can_flush_echo_skb(dev);
>> +}
>> +EXPORT_SYMBOL_GPL(can_close_cleanup);
> 
> You definitely want del_timer_sync() here.  You could potentially return
> with the timer still running.
> 
>> diff --git a/drivers/net/can/sysfs.c b/drivers/net/can/sysfs.c
>> new file mode 100644
>> index 0000000..746f641
>> --- /dev/null
>> +++ b/drivers/net/can/sysfs.c
> 
> Most of this file looks like typical sysfs cruft.  Again, though, I wonder
> about your locking...
> 
>> +/* use same locking rules as GIF* ioctl's */
>> +static ssize_t can_dev_show(struct device *d,
>> +			    struct device_attribute *attr, char *buf,
>> +			    ssize_t (*fmt)(struct net_device *, char *))
>> +{
>> +	struct net_device *dev = to_net_dev(d);
>> +	ssize_t ret = -EINVAL;
>> +
>> +	read_lock(&dev_base_lock);
>> +	if (dev_isalive(dev))
>> +		ret = (*fmt)(dev, buf);
>> +	read_unlock(&dev_base_lock);
>> +
>> +	return ret;
>> +}
> 
> I'm not sure what the GIF* ioctl() locking rules are, but do they really
> give you properly-serialized access to your device?  dev_base_lock seems
> like an unlikely choice, somehow, but maybe I'm missing something.

This locking code is from

http://lxr.linux.no/linux+v2.6.28.6/net/core/net-sysfs.c#L34

accessing SYSFS files for the network device in a similar way.

> [...]
> 
>> +/* use same locking and permission rules as SIF* ioctl's */
>> +static ssize_t can_dev_store(struct device *d, struct device_attribute *attr,
>> +			     const char *buf, size_t len,
>> +			     int (*set)(struct net_device *, unsigned long))
>> +{
>> +	struct net_device *dev = to_net_dev(d);
>> +	unsigned long new;
>> +	int ret = -EINVAL;
>> +
>> +	if (!capable(CAP_NET_ADMIN))
>> +		return -EPERM;
>> +
>> +	ret = strict_strtoul(buf, 0, &new);
>> +	if (ret)
>> +		goto out;
>> +
>> +	rtnl_lock();
>> +	if (dev_isalive(dev)) {
>> +		ret = (*set)(dev, new);
>> +		if (!ret)
>> +			ret = len;
>> +	}
>> +	rtnl_unlock();
>> +out:
>> +	return ret;
>> +}
> 
> Here we're using a different (global) lock?  Me confused...

See http://lxr.linux.no/linux+v2.6.28.6/net/core/net-sysfs.c#L63

> 
> [...]
> 
>> diff --git a/drivers/net/can/sysfs.h b/drivers/net/can/sysfs.h
>> new file mode 100644
>> index 0000000..e21f2fa
>> --- /dev/null
>> +++ b/drivers/net/can/sysfs.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the version 2 of the GNU General Public License
>> + * as published by the Free Software Foundation
>> + *
>> + * 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; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>> + */
>> +
>> +#ifndef CAN_SYSFS_H
>> +#define CAN_SYSFS_H
>> +
>> +void can_create_sysfs(struct net_device *dev);
>> +void can_remove_sysfs(struct net_device *dev);
>> +
>> +#endif /* CAN_SYSFS_H */
>> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
>> new file mode 100644
>> index 0000000..078ac03
>> --- /dev/null
>> +++ b/include/linux/can/dev.h
>> @@ -0,0 +1,136 @@
>> +/*
>> + * linux/can/dev.h
>> + *
>> + * Definitions for the CAN network device driver interface
>> + *
>> + * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
>> + *               Varma Electronics Oy
>> + *
>> + * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
> 
> Nothing in 2009? :)

Will fix.

> 
>> + *
>> + * Send feedback to <socketcan-users@lists.berlios.de>
>> + */
>> +
>> +#ifndef CAN_DEV_H
>> +#define CAN_DEV_H
>> +
>> +#include <linux/can/error.h>
>> +
>> +/*
>> + * CAN bitrate and bit-timing
>> + */
>> +struct can_bittiming {
>> +	u32 bitrate;
>> +	u32 sample_point;
>> +	u32 tq;
>> +	u32 prop_seg;
>> +	u32 phase_seg1;
>> +	u32 phase_seg2;
>> +	u32 sjw;
>> +	u32 clock;
>> +	u32 brp;
>> +};
> 
> It sure would be nice (again) to know what all these parameters are.
> 
>> +struct can_bittiming_const {
>> +	u32 tseg1_min;
>> +	u32 tseg1_max;
>> +	u32 tseg2_min;
>> +	u32 tseg2_max;
>> +	u32 sjw_max;
>> +	u32 brp_min;
>> +	u32 brp_max;
>> +	u32 brp_inc;
>> +};
> 
> Ditto.

OK, will add some documentation.

> [...]
> 
>> +/*
>> + * CAN common private data
>> + */
>> +#define CAN_ECHO_SKB_MAX  4
>> +
>> +struct can_priv {
>> +	struct can_device_stats can_stats;
>> +
>> +	struct can_bittiming bittiming;
>> +	struct can_bittiming_const *bittiming_const;
>> +
>> +	spinlock_t irq_lock;
> 
> ...protecting what...?

This is not OK, indeed. It is currently just used by the  SJA1000
driver. Either it can be moved to the SJA1000 private struct or it is
required for some missing locking. I will check.

>> +	enum can_state state;
>> +	u32 ctrlmode;
>> +
>> +	int restart_ms;
>> +	struct timer_list timer;
>> +
>> +	struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
>> +
>> +	int (*do_set_bittiming)(struct net_device *dev);
>> +	int (*do_get_state)(struct net_device *dev, enum can_state *state);
>> +	int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
>> +	int (*do_set_ctrlmode)(struct net_device *dev, u32 ctrlmode);
>> +	int (*do_get_ctrlmode)(struct net_device *dev, u32 *ctrlmode);
>> +};
>> +
>> +#define ND2D(_ndev)	(_ndev->dev.parent)
> 
> Does this macro really improve the clarity of the code?

IMO, yes, but a more descriptive name should be used, e.g. NDEV2DEV.

Thanks,

Wolfgang.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy - Feb. 20, 2009, 9:44 a.m.
Wolfgang Grandegger wrote:
> The CAN network device driver interface provides a generic interface to
> setup, configure and monitor CAN network devices. It exports a set of
> common data structures and functions, which all real CAN network device
> drivers should use. Please have a look to the SJA1000 or MSCAN driver
> to understand how to use them. The name of the module is can-dev.ko.
> 
> Furthermore adds a SYSFS interface to set and get CAN device properties.
> When the CAN device is registered, a set of SYSFS files is created in
> "/sys/class/net/canX/". These files allow to set and get device
> properties like bit-timing parameters, state, controller mode and CAN
> statistics.

Is sysfs really the best choice for this? It has the usual problems,
you can't change multiple parameters at once atomically. Now, I don't
know whether this is actually (and currently) a problem for CAN, but
given that we already have a generic netlink interface for creating
network interfaces that can easily support this, what are the reasons
for adding a new interface instead of using the existing one?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfgang Grandegger - Feb. 21, 2009, 3:09 p.m.
Patrick McHardy wrote:
> Wolfgang Grandegger wrote:
>> The CAN network device driver interface provides a generic interface to
>> setup, configure and monitor CAN network devices. It exports a set of
>> common data structures and functions, which all real CAN network device
>> drivers should use. Please have a look to the SJA1000 or MSCAN driver
>> to understand how to use them. The name of the module is can-dev.ko.
>>
>> Furthermore adds a SYSFS interface to set and get CAN device properties.
>> When the CAN device is registered, a set of SYSFS files is created in
>> "/sys/class/net/canX/". These files allow to set and get device
>> properties like bit-timing parameters, state, controller mode and CAN
>> statistics.
> 
> Is sysfs really the best choice for this? It has the usual problems,
> you can't change multiple parameters at once atomically. Now, I don't
> know whether this is actually (and currently) a problem for CAN, but
> given that we already have a generic netlink interface for creating
> network interfaces that can easily support this, what are the reasons
> for adding a new interface instead of using the existing one?

You refer to the API described at http://lwn.net/Articles/236919/, I
assume. Well, I know that netlink is used to define routes in the kernel
or VLANs but I was not aware that it can also be used to configure real
network devices. What a pity. At a first glance, I could also be used
for CAN, of course. There are the following requirements:

1. Set and get CAN device properties like bit-rate and controller mode.
2. Show CAN bus state (active, error-passive or bus-off).
3. Get device constants like clock frequency and bit-timing parameters.
4. Dump CAN device statistics.
5. Trigger device restart if CAN bus-off state has been detected.

Not sure yet, if the interface if good for all purposes. Especially
point 5. might be better handled by an IOCTL. And we need a user space
tool, e.g. canconfig, to handle the user requests and communicate with
the kernel side. We will follow that promising route. Any further help
or link is appreciated. Thanks.

Wolfgang.



--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy - Feb. 23, 2009, 9:55 a.m.
Wolfgang Grandegger wrote:
> Patrick McHardy wrote:
>> Is sysfs really the best choice for this? It has the usual problems,
>> you can't change multiple parameters at once atomically. Now, I don't
>> know whether this is actually (and currently) a problem for CAN, but
>> given that we already have a generic netlink interface for creating
>> network interfaces that can easily support this, what are the reasons
>> for adding a new interface instead of using the existing one?
> 
> You refer to the API described at http://lwn.net/Articles/236919/, I
> assume.

Exactly.

> Well, I know that netlink is used to define routes in the kernel
> or VLANs but I was not aware that it can also be used to configure real
> network devices. What a pity. At a first glance, I could also be used
> for CAN, of course. There are the following requirements:
> 
> 1. Set and get CAN device properties like bit-rate and controller mode.
> 2. Show CAN bus state (active, error-passive or bus-off).
> 3. Get device constants like clock frequency and bit-timing parameters.
> 4. Dump CAN device statistics.
> 5. Trigger device restart if CAN bus-off state has been detected.
> 
> Not sure yet, if the interface if good for all purposes. Especially
> point 5. might be better handled by an IOCTL.

The first points sound pretty regular. The last one - just triggering
it is no problem of course, but since I don't know how the detection
works, I can't really tell whether its suitable.

> And we need a user space
> tool, e.g. canconfig, to handle the user requests and communicate with
> the kernel side.

Thats pretty standard :)

> We will follow that promising route. Any further help
> or link is appreciated. Thanks.

It should be quite easy to move your interface on top. A few examples
that might be useful are vlan, ip_gre and macvlan.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfgang Grandegger - Feb. 23, 2009, 2:57 p.m.
Patrick McHardy wrote:
> Wolfgang Grandegger wrote:
>> Patrick McHardy wrote:
>>> Is sysfs really the best choice for this? It has the usual problems,
>>> you can't change multiple parameters at once atomically. Now, I don't
>>> know whether this is actually (and currently) a problem for CAN, but
>>> given that we already have a generic netlink interface for creating
>>> network interfaces that can easily support this, what are the reasons
>>> for adding a new interface instead of using the existing one?
>>
>> You refer to the API described at http://lwn.net/Articles/236919/, I
>> assume.
> 
> Exactly.
> 
>> Well, I know that netlink is used to define routes in the kernel
>> or VLANs but I was not aware that it can also be used to configure real
>> network devices. What a pity. At a first glance, I could also be used
>> for CAN, of course. There are the following requirements:
>>
>> 1. Set and get CAN device properties like bit-rate and controller mode.
>> 2. Show CAN bus state (active, error-passive or bus-off).
>> 3. Get device constants like clock frequency and bit-timing parameters.
>> 4. Dump CAN device statistics.
>> 5. Trigger device restart if CAN bus-off state has been detected.
>>
>> Not sure yet, if the interface if good for all purposes. Especially
>> point 5. might be better handled by an IOCTL.
> 
> The first points sound pretty regular. The last one - just triggering
> it is no problem of course, but since I don't know how the detection
> works, I can't really tell whether its suitable.

CAN errors and state changes might be delivered as CAN error messages to
the receiving socket/application, like normal messages. When the
application realizes the state change to CAN bus-off, it may want to
trigger a bus-off recovery (controller restart). The CAN controller HW
enters bus-off, when too much errors occurred on the bus. No more
messages can then be sent of received and therefore the driver calls
netif_carrier_off(). Is there already an interface for the user to
restart? An appropriate IOCTL request would be a simply option, but they
are generally deprecated, AFAIK. Using netlink would be more cumbersome,
as with SYSFS.

>> And we need a user space
>> tool, e.g. canconfig, to handle the user requests and communicate with
>> the kernel side.
> 
> Thats pretty standard :)

For the iproute2 utility "ip", mainliy a netlink_can.c would be
required. But a dedicated tool for CAN seems more appropriate to me.

>> We will follow that promising route. Any further help
>> or link is appreciated. Thanks.
> 
> It should be quite easy to move your interface on top. A few examples
> that might be useful are vlan, ip_gre and macvlan.

Also the drivers dummy and ipb are quite useful. Using netlink seems
straight-forward, indeed, but it requires still some effort. Hope to
find some time soon.

Wolfgang.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Patrick McHardy - Feb. 24, 2009, 9:38 a.m.
Wolfgang Grandegger wrote:
>>> 1. Set and get CAN device properties like bit-rate and controller mode.
>>> 2. Show CAN bus state (active, error-passive or bus-off).
>>> 3. Get device constants like clock frequency and bit-timing parameters.
>>> 4. Dump CAN device statistics.
>>> 5. Trigger device restart if CAN bus-off state has been detected.
>>>
>>> Not sure yet, if the interface if good for all purposes. Especially
>>> point 5. might be better handled by an IOCTL.
>> The first points sound pretty regular. The last one - just triggering
>> it is no problem of course, but since I don't know how the detection
>> works, I can't really tell whether its suitable.
> 
> CAN errors and state changes might be delivered as CAN error messages to
> the receiving socket/application, like normal messages. When the
> application realizes the state change to CAN bus-off, it may want to
> trigger a bus-off recovery (controller restart). The CAN controller HW
> enters bus-off, when too much errors occurred on the bus. No more
> messages can then be sent of received and therefore the driver calls
> netif_carrier_off(). Is there already an interface for the user to
> restart? An appropriate IOCTL request would be a simply option, but they
> are generally deprecated, AFAIK. Using netlink would be more cumbersome,
> as with SYSFS.

You could consider triggering the restart automatically, similar
to the netdev watchdog. In fact, you could simply use that one.
If you really want to trigger this from userspace, setting the
device DOWN and UP again seems like the most appropriate way to
me (even though not very nice to use from an application POV).

>>> And we need a user space
>>> tool, e.g. canconfig, to handle the user requests and communicate with
>>> the kernel side.
>> Thats pretty standard :)
> 
> For the iproute2 utility "ip", mainliy a netlink_can.c would be
> required. But a dedicated tool for CAN seems more appropriate to me.

I don't know the CAN specifics. One goal of the rtnl_link API
was to reduce to amount of userspace tools for link configuration
though, so please only create a new tool if there's really a good
reason. From my POV it would be preferrable to have link configuration
in iproute for direct use by users and possibly also support in
libnl for use by other applications.

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Wolfgang Grandegger - Feb. 24, 2009, 4:29 p.m.
Patrick McHardy wrote:
> Wolfgang Grandegger wrote:
>>>> 1. Set and get CAN device properties like bit-rate and controller mode.
>>>> 2. Show CAN bus state (active, error-passive or bus-off).
>>>> 3. Get device constants like clock frequency and bit-timing parameters.
>>>> 4. Dump CAN device statistics.
>>>> 5. Trigger device restart if CAN bus-off state has been detected.
>>>>
>>>> Not sure yet, if the interface if good for all purposes. Especially
>>>> point 5. might be better handled by an IOCTL.
>>> The first points sound pretty regular. The last one - just triggering
>>> it is no problem of course, but since I don't know how the detection
>>> works, I can't really tell whether its suitable.
>>
>> CAN errors and state changes might be delivered as CAN error messages to
>> the receiving socket/application, like normal messages. When the
>> application realizes the state change to CAN bus-off, it may want to
>> trigger a bus-off recovery (controller restart). The CAN controller HW
>> enters bus-off, when too much errors occurred on the bus. No more
>> messages can then be sent of received and therefore the driver calls
>> netif_carrier_off(). Is there already an interface for the user to
>> restart? An appropriate IOCTL request would be a simply option, but they
>> are generally deprecated, AFAIK. Using netlink would be more cumbersome,
>> as with SYSFS.
> 
> You could consider triggering the restart automatically, similar
> to the netdev watchdog. In fact, you could simply use that one.

Automatic restart is already support by this patch series but we do not
use the watchdog, because it would trigger on normal transmit timeouts
as well. But maybe we can suppress them by fiddling with the watchdog's
timeout value.

> If you really want to trigger this from userspace, setting the
> device DOWN and UP again seems like the most appropriate way to
> me (even though not very nice to use from an application POV).

That's an option, but it might be a bit heavy, though.

>>>> And we need a user space
>>>> tool, e.g. canconfig, to handle the user requests and communicate with
>>>> the kernel side.
>>> Thats pretty standard :)
>>
>> For the iproute2 utility "ip", mainliy a netlink_can.c would be
>> required. But a dedicated tool for CAN seems more appropriate to me.
> 
> I don't know the CAN specifics. One goal of the rtnl_link API
> was to reduce to amount of userspace tools for link configuration
> though, so please only create a new tool if there's really a good
> reason. From my POV it would be preferrable to have link configuration
> in iproute for direct use by users and possibly also support in
> libnl for use by other applications.

OK, it also depends on what we would like the tool finally to perform,
apart from setting and getting device properties. On idea is to move the
rather heavy calculation of bit-timing parameters out of the kernel to
the user-space configuration tool.

Wolfgang.


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 57def0d..d609895 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -12,6 +12,29 @@  config CAN_VCAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called vcan.
 
+config CAN_DEV
+	tristate "Platform CAN drivers with SYSFS support"
+	depends on CAN && SYSFS
+	default Y
+	---help---
+	  Enables the common framework for platform CAN drivers with SYSFS
+	  support. This is the standard library for CAN drivers.
+	  If unsure, say Y.
+
+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
+	  bit-rate specified via SYSFS file "bitrate" when the device gets
+	  started. This works fine for the most common CAN controllers
+	  with standard bit-rates but may fail for exotic bit-rates or CAN
+	  source clock frequencies. Disabling saves some space, but then the
+	  bit-timing parameters must be specified directly using the SYSFS
+	  files "tq", "prop_seg", "phase_seg1", "phase_seg2" and "sjw".
+	  If unsure, say Y.
+
 config CAN_DEBUG_DEVICES
 	bool "CAN devices debugging messages"
 	depends on CAN
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index c4bead7..557114b 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -3,3 +3,8 @@ 
 #
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
+
+obj-$(CONFIG_CAN_DEV)		+= can-dev.o
+can-dev-y			:= dev.o sysfs.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
new file mode 100644
index 0000000..faa75d1
--- /dev/null
+++ b/drivers/net/can/dev.c
@@ -0,0 +1,528 @@ 
+/*
+ * Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <net/rtnetlink.h>
+
+#include "sysfs.h"
+
+#define MOD_DESC "CAN device driver interface"
+
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+
+#ifdef CONFIG_CAN_CALC_BITTIMING
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
+
+/*
+ * Bit-timing calculation derived from:
+ *
+ * Code based on LinCAN sources and H8S2638 project
+ * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
+ * Copyright 2005      Stanislav Marek
+ * email: pisa@cmp.felk.cvut.cz
+ */
+static int can_update_spt(const struct can_bittiming_const *btc,
+			  int sampl_pt, int tseg, int *tseg1, int *tseg2)
+{
+	*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000;
+	if (*tseg2 < btc->tseg2_min)
+		*tseg2 = btc->tseg2_min;
+	if (*tseg2 > btc->tseg2_max)
+		*tseg2 = btc->tseg2_max;
+	*tseg1 = tseg - *tseg2;
+	if (*tseg1 > btc->tseg1_max) {
+		*tseg1 = btc->tseg1_max;
+		*tseg2 = tseg - *tseg1;
+	}
+	return 1000 * (tseg + 1 - *tseg2) / (tseg + 1);
+}
+
+static int can_calc_bittiming(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->bittiming;
+	const struct can_bittiming_const *btc = priv->bittiming_const;
+	long rate, best_rate = 0;
+	long best_error = 1000000000, error = 0;
+	int best_tseg = 0, best_brp = 0, brp = 0;
+	int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
+	int spt_error = 1000, spt = 0, sampl_pt;
+	u64 v64;
+
+	if (!priv->bittiming_const)
+		return -ENOTSUPP;
+
+	/* Use CIA recommended sample points */
+	if (bt->sample_point) {
+		sampl_pt = bt->sample_point;
+	} else {
+		if (bt->bitrate > 800000)
+			sampl_pt = 750;
+		else if (bt->bitrate > 500000)
+			sampl_pt = 800;
+		else
+			sampl_pt = 875;
+	}
+
+	/* tseg even = round down, odd = round up */
+	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
+	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
+		tsegall = 1 + tseg / 2;
+		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
+		brp = bt->clock / (tsegall * bt->bitrate) + tseg % 2;
+		/* chose brp step which is possible in system */
+		brp = (brp / btc->brp_inc) * btc->brp_inc;
+		if ((brp < btc->brp_min) || (brp > btc->brp_max))
+			continue;
+		rate = bt->clock / (brp * tsegall);
+		error = bt->bitrate - rate;
+		/* tseg brp biterror */
+		if (error < 0)
+			error = -error;
+		if (error > best_error)
+			continue;
+		best_error = error;
+		if (error == 0) {
+			spt = can_update_spt(btc, sampl_pt, tseg / 2,
+					     &tseg1, &tseg2);
+			error = sampl_pt - spt;
+			if (error < 0)
+				error = -error;
+			if (error > spt_error)
+				continue;
+			spt_error = error;
+		}
+		best_tseg = tseg / 2;
+		best_brp = brp;
+		best_rate = rate;
+		if (error == 0)
+			break;
+	}
+
+	if (best_error) {
+		/* Error in one-tenth of a percent */
+		error = (best_error * 1000) / bt->bitrate;
+		if (error > CAN_CALC_MAX_ERROR) {
+			dev_err(ND2D(dev), "bitrate error %ld.%ld%% too high\n",
+				error / 10, error % 10);
+			return -EDOM;
+		} else {
+			dev_warn(ND2D(dev), "bitrate error %ld.%ld%%\n",
+				 error / 10, error % 10);
+		}
+	}
+
+	spt = can_update_spt(btc, sampl_pt, best_tseg, &tseg1, &tseg2);
+
+	v64 = (u64)best_brp * 1000000000UL;
+	do_div(v64, bt->clock);
+	bt->tq = (u32)v64;
+	bt->prop_seg = tseg1 / 2;
+	bt->phase_seg1 = tseg1 - bt->prop_seg;
+	bt->phase_seg2 = tseg2;
+	bt->sjw = 1;
+	bt->brp = best_brp;
+
+	return 0;
+}
+#else /* !CONFIG_CAN_CALC_BITTIMING */
+static int can_calc_bittiming(struct net_device *dev)
+{
+	dev_err(ND2D(dev), "bit-timing calculation not available\n");
+	return -EINVAL;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
+
+int can_sample_point(struct can_bittiming *bt)
+{
+	return ((bt->prop_seg + bt->phase_seg1 + 1) * 1000) /
+		(bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1);
+}
+
+static int can_fixup_bittiming(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->bittiming;
+	const struct can_bittiming_const *btc = priv->bittiming_const;
+	int tseg1, alltseg;
+	u32 bitrate;
+	u64 brp64;
+
+	if (!priv->bittiming_const)
+		return -ENOTSUPP;
+
+	tseg1 = bt->prop_seg + bt->phase_seg1;
+	if (bt->sjw > btc->sjw_max ||
+	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
+	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
+		return -EINVAL;
+
+	brp64 = (u64)bt->clock * (u64)bt->tq;
+	if (btc->brp_inc > 1)
+		do_div(brp64, btc->brp_inc);
+	brp64 += 500000000UL - 1;
+	do_div(brp64, 1000000000UL); /* the practicable BRP */
+	if (btc->brp_inc > 1)
+		brp64 *= btc->brp_inc;
+	bt->brp = (u32)brp64;
+
+	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
+		return -EINVAL;
+
+	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
+	bitrate = bt->clock / (bt->brp * alltseg);
+	bt->bitrate = bitrate;
+
+	return 0;
+}
+
+/*
+ * Set CAN bit-timing for the device
+ *
+ * This functions should be called in the open function of the device
+ * driver to determine, check and set appropriate bit-timing parameters.
+ */
+int can_set_bittiming(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* Check if bit-timing parameters have been pre-defined */
+	if (!priv->bittiming.tq && !priv->bittiming.bitrate) {
+		dev_err(ND2D(dev), "bit-timing not yet defined\n");
+		return -EINVAL;
+	}
+
+	/* Check if the CAN device has bit-timing parameters */
+	if (priv->bittiming_const) {
+
+		/* Check if bit-timing parameters have already been set */
+		if (priv->bittiming.tq && priv->bittiming.bitrate)
+			return 0;
+
+		/* Non-expert mode? Check if the bitrate has been pre-defined */
+		if (!priv->bittiming.tq)
+			/* Determine bit-timing parameters */
+			err = can_calc_bittiming(dev);
+		else
+			/* Check bit-timing params and calculate proper brp */
+			err = can_fixup_bittiming(dev);
+		if (err)
+			return err;
+	}
+
+	if (priv->do_set_bittiming) {
+		/* Finally, set the bit-timing registers */
+		err = priv->do_set_bittiming(dev);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_set_bittiming);
+
+static void can_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_CAN;
+	dev->mtu = sizeof(struct can_frame);
+	dev->hard_header_len = 0;
+	dev->addr_len = 0;
+	dev->tx_queue_len = 10;
+
+	/* New-style flags. */
+	dev->flags = IFF_NOARP;
+	dev->features = NETIF_F_NO_CSUM;
+}
+
+/*
+ * Allocate and setup space for the CAN network device
+ */
+struct net_device *alloc_candev(int sizeof_priv)
+{
+	struct net_device *dev;
+	struct can_priv *priv;
+
+	dev = alloc_netdev(sizeof_priv, "can%d", can_setup);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+
+	priv->state = CAN_STATE_STOPPED;
+	spin_lock_init(&priv->irq_lock);
+
+	init_timer(&priv->timer);
+	priv->timer.expires = 0;
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_candev);
+
+/*
+ * Allocate space of the CAN network device
+ */
+void free_candev(struct net_device *dev)
+{
+	free_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(free_candev);
+
+/*
+ * Register the CAN network device
+ */
+int register_candev(struct net_device *dev)
+{
+	int err;
+
+	err = register_netdev(dev);
+	if (err)
+		return err;
+
+	can_create_sysfs(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(register_candev);
+
+/*
+ * Unregister the CAN network device
+ */
+void unregister_candev(struct net_device *dev)
+{
+	can_remove_sysfs(dev);
+	unregister_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_candev);
+
+/*
+ * Local echo of CAN messages
+ *
+ * CAN network devices *should* support a local echo functionality
+ * (see Documentation/networking/can.txt). To test the handling of CAN
+ * interfaces that do not support the local echo both driver types are
+ * implemented. In the case that the driver does not support the echo
+ * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
+ * to perform the echo as a fallback solution.
+ */
+
+static void can_flush_echo_skb(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	int i;
+
+	for (i = 0; i < CAN_ECHO_SKB_MAX; i++) {
+		if (priv->echo_skb[i]) {
+			kfree_skb(priv->echo_skb[i]);
+			priv->echo_skb[i] = NULL;
+			stats->tx_dropped++;
+			stats->tx_aborted_errors++;
+		}
+	}
+}
+
+/*
+ * Put the skb on the stack to be looped backed locally lateron
+ *
+ * The function is typically called in the start_xmit function
+ * of the device driver.
+ */
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* set flag whether this packet has to be looped back */
+	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) {
+		kfree_skb(skb);
+		return;
+	}
+
+	if (!priv->echo_skb[idx]) {
+		struct sock *srcsk = skb->sk;
+
+		if (atomic_read(&skb->users) != 1) {
+			struct sk_buff *old_skb = skb;
+
+			skb = skb_clone(old_skb, GFP_ATOMIC);
+			kfree_skb(old_skb);
+			if (!skb)
+				return;
+		} else
+			skb_orphan(skb);
+
+		skb->sk = srcsk;
+
+		/* make settings for echo to reduce code in irq context */
+		skb->protocol = htons(ETH_P_CAN);
+		skb->pkt_type = PACKET_BROADCAST;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->dev = dev;
+
+		/* save this skb for tx interrupt echo handling */
+		priv->echo_skb[idx] = skb;
+	} else {
+		/* locking problem with netif_stop_queue() ?? */
+		printk(KERN_ERR "%s: %s: BUG! echo_skb is occupied!\n",
+		       dev->name, __func__);
+		kfree_skb(skb);
+	}
+}
+EXPORT_SYMBOL_GPL(can_put_echo_skb);
+
+/*
+ * Get the skb from the stack and loop it back locally
+ *
+ * The function is typically called when the TX done interrupt
+ * is handled in the device driver.
+ */
+void can_get_echo_skb(struct net_device *dev, int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if ((dev->flags & IFF_ECHO) && priv->echo_skb[idx]) {
+		netif_rx(priv->echo_skb[idx]);
+		priv->echo_skb[idx] = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(can_get_echo_skb);
+
+/*
+ * CAN device restart for bus-off recovery
+ */
+int can_restart_now(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	int err;
+
+	if (netif_carrier_ok(dev))
+		netif_carrier_off(dev);
+
+	/* Cancel restart in progress */
+	if (priv->timer.expires) {
+		del_timer(&priv->timer);
+		priv->timer.expires = 0; /* mark inactive timer */
+	}
+
+	can_flush_echo_skb(dev);
+
+	err = priv->do_set_mode(dev, CAN_MODE_START);
+	if (err)
+		return err;
+
+	netif_carrier_on(dev);
+
+	dev_dbg(ND2D(dev), "restarted\n");
+	priv->can_stats.restarts++;
+
+	/* send restart message upstream */
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (skb == NULL)
+		return -ENOMEM;
+	skb->dev = dev;
+	skb->protocol = htons(ETH_P_CAN);
+	cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
+	memset(cf, 0, sizeof(struct can_frame));
+	cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
+	cf->can_dlc = CAN_ERR_DLC;
+
+	netif_rx(skb);
+
+	dev->last_rx = jiffies;
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 0;
+}
+
+static void can_restart_after(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct can_priv *priv = netdev_priv(dev);
+
+	priv->timer.expires = 0; /* mark inactive timer */
+	can_restart_now(dev);
+}
+
+/*
+ * CAN bus-off
+ *
+ * This functions should be called when the device goes bus-off to
+ * tell the netif layer that no more packets can be sent or received.
+ * If enabled, a timer is started to trigger bus-off recovery.
+ */
+void can_bus_off(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	dev_dbg(ND2D(dev), "bus-off\n");
+
+	netif_carrier_off(dev);
+
+	if (priv->restart_ms > 0 && !priv->timer.expires) {
+
+		priv->timer.function = can_restart_after;
+		priv->timer.data = (unsigned long)dev;
+		priv->timer.expires =
+			jiffies + (priv->restart_ms * HZ) / 1000;
+		add_timer(&priv->timer);
+	}
+}
+EXPORT_SYMBOL_GPL(can_bus_off);
+
+/*
+ * Cleanup function before the device gets closed.
+ *
+ * This functions should be called in the close function of the device
+ * driver.
+ */
+void can_close_cleanup(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (priv->timer.expires) {
+		del_timer(&priv->timer);
+		priv->timer.expires = 0;
+	}
+
+	can_flush_echo_skb(dev);
+}
+EXPORT_SYMBOL_GPL(can_close_cleanup);
+
+static __init int can_dev_init(void)
+{
+	printk(KERN_INFO MOD_DESC "\n");
+
+	return 0;
+}
+module_init(can_dev_init);
+
+static __exit void can_dev_exit(void)
+{
+}
+module_exit(can_dev_exit);
diff --git a/drivers/net/can/sysfs.c b/drivers/net/can/sysfs.c
new file mode 100644
index 0000000..746f641
--- /dev/null
+++ b/drivers/net/can/sysfs.c
@@ -0,0 +1,509 @@ 
+/*
+ * Copyright (C) 2007-2008 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/capability.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <net/sock.h>
+#include <linux/rtnetlink.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+
+#include "sysfs.h"
+
+#ifdef CONFIG_SYSFS
+
+/*
+ * SYSFS access functions and attributes. Use same locking as
+ * net/core/net-sysfs.c does.
+ */
+static inline int dev_isalive(const struct net_device *dev)
+{
+	return dev->reg_state <= NETREG_REGISTERED;
+}
+
+/* use same locking rules as GIF* ioctl's */
+static ssize_t can_dev_show(struct device *d,
+			    struct device_attribute *attr, char *buf,
+			    ssize_t (*fmt)(struct net_device *, char *))
+{
+	struct net_device *dev = to_net_dev(d);
+	ssize_t ret = -EINVAL;
+
+	read_lock(&dev_base_lock);
+	if (dev_isalive(dev))
+		ret = (*fmt)(dev, buf);
+	read_unlock(&dev_base_lock);
+
+	return ret;
+}
+
+/* generate a show function for simple field */
+#define CAN_DEV_SHOW(field, fmt_string)					\
+static ssize_t fmt_can_##field(struct net_device *dev, char *buf)	\
+{									\
+	struct can_priv *priv = netdev_priv(dev);			\
+	return sprintf(buf, fmt_string, priv->field);			\
+}									\
+static ssize_t show_can_##field(struct device *d,			\
+				struct device_attribute *attr,		\
+				char *buf)				\
+{									\
+	return can_dev_show(d, attr, buf, fmt_can_##field);		\
+}
+
+/* use same locking and permission rules as SIF* ioctl's */
+static ssize_t can_dev_store(struct device *d, struct device_attribute *attr,
+			     const char *buf, size_t len,
+			     int (*set)(struct net_device *, unsigned long))
+{
+	struct net_device *dev = to_net_dev(d);
+	unsigned long new;
+	int ret = -EINVAL;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	ret = strict_strtoul(buf, 0, &new);
+	if (ret)
+		goto out;
+
+	rtnl_lock();
+	if (dev_isalive(dev)) {
+		ret = (*set)(dev, new);
+		if (!ret)
+			ret = len;
+	}
+	rtnl_unlock();
+out:
+	return ret;
+}
+
+#define CAN_CREATE_FILE(_dev, _name)					\
+	if (device_create_file(&_dev->dev, &dev_attr_##_name))		\
+		dev_err(ND2D(_dev),					\
+			"Couldn't create device file for ##_name\n")
+
+#define CAN_REMOVE_FILE(_dev, _name)					\
+	device_remove_file(&_dev->dev, &dev_attr_##_name)		\
+
+CAN_DEV_SHOW(ctrlmode, "0x%x\n");
+
+static int change_can_ctrlmode(struct net_device *dev, unsigned long ctrlmode)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err = 0;
+
+	if (priv->state != CAN_STATE_STOPPED)
+		return -EBUSY;
+
+	if (priv->do_set_ctrlmode)
+		err = priv->do_set_ctrlmode(dev, ctrlmode);
+
+	if (!err)
+		priv->ctrlmode = ctrlmode;
+
+	return err;
+}
+
+static ssize_t store_can_ctrlmode(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t len)
+{
+	return can_dev_store(dev, attr, buf, len, change_can_ctrlmode);
+}
+
+static DEVICE_ATTR(can_ctrlmode, S_IRUGO | S_IWUSR,
+		   show_can_ctrlmode, store_can_ctrlmode);
+
+static const char *can_state_names[] = {
+	"active", "bus-warn", "bus-pass" , "bus-off",
+	"stopped", "sleeping", "unkown"
+};
+
+static ssize_t printf_can_state(struct net_device *dev, char *buf)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	enum can_state state;
+	int err = 0;
+
+	if (priv->do_get_state) {
+		err = priv->do_get_state(dev, &state);
+		if (err)
+			goto out;
+		priv->state = state;
+	} else
+		state = priv->state;
+
+	if (state >= ARRAY_SIZE(can_state_names))
+		state = ARRAY_SIZE(can_state_names) - 1;
+	err = sprintf(buf, "%s\n", can_state_names[state]);
+out:
+	return err;
+}
+
+static ssize_t show_can_state(struct device *d,
+			      struct device_attribute *attr, char *buf)
+{
+	return can_dev_show(d, attr, buf, printf_can_state);
+}
+
+static DEVICE_ATTR(can_state, S_IRUGO, show_can_state, NULL);
+
+CAN_DEV_SHOW(restart_ms, "%d\n");
+
+static int change_can_restart_ms(struct net_device *dev, unsigned long ms)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (priv->restart_ms < 0)
+		return -EOPNOTSUPP;
+	priv->restart_ms = ms;
+	return 0;
+}
+
+static ssize_t store_can_restart_ms(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t len)
+{
+	return can_dev_store(dev, attr, buf, len, change_can_restart_ms);
+}
+
+static DEVICE_ATTR(can_restart_ms, S_IRUGO | S_IWUSR,
+		   show_can_restart_ms, store_can_restart_ms);
+
+static ssize_t printf_can_echo(struct net_device *dev, char *buf)
+{
+	return sprintf(buf, "%d\n", dev->flags & IFF_ECHO ? 1 : 0);
+}
+
+static ssize_t show_can_echo(struct device *d,
+			  struct device_attribute *attr, char *buf)
+{
+	return can_dev_show(d, attr, buf, printf_can_echo);
+}
+
+static int change_can_echo(struct net_device *dev, unsigned long on)
+{
+	if (on)
+		dev->flags |= IFF_ECHO;
+	else
+		dev->flags &= ~IFF_ECHO;
+	return 0;
+}
+
+static ssize_t store_can_echo(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t len)
+{
+	return can_dev_store(dev, attr, buf, len, change_can_echo);
+}
+
+static DEVICE_ATTR(can_echo, S_IRUGO | S_IWUSR, show_can_echo, store_can_echo);
+
+static int change_can_restart(struct net_device *dev, unsigned long on)
+{
+	return can_restart_now(dev);
+}
+
+static ssize_t store_can_restart(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
+{
+	return can_dev_store(dev, attr, buf, len, change_can_restart);
+}
+
+static DEVICE_ATTR(can_restart, S_IWUSR, NULL, store_can_restart);
+
+/* Show a given attribute if the CAN bittiming group */
+static ssize_t can_btc_show(const struct device *d,
+			    struct device_attribute *attr, char *buf,
+			    unsigned long offset)
+{
+	struct net_device *dev = to_net_dev(d);
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming_const *btc = priv->bittiming_const;
+	ssize_t ret = -EINVAL;
+
+	WARN_ON(offset >= sizeof(struct can_bittiming_const) ||
+		offset % sizeof(u32) != 0);
+
+	read_lock(&dev_base_lock);
+	if (dev_isalive(dev) && btc)
+		ret = sprintf(buf, "%d\n",
+			      *(u32 *)(((u8 *)btc) + offset));
+
+	read_unlock(&dev_base_lock);
+	return ret;
+}
+
+/* Generate a read-only bittiming const attribute */
+#define CAN_BT_CONST_ENTRY(name)					\
+static ssize_t show_##name(struct device *d,				\
+			   struct device_attribute *attr, char *buf) 	\
+{									\
+	return can_btc_show(d, attr, buf,				\
+			    offsetof(struct can_bittiming_const, name));\
+}									\
+static DEVICE_ATTR(hw_##name, S_IRUGO, show_##name, NULL)
+
+CAN_BT_CONST_ENTRY(tseg1_min);
+CAN_BT_CONST_ENTRY(tseg1_max);
+CAN_BT_CONST_ENTRY(tseg2_min);
+CAN_BT_CONST_ENTRY(tseg2_max);
+CAN_BT_CONST_ENTRY(sjw_max);
+CAN_BT_CONST_ENTRY(brp_min);
+CAN_BT_CONST_ENTRY(brp_max);
+CAN_BT_CONST_ENTRY(brp_inc);
+
+static ssize_t can_bt_show(const struct device *d,
+			   struct device_attribute *attr, char *buf,
+			   unsigned long offset)
+{
+	struct net_device *dev = to_net_dev(d);
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->bittiming;
+	ssize_t ret = -EINVAL;
+	u32 *ptr, val;
+
+	WARN_ON(offset >= sizeof(struct can_bittiming) ||
+		offset % sizeof(u32) != 0);
+
+	read_lock(&dev_base_lock);
+	if (dev_isalive(dev)) {
+		ptr = (u32 *)(((u8 *)bt) + offset);
+		if (ptr == &bt->sample_point &&
+		    priv->state != CAN_STATE_STOPPED)
+			val = can_sample_point(bt);
+		else
+			val = *ptr;
+		ret = sprintf(buf, "%d\n", val);
+	}
+	read_unlock(&dev_base_lock);
+	return ret;
+}
+
+static ssize_t can_bt_store(const struct device *d,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count,
+			    unsigned long offset)
+{
+	struct net_device *dev = to_net_dev(d);
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_bittiming *bt = &priv->bittiming;
+	unsigned long new;
+	ssize_t ret = -EINVAL;
+	u32 *ptr;
+
+	if (priv->state != CAN_STATE_STOPPED)
+		return -EBUSY;
+
+	WARN_ON(offset >= sizeof(struct can_bittiming) ||
+		offset % sizeof(u32) != 0);
+
+	ret = strict_strtoul(buf, 0, &new);
+	if (ret)
+		goto out;
+
+	ptr = (u32 *)(((u8 *)bt) + offset);
+	rtnl_lock();
+	if (dev_isalive(dev)) {
+		*ptr = (u32)new;
+
+		if ((ptr == &bt->bitrate) || (ptr == &bt->sample_point)) {
+			bt->tq = 0;
+			bt->brp = 0;
+			bt->sjw = 0;
+			bt->prop_seg = 0;
+			bt->phase_seg1 = 0;
+			bt->phase_seg2 = 0;
+		} else {
+			bt->bitrate = 0;
+			bt->sample_point = 0;
+		}
+		ret = count;
+	}
+	rtnl_unlock();
+out:
+	return ret;
+}
+
+#define CAN_BT_ENTRY_RO(name)						\
+static ssize_t show_##name(struct device *d,				\
+			   struct device_attribute *attr, char *buf) 	\
+{									\
+	return can_bt_show(d, attr, buf,				\
+			   offsetof(struct can_bittiming, name));	\
+}									\
+static DEVICE_ATTR(hw_##name, S_IRUGO, show_##name, NULL)
+
+CAN_BT_ENTRY_RO(clock);
+
+#define CAN_BT_ENTRY(name)						\
+static ssize_t show_##name(struct device *d,				\
+			   struct device_attribute *attr, char *buf) 	\
+{									\
+	return can_bt_show(d, attr, buf,				\
+			   offsetof(struct can_bittiming, name));	\
+}									\
+static ssize_t store_##name(struct device *d,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t count)		\
+{									\
+	return can_bt_store(d, attr, buf, count,			\
+			    offsetof(struct can_bittiming, name));	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO | S_IWUSR, show_##name, store_##name)
+
+CAN_BT_ENTRY(bitrate);
+CAN_BT_ENTRY(sample_point);
+CAN_BT_ENTRY(tq);
+CAN_BT_ENTRY(prop_seg);
+CAN_BT_ENTRY(phase_seg1);
+CAN_BT_ENTRY(phase_seg2);
+CAN_BT_ENTRY(sjw);
+
+static struct attribute *can_bittiming_attrs[] = {
+	&dev_attr_hw_tseg1_min.attr,
+	&dev_attr_hw_tseg1_max.attr,
+	&dev_attr_hw_tseg2_max.attr,
+	&dev_attr_hw_tseg2_min.attr,
+	&dev_attr_hw_sjw_max.attr,
+	&dev_attr_hw_brp_min.attr,
+	&dev_attr_hw_brp_max.attr,
+	&dev_attr_hw_brp_inc.attr,
+	&dev_attr_hw_clock.attr,
+	&dev_attr_bitrate.attr,
+	&dev_attr_sample_point.attr,
+	&dev_attr_tq.attr,
+	&dev_attr_prop_seg.attr,
+	&dev_attr_phase_seg1.attr,
+	&dev_attr_phase_seg2.attr,
+	&dev_attr_sjw.attr,
+	NULL
+};
+
+static struct attribute_group can_bittiming_group = {
+	.name = "can_bittiming",
+	.attrs = can_bittiming_attrs,
+};
+
+/* Show a given attribute in the CAN statistics group */
+static ssize_t can_stat_show(const struct device *d,
+			     struct device_attribute *attr, char *buf,
+			     unsigned long offset)
+{
+	struct net_device *dev = to_net_dev(d);
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_device_stats *stats = &priv->can_stats;
+	ssize_t ret = -EINVAL;
+
+	WARN_ON(offset >= sizeof(struct can_device_stats) ||
+		offset % sizeof(unsigned long) != 0);
+
+	read_lock(&dev_base_lock);
+	if (dev_isalive(dev))
+		ret = sprintf(buf, "%ld\n",
+			      *(unsigned long *)(((u8 *)stats) + offset));
+
+	read_unlock(&dev_base_lock);
+	return ret;
+}
+
+/* Generate a read-only CAN statistics attribute */
+#define CAN_STAT_ENTRY(name)						\
+static ssize_t show_##name(struct device *d,				\
+			   struct device_attribute *attr, char *buf) 	\
+{									\
+	return can_stat_show(d, attr, buf,				\
+			     offsetof(struct can_device_stats, name));	\
+}									\
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+CAN_STAT_ENTRY(error_warning);
+CAN_STAT_ENTRY(error_passive);
+CAN_STAT_ENTRY(bus_error);
+CAN_STAT_ENTRY(arbitration_lost);
+CAN_STAT_ENTRY(data_overrun);
+CAN_STAT_ENTRY(wakeup);
+CAN_STAT_ENTRY(restarts);
+
+static struct attribute *can_statistics_attrs[] = {
+	&dev_attr_error_warning.attr,
+	&dev_attr_error_passive.attr,
+	&dev_attr_bus_error.attr,
+	&dev_attr_arbitration_lost.attr,
+	&dev_attr_data_overrun.attr,
+	&dev_attr_wakeup.attr,
+	&dev_attr_restarts.attr,
+	NULL
+};
+
+static struct attribute_group can_statistics_group = {
+	.name = "can_statistics",
+	.attrs = can_statistics_attrs,
+};
+
+void can_create_sysfs(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	CAN_CREATE_FILE(dev, can_ctrlmode);
+	CAN_CREATE_FILE(dev, can_echo);
+	CAN_CREATE_FILE(dev, can_restart);
+	CAN_CREATE_FILE(dev, can_state);
+	CAN_CREATE_FILE(dev, can_restart_ms);
+
+	err = sysfs_create_group(&(dev->dev.kobj),
+				 &can_statistics_group);
+	if (err) {
+		printk(KERN_EMERG
+		       "couldn't create sysfs group for CAN statistics\n");
+	}
+
+	if (priv->bittiming_const) {
+		err = sysfs_create_group(&(dev->dev.kobj),
+					 &can_bittiming_group);
+		if (err) {
+			printk(KERN_EMERG "couldn't create sysfs "
+			       "group for CAN bittiming\n");
+		}
+	}
+}
+
+void can_remove_sysfs(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	CAN_REMOVE_FILE(dev, can_ctrlmode);
+	CAN_REMOVE_FILE(dev, can_echo);
+	CAN_REMOVE_FILE(dev, can_state);
+	CAN_REMOVE_FILE(dev, can_restart);
+	CAN_REMOVE_FILE(dev, can_restart_ms);
+
+	sysfs_remove_group(&(dev->dev.kobj), &can_statistics_group);
+	if (priv->bittiming_const)
+		sysfs_remove_group(&(dev->dev.kobj), &can_bittiming_group);
+}
+
+#endif /* CONFIG_SYSFS */
+
+
+
diff --git a/drivers/net/can/sysfs.h b/drivers/net/can/sysfs.h
new file mode 100644
index 0000000..e21f2fa
--- /dev/null
+++ b/drivers/net/can/sysfs.h
@@ -0,0 +1,24 @@ 
+/*
+ * Copyright (C) 2007 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef CAN_SYSFS_H
+#define CAN_SYSFS_H
+
+void can_create_sysfs(struct net_device *dev);
+void can_remove_sysfs(struct net_device *dev);
+
+#endif /* CAN_SYSFS_H */
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
new file mode 100644
index 0000000..078ac03
--- /dev/null
+++ b/include/linux/can/dev.h
@@ -0,0 +1,136 @@ 
+/*
+ * linux/can/dev.h
+ *
+ * Definitions for the CAN network device driver interface
+ *
+ * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
+ *               Varma Electronics Oy
+ *
+ * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * Send feedback to <socketcan-users@lists.berlios.de>
+ */
+
+#ifndef CAN_DEV_H
+#define CAN_DEV_H
+
+#include <linux/can/error.h>
+
+/*
+ * CAN bitrate and bit-timing
+ */
+struct can_bittiming {
+	u32 bitrate;
+	u32 sample_point;
+	u32 tq;
+	u32 prop_seg;
+	u32 phase_seg1;
+	u32 phase_seg2;
+	u32 sjw;
+	u32 clock;
+	u32 brp;
+};
+
+struct can_bittiming_const {
+	u32 tseg1_min;
+	u32 tseg1_max;
+	u32 tseg2_min;
+	u32 tseg2_max;
+	u32 sjw_max;
+	u32 brp_min;
+	u32 brp_max;
+	u32 brp_inc;
+};
+
+/*
+ * CAN mode
+ */
+enum can_mode {
+	CAN_MODE_STOP = 0,
+	CAN_MODE_START,
+	CAN_MODE_SLEEP
+};
+
+/*
+ * CAN controller mode
+ */
+#define CAN_CTRLMODE_LOOPBACK	0x1
+#define CAN_CTRLMODE_LISTENONLY	0x2
+#define CAN_CTRLMODE_3_SAMPLES	0x4 /* Triple sampling mode */
+
+/*
+ * CAN operational and error states
+ */
+enum can_state {
+	CAN_STATE_ACTIVE = 0,
+	CAN_STATE_BUS_WARNING,
+	CAN_STATE_BUS_PASSIVE,
+	CAN_STATE_BUS_OFF,
+	CAN_STATE_STOPPED,
+	CAN_STATE_SLEEPING
+};
+
+/*
+ * CAN device statistics
+ */
+struct can_device_stats {
+	unsigned long error_warning;
+	unsigned long data_overrun;
+	unsigned long wakeup;
+	unsigned long bus_error;
+	unsigned long error_passive;
+	unsigned long arbitration_lost;
+	unsigned long restarts;
+	unsigned long bus_error_at_init;
+};
+
+/*
+ * CAN common private data
+ */
+#define CAN_ECHO_SKB_MAX  4
+
+struct can_priv {
+	struct can_device_stats can_stats;
+
+	struct can_bittiming bittiming;
+	struct can_bittiming_const *bittiming_const;
+
+	spinlock_t irq_lock;
+
+	enum can_state state;
+	u32 ctrlmode;
+
+	int restart_ms;
+	struct timer_list timer;
+
+	struct sk_buff *echo_skb[CAN_ECHO_SKB_MAX];
+
+	int (*do_set_bittiming)(struct net_device *dev);
+	int (*do_get_state)(struct net_device *dev, enum can_state *state);
+	int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
+	int (*do_set_ctrlmode)(struct net_device *dev, u32 ctrlmode);
+	int (*do_get_ctrlmode)(struct net_device *dev, u32 *ctrlmode);
+};
+
+#define ND2D(_ndev)	(_ndev->dev.parent)
+
+
+struct net_device *alloc_candev(int sizeof_priv);
+void free_candev(struct net_device *dev);
+int register_candev(struct net_device *dev);
+void unregister_candev(struct net_device *dev);
+
+int can_set_bittiming(struct net_device *dev);
+
+int can_restart_now(struct net_device *dev);
+
+void can_bus_off(struct net_device *dev);
+
+void can_close_cleanup(struct net_device *dev);
+
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx);
+void can_get_echo_skb(struct net_device *dev, int idx);
+
+int can_sample_point(struct can_bittiming *bt);
+
+#endif /* CAN_DEV_H */